package liquibase.servicelocator;
import org.osgi.framework.Bundle;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;
final public class BundlePackageScanClassResolver implements PackageScanClassResolver {
final private Set<ClassLoader> classLoaders = new LinkedHashSet<ClassLoader>();
final private Bundle bundle;
public BundlePackageScanClassResolver(final Bundle bundle) {
this.bundle = bundle;
}
@Override
public void setClassLoaders(Set<ClassLoader> classLoaders) {
this.classLoaders.clear();
classLoaders.addAll(classLoaders);
}
@Override
public Set<ClassLoader> getClassLoaders() {
return classLoaders;
}
@Override
public void addClassLoader(ClassLoader classLoader) {
classLoaders.add(classLoader);
}
@Override
public Set<Class<?>> findImplementations(final Class<?> parent, final String... packageNames) {
final Set<Class<?>> classSet = new LinkedHashSet<Class<?>>();
for (final String packageName : packageNames) {
final Enumeration entries = bundle.findEntries("/" + packageName.replace('.', '/'), "*.class", true);
while (entries.hasMoreElements()) {
final URL url = (URL) entries.nextElement();
final String path = url.getPath();
final int index = path.indexOf("/");
final int endIndex = path.length() - 6; //Strip ".class" substring
final String className = path.substring(index + 1, endIndex).replace('/', '.');
try {
final Class clazz = bundle.loadClass(className);
int modifiers = clazz.getModifiers();
if (!Modifier.isAbstract(modifiers) && !Modifier.isInterface(modifiers)) {
if (parent.isAssignableFrom(clazz)) {
classSet.add(clazz);
}
}
} catch (ClassNotFoundException e) {
//
}
}
}
return classSet;
}
}