KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgap > util > PluginDiscoverer


1 /*
2  * This file is part of JGAP.
3  *
4  * JGAP offers a dual license model containing the LGPL as well as the MPL.
5  *
6  * For licencing information please see the file license.txt included with JGAP
7  * or have a look at the top of class org.jgap.Chromosome which representatively
8  * includes the JGAP license policy applicable for any file delivered with JGAP.
9  */

10 package org.jgap.util;
11
12 import java.io.*;
13 import java.util.*;
14 import java.util.jar.*;
15
16 /**
17  * This class will (slightly inefficiently) look for all classes that implement
18  * a particular interface. It is useful for plugins. This is done by looking
19  * through the contents of all jar files in the classpath, as well as
20  * performing a recursive search for *.class files in the classpath directories
21  *
22  * This particular class may not work in restrictive ClassLoader environments
23  * such as Applets or WebStart. (It may...but unlikely and untested.)
24  *
25  * @author Klaus Meffert
26  * @since 2.3
27  */

28 public class PluginDiscoverer {
29   /** String containing the CVS revision. Read out via reflection!*/
30   private final static String JavaDoc CVS_REVISION = "$Revision: 1.8 $";
31
32   private static final boolean DEBUG = false;
33
34   //list of folders in the classpath
35
private List m_classpathFolders;
36
37   //list of jars in the classpath
38
private List m_classpathJars;
39
40   private String JavaDoc m_jarFile;
41
42   /**
43    * Reads the list of jars and classpath folders into instance variables
44    * for later (cached) access.
45    *
46    * @author Klaus Meffert
47    * @since 2.3
48    */

49   public PluginDiscoverer() {
50     init();
51     String JavaDoc classpath = System.getProperty("java.class.path");
52     StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator);
53     while (st.hasMoreTokens()) {
54       String JavaDoc item = st.nextToken();
55       File f = new File(item);
56       if (item.toLowerCase().endsWith(".jar") && f.isFile()) {
57         m_classpathJars.add(item);
58       }
59       else if (f.isDirectory()) {
60         m_classpathFolders.add(item);
61       }
62     }
63   }
64
65   /**
66    * Prepares the discoverer for a single jar file
67    * @param a_jarFile String
68    *
69    * @author Klaus Meffert
70    * @since 3.2
71    */

72   public PluginDiscoverer(String JavaDoc a_jarFile) {
73     init();
74     m_jarFile = a_jarFile;
75     m_classpathJars.add(m_jarFile);
76   }
77
78   private void init() {
79     m_classpathFolders = new Vector();
80     m_classpathJars = new Vector();
81   }
82
83   /**
84    * Checks if a given class matches a given interface
85    * @param interfaceClass The interface we are looking for
86    * @param testClass class under test against the interface
87    * @return corrected name of matched class, or null if not matching
88    *
89    * @author Klaus Meffert
90    * @since 2.3
91    */

