/** Constructs a hierarchy from the current scene. */ public Hierarchy() { this.sc = Scene.v(); state = sc.getState(); // Well, this used to be describable by 'Duh'. // Construct the subclasses hierarchy and the subinterfaces hierarchy. { Chain allClasses = sc.getClasses(); classToSubclasses = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f); interfaceToSubinterfaces = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f); classToDirSubclasses = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); interfaceToDirSubinterfaces = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); interfaceToDirImplementers = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); Iterator classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { interfaceToDirSubinterfaces.put(c, new ArrayList()); interfaceToDirImplementers.put(c, new ArrayList()); } else classToDirSubclasses.put(c, new ArrayList()); } classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.hasSuperclass()) { if (c.isInterface()) { Iterator subIt = c.getInterfaces().iterator(); while (subIt.hasNext()) { SootClass i = (SootClass) subIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; List<SootClass> l = interfaceToDirSubinterfaces.get(i); l.add(c); } } else { List<SootClass> l = classToDirSubclasses.get(c.getSuperclass()); l.add(c); Iterator subIt = c.getInterfaces().iterator(); while (subIt.hasNext()) { SootClass i = (SootClass) subIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; l = interfaceToDirImplementers.get(i); l.add(c); } } } } // Fill the directImplementers lists with subclasses. { classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { List<SootClass> imp = interfaceToDirImplementers.get(c); Set<SootClass> s = new ArraySet(); Iterator<SootClass> impIt = imp.iterator(); while (impIt.hasNext()) { SootClass c0 = impIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; s.addAll(getSubclassesOfIncluding(c0)); } imp.clear(); imp.addAll(s); } } } classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { interfaceToDirSubinterfaces.put( c, Collections.unmodifiableList(interfaceToDirSubinterfaces.get(c))); interfaceToDirImplementers.put( c, Collections.unmodifiableList(interfaceToDirImplementers.get(c))); } else classToDirSubclasses.put(c, Collections.unmodifiableList(classToDirSubclasses.get(c))); } } }
public void printTo(SootClass cl, PrintWriter out) { // add jimple line number tags setJimpleLnNum(1); // Print class name + modifiers { StringTokenizer st = new StringTokenizer(Modifier.toString(cl.getModifiers())); while (st.hasMoreTokens()) { String tok = (String) st.nextToken(); if (cl.isInterface() && tok.equals("abstract")) continue; out.print(tok + " "); } String classPrefix = ""; if (!cl.isInterface()) { classPrefix = classPrefix + " class"; classPrefix = classPrefix.trim(); } out.print(classPrefix + " " + Scene.v().quotedNameOf(cl.getName()) + ""); } // Print extension { if (cl.hasSuperclass()) out.print(" extends " + Scene.v().quotedNameOf(cl.getSuperclass().getName()) + ""); } // Print interfaces { Iterator interfaceIt = cl.getInterfaces().iterator(); if (interfaceIt.hasNext()) { out.print(" implements "); out.print("" + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + ""); while (interfaceIt.hasNext()) { out.print(","); out.print(" " + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + ""); } } } out.println(); incJimpleLnNum(); /* if (!addJimpleLn()) { Iterator clTagsIt = cl.getTags().iterator(); while (clTagsIt.hasNext()) { final Tag t = (Tag)clTagsIt.next(); out.println(t); } }*/ out.println("{"); incJimpleLnNum(); if (Options.v().print_tags_in_output()) { Iterator cTagIterator = cl.getTags().iterator(); while (cTagIterator.hasNext()) { Tag t = (Tag) cTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } // Print fields { Iterator fieldIt = cl.getFields().iterator(); if (fieldIt.hasNext()) { while (fieldIt.hasNext()) { SootField f = (SootField) fieldIt.next(); if (f.isPhantom()) continue; if (Options.v().print_tags_in_output()) { Iterator fTagIterator = f.getTags().iterator(); while (fTagIterator.hasNext()) { Tag t = (Tag) fTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } out.println(" " + f.getDeclaration() + ";"); if (addJimpleLn()) { setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), f)); } // incJimpleLnNum(); } } } // Print methods { Iterator methodIt = cl.methodIterator(); if (methodIt.hasNext()) { if (cl.getMethodCount() != 0) { out.println(); incJimpleLnNum(); } while (methodIt.hasNext()) { SootMethod method = (SootMethod) methodIt.next(); if (method.isPhantom()) continue; if (!Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers())) { if (!method.hasActiveBody()) throw new RuntimeException("method " + method.getName() + " has no active body!"); else if (Options.v().print_tags_in_output()) { Iterator mTagIterator = method.getTags().iterator(); while (mTagIterator.hasNext()) { Tag t = (Tag) mTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } printTo(method.getActiveBody(), out); if (methodIt.hasNext()) { out.println(); incJimpleLnNum(); } } else { if (Options.v().print_tags_in_output()) { Iterator mTagIterator = method.getTags().iterator(); while (mTagIterator.hasNext()) { Tag t = (Tag) mTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } out.print(" "); out.print(method.getDeclaration()); out.println(";"); incJimpleLnNum(); if (methodIt.hasNext()) { out.println(); incJimpleLnNum(); } } } } } out.println("}"); incJimpleLnNum(); }