package org.springblade.core.toolbox.kit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springblade.core.exception.ToolBoxException;
import org.springblade.core.toolbox.support.BasicType;
import org.springblade.core.toolbox.support.Singleton;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.net.URI;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* 类工具类
* 1、扫描指定包下的所有类
* 参考 http://www.oschina.net/code/snippet_234657_22722
* @author seaside_hi, xiaoleilu, chill
*
*/
public class ClassKit {
private final static Logger log = LogManager.getLogger(ClassKit.class);
private ClassKit() {
// 静态类不可实例化
}
/**
* 获得对象数组的类数组
* @param objects 对象数组
* @return 类数组
*/
public static Class>[] getClasses(Object... objects){
Class>[] classes = new Class>[objects.length];
for (int i = 0; i < objects.length; i++) {
classes[i] = objects[i].getClass();
}
return classes;
}
/**
* 获得泛型的第一个类
* @param clazz 当前类
* @return 泛型类
*/
@SuppressWarnings("rawtypes")
public static Class getSuperClassGenricFirstType(Class clazz){
return getSuperClassGenricType(clazz, 0);
}
/**
* 获得泛型的类
* @param clazz 当前类
* @param index 泛型顺序
* @return 泛型类
*/
@SuppressWarnings("rawtypes")
public static Class getSuperClassGenricType(Class clazz, int index){
Type t = clazz.getGenericSuperclass();
if (!(t instanceof ParameterizedType)) {
return null;
}
ParameterizedType parameterizedType = (ParameterizedType) t;
Type[] params = parameterizedType.getActualTypeArguments();
if (null == params) {
return null;
}
if (index < 0 || index > params.length - 1) {
return null;
}
Type param = params[index];
if (param instanceof Class) {
return (Class) param;
}
return null;
}
/**
* 扫面该包路径下所有class文件
*
* @return 类集合
*/
public static Set> scanPackage() {
return scanPackage(StrKit.EMPTY, null);
}
/**
* 扫面该包路径下所有class文件
*
* @param packageName 包路径 com | com. | com.abs | com.abs.
* @return 类集合
*/
public static Set> scanPackage(String packageName) {
return scanPackage(packageName, null);
}
/**
* 扫描指定包路径下所有包含指定注解的类
* @param packageName 包路径
* @param annotationClass 注解类
* @return 类集合
*/
public static Set> scanPackageByAnnotation(String packageName, final Class extends Annotation> annotationClass) {
return scanPackage(packageName, new ClassFilter() {
@Override
public boolean accept(Class> clazz) {
return clazz.isAnnotationPresent(annotationClass);
}
});
}
/**
* 扫描指定包路径下所有指定类的子类
* @param packageName 包路径
* @param superClass 父类
* @return 类集合
*/
public static Set> scanPackageBySuper(String packageName, final Class> superClass) {
return scanPackage(packageName, new ClassFilter() {
@Override
public boolean accept(Class> clazz) {
return superClass.isAssignableFrom(clazz) && !superClass.equals(clazz);
}
});
}
/**
* 扫面包路径下满足class过滤器条件的所有class文件,
* 如果包路径为 com.abs + A.class 但是输入 abs会产生classNotFoundException
* 因为className 应该为 com.abs.A 现在却成为abs.A,此工具类对该异常进行忽略处理,有可能是一个不完善的地方,以后需要进行修改
*
* @param packageName 包路径 com | com. | com.abs | com.abs.
* @param classFilter class过滤器,过滤掉不需要的class
* @return 类集合
*/
public static Set> scanPackage(String packageName, ClassFilter classFilter) {
if(StrKit.isBlank(packageName)) {
packageName = StrKit.EMPTY;
}
log.debug("Scan classes from package ["+packageName+"]...");
packageName = getWellFormedPackageName(packageName);
final Set> classes = new HashSet>();
for (String classPath : getClassPaths(packageName)) {
//bug修复,由于路径中空格和中文导致的Jar找不到
classPath = URLKit.decode(classPath, CharsetKit.systemCharset());
log.debug("Scan classpath: ["+classPath+"]");
// 填充 classes
fillClasses(classPath, packageName, classFilter, classes);
}
//如果在项目的ClassPath中未找到,去系统定义的ClassPath里找
if(classes.isEmpty()) {
for (String classPath : getJavaClassPaths()) {
//bug修复,由于路径中空格和中文导致的Jar找不到
classPath = URLKit.decode(classPath, CharsetKit.systemCharset());
log.debug("Scan java classpath: ["+classPath+"]");
// 填充 classes
fillClasses(classPath, new File(classPath), packageName, classFilter, classes);
}
}
return classes;
}
// ----------------------------------------------------------------------------------------- Method
/**
* 获得指定类中的Public方法名
* 去重重载的方法
*
* @param clazz 类
*/
public static Set getPublicMethodNames(Class> clazz) {
HashSet methodSet = new HashSet();
Method[] methodArray = getPublicMethods(clazz);
for (Method method : methodArray) {
String methodName = method.getName();
methodSet.add(methodName);
}
return methodSet;
}
/**
* 获得本类及其父类所有Public方法
*
* @param clazz 查找方法的类
* @return 过滤后的方法列表
*/
public static Method[] getPublicMethods(Class> clazz) {
return clazz.getMethods();
}
/**
* 获得指定类过滤后的Public方法列表
*
* @param clazz 查找方法的类
* @param filter 过滤器
* @return 过滤后的方法列表
*/
public static List getPublicMethods(Class> clazz, Filter filter) {
if (null == clazz) {
return null;
}
Method[] methods = getPublicMethods(clazz);
List methodList;
if (null != filter) {
methodList = new ArrayList<>();
Method filteredMethod;
for (Method method : methods) {
filteredMethod = filter.modify(method);
if (null != filteredMethod) {
methodList.add(method);
}
}
} else {
methodList = CollectionKit.newArrayList(methods);
}
return methodList;
}
/**
* 获得指定类过滤后的Public方法列表
*
* @param clazz 查找方法的类
* @param excludeMethods 不包括的方法
* @return 过滤后的方法列表
*/
public static List getPublicMethods(Class> clazz, Method... excludeMethods) {
final HashSet excludeMethodSet = CollectionKit.newHashSet(excludeMethods);
Filter filter = new Filter(){
@Override
public Method modify(Method method) {
return excludeMethodSet.contains(method) ? null : method;
}
};
return getPublicMethods(clazz, filter);
}
/**
* 获得指定类过滤后的Public方法列表
*
* @param clazz 查找方法的类
* @param excludeMethodNames 不包括的方法名列表
* @return 过滤后的方法列表
*/
public static List getPublicMethods(Class> clazz, String... excludeMethodNames) {
final HashSet excludeMethodNameSet = CollectionKit.newHashSet(excludeMethodNames);
Filter filter = new Filter(){
@Override
public Method modify(Method method) {
return excludeMethodNameSet.contains(method.getName()) ? null : method;
}
};
return getPublicMethods(clazz, filter);
}
/**
* 查找指定Public方法
*
* @param clazz 类
* @param methodName 方法名
* @param paramTypes 参数类型
* @return 方法
* @throws SecurityException
* @throws NoSuchMethodException
*/
public static Method getPublicMethod(Class> clazz, String methodName, Class>... paramTypes) throws NoSuchMethodException, SecurityException {
try {
return clazz.getMethod(methodName, paramTypes);
} catch (NoSuchMethodException ex) {
return getDeclaredMethod(clazz, methodName, paramTypes);
}
}
/**
* 获得指定类中的Public方法名
* 去重重载的方法
*
* @param clazz 类
*/
public static Set getDeclaredMethodNames(Class> clazz) {
HashSet methodSet = new HashSet();
Method[] methodArray = getDeclaredMethods(clazz);
for (Method method : methodArray) {
String methodName = method.getName();
methodSet.add(methodName);
}
return methodSet;
}
/**
* 获得声明的所有方法,包括本类及其父类和接口的所有方法和Object类的方法
*
* @param clazz 类
* @return 方法数组
*/
public static Method[] getDeclaredMethods(Class> clazz) {
Set methodSet = new HashSet<>();
Method[] declaredMethods;
for (; null != clazz; clazz = clazz.getSuperclass()) {
declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods) {
methodSet.add(method);
}
}
return methodSet.toArray(new Method[methodSet.size()]);
}
/**
* 查找指定对象中的所有方法(包括非public方法),也包括父对象和Object类的方法
*
* @param obj 被查找的对象
* @param methodName 方法名
* @param args 参数
* @return 方法
* @throws NoSuchMethodException 无此方法
* @throws SecurityException
*/
public static Method getDeclaredMethod(Object obj, String methodName, Object... args) throws NoSuchMethodException, SecurityException {
return getDeclaredMethod(obj.getClass(), methodName, getClasses(args));
}
/**
* 查找指定类中的所有方法(包括非public方法),也包括父类和Object类的方法
*
* @param clazz 被查找的类
* @param methodName 方法名
* @param parameterTypes 参数类型
* @return 方法
* @throws NoSuchMethodException 无此方法
* @throws SecurityException
*/
public static Method getDeclaredMethod(Class> clazz, String methodName, Class>... parameterTypes) throws NoSuchMethodException, SecurityException {
Method method = null;
for (; null != clazz; clazz = clazz.getSuperclass()) {
try {
method = clazz.getDeclaredMethod(methodName, parameterTypes);
break;
} catch (NoSuchMethodException e) {
// 继续向上寻找
}
}
return method;
}
/**
* 是否为equals方法
*
* @param method 方法
* @return 是否为equals方法
*/
public static boolean isEqualsMethod(Method method) {
if (method == null || !method.getName().equals("equals")) {
return false;
}
Class>[] paramTypes = method.getParameterTypes();
return (paramTypes.length == 1 && paramTypes[0] == Object.class);
}
/**
* 是否为hashCode方法
*
* @param method 方法
* @return 是否为hashCode方法
*/
public static boolean isHashCodeMethod(Method method) {
return (method != null && method.getName().equals("hashCode") && method.getParameterTypes().length == 0);
}
/**
* 是否为toString方法
*
* @param method 方法
* @return 是否为toString方法
*/
public static boolean isToStringMethod(Method method) {
return (method != null && method.getName().equals("toString") && method.getParameterTypes().length == 0);
}
// ----------------------------------------------------------------------------------------- Classpath
/**
* 获得ClassPath
*
* @return ClassPath集合
*/
public static Set getClassPathResources() {
return getClassPaths(StrKit.EMPTY);
}
/**
* 获得ClassPath
*
* @param packageName 包名称
* @return ClassPath路径字符串集合
*/
public static Set getClassPaths(String packageName) {
String packagePath = packageName.replace(StrKit.DOT, StrKit.SLASH);
Enumeration resources;
try {
resources = getClassLoader().getResources(packagePath);
} catch (IOException e) {
throw new ToolBoxException(StrKit.format("Loading classPath [{}] error!", packagePath), e);
}
Set paths = new HashSet();
while (resources.hasMoreElements()) {
paths.add(resources.nextElement().getPath());
}
return paths;
}
/**
* 获得ClassPath
*
* @return ClassPath
*/
public static String getClassPath() {
return getClassPathURL().getPath();
}
/**
* 获得ClassPath URL
*
* @return ClassPath URL
*/
public static URL getClassPathURL() {
return getURL(StrKit.EMPTY);
}
/**
* 获得资源的URL
*
* @param resource 资源(相对Classpath的路径)
* @return 资源URL
*/
public static URL getURL(String resource) {
return ClassKit.getClassLoader().getResource(resource);
}
/**
* @return 获得Java ClassPath路径,不包括 jre
*/
public static String[] getJavaClassPaths() {
String[] classPaths = System.getProperty("java.class.path").split(System.getProperty("path.separator"));
return classPaths;
}
/**
* 转换为原始类型
*
* @param clazz 被转换为原始类型的类,必须为包装类型的类
* @return 基本类型类
*/
public static Class> castToPrimitive(Class> clazz) {
if (null == clazz || clazz.isPrimitive()) {
return clazz;
}
BasicType basicType;
try {
basicType = BasicType.valueOf(clazz.getSimpleName().toUpperCase());
} catch (Exception e) {
return clazz;
}
// 基本类型
switch (basicType) {
case BYTE:
return byte.class;
case SHORT:
return short.class;
case INTEGER:
return int.class;
case LONG:
return long.class;
case DOUBLE:
return double.class;
case FLOAT:
return float.class;
case BOOLEAN:
return boolean.class;
case CHAR:
return char.class;
default:
return clazz;
}
}
/**
* @return 当前线程的class loader
*/
public static ClassLoader getContextClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
/**
* 获得class loader
* 若当前线程class loader不存在,取当前类的class loader
*
* @return 类加载器
*/
public static ClassLoader getClassLoader() {
ClassLoader classLoader = getContextClassLoader();
if (classLoader == null) {
classLoader = ClassKit.class.getClassLoader();
}
return classLoader;
}
/**
* 实例化对象
*
* @param clazz 类名
* @return 对象
*/
@SuppressWarnings("unchecked")
public static T newInstance(String clazz) {
if (null == clazz) {
return null;
}
try {
return (T) Class.forName(clazz).newInstance();
} catch (Exception e) {
throw new ToolBoxException(StrKit.format("Instance class [{}] error!", clazz), e);
}
}
/**
* 实例化对象
*
* @param clazz 类
* @return 对象
*/
public static T newInstance(Class clazz) {
if (null == clazz) {
return null;
}
try {
return (T) clazz.newInstance();
} catch (Exception e) {
throw new ToolBoxException(StrKit.format("Instance class [{}] error!", clazz), e);
}
}
/**
* 实例化对象
*
* @param clazz 类
* @return 对象
*/
public static T newInstance(Class clazz, Object... params) {
if (null == clazz) {
return null;
}
if (CollectionKit.isEmpty(params)) {
return newInstance(clazz);
}
try {
return clazz.getDeclaredConstructor(getClasses(params)).newInstance(params);
} catch (Exception e) {
throw new ToolBoxException(StrKit.format("Instance class [{}] error!", clazz), e);
}
}
/**
* 加载类
*
* @param
* @param className 类名
* @param isInitialized 是否初始化
* @return 类
*/
@SuppressWarnings("unchecked")
public static Class loadClass(String className, boolean isInitialized) {
Class clazz;
try {
clazz = (Class) Class.forName(className, isInitialized, getClassLoader());
} catch (ClassNotFoundException e) {
throw new ToolBoxException(e);
}
return clazz;
}
/**
* 加载类并初始化
*
* @param
* @param className 类名
* @return 类
*/
public static Class loadClass(String className) {
return loadClass(className, true);
}
// ---------------------------------------------------------------------------------------------------- Invoke start
/**
* 执行方法
* 可执行Private方法,也可执行static方法
* 执行非static方法时,必须满足对象有默认构造方法
* 非单例模式,如果是非静态方法,每次创建一个新对象
*
* @param
* @param classNameDotMethodName 类名和方法名表达式,例如:com.xiaoleilu.hutool.StrKit.isEmpty
* @param args 参数,必须严格对应指定方法的参数类型和数量
* @return 返回结果
*/
public static T invoke(String classNameDotMethodName, Object[] args) {
return invoke(classNameDotMethodName, false, args);
}
/**
* 执行方法
* 可执行Private方法,也可执行static方法
* 执行非static方法时,必须满足对象有默认构造方法
*
* @param
* @param classNameDotMethodName 类名和方法名表达式,例如:com.xiaoleilu.hutool.StrKit.isEmpty
* @param isSingleton 是否为单例对象,如果此参数为false,每次执行方法时创建一个新对象
* @param args 参数,必须严格对应指定方法的参数类型和数量
* @return 返回结果
*/
public static T invoke(String classNameDotMethodName, boolean isSingleton, Object[] args) {
if (StrKit.isBlank(classNameDotMethodName)) {
throw new ToolBoxException("Blank classNameDotMethodName!");
}
final int dotIndex = classNameDotMethodName.lastIndexOf('.');
if (dotIndex <= 0) {
throw new ToolBoxException("Invalid classNameDotMethodName [{}]!", classNameDotMethodName);
}
final String className = classNameDotMethodName.substring(0, dotIndex);
final String methodName = classNameDotMethodName.substring(dotIndex + 1);
return invoke(className, methodName, isSingleton, args);
}
/**
* 执行方法
* 可执行Private方法,也可执行static方法
* 执行非static方法时,必须满足对象有默认构造方法
* 非单例模式,如果是非静态方法,每次创建一个新对象
*
* @param
* @param className 类名,完整类路径
* @param methodName 方法名
* @param args 参数,必须严格对应指定方法的参数类型和数量
* @return 返回结果
*/
public static T invoke(String className, String methodName, Object[] args) {
return invoke(className, methodName, false, args);
}
/**
* 执行方法
* 可执行Private方法,也可执行static方法
* 执行非static方法时,必须满足对象有默认构造方法
*
* @param
* @param className 类名,完整类路径
* @param methodName 方法名
* @param isSingleton 是否为单例对象,如果此参数为false,每次执行方法时创建一个新对象
* @param args 参数,必须严格对应指定方法的参数类型和数量
* @return 返回结果
*/
public static T invoke(String className, String methodName, boolean isSingleton, Object[] args) {
Class