/* * This file is part of JGAP. * * JGAP offers a dual license model containing the LGPL as well as the MPL. * * For licensing information please see the file license.txt included with JGAP * or have a look at the top of class org.jgap.Chromosome which representatively * includes the JGAP license policy applicable for any file delivered with JGAP. */ package org.jgap.util; import java.io.*; import java.net.*; import java.util.*; import java.util.jar.*; import java.util.zip.*; import org.apache.log4j.*; public class ClassKit { /** String containing the CVS revision. Read out via reflection!*/ private final static String CVS_REVISION = "$Revision: 1.10 $"; private transient static Logger LOGGER = Logger.getLogger(ClassKit.class); public static void main(String[] args) throws Exception { File f = new File("."); // getPlugins("c:\\java\\jgap\\lib"); getPlugins(f.getCanonicalPath() + "\\lib"); if (true) { return; } List result = new Vector(); result = find("org.jgap.INaturalSelector"); for (int i = 0; i < result.size(); i++) { LOGGER.debug(result.get(i)); } // URL url = ClassKit.class.getResource("/info/clearthought/layout/"); URL url = ClassKit.class.getResource("/org/jgap/impl/"); findInJar(result, url, Class.forName("java.io.Serializable")); } /** * Retrieves all the classes inheriting or implementing a given class in the * currently loaded packages. * @param a_tosubclassname the name of the class to inherit from * @return classes inheriting or implementing a given class in the * currently loaded packages * @see http//www.javaworld.com/javaworld/javatips/jw-javatip113.html */ public static List find(final String a_tosubclassname) { try { List result = new Vector(); Class tosubclass = Class.forName(a_tosubclassname); Package[] pcks = Package.getPackages(); /**@todo take care of abstract classes --> introduce parameter for that*/ for (int i = 0; i < pcks.length; i++) { List subresult = find(pcks[i].getName(), tosubclass); result.addAll(subresult); } // List subresult = find("org.jgap.impl", tosubclass); // result.addAll(subresult); return result; } catch (ClassNotFoundException ex) { LOGGER.warn("Class " + a_tosubclassname + " not found!"); return null; } } /** * Display all the classes inheriting or implementing a given * class in a given package. * * @param a_pckname the fully qualified name of the package * @param a_tosubclassname the name of the class to inherit from * @return classes inheriting or implementing a given class in a given package * @throws ClassNotFoundException * * @see http//www.javaworld.com/javaworld/javatips/jw-javatip113.html */ public static List find(final String a_pckname, final String a_tosubclassname) throws ClassNotFoundException { Class tosubclass = Class.forName(a_tosubclassname); return find(a_pckname, tosubclass); } /** * Display all the classes inheriting or implementing a given * class in a given package. * @param a_pckgname the fully qualified name of the package * @param a_tosubclass the Class object to inherit from * See http//www.javaworld.com/javaworld/javatips/jw-javatip113.html */ public static List find(final String a_pckgname, final Class a_tosubclass) { List result = new Vector(); // Translate the package name into an absolute path String name = a_pckgname; if (!name.startsWith("/")) { name = "/" + name; } name = name.replace('.', '/'); // Get a File object for the package URL url = ClassKit.class.getResource(name); // URL url = tosubclass.getResource(name); // URL url = ClassLoader.getSystemClassLoader().getResource(name); // Happens only if the jar file is not well constructed, i.e. // if the directories do not appear alone in the jar file like here: // // meta-inf/ // meta-inf/manifest.mf // commands/ <== IMPORTANT // commands/Command.class // commands/DoorClose.class // commands/DoorOpen.class // ClassKit.class // if (url == null) { return result; } return find(url, a_pckgname, a_tosubclass); } public static List find(final URL a_url, final String a_pckgname, final Class a_tosubclass) { List result = new Vector(); File directory = new File(a_url.getFile()); if (directory.exists()) { // Get the list of the files contained in the package String[] files = directory.list(); for (int i = 0; i < files.length; i++) { // we are only interested in .class files if (files[i].endsWith(".class")) { // removes the .class extension String classname = files[i].substring(0, files[i].length() - 6); try { // Try to create an instance of the object Class c = Class.forName(a_pckgname + "." + classname); if (implementsInterface(c, a_tosubclass) || extendsClass(c, a_tosubclass)) { result.add(a_pckgname + "." + classname); } } catch (ClassNotFoundException cnfex) { LOGGER.error(cnfex); } // catch (InstantiationException iex) { // // We try to instanciate an interface or an object that does not // // have a default constructor // } // catch (IllegalAccessException iaex) { // // The class is not public // } } } } else { findInJar(result, a_url, a_tosubclass); } return result; } public static void findInJar(final List a_result, final URL a_url, Class a_tosubclass) { try { // It does not work with the filesystem: we must // be in the case of a package contained in a jar file. JarURLConnection conn = (JarURLConnection) a_url.openConnection(); String starts = conn.getEntryName(); JarFile jfile = conn.getJarFile(); Enumeration e = jfile.entries(); while (e.hasMoreElements()) { ZipEntry entry = (ZipEntry) e.nextElement(); String entryname = entry.getName(); if (entryname.startsWith(starts) && (entryname.lastIndexOf('/') <= starts.length()) && entryname.endsWith(".class")) { String classname = entryname.substring(0, entryname.length() - 6); if (classname.startsWith("/")) { classname = classname.substring(1); } classname = classname.replace('/', '.'); try { // Try to create an instance of the object Class c = Class.forName(classname); if (implementsInterface(c, a_tosubclass) || extendsClass(c, a_tosubclass)) { // Object o = Class.forName(classname).newInstance(); // if (tosubclass.isInstance(o)) { a_result.add(classname); } } catch (ClassNotFoundException cnfex) { LOGGER.error(cnfex); } } } } catch (IOException ioex) { LOGGER.error(ioex); } } public static boolean implementsInterface(final Class a_o, final Class a_clazz) { Class[] interfaces = a_o.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { Class c = interfaces[i]; if (c.equals(a_clazz)) { return true; } } return false; } public static boolean extendsClass(final Class a_o, final Class a_clazz) { if (a_clazz.getName().equals(a_o.getName())) { return false; } if (a_clazz.isAssignableFrom(a_o)) { return true; } else { return false; } } /**@todo add input param: type (or list of types) to look for*/ public static void getPlugins(final String a_directory) { File modulePath = new File(a_directory); // if(modulePath == null || !modulePath.exists())modulePath.mkdirs(); File[] jarFiles = modulePath.listFiles(new ExtensionsFilter("jar", false)); URL[] urls = new URL[jarFiles.length + 1]; int i = 0; for (; i < jarFiles.length; i++) { try { urls[i] = jarFiles[i].toURL(); } catch (Exception ex) { } } try { urls[i] = modulePath.toURL(); } catch (Exception ex) { ; //do nothing? } ClassLoader ucl = new URLClassLoader(urls); // ------------------------------- Vector classes = new Vector(); long startTime = System.currentTimeMillis(); addClasses(classes, modulePath, ""); LOGGER.info("Found plugin classes in: " + (System.currentTimeMillis() - startTime) + " milliseconds"); // ------------------------------- // Vector implementingClasses = new Vector(); Enumeration e = classes.elements(); while (e.hasMoreElements()) { try { String name = e.nextElement().toString(); /**@todo check if class assignable from given type*/ LOGGER.info("Found plugin class: " + name); } catch (Throwable ex) { ; // do nothing? } } } public static void addClasses(final Vector a_v, final File a_path, final String a_name) { addClassesFile(a_v, a_path, a_name); addClassesJar(a_v, a_path); } public static void addClassesJar(final Vector a_v, final File a_path) { File[] files = a_path.listFiles(new ExtensionsFilter("jar", false)); for (int i = 0; i < files.length; i++) { try { java.util.jar.JarFile jar = new java.util.jar.JarFile(files[i]); String wa; java.util.Enumeration e = jar.entries(); while (e.hasMoreElements()) { wa = e.nextElement().toString(); if (wa.endsWith(".class") && (wa.indexOf("$") == -1)) { a_v.add(wa.substring(0, wa.length() - 6).replace('/', '.')); } } } catch (Exception ex) { ; // do nothing? } } } //this method is recursive to go down sub-dirs public static void addClassesFile(Vector a_v, final File a_path, final String a_name) { File[] files = a_path.listFiles(new ExtensionsFilter("class", true)); for (int i = 0; i < files.length; i++) { if (files[i].isDirectory()) { addClassesFile(a_v, files[i], a_name + files[i].getName() + "."); } else if (files[i].getName().indexOf("$") == -1) { a_v.add(a_name + files[i].getName(). substring(0, files[i].getName().length() - 6)); } } } static class ExtensionsFilter implements FilenameFilter { private String m_ext; public ExtensionsFilter(final String a_extension, final boolean a_dummy) { m_ext = a_extension; } public boolean accept(final File a_dir, final String a_name) { return a_name != null && a_name.endsWith("." + m_ext); } } }