/*
* Copyright Technophobia Ltd 2012
*
* This file is part of Substeps.
*
* Substeps is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Substeps is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Substeps. If not, see <http://www.gnu.org/licenses/>.
*/
package com.technophobia.substeps.scanner;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
*
* @author imoore
*
*/
public class ClasspathScanner {
public List<Class<?>> getClassesWithAnnotation(final Class<? extends Annotation> desiredAnnotation,
final ClassLoader classLoader, final String[] cpElements) {
final List<Class<?>> classList = new ArrayList<Class<?>>();
final List<String> classNameList = new ArrayList<String>();
for (final String cpElement : cpElements) {
final File f = new File(cpElement);
if (f.exists() && f.isDirectory()) {
final List<File> files = getAllFiles(f, "class");
for (final File classFile : files) {
classNameList.add(convertFileToClass(classFile, f));
}
} else {
// jar file
JarFile jarFile;
try {
jarFile = new JarFile(f);
final Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
final JarEntry nextElement = entries.nextElement();
if (!nextElement.isDirectory()) {
final String name = nextElement.getName();
if (name.endsWith(".class")) {
final String classname = name.replace(File.separatorChar, '.');
classNameList.add(classname.substring(0, classname.length() - 6));
}
}
}
} catch (final IOException e) {
// don't care
}
// load up contents of jar
}
}
for (final String className : classNameList) {
try {
if (!className.contains("$")) {
// no inner classes here thanks
final Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(desiredAnnotation)) {
classList.add(clazz);
}
}
} catch (final NoClassDefFoundError e) {
// don't care
} catch (final ClassNotFoundException e) {
// don't care about that eitehr
}
}
return classList;
}
/**
* @param class1
* @param classLoader
* @return
*/
public List<Class<?>> getClassesWithAnnotation(final Class<? extends Annotation> desiredAnnotation,
final ClassLoader classLoader) {
// scan the classpath and look for classes with that annotation
// any dirs on the classpath - recursively look into them
final String cp = System.getProperty("java.class.path");
// chop up the path into constituent parts
final String[] cpElements = cp.split(String.valueOf(File.pathSeparatorChar));
return getClassesWithAnnotation(desiredAnnotation, classLoader, cpElements);
}
private String convertFileToClass(final File f, final File root) {
final String fqp = f.getAbsolutePath().substring(root.getAbsolutePath().length() + 1,
f.getAbsolutePath().length() - 6);
return fqp.replace(File.separatorChar, '.');
}
private List<File> getAllFiles(final File root, final String extension) {
final FileFilter filter = new FileFilter() {
public boolean accept(final File f) {
return f.isDirectory() || (f.isFile() && f.getName().endsWith(extension));
}
};
final List<File> files = new ArrayList<File>();
if (root.exists()) {
final File[] children = root.listFiles(filter);
for (final File child : children) {
if (child != null && child.exists()) {
if (child.isDirectory()) {
// recurse
final List<File> childsFiles = getAllFiles(child, extension);
files.addAll(childsFiles);
} else {
files.add(child);
}
}
}
}
return files;
}
}