sp-05/src/ch/usi/inf/sp/framework/ArchiveScanner.java

59 lines
1.8 KiB
Java

package ch.usi.inf.sp.framework;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
/**
* Scans a JAR archive containing Java class files, uses ASM to load each class,
* and for each class invokes Analyzer.analyze() on each registered Analyzer.
*
* @author Matthias.Hauswirth@usi.ch
*/
public final class ArchiveScanner {
private final ArrayList<ClassAnalyzer> analyzers;
public ArchiveScanner() {
analyzers = new ArrayList<ClassAnalyzer>();
}
public void addAnalyzer(final ClassAnalyzer analyzer) {
analyzers.add(analyzer);
}
public void removeAnalyzer(final ClassAnalyzer analyzer) {
analyzers.remove(analyzer);
}
public void scan(final String archiveName) throws IOException {
final ZipFile zipFile = new ZipFile(archiveName);
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
final ZipEntry zipEntry = entries.nextElement();
if (zipEntry.getName().toLowerCase().endsWith(".class"))
analyzeClass(zipFile, zipEntry);
}
}
private void analyzeClass(final ZipFile zipFile, final ZipEntry zipEntry) throws IOException {
final String location = zipFile.getName();
final ClassReader classReader = new ClassReader(zipFile.getInputStream(zipEntry));
// create an empty ClassNode (in-memory representation of a class)
final ClassNode classNode = new ClassNode();
// have the ClassReader read the class file and populate the ClassNode with the corresponding information
classReader.accept(classNode, 0);
for (final ClassAnalyzer analyzer : analyzers) {
analyzer.analyze(location, classNode);
}
}
}