Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.github.jcharm.common.Reproduce Maven / Gradle / Ivy
/**
* Copyright (c) 2016,Daniel Wang ([email protected] ) All rights reserved。
*/
package io.github.jcharm.common;
import java.lang.reflect.Modifier;
import java.util.function.Predicate;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
/**
* The Interface Reproduce.
*
* @param 目标对象的数据类型
* @param 源对象的数据类型
*/
public interface Reproduce {
/**
* Creates the.
*
* @param the generic type
* @param the generic type
* @param destClass the dest class
* @param srcClass the src class
* @return the Reproduce
*/
public static Reproduce create(final Class destClass, final Class srcClass) {
return Reproduce.create(destClass, srcClass, null);
}
/**
* Creates the.
*
* @param the generic type
* @param the generic type
* @param destClass the dest class
* @param srcClass the src class
* @param columnPredicate the column predicate
* @return the Reproduce
*/
public static Reproduce create(final Class destClass, final Class srcClass, final Predicate columnPredicate) {
final String supDynName = Reproduce.class.getName().replace('.', '/');
final String destName = destClass.getName().replace('.', '/');
final String srcName = srcClass.getName().replace('.', '/');
final String destDesc = Type.getDescriptor(destClass);
final String srcDesc = Type.getDescriptor(srcClass);
String newDynName = supDynName + "Dyn_" + destClass.getSimpleName() + "_" + srcClass.getSimpleName();
ClassLoader loader = Reproduce.class.getClassLoader();
if (String.class.getClassLoader() != destClass.getClassLoader()) {
loader = destClass.getClassLoader();
newDynName = destName + "_Dyn" + Reproduce.class.getSimpleName() + "_" + srcClass.getSimpleName();
}
try {
return (Reproduce) Class.forName(newDynName.replace('/', '.')).newInstance();
} catch (final Exception ex) {
}
final ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + destDesc + srcDesc + ">;", "java/lang/Object", new String[] { supDynName });
{ // 构造函数
mv = (cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null));
// mv.setDebug(true);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = (cw.visitMethod(Opcodes.ACC_PUBLIC, "copy", "(" + destDesc + srcDesc + ")" + destDesc, null, null));
for (final java.lang.reflect.Field field : srcClass.getFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (Modifier.isFinal(field.getModifiers())) {
continue;
}
if (!Modifier.isPublic(field.getModifiers())) {
continue;
}
final String fname = field.getName();
try {
if (!field.getType().equals(destClass.getField(fname).getType())) {
continue;
}
if (!columnPredicate.test(fname)) {
continue;
}
} catch (final Exception e) {
continue;
}
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitVarInsn(Opcodes.ALOAD, 2);
final String td = Type.getDescriptor(field.getType());
mv.visitFieldInsn(Opcodes.GETFIELD, srcName, fname, td);
mv.visitFieldInsn(Opcodes.PUTFIELD, destName, fname, td);
}
for (final java.lang.reflect.Method getter : srcClass.getMethods()) {
if (Modifier.isStatic(getter.getModifiers())) {
continue;
}
if (getter.getParameterTypes().length > 0) {
continue; // 为了兼容android 而不使用 getParameterCount()
}
if ("getClass".equals(getter.getName())) {
continue;
}
if (!getter.getName().startsWith("get") && !getter.getName().startsWith("is")) {
continue;
}
java.lang.reflect.Method setter;
final boolean is = getter.getName().startsWith("is");
try {
setter = destClass.getMethod(getter.getName().replaceFirst(is ? "is" : "get", "set"), getter.getReturnType());
if (columnPredicate != null) {
String col = setter.getName().substring(3);
if ((col.length() < 2) || Character.isLowerCase(col.charAt(1))) {
final char[] cs = col.toCharArray();
cs[0] = Character.toLowerCase(cs[0]);
col = new String(cs);
}
if (!columnPredicate.test(col)) {
continue;
}
}
} catch (final Exception e) {
continue;
}
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitVarInsn(Opcodes.ALOAD, 2);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, srcName, getter.getName(), Type.getMethodDescriptor(getter), false);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, destName, setter.getName(), Type.getMethodDescriptor(setter), false);
}
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
{
mv = (cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_BRIDGE + Opcodes.ACC_SYNTHETIC, "copy", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null));
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitTypeInsn(Opcodes.CHECKCAST, destName);
mv.visitVarInsn(Opcodes.ALOAD, 2);
mv.visitTypeInsn(Opcodes.CHECKCAST, srcName);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, newDynName, "copy", "(" + destDesc + srcDesc + ")" + destDesc, false);
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
cw.visitEnd();
final byte[] bytes = cw.toByteArray();
final Class> creatorClazz = new ClassLoader(loader) {
public final Class> loadClass(final String name, final byte[] b) {
return this.defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
try {
return (Reproduce) creatorClazz.newInstance();
} catch (final Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* Copy.
*
* @param dest the dest
* @param src the src
* @return the D
*/
public D copy(D dest, S src);
}