
shz.AccessibleHelp Maven / Gradle / Ivy
package shz;
import shz.cache.MapCache;
import shz.constant.ArrayConstant;
import shz.constant.NullConstant;
import shz.enums.IEnum;
import shz.msg.ServerFailure;
import shz.queue.IArrayQueue;
import shz.st.tst.LTST;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.*;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjuster;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Stream;
@SuppressWarnings("unchecked")
public final class AccessibleHelp {
private AccessibleHelp() {
throw new IllegalStateException();
}
public static Class> forName(String className, boolean initialize, ClassLoader loader) {
if (Validator.isBlank(className)) return null;
switch (className) {
case "boolean":
return boolean.class;
case "short":
return short.class;
case "char":
return char.class;
case "int":
return int.class;
case "long":
return long.class;
case "double":
return double.class;
case "byte":
return byte.class;
case "float":
return float.class;
case "void":
return void.class;
default:
try {
if (initialize && loader == null) return Class.forName(className);
return Class.forName(className, initialize, loader == null ? Thread.currentThread().getContextClassLoader() : loader);
} catch (ClassNotFoundException e) {
return null;
}
}
}
public static Class> forName(String className, boolean initialize) {
return forName(className, initialize, null);
}
public static Class> forName(String className) {
return forName(className, false, null);
}
public static boolean isPrimitive(Class> cls) {
if (cls == null || cls == void.class) return false;
return cls.isPrimitive();
}
public static boolean isPrimitiveWrap(Class> cls) {
if (cls == null) return false;
return cls == Boolean.class
|| cls == Byte.class
|| cls == Character.class
|| cls == Short.class
|| cls == Integer.class
|| cls == Long.class
|| cls == Double.class
|| cls == Float.class;
}
public static boolean isCommon(Class> cls) {
if (cls == null || cls == Void.class || cls == void.class) return false;
return cls.isPrimitive()
|| cls == Boolean.class
|| cls == Character.class
|| CharSequence.class.isAssignableFrom(cls)
|| Number.class.isAssignableFrom(cls)
|| TemporalAccessor.class.isAssignableFrom(cls)
|| TemporalAdjuster.class.isAssignableFrom(cls)
|| Date.class.isAssignableFrom(cls)
|| Enum.class.isAssignableFrom(cls);
}
public static boolean canCast(Class> src, Class> des) {
if (src == null || des == null) return false;
boolean srcIsP = src.isPrimitive(), srcIsPw = !srcIsP && isPrimitiveWrap(src);
boolean desIsP = des.isPrimitive(), desIsPw = !desIsP && isPrimitiveWrap(des);
if ((srcIsP | srcIsPw) ^ (desIsP | desIsPw)) return false;
if (!(srcIsP | srcIsPw | desIsP | desIsPw)) return des.isAssignableFrom(src);
String desName = des.getTypeName();
switch (src.getTypeName()) {
case "java.lang.Boolean":
case "boolean":
return desName.endsWith("n");
case "java.lang.Byte":
case "byte":
return desName.endsWith("te");
case "java.lang.Character":
case "char":
return desName.endsWith("ter") || desName.endsWith("ar");
case "java.lang.Short":
case "short":
return desName.endsWith("rt");
case "java.lang.Integer":
case "int":
return desName.endsWith("ger") || desName.endsWith("nt");
case "java.lang.Long":
case "long":
return desName.endsWith("g");
case "java.lang.Double":
case "double":
return desName.endsWith("le");
case "java.lang.Float":
case "float":
return desName.endsWith("at");
case "java.lang.Void":
case "void":
return desName.endsWith("d");
default:
return false;
}
}
/**
* 获取指定类对象的父类或实现的接口中指定泛型的类对象
*
* @param cls 指定类对象(superOrInterface 的子类或实现类)
* @param superOrInterface 指定类对象的父类或实现的接口
* @param typeParamName 父类或接口中泛型参数的名称(T,K或V...)
* @return 父类或接口中泛型参数的类对象
*/
public static Class getParameterizedType(Class> cls, Class> superOrInterface, String typeParamName) {
return (Class) getParameterizedType0(cls, superOrInterface, typeParamName);
}
private static Class> getParameterizedType0(Class> cls, Class> superOrInterface, String typeParamName) {
Class> cur = cls;
for (; ; ) {
if ((cur = oneTopChild(cur, superOrInterface)) == null) return Object.class;
int idx = -1;
TypeVariable>[] typeParams = superOrInterface.getTypeParameters();
for (int i = 0; i < typeParams.length; ++i)
if (typeParamName.equals(typeParams[i].getName())) {
idx = i;
break;
}
if (idx < 0) return Object.class;
Type genericSuperType = null;
if (superOrInterface.isInterface()) {
for (Type type : cur.getGenericInterfaces())
if (tryToClass(type) == superOrInterface) {
genericSuperType = type;
break;
}
} else genericSuperType = cur.getGenericSuperclass();
if (!(genericSuperType instanceof ParameterizedType)) return Object.class;
Type[] actualTypeParams = ((ParameterizedType) genericSuperType).getActualTypeArguments();
Type actualTypeParam = actualTypeParams[idx];
Class> result;
if ((result = tryToClass(actualTypeParam)) != null) return result;
if (actualTypeParam instanceof TypeVariable) {
cur = cls;
TypeVariable> v = (TypeVariable>) actualTypeParam;
GenericDeclaration d;
if (!((d = v.getGenericDeclaration()) instanceof Class)) return Object.class;
typeParamName = v.getName();
if (!(superOrInterface = (Class>) d).isAssignableFrom(cls)) return Object.class;
continue;
}
return Object.class;
}
}
private static Class> oneTopChild(Class> c, Class> p) {
if (c == null || c == Object.class) return null;
Class> cur = c, sup;
do {
if ((sup = cur.getSuperclass()) == p) return cur;
if (sup == null || !p.isAssignableFrom(sup)) break;
cur = sup;
} while (true);
c = null;
for (Class> cls : cur.getInterfaces()) {
if (cls == p) return cur;
if (c == null && p.isAssignableFrom(cls)) c = cls;
}
return oneTopChild(c, p);
}
private static Class> tryToClass(Type type) {
if (type instanceof ParameterizedType) type = ((ParameterizedType) type).getRawType();
if (type instanceof Class) return (Class>) type;
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
if (componentType instanceof ParameterizedType)
componentType = ((ParameterizedType) componentType).getRawType();
if (componentType instanceof Class) return Array.newInstance((Class>) componentType, 0).getClass();
}
return null;
}
public static Type[] getTypes(Field field) {
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) return ((ParameterizedType) genericType).getActualTypeArguments();
return Validator.empty(Type[].class);
}
public static Type[] getTypes(Class> cls) {
if (cls == null) return Validator.empty(Type[].class);
Type genericSuperType = null;
if (cls.isInterface()) {
for (Type type : cls.getGenericInterfaces())
if ((genericSuperType = type) instanceof ParameterizedType) break;
} else genericSuperType = cls.getGenericSuperclass();
if (genericSuperType instanceof ParameterizedType)
return ((ParameterizedType) genericSuperType).getActualTypeArguments();
return Validator.empty(Type[].class);
}
public static Class> typeToClass(Type type) {
if (type == null) return null;
Class> cls;
if ((cls = tryToClass(type)) != null) return cls;
if (type instanceof TypeVariable) {
TypeVariable> v = (TypeVariable>) type;
if (!(v.getGenericDeclaration() instanceof Class)) return Object.class;
}
return forName(type.getTypeName());
}
public static Class>[] typeToClass(Type[] types, int... indexes) {
if (Validator.isEmpty(types)) return ArrayConstant.EMPTY_CLASS_ARRAY;
Validator.requireNon(types.length < indexes.length);
Type[] result = new Type[indexes.length];
for (int i = 0; i < indexes.length; ++i) {
Validator.requireNon(indexes[i] < 0 || indexes[i] >= types.length);
result[i] = types[indexes[i]];
}
return Arrays.stream(result).map(AccessibleHelp::typeToClass).toArray(Class[]::new);
}
/**
* 获取类对象的唯一标识符
*/
public static String identify(Class> cls) {
if (cls == null) return NullConstant.STRING;
Type[] types = getTypes(cls);
if (types.length == 0) return cls.getName();
StringBuilder sb = new StringBuilder(cls.getName());
Set> exists = new HashSet<>();
Arrays.stream(types).map(AccessibleHelp::typeToClass).filter(Objects::nonNull).forEach(c -> identify0(c, sb, exists, 1));
return sb.toString();
}
private static void identify0(Class> cls, StringBuilder sb, Set> exists, int nest) {
Type[] types = getTypes(cls);
if (types.length == 0) sb.append("-").append(cls.getName()).append(nest);
else
Arrays.stream(types).map(AccessibleHelp::typeToClass).filter(Objects::nonNull).forEach(c -> {
if (exists.contains(c)) sb.append("-").append(c.getName()).append(nest + 1);
else {
exists.add(c);
identify0(c, sb, exists, nest + 1);
}
});
}
public static Field accessible(Field field) {
Objects.requireNonNull(field);
if (field.isAccessible()) return field;
if ((field.getModifiers() & Modifier.PUBLIC) == 0
|| (field.getDeclaringClass().getModifiers() & Modifier.PUBLIC) == 0
|| (field.getModifiers() & Modifier.FINAL) != 0)
field.setAccessible(true);
return field;
}
public static Constructor accessible(Constructor constructor) {
Objects.requireNonNull(constructor);
if (constructor.isAccessible()) return constructor;
if ((constructor.getModifiers() & Modifier.PUBLIC) == 0
|| (constructor.getDeclaringClass().getModifiers() & Modifier.PUBLIC) == 0)
constructor.setAccessible(true);
return constructor;
}
public static Method accessible(Method method) {
Objects.requireNonNull(method);
if (method.isAccessible()) return method;
if ((method.getModifiers() & Modifier.PUBLIC) == 0
|| (method.getDeclaringClass().getModifiers() & Modifier.PUBLIC) == 0)
method.setAccessible(true);
return method;
}
private static final MapCache, List> FIELD_CACHE = new MapCache<>(128);
/**
* 获取类属性
*
* @param cls 类的class对象
* @param predicate 属性过滤器
* @param limit 限制获取属性个数
*/
public static List fields(Class> cls, Predicate predicate, int limit) {
if (cls == null || predicate == null) return Collections.emptyList();
List fields = FIELD_CACHE.get(cls);
if (fields == null) {
fields = new LinkedList<>();
Class> cur = cls;
do {
Arrays.stream(cur.getDeclaredFields()).map(AccessibleHelp::accessible).forEach(fields::add);
cur = cur.getSuperclass();
} while (cur != null && cur != Object.class);
if (fields.isEmpty()) {
FIELD_CACHE.put(cls, Collections.emptyList());
return Collections.emptyList();
}
FIELD_CACHE.put(cls, new ArrayList<>(fields));
}
if (fields.isEmpty()) return Collections.emptyList();
Stream stream = fields.stream().filter(predicate);
return ToList.collect(limit > 0 ? stream.limit(limit) : stream);
}
public static List fields(Class> cls, Predicate predicate) {
return fields(cls, predicate, 0);
}
public static List fields(Class> cls) {
//默认不获取静态属性
return fields(cls, f -> (f.getModifiers() & Modifier.STATIC) == 0, 0);
}
private static final MapCache, List> FIELD_NAME_CACHE = new MapCache<>(128);
/**
* 获取类属性名称
*/
public static List fieldNames(Class> cls, Predicate predicate, int limit) {
if (cls == null || predicate == null) return Collections.emptyList();
List fieldNames = FIELD_NAME_CACHE.get(cls);
if (fieldNames == null) {
List fields = fields(cls);
if (fields.isEmpty()) {
FIELD_NAME_CACHE.put(cls, Collections.emptyList());
return Collections.emptyList();
}
fieldNames = ToList.explicitCollect(fields.stream().map(Field::getName), fields.size());
FIELD_NAME_CACHE.put(cls, fieldNames);
}
if (fieldNames.isEmpty()) return Collections.emptyList();
Stream stream = fieldNames.stream().filter(predicate);
return ToList.collect(limit > 0 ? stream.limit(limit) : stream);
}
public static List fieldNames(Class> cls, Predicate predicate) {
return fieldNames(cls, predicate, 0);
}
public static List fieldNames(Class> cls) {
return fieldNames(cls, f -> true, 0);
}
private static final MapCache, List>> CONSTRUCTOR_CACHE = new MapCache<>(128);
/**
* 获取类的构造方法
*/
public static List> constructors(Class> cls, Predicate> predicate, int limit) {
if (cls == null || predicate == null) return Collections.emptyList();
List> constructors = CONSTRUCTOR_CACHE.get(cls);
if (constructors == null) {
constructors = new LinkedList<>();
Class> cur = cls;
do {
Arrays.stream(cur.getDeclaredConstructors()).map(AccessibleHelp::accessible).forEach(constructors::add);
cur = cur.getSuperclass();
} while (cur != null && cur != Object.class);
if (constructors.isEmpty()) {
CONSTRUCTOR_CACHE.put(cls, Collections.emptyList());
return Collections.emptyList();
}
CONSTRUCTOR_CACHE.put(cls, new ArrayList<>(constructors));
}
if (constructors.isEmpty()) return Collections.emptyList();
Stream> stream = constructors.stream().filter(predicate);
return ToList.collect(limit > 0 ? stream.limit(limit) : stream);
}
public static List> constructors(Class> cls, Predicate> predicate) {
return constructors(cls, predicate, 0);
}
public static List> constructors(Class> cls) {
return constructors(cls, f -> true, 0);
}
private static final MapCache, List> METHOD_CACHE = new MapCache<>(128);
/**
* 获取类的方法
*/
public static List methods(Class> cls, Predicate predicate, int limit) {
if (cls == null || predicate == null) return Collections.emptyList();
List methods = METHOD_CACHE.get(cls);
if (methods == null) {
methods = new LinkedList<>();
Class> cur = cls;
do {
Arrays.stream(cur.getDeclaredMethods()).map(AccessibleHelp::accessible).forEach(methods::add);
cur = cur.getSuperclass();
} while (cur != null && cur != Object.class);
if (methods.isEmpty()) {
METHOD_CACHE.put(cls, Collections.emptyList());
return Collections.emptyList();
}
METHOD_CACHE.put(cls, new ArrayList<>(methods));
}
if (methods.isEmpty()) return Collections.emptyList();
Stream stream = methods.stream().filter(predicate);
return ToList.collect(limit > 0 ? stream.limit(limit) : stream);
}
public static List methods(Class> cls, Predicate predicate) {
return methods(cls, predicate, 0);
}
public static List methods(Class> cls) {
return methods(cls, f -> !Modifier.isStatic(f.getModifiers()), 0);
}
/**
* 根据方法名称获取空参方法
*/
public static Method getMethod(Class> cls, String methodName) {
List methods = methods(cls, m -> m.getName().equals(methodName) && m.getParameterCount() == 0, 1);
Validator.requireNonEmpty(methods);
return methods.get(0);
}
/**
* 根据方法名称及参数类型获取一个参数的方法
*/
public static Method getMethod(Class> cls, String methodName, Class> ptype) {
List methods = methods(cls, m -> {
if (!m.getName().equals(methodName)) return false;
Class>[] ptypes = m.getParameterTypes();
return ptypes.length == 1 && ptypes[0].isAssignableFrom(ptype);
}, 0);
Validator.requireNonEmpty(methods);
if (methods.size() == 1) return methods.get(0);
Class>[] pa = methods.stream().map(m -> m.getParameterTypes()[0]).toArray(Class[]::new);
int idx = 0;
for (int i = 1; i < pa.length; ++i) {
if (pa[idx] == ptype) break;
if (pa[idx].isAssignableFrom(pa[i])) idx = i;
}
return methods.get(idx);
}
/**
* 根据方法名称及参数类型获取二个参数的方法
*/
public static Method getMethod(Class> cls, String methodName, Class> ptype1, Class> ptype2) {
List methods = methods(cls, m -> {
if (!m.getName().equals(methodName)) return false;
Class>[] ptypes = m.getParameterTypes();
return ptypes.length == 2 && ptypes[0].isAssignableFrom(ptype1) && ptypes[1].isAssignableFrom(ptype2);
}, 0);
Validator.requireNonEmpty(methods);
if (methods.size() == 1) return methods.get(0);
Class>[][] psa = methods.stream().map(Method::getParameterTypes).toArray(Class[][]::new);
return methods.get(match(psa, ptype1, ptype2));
}
private static int match(Class>[][] psa, Class>... ptypes) {
int mlen = psa.length, j = 0;
IArrayQueue ia = IArrayQueue.of(mlen);
for (int i = 0; i < mlen; ++i) ia.offer(i);
while (j < ptypes.length - 1) {
IArrayQueue nia = IArrayQueue.of(mlen);
for (int k = 0; k < mlen; ++k) {
int i = ia.poll();
if (psa[i][j] == ptypes[j]) ia.offer(i);
else nia.offer(i);
}
mlen = ia.size();
if (mlen == 1) return ia.poll();
else if (mlen == 0) {
int nmlen = nia.size();
Class> cls = psa[nia.head()][j];
nia.offer(nia.poll());
for (int k = 1; k < nmlen; ++k) {
int i = nia.poll();
if (cls.isAssignableFrom(psa[i][j])) {
nia.offer(i);
cls = psa[i][j];
}
}
if (nia.size() == 1) return nia.poll();
while (!nia.isEmpty()) {
int i = nia.poll();
if (psa[i][j] == cls) ia.offer(i);
}
mlen = ia.size();
if (mlen == 1) return ia.poll();
}
++j;
}
int idx = ia.poll();
if (psa[idx][j] == ptypes[j]) return idx;
while (!ia.isEmpty()) {
int i = ia.poll();
if (psa[i][j] == ptypes[j]) return i;
if (psa[idx][j].isAssignableFrom(psa[i][j])) idx = i;
}
return idx;
}
/**
* 根据方法名称及参数类型获取多个参数的方法
*/
public static Method getMethod(Class> cls, String methodName, Class>... ptypes) {
List methods = methods(cls, m -> {
if (!m.getName().equals(methodName)) return false;
Class>[] pTypes = m.getParameterTypes();
if (pTypes.length != ptypes.length) return false;
for (int i = 0; i < pTypes.length; ++i) if (!pTypes[i].isAssignableFrom(ptypes[i])) return false;
return true;
}, 0);
Validator.requireNonEmpty(methods);
if (methods.size() == 1) return methods.get(0);
Class>[][] psa = methods.stream().map(Method::getParameterTypes).toArray(Class[][]::new);
return methods.get(match(psa, ptypes));
}
/**
* 自定义类加载器
*/
public static final class CustomClassLoader extends ClassLoader {
private final Function classByteFunc;
public CustomClassLoader(Function classByteFunc) {
super(CustomClassLoader.class.getClassLoader());
this.classByteFunc = classByteFunc;
}
public CustomClassLoader() {
this(null);
}
@Override
public Class> loadClass(String name) throws ClassNotFoundException {
if (Validator.nonBlank(name)) return super.loadClass(name, true);
return classByteFunc == null ? null : loadClass(classByteFunc.apply(null));
}
public Class> loadClass(byte[] bytes) {
Validator.requireNonEmpty(bytes);
return defineClass(null, bytes, 0, bytes.length);
}
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
byte[] bytes;
if (classByteFunc != null && Validator.nonEmpty(bytes = classByteFunc.apply(name)))
return defineClass(name, bytes, 0, bytes.length);
return super.findClass(name);
}
}
public static ClassLoader getClassLoader(Function classIs) {
if (classIs == null) return null;
return new CustomClassLoader(name -> IOHelp.read(classIs.apply(name)));
}
public static ClassLoader getClassLoader(Function classIs, Function modifier) {
if (classIs == null) return null;
return new CustomClassLoader(name -> modifier.apply(IOHelp.read(classIs.apply(name))));
}
@SafeVarargs
public static ClassLoader getClassLoader(Function classIs, Function... modifiers) {
if (classIs == null) return null;
return new CustomClassLoader(name -> {
Function modifier = modifiers[0];
for (int i = 1; i < modifiers.length; ++i) modifier = modifier.andThen(modifiers[i]);
return modifier.apply(IOHelp.read(classIs.apply(name)));
});
}
public static ClassLoader getClassLoader(String classpath) {
return getClassLoader(t -> getLocalClassIs(classpath, t));
}
public static InputStream getLocalClassIs(String classpath, String name) {
if (Validator.isBlank(name)) return null;
String path = name.replace('.', '/') + ".class";
try {
return IOHelp.getBis(Validator.isBlank(classpath)
? new File(FileHelp.urlToFile(Thread.currentThread().getContextClassLoader().getResource("")), path)
: new File(classpath, path));
} catch (Throwable t) {
try {
return IOHelp.getIsFromURL(path);
} catch (Throwable cause) {
return null;
}
}
}
public static ClassLoader getClassLoader(String classpath, Function modifier) {
return getClassLoader(name -> getLocalClassIs(classpath, name), modifier);
}
@SafeVarargs
public static ClassLoader getClassLoader(String classpath, Function... modifiers) {
return getClassLoader(name -> getLocalClassIs(classpath, name), modifiers);
}
/**
* 获取父类(包括父类的父类)
*/
public static List> getSuperClasses(Class cls) {
if (cls == null) return Collections.emptyList();
List> result = new LinkedList<>();
Class super T> cur = cls.getSuperclass();
while (cur != Object.class) {
result.add(cur);
cur = cur.getSuperclass();
}
return result.isEmpty() ? Collections.emptyList() : result;
}
/**
* 获取内部类(包括内部类的内部类)
*/
public static List> getInnerClasses(Class> cls) {
if (cls == null) return Collections.emptyList();
List> result = new LinkedList<>();
Queue[]> queue = new LinkedList<>();
queue.offer(cls.getDeclaredClasses());
while (queue.size() > 0) {
for (Class> c : queue.poll()) {
result.add(c);
queue.offer(c.getDeclaredClasses());
}
}
return result.isEmpty() ? Collections.emptyList() : result;
}
/**
* 获取指定包下指定条件的类
*/
public static List> getClasses(Predicate> predicate, int limit, String packageName) {
if (predicate == null || packageName == null) return Collections.emptyList();
String packagePath = packageName.replace('.', '/');
Enumeration resources;
try {
resources = Thread.currentThread().getContextClassLoader().getResources(packagePath);
} catch (IOException e) {
return Collections.emptyList();
}
packageName = "".equals(packageName) ? "" : packageName + ".";
List> result = new LinkedList<>();
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
String protocol = url.getProtocol();
if ("file".equals(protocol)) try {
getClassesFromFile(predicate, limit, packageName, new File(URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8.name())), result);
} catch (UnsupportedEncodingException ignored) {
}
else if ("jar".equals(protocol)) try {
getClassesFromJarFile(predicate, limit, packageName, ((JarURLConnection) url.openConnection()).getJarFile(), packagePath, result);
} catch (IOException ignored) {
}
if (limit > 0 && result.size() >= limit) break;
}
return result.isEmpty() ? Collections.emptyList() : result;
}
private static void getClassesFromFile(Predicate> predicate, int limit, String packageName, File file, List> result) {
File[] files = file.listFiles(f -> f.isDirectory() || f.getName().endsWith(".class"));
if (Validator.isEmpty(files)) return;
for (File f : files) {
if (f.isDirectory()) getClassesFromFile(predicate, limit, packageName + f.getName() + ".", f, result);
else try {
Class> forName = forName(packageName + f.getName().substring(0, f.getName().length() - 6), false, null);
if (predicate.test(forName)) {
result.add(forName);
if (limit > 0 && result.size() >= limit) break;
}
} catch (Throwable ignored) {
}
}
}
private static void getClassesFromJarFile(Predicate> predicate, int limit, String packageName, JarFile jarFile, String packagePath, List> result) {
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
name = name.charAt(0) == '/' ? name.substring(1) : name;
if (name.startsWith(packagePath)) {
int last = name.lastIndexOf('/');
packageName = last != -1 ? name.substring(0, last).replace('/', '.') + '.' : packageName;
if (name.endsWith(".class") && !entry.isDirectory()) try {
Class> forName = forName(packageName + name.substring(packageName.length(), name.length() - 6), false, null);
if (predicate.test(forName)) {
result.add(forName);
if (limit > 0 && result.size() >= limit) break;
}
} catch (Throwable ignored) {
}
}
}
}
public static List> getClasses(Predicate> predicate, int limit) {
return getClasses(predicate, limit, "");
}
public static List> getClasses(Predicate> predicate, String packageName) {
return getClasses(predicate, 0, packageName);
}
public static List> getClasses(Predicate> predicate) {
return getClasses(predicate, 0, "");
}
public static List> getClasses(Predicate> predicate, int limit, String... packageNames) {
if (predicate == null) return Collections.emptyList();
List> result = new LinkedList<>();
for (String name : packageNames) {
if (Validator.isBlank(name)) continue;
if (limit > 0) {
if (result.size() >= limit) break;
result.addAll(getClasses(predicate, limit - result.size(), name));
} else result.addAll(getClasses(predicate, limit, name));
}
return result.isEmpty() ? Collections.emptyList() : result;
}
public static List> getClasses(Predicate> predicate, String... packageNames) {
return getClasses(predicate, 0, packageNames);
}
/**
* 获取指定包下指定条件的子类或实现类
*/
public static List> getChildClasses(Class> cls, Predicate> predicate, int limit, String packageName) {
if (cls == null || predicate == null || packageName == null) return Collections.emptyList();
return getClasses(
c -> !Modifier.isAbstract(c.getModifiers())
&& !Modifier.isInterface(c.getModifiers())
&& cls.isAssignableFrom(c)
&& predicate.test(c),
limit,
packageName
);
}
public static List> getChildClasses(Class> cls, Predicate> predicate, int limit) {
return getChildClasses(cls, predicate, limit, "");
}
public static List> getChildClasses(Class> cls, Predicate> predicate, String packageName) {
return getChildClasses(cls, predicate, 0, packageName);
}
public static List> getChildClasses(Class> cls, Predicate> predicate) {
return getChildClasses(cls, predicate, 0, "");
}
public static List> getChildClasses(Class> cls, Predicate> predicate, int limit, String... packageNames) {
if (cls == null || predicate == null) return Collections.emptyList();
return getClasses(
c -> !Modifier.isAbstract(c.getModifiers())
&& !Modifier.isInterface(c.getModifiers())
&& cls.isAssignableFrom(c)
&& predicate.test(c),
limit,
packageNames
);
}
public static List> getChildClasses(Class> cls, Predicate> predicate, String... packageNames) {
return getChildClasses(cls, predicate, 0, packageNames);
}
public static List> getChildClasses(Class> cls, int limit, String packageName) {
return getChildClasses(cls, c -> true, limit, packageName);
}
public static List> getChildClasses(Class> cls, int limit) {
return getChildClasses(cls, limit, "");
}
public static List> getChildClasses(Class> cls, String packageName) {
return getChildClasses(cls, 0, packageName);
}
public static List> getChildClasses(Class> cls) {
return getChildClasses(cls, 0, "");
}
public static T newObject(Class extends T> cls) {
if (cls == null) return null;
if (Modifier.isAbstract(cls.getModifiers()) || Modifier.isInterface(cls.getModifiers()))
return (T) getChildClasses(cls).stream().map(AccessibleHelp::newObject).filter(Objects::nonNull).findFirst().orElse(null);
if (isPrimitive(cls)) {
if (cls == boolean.class) return (T) Boolean.FALSE;
if (cls == byte.class) return (T) Byte.valueOf((byte) 0);
if (cls == char.class) return (T) Character.valueOf((char) 0);
if (cls == short.class) return (T) Short.valueOf((short) 0);
if (cls == int.class) return (T) Integer.valueOf(0);
if (cls == long.class) return (T) Long.valueOf(0);
if (cls == double.class) return (T) Double.valueOf(0d);
if (cls == float.class) return (T) Float.valueOf(0f);
throw PRException.impossible();
}
if (cls == void.class || cls == Void.class) return null;
List> constructors = constructors(cls, c -> c.getParameterCount() == 0, 1);
if (constructors.isEmpty()) return null;
try {
return ((Constructor) constructors.get(0)).newInstance();
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
return null;
}
}
public static T newObject(Class extends T> cls, Object initarg) {
if (cls == null) return null;
if (Modifier.isAbstract(cls.getModifiers()) || Modifier.isInterface(cls.getModifiers()))
return (T) getChildClasses(cls).stream().map(c -> newObject(c, initarg)).filter(Objects::nonNull).findFirst().orElse(null);
for (Constructor> constructor : constructors(cls, c -> c.getParameterCount() == 1)) {
try {
return (T) constructor.newInstance(initarg);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException ignored) {
}
}
return null;
}
public static T newObject(Class extends T> cls, Object... initargs) {
if (cls == null) return null;
if (Modifier.isAbstract(cls.getModifiers()) || Modifier.isInterface(cls.getModifiers()))
return (T) getChildClasses(cls).stream().map(c -> newObject(c, initargs)).filter(Objects::nonNull).findFirst().orElse(null);
for (Constructor> constructor : constructors(cls, c -> c.getParameterCount() == initargs.length)) {
try {
return (T) constructor.newInstance(initargs);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException ignored) {
}
}
return null;
}
public static T newObject(String className, ClassLoader classLoader) {
try {
return newObject(classLoader == null ? (Class extends T>) forName(className, true) : (Class extends T>) classLoader.loadClass(className));
} catch (Throwable t) {
return null;
}
}
public static T newObject(String className, ClassLoader classLoader, Object initarg) {
try {
return newObject(classLoader == null ? (Class extends T>) forName(className, true) : (Class extends T>) classLoader.loadClass(className), initarg);
} catch (Throwable t) {
return null;
}
}
public static T newObject(String className, ClassLoader classLoader, Object... initargs) {
try {
return newObject(classLoader == null ? (Class extends T>) forName(className, true) : (Class extends T>) classLoader.loadClass(className), initargs);
} catch (Throwable t) {
return null;
}
}
public static T newObject(String className, String classpath) {
return newObject(className, getClassLoader(classpath));
}
public static T newObject(String className, String classpath, Object initarg) {
return newObject(className, getClassLoader(classpath), initarg);
}
public static T newObject(String className, String classpath, Object... initargs) {
return newObject(className, getClassLoader(classpath), initargs);
}
public static T cloneObject(T t) {
if (t == null) return null;
Class cls = (Class) t.getClass();
T obj;
Objects.requireNonNull(obj = newObject(cls));
fields(cls).parallelStream().forEach(f -> setField(f, obj, getField(f, t)));
return obj;
}
public static T getField(Field field, Object obj) {
try {
return (T) field.get(obj);
} catch (IllegalAccessException e) {
return null;
}
}
public static void setField(Field field, Object obj, Object val) {
try {
field.set(obj, val);
} catch (IllegalAccessException ignored) {
}
}
private static final MapCache, List>> ENUM_CACHE = new MapCache<>(128);
/**
* 获取枚举类的所有实例
*/
public static > List enumSet(Class> cls) {
if (cls == null || !Enum.class.isAssignableFrom(cls)) return Collections.emptyList();
List result = (List) ENUM_CACHE.get(cls);
if (result != null) return result;
EnumSet enumSet = null;
try {
enumSet = EnumSet.allOf((Class) cls);
} catch (Throwable ignored) {
}
if (enumSet == null) {
ENUM_CACHE.put(cls, Collections.emptyList());
return Collections.emptyList();
}
result = ToList.collectArray(enumSet.stream());
ENUM_CACHE.put(cls, result);
return result;
}
/**
* 获取枚举类或接口的实现枚举类的所有实例
*/
public static List enumSets(Class cls) {
if (cls == null) return Collections.emptyList();
List result = (List) ENUM_CACHE.get(cls);
if (result != null) return result;
if (!Modifier.isInterface(cls.getModifiers())) return (List) enumSet(cls);
result = ToList.collectArray(getChildClasses(cls).parallelStream().map(AccessibleHelp::enumSet).filter(Validator::nonEmpty).flatMap(Collection::stream).map(t -> (S) t));
ENUM_CACHE.put(cls, result);
return result;
}
private static final LTST> ENUM_CLASS_ST = LTST.of();
/**
* 根据全限定名或类名获取枚举类的所有实例
*/
public static , T extends IEnum, ?>> List enumSet(String typeName) {
if (Validator.isBlank(typeName)) return Collections.emptyList();
char[] chars = typeName.toCharArray();
Class> cls = ENUM_CLASS_ST.get(chars);
if (cls == null) {
//全限定名
if (typeName.indexOf(".") > 0) cls = AccessibleHelp.forName(typeName);
else {
//类名
List> classes = AccessibleHelp.getClasses(c -> IEnum.class.isAssignableFrom(c) && c.getSimpleName().equals(typeName), 1);
if (classes.isEmpty()) cls = null;
else cls = classes.get(0);
}
if (cls == null || !IEnum.class.isAssignableFrom(cls)) cls = NullConstant.CLASS;
ENUM_CLASS_ST.put(chars, cls);
}
if (cls == NullConstant.CLASS) return Collections.emptyList();
List ts = enumSet(cls);
if (ts.isEmpty()) return Collections.emptyList();
return ToList.explicitCollect(ts.stream().map(e -> (T) e), ts.size());
}
/**
* 通过反射执行方法
*/
public static U invoke(T receiver, String methodName) {
Objects.requireNonNull(receiver);
Validator.requireNonBlank(methodName);
try {
Method method = getMethod(receiver.getClass(), methodName);
if (method.getReturnType() == void.class) method.invoke(receiver);
else return (U) method.invoke(receiver);
} catch (IllegalAccessException | InvocationTargetException e) {
throw PRException.of(e);
}
return null;
}
public static U invoke(T receiver, String methodName, Class> ptype, Object arg) {
Validator.requireNonAnyNull(receiver, ptype);
Validator.requireNonBlank(methodName);
try {
Method method = getMethod(receiver.getClass(), methodName, ptype);
if (method.getReturnType() == void.class) method.invoke(receiver, arg);
else return (U) method.invoke(receiver, arg);
} catch (IllegalAccessException | InvocationTargetException e) {
throw PRException.of(e);
}
return null;
}
public static U invoke(T receiver, String methodName, Class>[] ptypes, Object[] args) {
Validator.requireNonAnyNull(receiver, ptypes, args);
Validator.requireNonBlank(methodName);
Validator.requireNon(ptypes.length != args.length);
try {
Method method = getMethod(receiver.getClass(), methodName, ptypes);
if (method.getReturnType() == void.class) method.invoke(receiver, args);
else return (U) method.invoke(receiver, args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw PRException.of(e);
}
return null;
}
public static T invoke(String name, ClassLoader classLoader, String methodName) {
return invoke(newObject(name, classLoader), methodName);
}
public static T invoke(String name, ClassLoader classLoader, String methodName, Class> ptype, Object arg) {
return invoke(newObject(name, classLoader), methodName, ptype, arg);
}
public static T invoke(String name, ClassLoader classLoader, String methodName, Class>[] ptypes, Object[] args) {
return invoke(newObject(name, classLoader), methodName, ptypes, args);
}
public static U invoke(T receiver, String methodName, String limit, Class> rtype) {
Objects.requireNonNull(receiver);
Validator.requireNonBlank(methodName);
MethodHandle methodHandle = getMethodHandle(limit, MethodHandles.lookup(), receiver, methodName, MethodType.methodType(rtype == null ? void.class : rtype));
try {
if (rtype == null || rtype == void.class) methodHandle.invokeWithArguments();
else return (U) methodHandle.invokeWithArguments();
} catch (Throwable t) {
return invoke(receiver, methodName);
}
return null;
}
private static MethodHandle getMethodHandle(String limit, MethodHandles.Lookup lookup, T receiver, String name, MethodType type) {
try {
if ("static".equals(limit)) return lookup.findStatic(receiver.getClass(), name, type);
try {
//"virtual"
return lookup.findVirtual(receiver.getClass(), name, type).bindTo(receiver);
} catch (NoSuchMethodException e) {
throw PRException.of(ServerFailure.NoSuchMethodException);
} catch (IllegalAccessException e) {
return lookup.findStatic(receiver.getClass(), name, type);
}
} catch (Throwable t) {
throw PRException.of(t);
}
}
public static U invoke(T receiver, String methodName, Class> rtype) {
return invoke(receiver, methodName, "", rtype);
}
public static U invoke(T receiver, String methodName, String limit, Class> rtype, Class> ptype, Object arg) {
Validator.requireNonAnyNull(receiver, ptype);
Validator.requireNonBlank(methodName);
MethodHandle methodHandle = getMethodHandle(limit, MethodHandles.lookup(), receiver, methodName, MethodType.methodType(rtype == null ? void.class : rtype, ptype));
try {
if (rtype == null || rtype == void.class) methodHandle.invokeWithArguments(arg);
else return (U) methodHandle.invokeWithArguments(arg);
} catch (Throwable t) {
return invoke(receiver, methodName, ptype, arg);
}
return null;
}
public static U invoke(T receiver, String methodName, Class> rtype, Class> ptype, Object arg) {
return invoke(receiver, methodName, null, rtype, ptype, arg);
}
public static U invoke(T receiver, String methodName, String limit, Class> rtype, Class>[] ptypes, Object[] args) {
Validator.requireNonAnyNull(receiver, ptypes, args);
Validator.requireNonBlank(methodName);
Validator.requireNon(ptypes.length != args.length);
MethodHandle methodHandle = getMethodHandle(limit, MethodHandles.lookup(), receiver, methodName, MethodType.methodType(rtype == null ? void.class : rtype, ptypes));
try {
if (rtype == null || rtype == void.class) methodHandle.invokeWithArguments(args);
else return (U) methodHandle.invokeWithArguments(args);
} catch (Throwable t) {
return invoke(receiver, methodName, ptypes, args);
}
return null;
}
public static U invoke(T receiver, String methodName, Class> rtype, Class>[] ptypes, Object[] args) {
return invoke(receiver, methodName, null, rtype, ptypes, args);
}
public static T invoke(String name, ClassLoader classLoader, String methodName, String limit, Class> rtype) {
return invoke(newObject(name, classLoader), methodName, limit, rtype);
}
public static T invoke(String name, ClassLoader classLoader, String methodName, Class> rtype) {
return invoke(newObject(name, classLoader), methodName, "", rtype);
}
public static T invoke(String name, ClassLoader classLoader, String methodName, String limit, Class> rtype, Class> ptype, Object arg) {
return invoke(newObject(name, classLoader), methodName, limit, rtype, ptype, arg);
}
public static T invoke(String name, ClassLoader classLoader, String methodName, Class> rtype, Class> ptype, Object arg) {
return invoke(newObject(name, classLoader), methodName, null, rtype, ptype, arg);
}
public static T invoke(String name, ClassLoader classLoader, String methodName, String limit, Class> rtype, Class>[] ptypes, Object[] args) {
return invoke(newObject(name, classLoader), methodName, limit, rtype, ptypes, args);
}
public static T invoke(String name, ClassLoader classLoader, String methodName, Class> rtype, Class>[] ptypes, Object[] args) {
return invoke(newObject(name, classLoader), methodName, null, rtype, ptypes, args);
}
public static boolean isAnnotationPresent(AnnotatedElement a, Class extends Annotation> c) {
return a != null && c != null && a.isAnnotationPresent(c);
}
public static boolean nonAnnotationPresent(AnnotatedElement a, Class extends Annotation> c) {
return !isAnnotationPresent(a, c);
}
public static boolean isAnyAnnotationPresent(AnnotatedElement a, Class extends Annotation> c1, Class extends Annotation> c2) {
return isAnnotationPresent(a, c1) || isAnnotationPresent(a, c2);
}
public static boolean nonAnyAnnotationPresent(AnnotatedElement a, Class extends Annotation> c1, Class extends Annotation> c2) {
return !isAnyAnnotationPresent(a, c1, c2);
}
public static boolean isAnyAnnotationPresent(AnnotatedElement a, Class extends Annotation>... cs) {
return Arrays.stream(cs).parallel().anyMatch(c -> isAnnotationPresent(a, c));
}
public static boolean nonAnyAnnotationPresent(AnnotatedElement a, Class extends Annotation>... cs) {
return !isAnyAnnotationPresent(a, cs);
}
public static boolean isAllAnnotationPresent(AnnotatedElement a, Class extends Annotation> c1, Class extends Annotation> c2) {
return isAnnotationPresent(a, c1) && isAnnotationPresent(a, c2);
}
public static boolean nonAllAnnotationPresent(AnnotatedElement a, Class extends Annotation> c1, Class extends Annotation> c2) {
return !isAllAnnotationPresent(a, c1, c2);
}
public static boolean isAllAnnotationPresent(AnnotatedElement a, Class extends Annotation>... cs) {
return Arrays.stream(cs).parallel().allMatch(c -> isAnnotationPresent(a, c));
}
public static boolean nonAllAnnotationPresent(AnnotatedElement a, Class extends Annotation>... cs) {
return !isAllAnnotationPresent(a, cs);
}
public static T getField(Object obj, Predicate predicate) {
List fields;
if (obj == null || (fields = fields(obj.getClass(), predicate, 1)).isEmpty()) return null;
return getField(fields.get(0), obj);
}
/**
* 获取具有指定注解条件的属性值
*/
public static T getFieldByAnnotation(Object obj, Class cls, Predicate predicate) {
return getField(obj, f -> isAnnotationPresent(f, cls) && (predicate == null || predicate.test(f.getAnnotation(cls))));
}
public static T getFieldByAnnotation(Object obj, Class cls) {
return getField(obj, f -> isAnnotationPresent(f, cls));
}
public static void setField(Object obj, Predicate predicate, Object value) {
List fields;
if (obj == null || (fields = fields(obj.getClass(), predicate, 1)).isEmpty()) return;
setField(fields.get(0), obj, value);
}
/**
* 设置具有指定注解条件的属性
*/
public static void setFieldByAnnotation(Object obj, Class cls, Predicate predicate, Object value) {
setField(obj, f -> isAnnotationPresent(f, cls) && (predicate == null || predicate.test(f.getAnnotation(cls))), value);
}
public static void setFieldByAnnotation(Object obj, Class cls, Object value) {
setField(obj, f -> isAnnotationPresent(f, cls), value);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy