package org.hotswap.agent.util.scanner;
import org.hotswap.agent.javassist.bytecode.AnnotationsAttribute;
import org.hotswap.agent.javassist.bytecode.ClassFile;
import org.hotswap.agent.javassist.bytecode.annotation.Annotation;
import org.hotswap.agent.logging.AgentLogger;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
/**
* Scan a directory for annotation returning class names.
* <p/>
*
* @author Jiri Bubnik
*/
public class ClassPathAnnotationScanner {
private static AgentLogger LOGGER = AgentLogger.getLogger(ClassPathAnnotationScanner.class);
// Annotation name to search for
String annotation;
// scanner to search path
Scanner scanner;
/**
* Create scanner for the annotation.
*/
public ClassPathAnnotationScanner(String annotation, Scanner scanner) {
this.annotation = annotation;
this.scanner = scanner;
}
/**
* Run the scan - search path for files containing annotation.
*
* @param classLoader classloader to resolve path
* @param path path to scan {@link org.hotswap.agent.util.scanner.Scanner#scan(ClassLoader, String, ScannerVisitor)}
* @return list of class names containing the annotation
* @throws IOException scan exception.
*/
public List<String> scanPlugins(ClassLoader classLoader, String path) throws IOException {
final List<String> files = new LinkedList<String>();
scanner.scan(classLoader, path, new ScannerVisitor() {
@Override
public void visit(InputStream file) throws IOException {
ClassFile cf;
try {
DataInputStream dstream = new DataInputStream(file);
cf = new ClassFile(dstream);
} catch (IOException e) {
throw new IOException("Stream not a valid classFile", e);
}
if (hasAnnotation(cf))
files.add(cf.getName());
}
});
return files;
}
/**
* Check if the file contains annotation.
*/
protected boolean hasAnnotation(ClassFile cf) throws IOException {
AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute(AnnotationsAttribute.visibleTag);
if (visible != null) {
for (Annotation ann : visible.getAnnotations()) {
if (annotation.equals(ann.getTypeName())) {
return true;
}
}
}
return false;
}
}