//可以动态查找出工作空间中已知父类的所有子类。 package util; import java.io.File; import java.io.IOException; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.Comparator; import java.util.Enumeration; import java.util.Set; import java.util.StringTokenizer; import java.util.TreeSet; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * <code>ClassUtil</code> file contains code used for loading all * implementations of specified <em>interface</em> or <em>abstract class</em> * found in classpath. As a result of calling some functions you can have * <code>Set</code> containing all required classes. * * <p> * </p> */ public class ClassUtil { private static final String[] SKIP_CONTAINS = { ".ui.", ".swing", ".awt", ".sql.", ".xml.", ".terracotta." }; private static final String[] SKIP_STARTS = { "com.mysql", "tigase.pubsub.Utils", "org.apache.derby", "org.apache.xml", "org.postgresql", "com.sun", "groovy", "org.codehaus.groovy", "org.netbeans", "org.python" }; /** * Method description * * * @param fileName * * @return */ public static String getClassNameFromFileName(String fileName) { String class_name = null; if (fileName.endsWith(".class")) { // class_name = fileName.substring(0, // fileName.length()-6).replace(File.separatorChar, '.'); // Above code does not works on MS Windows if we load // files from jar file. Jar manipulation code always returns // file names with unix style separators String tmp_class_name = fileName.substring(0, fileName.length() - 6).replace('\\', '.'); class_name = tmp_class_name.replace('/', '.'); } // end of if (entry_name.endsWith(".class")) return class_name; } /** * Method description * * * @param dir * * @return */ public static Set<String> getClassNamesFromDir(File dir) { Set<String> tmp_set = getFileListDeep(dir); Set<String> result = new TreeSet<String>(); for (String elem : tmp_set) { String class_name = getClassNameFromFileName(elem); if (class_name != null) { result.add(class_name); // System.out.println("class name: "+class_name); } // end of if (class_name != null) } // end of for () return result; } /** * Method description * * * @param jarFile * * @return * * @throws IOException */ public static Set<String> getClassNamesFromJar(File jarFile) throws IOException { Set<String> result = new TreeSet<String>(); JarFile jar = new JarFile(jarFile); Enumeration<JarEntry> jar_entries = jar.entries(); while (jar_entries.hasMoreElements()) { JarEntry jar_entry = jar_entries.nextElement(); String class_name = getClassNameFromFileName(jar_entry.getName()); if (class_name != null) { result.add(class_name); // System.out.println("class name: "+class_name); } // end of if (entry_name.endsWith(".class")) } // end of while (jar_entries.hasMoreElements()) return result; } /** * Method description * * * @return * * @throws ClassNotFoundException * @throws IOException */ public static Set<Class<?>> getClassesFromClassPath() throws IOException, ClassNotFoundException { Set<Class<?>> classes_set = new TreeSet<Class<?>>(new ClassComparator()); String classpath = System.getProperty("java.class.path"); // System.out.println("classpath: "+classpath); StringTokenizer stok = new StringTokenizer(classpath, File.pathSeparator, false); while (stok.hasMoreTokens()) { String path = stok.nextToken(); File file = new File(path); if (file.exists()) { if (file.isDirectory()) { // System.out.println("directory: "+path); Set<String> class_names = getClassNamesFromDir(file); classes_set.addAll(getClassesFromNames(class_names)); } // end of if (file.isDirectory()) if (file.isFile()) { // System.out.println("jar file: "+path); Set<String> class_names = getClassNamesFromJar(file); classes_set.addAll(getClassesFromNames(class_names)); // System.out.println("Loaded jar file: "+path); } // end of if (file.isFile()) } // end of if (file.exists()) } // end of while (stok.hasMoreTokens()) return classes_set; } /** * Method description * * * @param names * * @return * * @throws ClassNotFoundException */ public static Set<Class<?>> getClassesFromNames(Set<String> names) throws ClassNotFoundException { Set<Class<?>> classes = new TreeSet<Class<?>>(new ClassComparator()); for (String name : names) { try { boolean skip_class = false; for (String test_str : SKIP_CONTAINS) { skip_class = name.contains(test_str); if (skip_class) { break; } } if (!skip_class) { for (String test_str : SKIP_STARTS) { skip_class = name.startsWith(test_str); if (skip_class) { break; } } } if (!skip_class) { // System.out.println(new Date() + " - Class name: " + name); Class cls = Class.forName(name, false, ClassLoader.getSystemClassLoader()); classes.add(cls); } } catch (SecurityException e) { } catch (NoClassDefFoundError e) { } catch (UnsatisfiedLinkError e) { } catch (Throwable e) { Throwable cause = e.getCause(); System.out.println("Class name: " + name); e.printStackTrace(); if (cause != null) { cause.printStackTrace(); } } } // end of for () return classes; } /** * Method description * * * @param classes * @param cls * @param <T> * * @return */ @SuppressWarnings({ "unchecked" }) public static <T extends Class> Set<T> getClassesImplementing(Collection<Class<?>> classes, T cls) { Set<T> classes_set = new TreeSet<T>(new ClassComparator()); for (Class c : classes) { // System.out.println("Checking class: " + c.getName()); if (cls.isAssignableFrom(c)) { int mod = c.getModifiers(); if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod)) { classes_set.add((T) c); } // end of if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod)) } // end of if (cls.isAssignableFrom(c)) } // end of for () return classes_set; } /** * Method description * * * @param cls * @param <T> * * @return * * @throws ClassNotFoundException * @throws IOException */ public static <T extends Class> Set<T> getClassesImplementing(T cls) throws IOException, ClassNotFoundException { return getClassesImplementing(getClassesFromClassPath(), cls); } /** * Method description * * * @param path * * @return */ public static Set<String> getFileListDeep(File path) { Set<String> set = new TreeSet<String>(); if (path.isDirectory()) { String[] files = path.list(); for (String file : files) { walkInDirForFiles(path, file, set); } // end of for () } else { set.add(path.toString()); } // end of if (file.isDirectory()) else return set; } /** * Method description * * * @param obj * @param <T> * * @return * * @throws ClassNotFoundException * @throws IOException * @throws IllegalAccessException * @throws InstantiationException */ @SuppressWarnings("unchecked") public static <T> Set<T> getImplementations(Class<T> obj) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { Set<T> result = new TreeSet<T>(new ObjectComparator()); for (Class cls : getClassesImplementing(obj)) { result.add((T) cls.newInstance()); } // end of for () return result; } /** * Method description * * * @param base_dir * @param path * @param set */ public static void walkInDirForFiles(File base_dir, String path, Set<String> set) { File tmp_file = new File(base_dir, path); if (tmp_file.isDirectory()) { String[] files = tmp_file.list(); for (String file : files) { walkInDirForFiles(base_dir, new File(path, file).toString(), set); } // end of for () } else { // System.out.println("File: " + path.toString()); set.add(path); } // end of if (file.isDirectory()) else } public static void main(String[] args) { try { Set<Class<Comparator>> procs= ClassUtil.getClassesImplementing(Comparator.class); System.out.println(procs.size()); for (Class<Comparator> c:procs) { System.out.println(c.getName()); } //2 //util.ClassComparator //util.ObjectComparator } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // ClassUtil
/* * Tigase Jabber/XMPP Utils * Copyright (C) 2004-2012 "Artur Hefczyc" <[email protected]> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. Look for COPYING file in the top folder. * If not, see http://www.gnu.org/licenses/. * * $Rev$ * Last modified by $Author$ * $Date$ */ package util; import java.util.Comparator; import java.io.Serializable; /** * In a few cases classes have to be kept in <code>Set</code>. This * <code>Comparator</code> implementation has been created to return proper * value for <code>compare</code> method and to make it possible to store * classes in any <code>Set</code>. * * <p> * Created: Sat Oct 9 22:27:54 2004 * </p> * @author <a href="mailto:[email protected]">Artur Hefczyc</a> * @version $Rev$ */ public class ClassComparator implements Comparator<Class>, Serializable { private static final long serialVersionUID = 1L; // Implementation of java.util.Comparator /** * Method <code>compare</code> is used to perform * * @param c1 an <code>Object</code> value * @param c2 an <code>Object</code> value * @return an <code>int</code> value */ // @Override public int compare(Class c1, Class c2) { return c1.getName().compareTo(c2.getName()); } }// ClassComparator
/* * Tigase Jabber/XMPP Utils * Copyright (C) 2004-2012 "Artur Hefczyc" <[email protected]> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. Look for COPYING file in the top folder. * If not, see http://www.gnu.org/licenses/. * * $Rev$ * Last modified by $Author$ * $Date$ */ package util; import java.util.Comparator; import java.io.Serializable; /** * Describe class ObjectComparator here. * * * Created: Tue May 17 23:53:20 2005 * * @author <a href="mailto:[email protected]">Artur Hefczyc</a> * @version $Rev$ */ public class ObjectComparator implements Comparator<Object>, Serializable { private static final long serialVersionUID = 1L; /** * Describe <code>compare</code> method here. * * @param object an <code>Object</code> value * @param object1 an <code>Object</code> value * @return an <code>int</code> value */ public int compare(final Object o1, final Object o2) { return o1.getClass().getName().compareTo(o2.getClass().getName()); } } // ObjectComparator