package net.sf.openrocket.plugin;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.JarUtil;
import eu.infomas.annotation.AnnotationDetector;
import eu.infomas.annotation.AnnotationDetector.TypeReporter;
/**
* An AnnotationFinder that uses annotation-detector library to scan
* the class path. Compatible with the JIJ loader.
*/
public class AnnotationFinderImpl implements AnnotationFinder {
@Override
public List<Class<?>> findAnnotatedTypes(Class<?> annotation) {
final List<Class<?>> classes = new ArrayList<Class<?>>();
TypeReporter reporter = new ListReporter(classes);
final AnnotationDetector cf = new AnnotationDetector(reporter);
try {
ClassLoader loader = this.getClass().getClassLoader();
if (loader instanceof URLClassLoader) {
/*
* In case of URLClassLoader (which may be our own instantiation)
* use the URLs from there, as java.class.path may not be up-to-date.
*/
URLClassLoader urlClassLoader = (URLClassLoader) loader;
URL[] urls = urlClassLoader.getURLs();
List<File> files = new ArrayList<File>();
for (URL url : urls) {
if (url.getProtocol().equals("file")) {
files.add(JarUtil.urlToFile(url));
}
}
cf.detect(files.toArray(new File[0]));
} else {
/*
* If not using a URLClassLoader, just do the default.
*/
cf.detect();
}
} catch (IOException e) {
throw new BugException("Unable to search class path", e);
}
return classes;
}
private static class ListReporter implements TypeReporter {
private final List<Class<?>> classes;
private final Set<String> names = new HashSet<String>();
public ListReporter(List<Class<?>> classes) {
this.classes = classes;
}
@SuppressWarnings("unchecked")
@Override
public Class<? extends Annotation>[] annotations() {
return new Class[] { Plugin.class };
}
@Override
public void reportTypeAnnotation(Class<? extends Annotation> annotation, String className) {
if (names.add(className)) {
try {
classes.add(this.getClass().getClassLoader().loadClass(className));
} catch (ClassNotFoundException e) {
// Ignore
}
}
}
}
}