View Javadoc
1 /* 2 * The Apache Software License, Version 1.1 3 * 4 * Copyright (c) 2002 The Apache Software Foundation. All rights 5 * reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. The end-user documentation included with the redistribution, 20 * if any, must include the following acknowledgment: 21 * "This product includes software developed by the 22 * Apache Software Foundation (http://www.apache.org/)." 23 * Alternately, this acknowledgment may appear in the software itself, 24 * if and wherever such third-party acknowledgments normally appear. 25 * 26 * 4. The names "Apache" and "Apache Software Foundation" must 27 * not be used to endorse or promote products derived from this 28 * software without prior written permission. For written 29 * permission, please contact apache@apache.org. 30 * 31 * 5. Products derived from this software may not be called "Apache", 32 * nor may "Apache" appear in their name, without prior written 33 * permission of the Apache Software Foundation. 34 * 35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 46 * SUCH DAMAGE. 47 * ==================================================================== 48 * 49 * This software consists of voluntary contributions made by many 50 * individuals on behalf of the Apache Software Foundation. For more 51 * information on the Apache Software Foundation, please see 52 * <http://www.apache.org/>;. 53 */ 54 package net.sf.cglib.beans; 55 56 import java.beans.PropertyDescriptor; 57 import java.lang.reflect.Method; 58 import net.sf.cglib.core.*; 59 import org.objectweb.asm.ClassVisitor; 60 import org.objectweb.asm.Type; 61 import java.util.*; 62 63 /*** 64 * @author Chris Nokleberg 65 */ 66 abstract public class BeanCopier 67 { 68 private static final BeanCopierKey KEY_FACTORY = 69 (BeanCopierKey)KeyFactory.create(BeanCopierKey.class); 70 private static final Signature COPY = 71 TypeUtils.parseSignature("void copy(Object, Object, net.sf.cglib.core.Converter)"); 72 private static final Signature CONVERT = 73 TypeUtils.parseSignature("Object convert(Object, Class, Object)"); 74 private static final Type CONVERTER = 75 TypeUtils.parseType("net.sf.cglib.core.Converter"); 76 private static final Type BEAN_COPIER = 77 TypeUtils.parseType("net.sf.cglib.beans.BeanCopier"); 78 79 interface BeanCopierKey { 80 public Object newInstance(Class source, Class target, boolean useConverter); 81 } 82 83 public static BeanCopier create(Class source, Class target, boolean useConverter) { 84 Generator gen = new Generator(); 85 gen.setSource(source); 86 gen.setTarget(target); 87 gen.setUseConverter(useConverter); 88 return gen.create(); 89 } 90 91 abstract public void copy(Object from, Object to, Converter converter); 92 93 public static class Generator extends AbstractClassGenerator { 94 private static final Source SOURCE = new Source(BeanCopier.class.getName()); 95 private Class source; 96 private Class target; 97 private boolean useConverter; 98 99 public Generator() { 100 super(SOURCE); 101 } 102 103 public void setSource(Class source) { 104 this.source = source; 105 } 106 107 public void setTarget(Class target) { 108 this.target = target; 109 } 110 111 public void setUseConverter(boolean useConverter) { 112 this.useConverter = useConverter; 113 } 114 115 protected ClassLoader getDefaultClassLoader() { 116 return source.getClassLoader(); 117 } 118 119 public BeanCopier create() { 120 Object key = KEY_FACTORY.newInstance(source, target, useConverter); 121 return (BeanCopier)super.create(key); 122 } 123 124 public void generateClass(ClassVisitor v) { 125 Type sourceType = Type.getType(source); 126 Type targetType = Type.getType(target); 127 ClassEmitter ce = new ClassEmitter(v); 128 ce.begin_class(Constants.ACC_PUBLIC, 129 getClassName(), 130 BEAN_COPIER, 131 null, 132 Constants.SOURCE_FILE); 133 134 EmitUtils.null_constructor(ce); 135 CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null, null); 136 PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source); 137 PropertyDescriptor[] setters = ReflectUtils.getBeanGetters(target); 138 139 Map names = new HashMap(); 140 for (int i = 0; i < getters.length; i++) { 141 names.put(getters[i].getName(), getters[i]); 142 } 143 Local targetLocal = e.make_local(); 144 Local sourceLocal = e.make_local(); 145 if (useConverter) { 146 e.load_arg(1); 147 e.checkcast(targetType); 148 e.store_local(targetLocal); 149 e.load_arg(0); 150 e.checkcast(sourceType); 151 e.store_local(sourceLocal); 152 } else { 153 e.load_arg(1); 154 e.checkcast(targetType); 155 e.load_arg(0); 156 e.checkcast(sourceType); 157 } 158 for (int i = 0; i < setters.length; i++) { 159 PropertyDescriptor setter = setters[i]; 160 PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName()); 161 if (getter != null) { 162 if (useConverter) { 163 Type getterType = Type.getType(getter.getPropertyType()); 164 Type setterType = Type.getType(setter.getPropertyType()); 165 e.load_local(targetLocal); 166 e.load_arg(2); 167 e.load_local(sourceLocal); 168 e.invoke(getter.getReadMethod()); 169 e.box(getterType); 170 EmitUtils.load_class(e, setterType); 171 e.push(setter.getName()); 172 e.invoke_interface(CONVERTER, CONVERT); 173 e.unbox_or_zero(setterType); 174 e.invoke(setter.getWriteMethod()); 175 } else if (compatible(getter, setter)) { 176 e.dup2(); 177 e.invoke(getter.getReadMethod()); 178 e.invoke(setter.getWriteMethod()); 179 } 180 } 181 } 182 e.return_value(); 183 e.end_method(); 184 ce.end_class(); 185 } 186 187 private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) { 188 // TODO: allow automatic widening conversions? 189 return setter.getPropertyType().isAssignableFrom(getter.getPropertyType()); 190 } 191 192 protected Object firstInstance(Class type) { 193 return ReflectUtils.newInstance(type); 194 } 195 196 protected Object nextInstance(Object instance) { 197 return instance; 198 } 199 } 200 }

This page was automatically generated by Maven