-
- /*
- * @(#)InterfaceFinder.java v0.8, 2009/05/06-2020/2/8
- *
- * Search the class path for classes which implement a specific interface
- *
- * Usage: java -cp jar_file;class_folder;. InterfaceFinder interface_name_to_search
- */
-
- import java.util.Enumeration;
- import java.util.List;
- import java.util.Vector;
- import java.util.Stack;
- import java.util.HashSet;
- import java.util.jar.JarEntry;
- import java.util.jar.JarInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
-
- /**
- The interface finder is used to find all classes
- implementing a specific interface.
- The location in search includes all the subdirectories
- in the class path. Typical usage is as follows.
-
- List<Class> InterfaceFinder.getAvailableInterfaces("java.util.List");
-
- * @since 0.8
- * @version 0.8, 2009/05/06-2020/2/8
- * @author Seke Wei
- */
- public class InterfaceFinder
- {
- public static final String version="InterfaceFinder.java v0.8 2020/02/08";
-
- /**
- a file lister which uses the depth first strategy
- to traverse all files under a given directory.
- */
- public static class FileLister implements Enumeration
- {
- boolean hasMore;
- Stack<File> fstack;
-
- /**
- constructor for file lister.
- @param dir the root directory for search.
- */
- public FileLister(File dir)
- {
- fstack = new Stack<>();
- if(dir.isDirectory())
- fstack.push(dir);
- hasMore = true;
- }
-
- /**
- check if there is still file available for listing.
- @return true for elements available and false for otherwise.
- */
- public boolean hasMoreElements()
- {
- return hasMore;
- }
-
- /**
- get the next available file.
- directories are skipped.
- @return the file.
- */
- public File nextElement()
- {
- File next = null;
-
- while(fstack.empty()==false)
- {
- next = (File) fstack.pop();
- if(next.isFile())
- break;
-
- for(File f : next.listFiles())
- fstack.push(f);
- }
-
- if(fstack.empty()) hasMore=false;
-
- return next;
- }
- }
-
- /**
- get classes from a jar file which implements an interface.
- @param jarFileName the jar filename.
- @param iface the interface in search.
- @return the set of classes in jar implementing the interface.
- */
- public static List<Class> getClassesFromJARFile(String jarFileName, Class iface)
- {
- final List<Class> classes = new Vector<>();
- JarInputStream jarFile = null;
- String className = "";
- try
- {
- jarFile = new JarInputStream(new FileInputStream(jarFileName));
- JarEntry jarEntry;
- while(true)
- {
- jarEntry = jarFile.getNextJarEntry();
- if(jarEntry == null) break;
-
- className = jarEntry.toString();
-
- //System.err.println(className);
-
- if(className.endsWith(".class") && className.indexOf("$") < 0 )
- {
- //extractClassFromJar(jar, packageName, classes, jarEntry)
- className = className.replace('/','.');
- className = className.substring(0, className.length() - ".class".length());
- Class cl = Class.forName(className);
- if(iface.isAssignableFrom(cl))
- {
- //System.err.println("\t"+className+" can be assigned to "+iface);
- classes.add(cl);
- }
- }
- }
- jarFile.close();
- }
- catch (IOException ioe)
- {
- System.err.println("Unable to get Jar input stream from '"+jarFileName+"'"+ioe);
- }
- catch (ClassNotFoundException cnfe)
- {
- System.err.println("unable to find class named " + className.replace('/', '.') + "' within jar '" + jarFileName + "'"+cnfe);
- }
-
- return classes;
- }
-
- /**
- get classes from a root directory which implements an interface.
- @param dir the root directory.
- @param iface the interface in search.
- @return the set of classes in jar implementing the interface.
- @throws IOException when there is a file open error.
- */
- public static List<Class> getClassesFromDirectory(File dir, Class iface)
- {
- List<Class> classes = new Vector<>();
-
- FileLister lister = new FileLister(dir);
- while(lister.hasMoreElements())
- {
- File f = lister.nextElement();
- String className = f.toString();
-
- //System.err.println(className);
-
- if(className.endsWith(".class") && className.indexOf("$") < 0 )
- {
- className = className.replace(File.separatorChar,'.');
- className = className.substring(0, className.length() - ".class".length());
- while(className.charAt(0)=='.') className = className.substring(1);
- //System.err.println("\t"+className);
-
- try
- {
- Class cl = Class.forName(className);
- if(iface.isAssignableFrom(cl))
- {
- //System.err.println("\t"+className+" can be assigned to "+iface);
- classes.add(cl);
- }
- }
- catch(ClassNotFoundException cnfe)
- {}
- }
- }
-
- return classes;
- }
-
- /**
- get classes from the class path which implements an interface.
- @param iface the interface in search.
- @return the set of classes in jar implementing the interface.
- */
- public static List<Class> getAvailableClassesOfInterface(String iface)
- {
- List<Class> result = null;
-
- try
- {
- Class iface_class = Class.forName(iface);
- result = getAvailableClassesOfInterface(iface_class);
- }
- catch(ClassNotFoundException cnfe) {}
-
- return result;
- }
-
- /**
- get classes from the class path which implements an interface.
- @param iface the interface in search.
- @return the set of classes in jar implementing the interface.
- */
- public static List<Class> getAvailableClassesOfInterface(Class iface)
- {
- String cp = System.getProperty("java.class.path");
- //System.out.println("java.class.path = " + cp);
-
- List<Class> result = new Vector<>();
-
- // semicolon (Windows) or colon (Unix) by System.getProperty("path.separator")
- String separator = System.getProperty("path.separator");
- for(String p : cp.split(separator))
- {
- File f = new File(p);
- if(f.isDirectory())
- result.addAll(getClassesFromDirectory(f, iface));
- else if(f.isFile() && p.endsWith("jar"))
- result.addAll(getClassesFromJARFile(p, iface));
- }
-
- HashSet<Class> set = new HashSet<>(result);
-
- result.clear();
-
- for(Class c : set)
- {
- //System.err.println(c);
- result.add(c);
- }
-
- return result;
- }
-
- /**
- InterfaceFinder.java
-
- Search the class path for classes which implement a specific interface
-
- Usage: java -cp jar_file;class_folder;. InterfaceFinder interface_name_to_search
-
- Example:
- > javac InterfaceFinder.java
- > java -cp rt.jar;. InterfaceFinder java.util.List
- class javax.management.relation.RoleUnresolvedList
- class java.util.AbstractList
- class java.util.SubList
- class java.util.concurrent.CopyOnWriteArrayList
- class javax.management.AttributeList
- class java.util.AbstractSequentialList
- class java.util.RandomAccessSubList
- class java.util.ArrayList
- class java.util.Vector
- class java.util.Stack
- class java.util.LinkedList
- class javax.management.relation.RoleList
- interface java.util.List
-
- Note that since JDK 9 there is no rt.jar for testing
- */
- public static void main(String args[])
- {
- String iface = "java.util.List";
- if(args.length > 0)
- iface = args[0];
-
- List<Class> classes =
- getAvailableClassesOfInterface(iface);
-
- for(Class c : classes)
- {
- System.err.println(c);
- }
- }
- }
2009年5月21日 星期四
interface finder
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言