//可以动态查找出工作空间中已知父类的所有子类。
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" <artur.hefczyc@tigase.org>
*
* 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:artur.hefczyc@tigase.org">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" <artur.hefczyc@tigase.org>
*
* 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:artur.hefczyc@tigase.org">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