DependencyFinderpublic class DependencyFinder extends Object Analyzes the input JAR using the ASM java bytecode manipulation library
to list the classes and their dependencies. A "dependency" is a class
used by another class. |
Fields Summary |
---|
private final Log | mLogOutput logger. |
Constructors Summary |
---|
public DependencyFinder(Log log)Creates a new analyzer.
mLog = log;
|
Methods Summary |
---|
static java.lang.String | classReaderToClassName(org.objectweb.asm.ClassReader classReader)Utility that returns the fully qualified binary class name for a ClassReader.
E.g. it returns something like android.view.View.
if (classReader == null) {
return null;
} else {
return classReader.getClassName().replace('/", '.");
}
| java.util.Map | findClassesDeps(java.util.Map zipClasses)Finds all dependencies for all classes in keepClasses which are also
listed in zipClasses. Returns a map of all the dependencies found.
// The dependencies that we'll collect.
// It's a map Class name => uses class names.
Map<String, Set<String>> dependencyMap = new TreeMap<String, Set<String>>();
DependencyVisitor visitor = getVisitor();
int count = 0;
try {
for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
String name = entry.getKey();
TreeSet<String> set = new TreeSet<String>();
dependencyMap.put(name, set);
visitor.setDependencySet(set);
ClassReader cr = entry.getValue();
cr.accept(visitor, 0 /* flags */);
visitor.setDependencySet(null);
mLog.debugNoln("Visited %d classes\r", ++count);
}
} finally {
mLog.debugNoln("\n");
}
return dependencyMap;
| public java.util.List | findDeps(java.util.List osJarPath)Starts the analysis using parameters from the constructor.
Map<String, ClassReader> zipClasses = parseZip(osJarPath);
mLog.info("Found %d classes in input JAR%s.",
zipClasses.size(),
osJarPath.size() > 1 ? "s" : "");
Map<String, Set<String>> deps = findClassesDeps(zipClasses);
Map<String, Set<String>> missing = findMissingClasses(deps, zipClasses.keySet());
List<Map<String, Set<String>>> result = new ArrayList<Map<String,Set<String>>>(2);
result.add(deps);
result.add(missing);
return result;
| private java.util.Map | findMissingClasses(java.util.Map deps, java.util.Set zipClasses)Computes which classes FQCN were found as dependencies that are NOT listed
in the original JAR classes.
Map<String, Set<String>> missing = new TreeMap<String, Set<String>>();
for (Entry<String, Set<String>> entry : deps.entrySet()) {
String name = entry.getKey();
for (String dep : entry.getValue()) {
if (!zipClasses.contains(dep)) {
// This dependency doesn't exist in the zip classes.
Set<String> set = missing.get(dep);
if (set == null) {
set = new TreeSet<String>();
missing.put(dep, set);
}
set.add(name);
}
}
}
return missing;
| com.android.tools.layoutlib.create.DependencyFinder$DependencyVisitor | getVisitor()Instantiates a new DependencyVisitor. Useful for unit tests.
return new DependencyVisitor();
| static java.lang.String | internalToBinaryClassName(java.lang.String className)Utility that returns the fully qualified binary class name from a path-like FQCN.
E.g. it returns android.view.View from android/view/View.
if (className == null) {
return null;
} else {
return className.replace('/", '.");
}
| java.util.Map | parseZip(java.util.List jarPathList)Parses a JAR file and returns a list of all classes founds using a map
class name => ASM ClassReader. Class names are in the form "android.view.View".
TreeMap<String, ClassReader> classes = new TreeMap<String, ClassReader>();
for (String jarPath : jarPathList) {
ZipFile zip = new ZipFile(jarPath);
Enumeration<? extends ZipEntry> entries = zip.entries();
ZipEntry entry;
while (entries.hasMoreElements()) {
entry = entries.nextElement();
if (entry.getName().endsWith(".class")) {
ClassReader cr = new ClassReader(zip.getInputStream(entry));
String className = classReaderToClassName(cr);
classes.put(className, cr);
}
}
}
return classes;
| public void | printAllDeps(java.util.List result)Prints dependencies to the current logger, found stuff and missing stuff.
assert result.size() == 2;
Map<String, Set<String>> deps = result.get(0);
Map<String, Set<String>> missing = result.get(1);
// Print all dependences found in the format:
// +Found: <FQCN from zip>
// uses: FQCN
mLog.info("++++++ %d Entries found in source JARs", deps.size());
mLog.info("");
for (Entry<String, Set<String>> entry : deps.entrySet()) {
mLog.info( "+Found : %s", entry.getKey());
for (String dep : entry.getValue()) {
mLog.info(" uses: %s", dep);
}
mLog.info("");
}
// Now print all missing dependences in the format:
// -Missing <FQCN>:
// used by: <FQCN>
mLog.info("");
mLog.info("------ %d Entries missing from source JARs", missing.size());
mLog.info("");
for (Entry<String, Set<String>> entry : missing.entrySet()) {
mLog.info( "-Missing : %s", entry.getKey());
for (String dep : entry.getValue()) {
mLog.info(" used by: %s", dep);
}
mLog.info("");
}
| public void | printMissingDeps(java.util.List result)Prints only a summary of the missing dependencies to the current logger.
assert result.size() == 2;
@SuppressWarnings("unused") Map<String, Set<String>> deps = result.get(0);
Map<String, Set<String>> missing = result.get(1);
for (String fqcn : missing.keySet()) {
mLog.info("%s", fqcn);
}
|
|