All Downloads are FREE. Search and download functionalities are using the official Maven repository.

coo.base.util.ClassUtils Maven / Gradle / Ivy

The newest version!
package coo.base.util;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import coo.base.constants.Chars;
import coo.base.constants.Encoding;
import coo.base.exception.UncheckedException;

/**
 * Class工具类。
 */
public class ClassUtils {
	private static Logger log = LoggerFactory.getLogger(ClassUtils.class);

	/**
	 * 查找指定包下继承了指定类或实现了指定接口的类集合。
	 * 
	 * @param parentClass
	 *            父类或接口
	 * @param packageNames
	 *            包名
	 * @return 返回指定包下继承了指定类或实现了指定接口的类集合。
	 */
	public static List> findClassesByParentClass(Class parentClass,
			String... packageNames) {
		List> classes = new ArrayList>();
		for (Class targetClass : findClasses(packageNames)) {
			if (!targetClass.equals(parentClass)
					&& parentClass.isAssignableFrom(targetClass)
					&& !Modifier.isAbstract(targetClass.getModifiers())) {
				classes.add(targetClass);
			}
		}
		return classes;
	}

	/**
	 * 查找指定包下标注了指定注解的类集合。
	 * 
	 * @param annotationClass
	 *            注解
	 * @param packageNames
	 *            包名
	 * @return 返回指定包下标注了指定注解的类集合。
	 */
	public static List> findClassesByAnnotationClass(
			Class annotationClass, String... packageNames) {
		List> classes = new ArrayList>();
		for (Class targetClass : findClasses(packageNames)) {
			if (targetClass.isAnnotationPresent(annotationClass)) {
				classes.add(targetClass);
			}
		}
		return classes;
	}

	/**
	 * 查找指定包下的类集合。
	 * 
	 * @param packageNames
	 *            包名
	 * @return 返回指定包下的类集合。
	 */
	public static List> findClasses(String... packageNames) {
		List> classes = new ArrayList>();
		for (String className : findClassNames(packageNames)) {
			try {
				classes.add(Class.forName(className));
			} catch (Exception e) {
				log.warn("加载[" + className + "]类时发生异常。", e);
			}
		}
		return classes;
	}

	/**
	 * 查找指定包下的类名集合。
	 * 
	 * @param packageNames
	 *            包名
	 * @return 返回指定包下的类名集合。
	 */
	private static List findClassNames(String... packageNames) {
		List classNames = new ArrayList();
		try {
			for (String packageName : packageNames) {
				String packagePath = packageName.replace(".", Chars.BACKSLASH);
				Enumeration packageUrls = Thread.currentThread()
						.getContextClassLoader().getResources(packagePath);
				while (packageUrls.hasMoreElements()) {
					URL packageUrl = packageUrls.nextElement();
					if ("jar".equals(packageUrl.getProtocol())) {
						classNames.addAll(getClassNamesFromJar(packageUrl,
								packageName));
					} else {
						classNames.addAll(getClassNamesFromDir(packageUrl,
								packageName));
					}
				}
			}
		} catch (Exception e) {
			throw new UncheckedException("获取指定包下类名集合时发生异常。", e);
		}
		return classNames;
	}

	/**
	 * 从jar包中获取指定包下的类名集合。
	 * 
	 * @param url
	 *            jar包的url
	 * @param packageName
	 *            包名
	 * @return 返回jar包中指定包下的类名集合。
	 */
	private static List getClassNamesFromJar(URL url, String packageName) {
		List classNames = new ArrayList();
		try {
			String jarPath = URLDecoder.decode(url.toExternalForm(),
					Encoding.UTF_8);
			log.debug("开始获取[{}]中的类名...", jarPath);
			jarPath = StringUtils.substringAfter(jarPath, "jar:file:");
			jarPath = StringUtils.substringBeforeLast(jarPath, "!");
			JarFile jarInputStream = new JarFile(jarPath);
			Enumeration jarEntries = jarInputStream.entries();
			while (jarEntries.hasMoreElements()) {
				JarEntry jarEntry = jarEntries.nextElement();
				classNames.addAll(getClassNamesFromJar(jarEntry, packageName));
			}
			jarInputStream.close();
		} catch (Exception e) {
			log.warn("获取jar包中的类名时发生异常。", e);
		}
		return classNames;
	}

	/**
	 * 从jar包文件单元中获取指定包下的类名集合。
	 * 
	 * @param jarEntry
	 *            jar包文件单元
	 * @param packageName
	 *            包名
	 * @return 返回jar包文件单元中获取指定包下的类名集合。
	 */
	private static List getClassNamesFromJar(JarEntry jarEntry,
			String packageName) {
		List classNames = new ArrayList();
		if (!jarEntry.isDirectory() && jarEntry.getName().endsWith(".class")) {
			String className = jarEntry.getName();
			className = className.replaceFirst(".class$", "");
			className = className.replace('/', '.');
			if (className.contains(packageName)) {
				classNames.add(className);
			}
		}
		return classNames;
	}

	/**
	 * 从目录中获取指定包下的类名集合。
	 * 
	 * @param url
	 *            目录url
	 * @param packageName
	 *            包名
	 * @return 返回目录中指定包下的类名集合。
	 */
	private static List getClassNamesFromDir(URL url, String packageName) {
		try {
			String dirPath = URLDecoder.decode(url.getFile(), Encoding.UTF_8);
			log.debug("开始获取[{}]中的类名...", dirPath);
			return getClassNamesFromDir(new File(dirPath), packageName);
		} catch (Exception e) {
			throw new UncheckedException("从目录中获取类名时发生异常。", e);
		}
	}

	/**
	 * 从目录中获取指定包下的类名集合。
	 * 
	 * @param dir
	 *            目录
	 * @param packageName
	 *            包名
	 * @return 返回目录中指定包下的类名集合。
	 */
	private static List getClassNamesFromDir(File dir,
			String packageName) {
		List classNames = new ArrayList();
		try {
			File[] files = dir.listFiles();
			String separator = System.getProperty("file.separator");
			for (File file : files) {
				if (file.isDirectory()) {
					classNames.addAll(getClassNamesFromDir(file, packageName
							+ "." + file.getName()));
				} else if (file.getName().endsWith(".class")) {
					String className = file.getPath();
					className = className.replace(separator, ".");
					className = packageName
							+ StringUtils.substringAfterLast(className,
									packageName);
					className = className.replaceFirst(".class$", "");
					classNames.add(className);
				}
			}
		} catch (Exception e) {
			log.warn("获取目录中的类名时发生异常。", e);
		}
		return classNames;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy