`
jianfulove
  • 浏览: 118442 次
  • 性别: Icon_minigender_1
  • 来自: 湛江
社区版块
存档分类
最新评论

可以动态查找出工作空间中已知父类的所有子类

    博客分类:
  • util
 
阅读更多
//可以动态查找出工作空间中已知父类的所有子类。



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

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics