Java tutorial
/* * $Id: ClassSearchUtils.java,v 1.1 2009/03/01 12:01:11 rah003 Exp $ * * Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library 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 2.1 of the License, or (at your option) any later version. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ import java.awt.HeadlessException; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.StringTokenizer; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.Logger; public class ClassSearchUtils { private static final Logger log = Logger.getAnonymousLogger(); /** * Classloader to be used to obtain resources from file system. */ private ClassLoader classloader; /** * List of the resource found in the classpath. */ private ArrayList list; /** * Extension of the resource to be found in the classpath. */ private String extension; private String prefix; /** * Search for the resource with the extension in the classpath. Method * self-instantiate factory for every call to ensure thread safety. * @param extension Mandatory extension of the resource. If all resources * are required extension should be empty string. Null extension is not * allowed and will cause method to fail. * @return List of all resources with specified extension. */ public static List<Class<?>> searchClassPath(String prefix) { return searchClassPath(prefix, ".class"); } /** * Search for the resource with the extension in the classpath. Method * self-instantiate factory for every call to ensure thread safety. * @param extension Mandatory extension of the resource. If all resources * are required extension should be empty string. Null extension is not * allowed and will cause method to fail. * @return List of all resources with specified extension. */ public static List searchClassPath(String prefix, String extension) { ClassSearchUtils factory = new ClassSearchUtils(); factory.prefix = prefix; return factory.find(extension); } /** * Search for the resource with the extension in the classpath. * @param extension Mandatory extension of the resource. If all resources * are required extension should be empty string. Null extension is not * allowed and will cause method to fail. * @return List of all resources with specified extension. */ private List<Class<?>> find(String extension) { this.extension = extension; this.list = new ArrayList(); this.classloader = this.getClass().getClassLoader(); String classpath = System.getProperty("java.class.path"); try { Method method = this.classloader.getClass().getMethod("getClassPath", (Class<?>) null); if (method != null) { classpath = (String) method.invoke(this.classloader, (Object) null); } } catch (Exception e) { // ignore } if (classpath == null) { classpath = System.getProperty("java.class.path"); } StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator); String token; File dir; String name; while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken(); dir = new File(token); if (dir.isDirectory()) { lookInDirectory("", dir); } if (dir.isFile()) { name = dir.getName().toLowerCase(); if (name.endsWith(".zip") || name.endsWith(".jar")) { this.lookInArchive(dir); } } } return this.list; } /** * @param name Name of to parent directories in java class notation (dot * separator) * @param dir Directory to be searched for classes. */ private void lookInDirectory(String name, File dir) { log.fine("Looking in directory [" + dir.getName() + "]."); File[] files = dir.listFiles(); File file; String fileName; final int size = files.length; for (int i = 0; i < size; i++) { file = files[i]; fileName = file.getName(); if (file.isFile() && fileName.toLowerCase().endsWith(this.extension)) { try { if (this.extension.equalsIgnoreCase(".class")) { fileName = fileName.substring(0, fileName.length() - 6); // filter ignored resources if (!(name + fileName).startsWith(this.prefix)) { continue; } log.fine("Found class: [" + name + fileName + "]."); this.list.add(Class.forName(name + fileName)); } else { this.list.add( this.classloader.getResource(name.replace('.', File.separatorChar) + fileName)); } } catch (ClassNotFoundException e) { // ignore } catch (NoClassDefFoundError e) { //ignore too } catch (ExceptionInInitializerError e) { if (e.getCause() instanceof HeadlessException) { // running in headless env ... ignore } else { throw e; } } } // search recursively. // I don't like that but we will see how it will work. if (file.isDirectory()) { lookInDirectory(name + fileName + ".", file); } } } /** * Search archive files for required resource. * @param archive Jar or zip to be searched for classes or other resources. */ private void lookInArchive(File archive) { log.fine("Looking in archive [" + archive.getName() + "] for extension [" + this.extension + "]."); JarFile jarFile = null; try { jarFile = new JarFile(archive); } catch (IOException e) { log.warning("Non fatal error. Unable to read jar item."); return; } Enumeration entries = jarFile.entries(); JarEntry entry; String entryName; while (entries.hasMoreElements()) { entry = (JarEntry) entries.nextElement(); entryName = entry.getName(); if (entryName.toLowerCase().endsWith(this.extension)) { try { if (this.extension.equalsIgnoreCase(".class")) { // convert name into java classloader notation entryName = entryName.substring(0, entryName.length() - 6); entryName = entryName.replace('/', '.'); // filter ignored resources if (!entryName.startsWith(this.prefix)) { continue; } log.fine("Found class: [" + entryName + "]. "); this.list.add(Class.forName(entryName)); } else { this.list.add(this.classloader.getResource(entryName)); log.fine("Found appropriate resource with name [" + entryName + "]. Resource instance:" + this.classloader.getResource(entryName)); } } catch (Throwable e) { // ignore log.warning("Unable to load resource [" + entryName + "] form file [" + archive.getAbsolutePath() + "]."); } } } } }