1 16 package net.sf.cglib.beans; 17 18 import java.beans.PropertyDescriptor ; 19 import java.lang.reflect.*; 20 import net.sf.cglib.core.*; 21 import org.objectweb.asm.ClassVisitor; 22 import org.objectweb.asm.Type; 23 import java.util.*; 24 25 28 abstract public class BeanCopier 29 { 30 private static final BeanCopierKey KEY_FACTORY = 31 (BeanCopierKey)KeyFactory.create(BeanCopierKey.class); 32 private static final Type CONVERTER = 33 TypeUtils.parseType("net.sf.cglib.core.Converter"); 34 private static final Type BEAN_COPIER = 35 TypeUtils.parseType("net.sf.cglib.beans.BeanCopier"); 36 private static final Signature COPY = 37 new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER }); 38 private static final Signature CONVERT = 39 TypeUtils.parseSignature("Object convert(Object, Class, Object)"); 40 41 interface BeanCopierKey { 42 public Object newInstance(String source, String target, boolean useConverter); 43 } 44 45 public static BeanCopier create(Class source, Class target, boolean useConverter) { 46 Generator gen = new Generator(); 47 gen.setSource(source); 48 gen.setTarget(target); 49 gen.setUseConverter(useConverter); 50 return gen.create(); 51 } 52 53 abstract public void copy(Object from, Object to, Converter converter); 54 55 public static class Generator extends AbstractClassGenerator { 56 private static final Source SOURCE = new Source(BeanCopier.class.getName()); 57 private Class source; 58 private Class target; 59 private boolean useConverter; 60 61 public Generator() { 62 super(SOURCE); 63 } 64 65 public void setSource(Class source) { 66 if(!Modifier.isPublic(source.getModifiers())){ 67 setNamePrefix(source.getName()); 68 } 69 this.source = source; 70 } 71 72 public void setTarget(Class target) { 73 if(!Modifier.isPublic(target.getModifiers())){ 74 setNamePrefix(target.getName()); 75 } 76 77 this.target = target; 78 } 79 80 public void setUseConverter(boolean useConverter) { 81 this.useConverter = useConverter; 82 } 83 84 protected ClassLoader getDefaultClassLoader() { 85 return source.getClassLoader(); 86 } 87 88 public BeanCopier create() { 89 Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter); 90 return (BeanCopier)super.create(key); 91 } 92 93 public void generateClass(ClassVisitor v) { 94 Type sourceType = Type.getType(source); 95 Type targetType = Type.getType(target); 96 ClassEmitter ce = new ClassEmitter(v); 97 ce.begin_class(Constants.V1_2, 98 Constants.ACC_PUBLIC, 99 getClassName(), 100 BEAN_COPIER, 101 null, 102 Constants.SOURCE_FILE); 103 104 EmitUtils.null_constructor(ce); 105 CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null); 106 PropertyDescriptor [] getters = ReflectUtils.getBeanGetters(source); 107 PropertyDescriptor [] setters = ReflectUtils.getBeanGetters(target); 108 109 Map names = new HashMap(); 110 for (int i = 0; i < getters.length; i++) { 111 names.put(getters[i].getName(), getters[i]); 112 } 113 Local targetLocal = e.make_local(); 114 Local sourceLocal = e.make_local(); 115 if (useConverter) { 116 e.load_arg(1); 117 e.checkcast(targetType); 118 e.store_local(targetLocal); 119 e.load_arg(0); 120 e.checkcast(sourceType); 121 e.store_local(sourceLocal); 122 } else { 123 e.load_arg(1); 124 e.checkcast(targetType); 125 e.load_arg(0); 126 e.checkcast(sourceType); 127 } 128 for (int i = 0; i < setters.length; i++) { 129 PropertyDescriptor setter = setters[i]; 130 PropertyDescriptor getter = (PropertyDescriptor )names.get(setter.getName()); 131 if (getter != null) { 132 MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod()); 133 MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod()); 134 if (useConverter) { 135 Type setterType = write.getSignature().getArgumentTypes()[0]; 136 e.load_local(targetLocal); 137 e.load_arg(2); 138 e.load_local(sourceLocal); 139 e.invoke(read); 140 e.box(read.getSignature().getReturnType()); 141 EmitUtils.load_class(e, setterType); 142 e.push(write.getSignature().getName()); 143 e.invoke_interface(CONVERTER, CONVERT); 144 e.unbox_or_zero(setterType); 145 e.invoke(write); 146 } else if (compatible(getter, setter)) { 147 e.dup2(); 148 e.invoke(read); 149 e.invoke(write); 150 } 151 } 152 } 153 e.return_value(); 154 e.end_method(); 155 ce.end_class(); 156 } 157 158 private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) { 159 return setter.getPropertyType().isAssignableFrom(getter.getPropertyType()); 161 } 162 163 protected Object firstInstance(Class type) { 164 return ReflectUtils.newInstance(type); 165 } 166 167 protected Object nextInstance(Object instance) { 168 return instance; 169 } 170 } 171 } 172 | Popular Tags |