92   private String JavaDoc checkIfClassMatches(String JavaDoc a_jarFilename, final Class JavaDoc a_interfaceClass,
93                                      String JavaDoc a_testClass) {
94     // remove trailing dots
95
if (a_testClass.toLowerCase().endsWith(".class")) {
96       a_testClass = a_testClass.substring(0, a_testClass.length() - 6);
97     }
98     // replace slashes with dots
99
a_testClass = a_testClass.replace('\\', '.').replace('/', '.');
100     // remove leading dots
101
while (a_testClass.startsWith(".")) {
102       a_testClass = a_testClass.substring(1);
103     }
104     if (a_testClass.indexOf('$') != -1) {
105       // don't handle inner/internal classes
106
return null;
107     }
108     try {
109       ClassLoader JavaDoc cl;
110       if (a_jarFilename == null) {
111         cl = getClass().getClassLoader();
112       }
113       else {
114         cl = new JarClassLoader(a_jarFilename);
115       }
116       Class JavaDoc testClassObj = Class.forName(a_testClass, false,
117           cl);
118       if (a_interfaceClass.isAssignableFrom(testClassObj)) {
119         if (testClassObj.isInterface()) {
120           // no interfaces wanted as result
121
return null;
122         }
123         if ( (testClassObj.getModifiers() & java.lang.reflect.Modifier.ABSTRACT)
124             > 0) {
125           // no abstract classes wanted as result
126
return null;
127         }
128         return a_testClass;
129       }
130     } catch (UnsatisfiedLinkError JavaDoc ule) {
131       if (DEBUG) {
132         System.out.println("Unsatisfied link error for class: " + a_testClass);
133       }
134     } catch (IllegalAccessError JavaDoc e) {
135       if (DEBUG) {
136         System.out.println("Unable to load class: " + a_testClass);
137       }
138     } catch (ClassNotFoundException JavaDoc cnfe) {
139       if (DEBUG) {
140         System.out.println("Class not found: " + a_testClass);
141       }
142     } catch (NoClassDefFoundError JavaDoc nex) {
143       if (DEBUG) {
144         System.out.println("No class definition found: " + a_testClass);
145       }
146     }
147     return null;
148   }
149
150   /**
151    * Finds all classes implementing the given interface
152    * @param a_fullInterfaceName name of the interface (inclusive package name)
153    * to find implementing classes (not abstract) for
154    * @return list of class names that implement the given interface
155    *
156    * @throws ClassNotFoundException
157    *
158    * @author Klaus Meffert
159    * @since 2.4
160    */

161   public List findImplementingClasses(final String JavaDoc a_fullInterfaceName)
162       throws ClassNotFoundException JavaDoc {
163     Class JavaDoc interfaceToLookFor = Class.forName(a_fullInterfaceName);
164     return findImplementingClasses(interfaceToLookFor);
165   }
166
167   /**
168    * Finds all classes implementing the given interface
169    * @param a_intrface the interface to check against
170    * @return list of class names that implement the given interface
171    *
172    * @author Klaus Meffert
173    * @since 2.3
174    */

175   public List findImplementingClasses(final Class JavaDoc a_intrface) {
176     List result = new Vector();
177     // Check the jar files
178
String JavaDoc s = null;
179     try {
180       // determine current directory
181
File f = new File(".");
182       s = f.getCanonicalPath();
183       s = FileKit.getConformPath(s, true);
184     } catch (IOException iex) {
185       throw new RuntimeException JavaDoc("Unable to determine current directory",iex);
186     }
187     Iterator i = m_classpathJars.iterator();
188     while (i.hasNext()) {
189       String JavaDoc filename = (String JavaDoc) i.next();
190       filename = FileKit.getConformPath(filename, true);
191       // only search for jars in current dir or subdir (otherwise we would scan
192
// the whole bunch of system and external library jars, too, and that
193
// would be really inperformant)
194
if (filename.startsWith(s)) {
195         try {
196           JarFile jar = new JarFile(filename);
197           Enumeration item = jar.entries();
198           while (item.hasMoreElements()) {
199             JarEntry entry = (JarEntry) item.nextElement();
200             String JavaDoc name = entry.getName();
201             if (name.toLowerCase().endsWith(".class")) {
202               String JavaDoc classname = checkIfClassMatches(filename, a_intrface, name);
203               if (classname != null) {
204                 result.add(classname);
205               }
206             }
207           }
208         } catch (IOException e) {
209           System.out.println("Unable to open jar " + filename);
210         }
211       }
212     }
213     // Iterate over the classpath folders
214
i = m_classpathFolders.iterator();
215     while (i.hasNext()) {
216       String JavaDoc folder = (String JavaDoc) i.next();
217       System.err.println(folder);
218       findImplementingClasses0(a_intrface, result, folder, "");
219     }
220     return result;
221   }
222
223   /**
224    * Recursive helper method, searching a path recursively for class files
225    * conforming to a given interface
226    * @param intrface the interface we are looking for
227    * @param result container for storing the results
228    * @param base base directory
229    * @param path current location in the traversal
230    *
231    * @author Klaus Meffert
232    * @since 2.3
233    */

