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