package com.qianwen.core.tool.beans;
|
|
import java.beans.PropertyDescriptor;
|
import java.lang.reflect.Method;
|
import java.lang.reflect.Modifier;
|
import java.security.ProtectionDomain;
|
import java.util.HashMap;
|
import java.util.Map;
|
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentMap;
|
import com.qianwen.core.tool.utils.BeanUtil;
|
import com.qianwen.core.tool.utils.ClassUtil;
|
import com.qianwen.core.tool.utils.ReflectUtil;
|
import com.qianwen.core.tool.utils.StringUtil;
|
import org.springframework.asm.ClassVisitor;
|
import org.springframework.asm.Label;
|
import org.springframework.asm.Type;
|
import org.springframework.cglib.core.AbstractClassGenerator;
|
import org.springframework.cglib.core.ClassEmitter;
|
import org.springframework.cglib.core.CodeEmitter;
|
import org.springframework.cglib.core.Constants;
|
import org.springframework.cglib.core.Converter;
|
import org.springframework.cglib.core.EmitUtils;
|
import org.springframework.cglib.core.Local;
|
import org.springframework.cglib.core.MethodInfo;
|
import org.springframework.cglib.core.ReflectUtils;
|
import org.springframework.cglib.core.Signature;
|
import org.springframework.cglib.core.TypeUtils;
|
import org.springframework.lang.Nullable;
|
import org.springframework.util.ClassUtils;
|
|
/* loaded from: blade-core-tool-9.3.0.0-SNAPSHOT.jar:org/springblade/core/tool/beans/BladeBeanCopier.class */
|
public abstract class BladeBeanCopier {
|
private static final Type CONVERTER = TypeUtils.parseType("org.springframework.cglib.core.Converter");
|
private static final Type BEAN_COPIER = TypeUtils.parseType(BladeBeanCopier.class.getName());
|
private static final Type BEAN_MAP = TypeUtils.parseType(Map.class.getName());
|
private static final Signature COPY = new Signature("copy", Type.VOID_TYPE, new Type[]{Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER});
|
private static final Signature CONVERT = TypeUtils.parseSignature("Object convert(Object, Class, Object)");
|
private static final Signature BEAN_MAP_GET = TypeUtils.parseSignature("Object get(Object)");
|
private static final Type CLASS_UTILS = TypeUtils.parseType(ClassUtils.class.getName());
|
private static final Signature IS_ASSIGNABLE_VALUE = TypeUtils.parseSignature("boolean isAssignableValue(Class, Object)");
|
private static final ConcurrentMap<BladeBeanCopierKey, BladeBeanCopier> BEAN_COPIER_MAP = new ConcurrentHashMap();
|
|
public abstract void copy(Object from, Object to, @Nullable Converter converter);
|
|
public static BladeBeanCopier create(Class source, Class target, boolean useConverter) {
|
return create(source, target, useConverter, false);
|
}
|
|
public static BladeBeanCopier create(Class source, Class target, boolean useConverter, boolean nonNull) {
|
BladeBeanCopierKey copierKey = new BladeBeanCopierKey(source, target, useConverter, nonNull);
|
return BEAN_COPIER_MAP.computeIfAbsent(copierKey, key -> {
|
Generator gen = new Generator();
|
gen.setSource(key.getSource());
|
gen.setTarget(key.getTarget());
|
gen.setUseConverter(key.isUseConverter());
|
gen.setNonNull(key.isNonNull());
|
return gen.m3create((Object) key);
|
});
|
}
|
|
/* loaded from: blade-core-tool-9.3.0.0-SNAPSHOT.jar:org/springblade/core/tool/beans/BladeBeanCopier$Generator.class */
|
public static class Generator extends AbstractClassGenerator {
|
private static final AbstractClassGenerator.Source SOURCE = new AbstractClassGenerator.Source(BladeBeanCopier.class.getName());
|
private Class source;
|
private Class target;
|
private boolean useConverter;
|
private boolean nonNull;
|
|
Generator() {
|
super(SOURCE);
|
}
|
|
public void setSource(Class source) {
|
if (!Modifier.isPublic(source.getModifiers())) {
|
setNamePrefix(source.getName());
|
}
|
this.source = source;
|
}
|
|
public void setTarget(Class target) {
|
if (!Modifier.isPublic(target.getModifiers())) {
|
setNamePrefix(target.getName());
|
}
|
this.target = target;
|
}
|
|
public void setUseConverter(boolean useConverter) {
|
this.useConverter = useConverter;
|
}
|
|
public void setNonNull(boolean nonNull) {
|
this.nonNull = nonNull;
|
}
|
|
protected ClassLoader getDefaultClassLoader() {
|
return this.target.getClassLoader();
|
}
|
|
protected ProtectionDomain getProtectionDomain() {
|
return ReflectUtils.getProtectionDomain(this.source);
|
}
|
|
/* renamed from: create */
|
public BladeBeanCopier m3create(Object key) {
|
return (BladeBeanCopier) super.create(key);
|
}
|
|
public void generateClass(ClassVisitor v) {
|
Type sourceType = Type.getType(this.source);
|
Type targetType = Type.getType(this.target);
|
ClassEmitter ce = new ClassEmitter(v);
|
ce.begin_class(46, 1, getClassName(), BladeBeanCopier.BEAN_COPIER, (Type[]) null, "<generated>");
|
EmitUtils.null_constructor(ce);
|
CodeEmitter e = ce.begin_method(1, BladeBeanCopier.COPY, (Type[]) null);
|
if (Map.class.isAssignableFrom(this.source)) {
|
generateClassFormMap(ce, e, sourceType, targetType);
|
return;
|
}
|
PropertyDescriptor[] getters = ReflectUtil.getBeanGetters(this.source);
|
PropertyDescriptor[] setters = ReflectUtil.getBeanSetters(this.target);
|
Map<String, PropertyDescriptor> names = new HashMap<>(16);
|
for (PropertyDescriptor getter : getters) {
|
names.put(getter.getName(), getter);
|
}
|
Local targetLocal = e.make_local();
|
Local sourceLocal = e.make_local();
|
e.load_arg(1);
|
e.checkcast(targetType);
|
e.store_local(targetLocal);
|
e.load_arg(0);
|
e.checkcast(sourceType);
|
e.store_local(sourceLocal);
|
for (PropertyDescriptor setter : setters) {
|
String propName = setter.getName();
|
CopyProperty targetIgnoreCopy = (CopyProperty) ReflectUtil.getAnnotation(this.target, propName, CopyProperty.class);
|
if (targetIgnoreCopy != null) {
|
if (!targetIgnoreCopy.ignore()) {
|
String aliasTargetPropName = targetIgnoreCopy.value();
|
if (StringUtil.isNotBlank(aliasTargetPropName)) {
|
propName = aliasTargetPropName;
|
}
|
}
|
}
|
PropertyDescriptor getter2 = names.get(propName);
|
if (getter2 != null) {
|
MethodInfo read = ReflectUtils.getMethodInfo(getter2.getReadMethod());
|
Method writeMethod = setter.getWriteMethod();
|
MethodInfo write = ReflectUtils.getMethodInfo(writeMethod);
|
Type returnType = read.getSignature().getReturnType();
|
Type setterType = write.getSignature().getArgumentTypes()[0];
|
Class<?> getterPropertyType = getter2.getPropertyType();
|
Class<?> setterPropertyType = setter.getPropertyType();
|
Label l0 = e.make_label();
|
if (ClassUtil.isAssignable(setterPropertyType, getterPropertyType)) {
|
e.load_local(targetLocal);
|
e.load_local(sourceLocal);
|
e.invoke(read);
|
boolean getterIsPrimitive = getterPropertyType.isPrimitive();
|
boolean setterIsPrimitive = setterPropertyType.isPrimitive();
|
if (this.nonNull) {
|
e.box(returnType);
|
Local var = e.make_local();
|
e.store_local(var);
|
e.load_local(var);
|
e.ifnull(l0);
|
e.load_local(targetLocal);
|
e.load_local(var);
|
e.unbox_or_zero(setterType);
|
} else {
|
if (getterIsPrimitive && !setterIsPrimitive) {
|
e.box(returnType);
|
}
|
if (!getterIsPrimitive && setterIsPrimitive) {
|
e.unbox_or_zero(setterType);
|
}
|
}
|
invokeWrite(e, write, writeMethod, this.nonNull, l0);
|
} else if (this.useConverter) {
|
e.load_local(targetLocal);
|
e.load_arg(2);
|
e.load_local(sourceLocal);
|
e.invoke(read);
|
e.box(returnType);
|
if (this.nonNull) {
|
Local var2 = e.make_local();
|
e.store_local(var2);
|
e.load_local(var2);
|
e.ifnull(l0);
|
e.load_local(targetLocal);
|
e.load_arg(2);
|
e.load_local(var2);
|
}
|
EmitUtils.load_class(e, setterType);
|
e.push(propName);
|
e.invoke_interface(BladeBeanCopier.CONVERTER, BladeBeanCopier.CONVERT);
|
e.unbox_or_zero(setterType);
|
invokeWrite(e, write, writeMethod, this.nonNull, l0);
|
}
|
}
|
}
|
e.return_value();
|
e.end_method();
|
ce.end_class();
|
}
|
|
private static void invokeWrite(CodeEmitter e, MethodInfo write, Method writeMethod, boolean nonNull, Label l0) {
|
Class<?> returnType = writeMethod.getReturnType();
|
e.invoke(write);
|
if (!returnType.equals(Void.TYPE)) {
|
e.pop();
|
}
|
if (nonNull) {
|
e.visitLabel(l0);
|
}
|
}
|
|
protected Object firstInstance(Class type) {
|
return BeanUtil.newInstance(type);
|
}
|
|
protected Object nextInstance(Object instance) {
|
return instance;
|
}
|
|
public void generateClassFormMap(ClassEmitter ce, CodeEmitter e, Type sourceType, Type targetType) {
|
PropertyDescriptor[] setters = ReflectUtil.getBeanSetters(this.target);
|
Local targetLocal = e.make_local();
|
Local sourceLocal = e.make_local();
|
e.load_arg(1);
|
e.checkcast(targetType);
|
e.store_local(targetLocal);
|
e.load_arg(0);
|
e.checkcast(sourceType);
|
e.store_local(sourceLocal);
|
Type mapBox = Type.getType(Object.class);
|
for (PropertyDescriptor setter : setters) {
|
String propName = setter.getName();
|
CopyProperty targetIgnoreCopy = (CopyProperty) ReflectUtil.getAnnotation(this.target, propName, CopyProperty.class);
|
if (targetIgnoreCopy != null) {
|
if (!targetIgnoreCopy.ignore()) {
|
String aliasTargetPropName = targetIgnoreCopy.value();
|
if (StringUtil.isNotBlank(aliasTargetPropName)) {
|
propName = aliasTargetPropName;
|
}
|
}
|
}
|
Method writeMethod = setter.getWriteMethod();
|
MethodInfo write = ReflectUtils.getMethodInfo(writeMethod);
|
Type setterType = write.getSignature().getArgumentTypes()[0];
|
e.load_local(targetLocal);
|
e.load_local(sourceLocal);
|
e.push(propName);
|
e.invoke_interface(BladeBeanCopier.BEAN_MAP, BladeBeanCopier.BEAN_MAP_GET);
|
e.box(mapBox);
|
Local var = e.make_local();
|
e.store_local(var);
|
e.load_local(var);
|
Label l0 = e.make_label();
|
e.ifnull(l0);
|
EmitUtils.load_class(e, setterType);
|
e.load_local(var);
|
e.invoke_static(BladeBeanCopier.CLASS_UTILS, BladeBeanCopier.IS_ASSIGNABLE_VALUE);
|
Label l1 = new Label();
|
Class<?> returnType = writeMethod.getReturnType();
|
if (this.useConverter) {
|
e.if_jump(153, l1);
|
e.load_local(targetLocal);
|
e.load_local(var);
|
e.unbox_or_zero(setterType);
|
e.invoke(write);
|
if (!returnType.equals(Void.TYPE)) {
|
e.pop();
|
}
|
e.goTo(l0);
|
e.visitLabel(l1);
|
e.load_local(targetLocal);
|
e.load_arg(2);
|
e.load_local(var);
|
EmitUtils.load_class(e, setterType);
|
e.push(propName);
|
e.invoke_interface(BladeBeanCopier.CONVERTER, BladeBeanCopier.CONVERT);
|
e.unbox_or_zero(setterType);
|
e.invoke(write);
|
} else {
|
e.if_jump(153, l0);
|
e.load_local(targetLocal);
|
e.load_local(var);
|
e.unbox_or_zero(setterType);
|
e.invoke(write);
|
}
|
if (!returnType.equals(Void.TYPE)) {
|
e.pop();
|
}
|
e.visitLabel(l0);
|
}
|
e.return_value();
|
e.end_method();
|
ce.end_class();
|
}
|
}
|
}
|