234   private void findImplementingClasses0(final Class JavaDoc a_intrface,
235                                         final List a_result,
236                                         final String JavaDoc a_base,
237                                         final String JavaDoc a_path) {
238     a_result.addAll(findImplementingClasses(a_intrface, a_base, a_path));
239     File f = new File(a_base + File.separator + a_path);
240     if (!f.isDirectory()) {
241       return;
242     }
243 // File[] matches = f.listFiles(new ClassFilter());
244
// for (int i = 0; i < matches.length; i++) {
245
// String classname = a_path + File.separator + matches[i].getName();
246
// classname = checkIfClassMatches(a_intrface, classname);
247
// if (classname != null) {
248
// a_result.add(classname);
249
// }
250
// }
251
File[] matches = f.listFiles(new DirectoryFilter());
252     for (int i = 0; i < matches.length; i++) {
253       String JavaDoc folder = a_path + File.separator + matches[i].getName();
254       findImplementingClasses0(a_intrface, a_result, a_base, folder);
255     }
256   }
257
258   /**
259    * Finds all classes implementing the given interface within a given
260    * directory.
261    *
262    * @param a_intrface Class
263    * @param a_base String
264    * @param a_path String
265    * @return List
266    */

267   public List findImplementingClasses(final Class JavaDoc a_intrface,
268                                       final String JavaDoc a_base,
269                                       final String JavaDoc a_path) {
270     List result = new Vector();
271     File f = new File(a_base + File.separator + a_path);
272     if (!f.isDirectory()) {
273       return result;
274     }
275     File[] matches = f.listFiles(new ClassFilter());
276     for (int i = 0; i < matches.length; i++) {
277       String JavaDoc classname = a_path + File.separator + matches[i].getName();
278       classname = checkIfClassMatches(null, a_intrface, classname);
279       if (classname != null) {
280         result.add(classname);
281       }
282     }
283     return result;
284   }
285
286   /**
287    * Filter that only matches class files
288    */

289   public class ClassFilter
290       implements FilenameFilter {
291     public boolean accept(final File a_dir, final String JavaDoc a_name) {
292       return (a_name != null && a_name.toLowerCase().endsWith(".class"));
293     }
294   }
295   /**
296    * Filter that only matches subdirectories
297    */

298   public class DirectoryFilter
299       implements FilenameFilter {
300     public boolean accept(final File a_dir, final String JavaDoc a_name) {
301       return (a_dir != null
302               && new File(a_dir.getPath()
303                           + File.separator + a_name).isDirectory());
304     }
305   }
306   /**
307    * For testing purpose
308    * @param args not used
309    * @throws Exception in case of any problem
310    *
311    * @author Klaus Meffert
312    * @since 2.3
313    */

314   public static void main(String JavaDoc[] args)
315       throws Exception JavaDoc {
316     PluginDiscoverer discoverer = new PluginDiscoverer();
317 // Manifest mf = discoverer.getManifestOfJar("C:/temp/jgap/jgap.jar!/");
318
// String version = discoverer.getJGAPVersion(mf);
319
//
320
List plugins = discoverer.findImplementingClasses(
321         "org.jgap.INaturalSelector");
322     System.out.println();
323     int size = plugins.size();
324     System.out.println("" + size + " plugin"
325                        + (size == 1 ? "" : "s") + " discovered"
326                        + (size == 0 ? "" : ":"));
327     for (int i = 0; i < size; i++) {
328       System.out.println(plugins.get(i));
329     }
330 // System.out.println("\n\n");
331
// plugins = discoverer.findImplementingClasses(IGridConfiguration.class,
332
// "c:/JavaProjekte/JGAP_CVS/classes", "examples/grid/fitnessDistributed");
333
// System.out.println();
334
// size = plugins.size();
335
// System.out.println("" + size + " plugin"
336
// + (size == 1 ? "" : "s") + " discovered"
337
// + (size == 0 ? "" : ":"));
338
// for (int i = 0; i < size; i++) {
339
// System.out.println(plugins.get(i));
340
// }
341
System.exit(0);
342   }
343 }
344
Popular Tags