帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

174 lines
5.1 KiB

package com.fr.base;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
/**
* @author hades
* @version 10.0
* Created by hades on 2020/12/28
*/
public class ClassHelper {
private static final Set<String> primClasses = new HashSet<>();
private static final Set<ClassLoader> classLoaders = new HashSet<>();
private static final Map<String, Field[]> map = new HashMap<>();
private static final Set<Object> data = new HashSet<>();
private static final String PLUGIN_CLASS_CLASSLOADER= "com.fr.plugin.engine.core.PluginClassLoader";
static {
primClasses.add("boolean");
primClasses.add("byte");
primClasses.add("char");
primClasses.add("short");
primClasses.add("int");
primClasses.add("long");
primClasses.add("float");
primClasses.add("double");
primClasses.add("void");
primClasses.add("java.lang.Boolean");
primClasses.add("java.lang.Byte");
primClasses.add("java.lang.Character");
primClasses.add("java.lang.Short");
primClasses.add("java.lang.Integer");
primClasses.add("java.lang.Long");
primClasses.add("java.lang.FLOAT");
primClasses.add("java.lang.DOUBLE");
primClasses.add("java.lang.Void");
primClasses.add("java.lang.String");
primClasses.add("java.awt.image.BufferedImage");
}
/**
* 获取当前对象字段中由插件加载出类的classloader
*
* @param o
* @return
*/
@Nullable
public static Set<ClassLoader> getPluginClassLoaders(Object o) {
try {
collectClassloader(o);
Set<ClassLoader> result = new HashSet<>(classLoaders);
data.clear();
classLoaders.clear();
map.clear();
return result;
} catch (Throwable e) {
FineLoggerFactory.getLogger().warn(e.getMessage(), e);
data.clear();
classLoaders.clear();
map.clear();
return null;
}
}
private static void collectClassloader(Object o) {
if (o == null) {
return;
}
Field[] fields;
Class<?> aclass = o.getClass();
String className = aclass.getName();
if (map.containsKey(className)) {
fields = map.get(className);
} else {
fields = fields(aclass, o);
map.put(className, fields);
}
if (aclass.isArray()) {
for (int i = 0, len = Array.getLength(o); i < len; i++) {
Object arrayOb = Array.get(o, i);
if (arrayOb != null) {
Class<?> arrayObClass = arrayOb.getClass();
String name = arrayObClass.getName();
if (primClasses.contains(name)) {
return;
}
data.add(arrayOb);
ClassLoader loader = arrayObClass.getClassLoader();
if (loader != null && ComparatorUtils.equals(loader.getClass().getName(), PLUGIN_CLASS_CLASSLOADER)) {
classLoaders.add(loader);
}
} else {
continue;
}
collectClassloader(arrayOb);
}
}
if (fields.length == 0) {
return;
}
for (Field field : fields) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
Object ob = null;
try {
ob = field.get(o);
if (ob == null) {
continue;
}
Class<?> clazz = ob.getClass();
String name = clazz.getName();
if (primClasses.contains(name)) {
continue;
}
if (!data.contains(ob)) {
data.add(ob);
ClassLoader loader = clazz.getClassLoader();
if (loader != null && ComparatorUtils.equals(loader.getClass().getName(), PLUGIN_CLASS_CLASSLOADER)) {
classLoaders.add(loader);
}
collectClassloader(ob);
}
} catch (Throwable e) {
FineLoggerFactory.getLogger().warn(e.getMessage(), e);
}
}
}
private static Field[] fields(Class<?> clazz, Object o) {
Class<?> t = clazz;
Set<Field> result = new HashSet<>();
do {
for (Field field : t.getDeclaredFields()) {
if (clazz != o ^ Modifier.isStatic(field.getModifiers())) {
result.add(field);
}
}
t = t.getSuperclass();
}
while (t != null);
return result.toArray(new Field[0]);
}
}