| 33 | import java.util.Map; |
| 34 | |
| 35 | class SootClassLoader implements JClassLoader { |
| 36 | |
| 37 | private final transient Scene scene; |
| 38 | |
| 39 | private final ClassHierarchy hierarchy; |
| 40 | |
| 41 | private final boolean allowPhantom; |
| 42 | |
| 43 | private transient Converter converter; |
| 44 | |
| 45 | private final Map<String, JClass> classes = Maps.newMap(1024); |
| 46 | |
| 47 | SootClassLoader(Scene scene, ClassHierarchy hierarchy, boolean allowPhantom) { |
| 48 | this.scene = scene; |
| 49 | this.hierarchy = hierarchy; |
| 50 | this.allowPhantom = allowPhantom; |
| 51 | } |
| 52 | |
| 53 | @Override |
| 54 | public JClass loadClass(String name) { |
| 55 | JClass jclass = classes.get(name); |
| 56 | if (jclass == null && scene != null) { |
| 57 | SootClass sootClass = scene.getSootClassUnsafe(name, allowPhantom); |
| 58 | if (sootClass != null && (!sootClass.isPhantom() || allowPhantom)) { |
| 59 | // TODO: handle phantom class more comprehensively |
| 60 | jclass = new JClass(this, sootClass.getName(), |
| 61 | sootClass.moduleName); |
| 62 | // New class must be put into classes map at first, |
| 63 | // at build(jclass) may also trigger the loading of |
| 64 | // the new created class. Not putting the class into classes |
| 65 | // may cause infinite recursion. |
| 66 | classes.put(name, jclass); |
| 67 | new SootClassBuilder(converter, sootClass).build(jclass); |
| 68 | hierarchy.addClass(jclass); |
| 69 | } |
| 70 | } |
| 71 | // TODO: add warning for missing classes |
| 72 | return jclass; |
| 73 | } |
| 74 | |
| 75 | @Override |
| 76 | public Collection<JClass> getLoadedClasses() { |
| 77 | return classes.values(); |
| 78 | } |
| 79 | |
| 80 | void setConverter(Converter converter) { |
| 81 | this.converter = converter; |
| 82 | } |
| 83 | } |