This class implements the capability to search over the current classpath * retrieving classes that implement a certain interface.
* * Copyright 2001 Sapient * @since carbon 1.0 * @author Greg Hinkle, June 2001 * @version $Revision: 1.10 $($Author: dvoet $ / $Date: 2003/05/05 21:21:23 $) */ public class ClassFinder { /** * Tracks the count of classes found that match the * provided criteria. */ protected long foundClasses = 0; /** * The super class criteria */ protected Class superClass = null; /** * The required substring path criteria for this searcher */ protected String requiredPathSubstring = null; /** * The set of classes found matching the provided criteria. */ protected Set classes = new HashSet(2000); /** *Instantiates the type of MBeanHarvester that will return all classes * in the entire classpath.
*/ public ClassFinder() { } /** *Instantiates the type of MBeanHarvester that will return all classes * that are assignable to the supplied class. This would include all * implementations of it, if it is an interface or it and all subclasses * of it if it's a class.
* * @param superClass the Class that should be searched for along with * implementations and subclasses */ public ClassFinder(Class superClass) { this.superClass = superClass; } /** *Instantiates the type of MBeanHarvester that will return all classes
* that are assignable to the supplied class and are part of the supplied
* package. This would include all implementations of it, if it is an
* interface or it and all subclasses of it if it's a class. The
* supplied requiredPathSubstring must be part of the fully
* qualified classname.
Adds a class name to the list of found classes if and only if it meets * the configured requirements.
* * @param className the FQN String name of the class to add */ protected void addClassName(String className) { // Only add this class if we're not checking for a particular // substring of the FQN or we find that substring if ((this.requiredPathSubstring == null) || (className.indexOf(this.requiredPathSubstring) >= 0)) { if (this.superClass == null) { this.classes.add(className); } else { try { // TODO: GH - add a way to search other classpaths and the // system classpath. Class theClass = Class.forName( className, false, this.getClass().getClassLoader()); if (this.superClass.isAssignableFrom(theClass)) { this.classes.add(className); } } catch (ClassNotFoundException cnfe) { // Used to catch mis-parsed classnames } catch (Throwable t) { // Used to catch JVM security and linkage errors } } } } /** *Used to retrieve the results Set
from this harvester's
* search.
Looks at the name of a file to determine if it is an archive
* @param name the name of a file * @return true if a file in the classpath is an archive * such as a Jar or Zip file */ protected boolean isArchive(String name) { if ((name.endsWith(".jar") || (name.endsWith(".zip")))) { return true; } else { return false; } } /** *Returns the Fully Qualified Class name of a class from it's path * @param fileName the full path to a class * @return the FQN of a class */ protected String getClassName(String fileName) { String newName = fileName.replace(File.separatorChar,'.'); // Because zipfiles don't have platform specific seperators newName = newName.replace('/','.'); return newName.substring(0, fileName.length() - 6); } /** *
Iterates through the files in a zip looking for files that may be * classes. This is not recursive as zip's in zip's are not searched by the * classloader either.
* * @param file The ZipFile to be searched */ protected void processZip(ZipFile file) { Enumeration files = file.entries(); while (files.hasMoreElements()) { Object tfile = files.nextElement(); ZipEntry child = (ZipEntry) tfile; if (child.getName().endsWith(".class")) { addClassName(getClassName(child.getName())); this.foundClasses++; } } } }