1 package com.explosion.utilities.classes;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.MalformedURLException;
6 import java.net.URL;
7 import java.util.ArrayList;
8 import java.util.Enumeration;
9 import java.util.List;
10 import java.util.jar.JarEntry;
11 import java.util.jar.JarFile;
12
13 import org.apache.log4j.LogManager;
14 import org.apache.log4j.Logger;
15
16 import com.explosion.utilities.FileIterator;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 /***
39 * @author Stephen This class contains some handy methods for working with
40 * classes and types Created on Apr 17, 2004
41 */
42 public class ClassUtilities
43 {
44
45 private static Logger log = LogManager.getLogger(ClassUtilities.class);
46
47 /***
48 * This method finds all of the classes of a particular type in a particular
49 * set if Files. The file scan be directories or libraries. The libraries
50 * must be in jar or zip format
51 *
52 * @param jarFile
53 * @param superClass
54 * @return @throws Exception
55 */
56 public static List findClassesOfType(Class superClass, List classPath) throws Exception
57 {
58
59 log.debug("Creating new loader.");
60 String[] resolvedClasspath = resolveClasspath(classPath);
61 StandardClassLoader loader = new StandardClassLoader(resolvedClasspath);
62 loader.setDelegate(true);
63
64 return findClassesOfType(superClass, loader, classPath);
65 }
66
67 /***
68 * @param classPath
69 * @throws MalformedURLException
70 * @throws IOException
71 */
72 private static String[] resolveClasspath(List classPath) throws MalformedURLException, IOException
73 {
74
75
76
77
78 List resolvedClasspath = new ArrayList();
79
80
81 for (int i=0;i<classPath.size();i++)
82 {
83 File file = (File) classPath.get(i);
84 if (file.isFile() && file.exists() && (file.getName().endsWith(".jar") || file.getName().endsWith(".zip"))
85 || (file.isDirectory() && file.exists()))
86 {
87
88
89
90 URL url = new URL("file", null, new File(file.getAbsolutePath()).getCanonicalPath());
91 resolvedClasspath.add("file:///" + file.getAbsolutePath());
92 }
93 }
94
95 String[] repo = new String[resolvedClasspath.size()];
96 if (resolvedClasspath.size() > 0)
97 {
98 return (String[]) resolvedClasspath.toArray(repo);
99 }
100
101 return new String[0];
102 }
103
104 /***
105 * This method finds all of the classes of a particular type in the classpath of a
106 *
107 * @param jarFile, this must be a jar file or a zip file
108 * @param superClass
109 * @return @throws Exception
110 */
111 public static List findClassesOfType(Class superClass, ClassLoader loader, List files) throws Exception
112 {
113 ArrayList classNames = new ArrayList();
114 log.debug("called findClassesOfType");
115
116 if (loader != null)
117 {
118 log.debug("loader is not null and there are " + files.size() + " files on the classpath.");
119 ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
120 Thread.currentThread().setContextClassLoader(loader);
121
122 for (int i=0;i<files.size();i++)
123 {
124 File theFile = (File) files.get(i);
125 if (theFile.isFile())
126 {
127 JarFile file = new JarFile(theFile.getAbsolutePath());
128 log.debug("Checking " + file.getName() + " for instances of " + superClass.getName());
129 Enumeration en = file.entries();
130 while (en.hasMoreElements())
131 {
132 JarEntry entry = (JarEntry) en.nextElement();
133 log.debug("Checking entry " + entry.getName());
134 if (entry.getName().endsWith(".class"))
135 {
136 log.debug("Examining " + entry.getName());
137 try
138 {
139 String name = entry.getName().substring(0, entry.getName().length() - 6).replaceAll("/",".");
140 log.debug("Loading class " + name);
141
142 Class c = Class.forName(name,true, loader);
143 if (superClass.isAssignableFrom(c))
144 {
145 log.debug("Yes, " + c.getName() + " is a " + c.getName());
146 classNames.add(c.getName());
147 }
148 else
149 {
150 log.debug("No, " + c.getName() + " is a " + c.getName());
151 }
152 }
153 catch (Throwable e)
154 {
155 log.error("Exception checking for classes of type " + superClass.getName(), e);
156 }
157 }
158 }
159
160 }
161 }
162 Thread.currentThread().setContextClassLoader(originalLoader);
163
164 }
165
166 return classNames;
167 }
168
169 /***
170 * This method finds all of the classes of a particular type in a particular
171 * JarFile
172 *
173 * @param jarFile, this must be a jar file or a zip file
174 * @param superClass
175 * @return @throws Exception
176 */
177 public static List findClassesOfType(Class superClass, String jarFilePath) throws Exception
178 {
179 ArrayList classNames = new ArrayList();
180
181 if (jarFilePath != null)
182 {
183 JarFile file = new JarFile(jarFilePath);
184 log.debug("Checking " + file.getName() + " for instances of " + superClass.getName());
185 StandardClassLoader loader = null;
186 Enumeration en = file.entries();
187 while (en.hasMoreElements())
188 {
189 JarEntry entry = (JarEntry) en.nextElement();
190 if (entry.getName().endsWith(".class"))
191 {
192 log.debug("Examining " + entry.getName());
193 try
194 {
195
196
197
198
199 if (loader == null)
200 {
201 log.debug("Creating new loader.");
202 URL url = new URL("file", null, new File(jarFilePath).getCanonicalPath());
203 String[] repo = {url.toString()};
204 loader = new StandardClassLoader(repo);
205 loader.setDelegate(true);
206 }
207
208 String name = entry.getName().substring(0, entry.getName().length() - 6).replaceAll("/",".");
209 log.debug("Loading class " + name);
210 Class c = Class.forName(name,false, loader);
211 if (superClass.isAssignableFrom(c))
212 {
213 log.debug("Yes, " + c.getName() + " is a " + c.getName());
214 classNames.add(c.getName());
215 }
216 else
217 {
218 log.debug("No, " + c.getName() + " is a " + c.getName());
219 }
220 } catch (Exception e)
221 {
222 log.error("Exception checking for classes of type " + superClass.getName(), e);
223 }
224 }
225 }
226
227 }
228
229 return classNames;
230 }
231
232 /***
233 * This method finds all of the classes of a particular type in a particular
234 * JarFile
235 *
236 * @param directory, this must be a directory with class files in it
237 * @param superClass
238 * @return @throws Exception
239 */
240 public static List findClassesOfType(Class superClass, File directory) throws Exception
241 {
242 ArrayList classNames = new ArrayList();
243
244 if (directory != null && directory.isDirectory())
245 {
246 log.debug("Checking " + directory.getName() + " for instances of " + superClass.getName());
247 StandardClassLoader loader = null;
248 FileIterator it = new FileIterator(directory.getAbsolutePath(),"//.class",true,true, true);
249 while (it.hasNext())
250 {
251 File file = it.next();
252 log.debug("Examining " + file.getName());
253 try
254 {
255
256
257
258
259 if (loader == null)
260 {
261 log.debug("Creating new loader.");
262 URL url = new URL("file", null, directory.getCanonicalPath());
263 String[] repo = {url.toString()};
264 loader = new StandardClassLoader(repo);
265 loader.setDelegate(true);
266 }
267
268 String name = file.getAbsolutePath().substring(directory.getAbsolutePath().length(), file.getAbsolutePath().length() - 6).replaceAll("/",".");
269 log.debug("Loading class " + name);
270 Class c = Class.forName(name,false, loader);
271 if (superClass.isAssignableFrom(c))
272 {
273 log.debug("Yes, " + c.getName() + " is a " + c.getName());
274 classNames.add(c.getName());
275 }
276 else
277 {
278 log.debug("No, " + c.getName() + " is a " + c.getName());
279 }
280 } catch (Exception e)
281 {
282 log.error("Exception checking for classes of type " + superClass.getName(), e);
283 }
284 }
285
286 }
287
288 return classNames;
289 }
290
291 /***
292 * This method finds all of the classes of a particular type in a particular
293 * JarFile
294 *
295 * @param jarFile
296 * @param superClass
297 * @return @throws Exception
298 */
299 public static boolean containsClassWithName(String name, String jarFilePath, boolean caseSensitive) throws Exception
300 {
301 ArrayList classNames = new ArrayList();
302
303 if (jarFilePath != null)
304 {
305 JarFile file = new JarFile(jarFilePath);
306 log.debug("Checking " + file.getName() + " for classes with name " + name);
307
308 Enumeration en = file.entries();
309 while (en.hasMoreElements())
310 {
311 JarEntry entry = (JarEntry) en.nextElement();
312 if (entry.getName().endsWith(".class"))
313 {
314 log.debug("Examining " + entry.getName());
315 try
316 {
317 String foundName = entry.getName().substring(0, entry.getName().length() - 6).replaceAll("/",".");
318 if ( !caseSensitive && foundName.equalsIgnoreCase(name))
319 return true;
320 else if (caseSensitive && foundName.equals(name))
321 return true;
322
323 } catch (Exception e)
324 {
325 log.error("Exception checking for classes with a name " + name, e);
326 }
327 }
328 }
329 }
330
331 return false;
332 }
333
334 /***
335 * This method determines if srgument1 is an instance of argument2
336 *
337 */
338 public static boolean instanceOf(Class theClass, Class instanceOf)
339 {
340 log.debug("Is " + theClass + " an instance of " + instanceOf);
341 ArrayList superClasses = new ArrayList();
342
343 getSuperClasses(theClass, superClasses);
344
345 for (int i = 0; i < superClasses.size(); i++)
346 {
347 Class superClass = (Class) superClasses.get(i);
348 if (superClass.getName().equals(instanceOf.getName()))
349 return true;
350 }
351
352 return false;
353 }
354
355 /***
356 * This is a recursive method which fills up the provided list with all of
357 * the super classes and super interfaces of the class provided
358 *
359 */
360 private static void getSuperClasses(Class theClass, List fillMeUp)
361 {
362 log.debug("Getting superclasses of " + theClass);
363
364 Class[] theClassInterfaces = theClass.getInterfaces();
365
366 for (int zx = 0; zx < theClassInterfaces.length; zx++)
367 {
368 fillMeUp.add(theClassInterfaces[zx]);
369 getSuperClasses(theClassInterfaces[zx], fillMeUp);
370 }
371
372
373 Class superClass = theClass.getSuperclass();
374 if (superClass != null)
375 {
376 fillMeUp.add(superClass);
377 Class[] superClassInterfaces = superClass.getInterfaces();
378
379
380 for (int zx = 0; zx < superClassInterfaces.length; zx++)
381 {
382 fillMeUp.add(superClassInterfaces[zx]);
383 getSuperClasses(superClassInterfaces[zx], fillMeUp);
384 }
385
386 getSuperClasses(superClass, fillMeUp);
387 }
388 }
389 }