|
16 | 16 | package org.springframework.cglib.beans;
|
17 | 17 |
|
18 | 18 | import java.beans.PropertyDescriptor;
|
19 |
| -import java.lang.reflect.Modifier; |
20 | 19 | import java.security.ProtectionDomain;
|
21 | 20 | import java.util.HashMap;
|
22 | 21 | import java.util.Map;
|
|
42 | 41 | @SuppressWarnings({"rawtypes", "unchecked"})
|
43 | 42 | abstract public class BeanCopier
|
44 | 43 | {
|
45 |
| - private static final BeanCopierKey KEY_FACTORY = |
46 |
| - (BeanCopierKey)KeyFactory.create(BeanCopierKey.class); |
47 |
| - private static final Type CONVERTER = |
48 |
| - TypeUtils.parseType("org.springframework.cglib.core.Converter"); |
49 |
| - private static final Type BEAN_COPIER = |
50 |
| - TypeUtils.parseType("org.springframework.cglib.beans.BeanCopier"); |
51 |
| - private static final Signature COPY = |
52 |
| - new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER }); |
53 |
| - private static final Signature CONVERT = |
54 |
| - TypeUtils.parseSignature("Object convert(Object, Class, Object)"); |
55 |
| - |
56 |
| - interface BeanCopierKey { |
57 |
| - public Object newInstance(String source, String target, boolean useConverter); |
58 |
| - } |
59 |
| - |
60 |
| - public static BeanCopier create(Class source, Class target, boolean useConverter) { |
61 |
| - Generator gen = new Generator(); |
62 |
| - gen.setSource(source); |
63 |
| - gen.setTarget(target); |
64 |
| - gen.setUseConverter(useConverter); |
65 |
| - return gen.create(); |
66 |
| - } |
67 |
| - |
68 |
| - abstract public void copy(Object from, Object to, Converter converter); |
69 |
| - |
70 |
| - public static class Generator extends AbstractClassGenerator { |
71 |
| - private static final Source SOURCE = new Source(BeanCopier.class.getName()); |
72 |
| - private Class source; |
73 |
| - private Class target; |
74 |
| - private boolean useConverter; |
75 |
| - |
76 |
| - public Generator() { |
77 |
| - super(SOURCE); |
78 |
| - } |
79 |
| - |
80 |
| - public void setSource(Class source) { |
81 |
| - if(!Modifier.isPublic(source.getModifiers())){ |
82 |
| - setNamePrefix(source.getName()); |
83 |
| - } |
84 |
| - this.source = source; |
85 |
| - } |
86 |
| - |
87 |
| - public void setTarget(Class target) { |
88 |
| - if(!Modifier.isPublic(target.getModifiers())){ |
89 |
| - setNamePrefix(target.getName()); |
90 |
| - } |
91 |
| - this.target = target; |
| 44 | + private static final BeanCopierKey KEY_FACTORY = |
| 45 | + (BeanCopierKey)KeyFactory.create(BeanCopierKey.class); |
| 46 | + private static final Type CONVERTER = |
| 47 | + TypeUtils.parseType("org.springframework.cglib.core.Converter"); |
| 48 | + private static final Type BEAN_COPIER = |
| 49 | + TypeUtils.parseType("org.springframework.cglib.beans.BeanCopier"); |
| 50 | + private static final Signature COPY = |
| 51 | + new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER }); |
| 52 | + private static final Signature CONVERT = |
| 53 | + TypeUtils.parseSignature("Object convert(Object, Class, Object)"); |
| 54 | + |
| 55 | + interface BeanCopierKey { |
| 56 | + public Object newInstance(String source, String target, boolean useConverter); |
| 57 | + } |
| 58 | + |
| 59 | + public static BeanCopier create(Class source, Class target, boolean useConverter) { |
| 60 | + Generator gen = new Generator(); |
| 61 | + gen.setSource(source); |
| 62 | + gen.setTarget(target); |
| 63 | + gen.setUseConverter(useConverter); |
| 64 | + return gen.create(); |
| 65 | + } |
| 66 | + |
| 67 | + abstract public void copy(Object from, Object to, Converter converter); |
| 68 | + |
| 69 | + public static class Generator extends AbstractClassGenerator { |
| 70 | + private static final Source SOURCE = new Source(BeanCopier.class.getName()); |
| 71 | + private Class source; |
| 72 | + private Class target; |
| 73 | + private boolean useConverter; |
| 74 | + |
| 75 | + public Generator() { |
| 76 | + super(SOURCE); |
| 77 | + } |
| 78 | + |
| 79 | + public void setSource(Class source) { |
| 80 | + this.source = source; |
| 81 | + // SPRING PATCH BEGIN |
| 82 | + setContextClass(source); |
| 83 | + setNamePrefix(source.getName()); |
| 84 | + // SPRING PATCH END |
| 85 | + } |
| 86 | + |
| 87 | + public void setTarget(Class target) { |
| 88 | + this.target = target; |
92 | 89 | // SPRING PATCH BEGIN
|
93 | 90 | setContextClass(target);
|
| 91 | + setNamePrefix(target.getName()); |
94 | 92 | // SPRING PATCH END
|
95 |
| - } |
| 93 | + } |
96 | 94 |
|
97 |
| - public void setUseConverter(boolean useConverter) { |
98 |
| - this.useConverter = useConverter; |
99 |
| - } |
| 95 | + public void setUseConverter(boolean useConverter) { |
| 96 | + this.useConverter = useConverter; |
| 97 | + } |
100 | 98 |
|
101 |
| - @Override |
| 99 | + @Override |
102 | 100 | protected ClassLoader getDefaultClassLoader() {
|
103 |
| - return source.getClassLoader(); |
104 |
| - } |
| 101 | + return source.getClassLoader(); |
| 102 | + } |
105 | 103 |
|
106 |
| - @Override |
| 104 | + @Override |
107 | 105 | protected ProtectionDomain getProtectionDomain() {
|
108 |
| - return ReflectUtils.getProtectionDomain(source); |
109 |
| - } |
| 106 | + return ReflectUtils.getProtectionDomain(source); |
| 107 | + } |
110 | 108 |
|
111 |
| - public BeanCopier create() { |
112 |
| - Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter); |
113 |
| - return (BeanCopier)super.create(key); |
114 |
| - } |
| 109 | + public BeanCopier create() { |
| 110 | + Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter); |
| 111 | + return (BeanCopier)super.create(key); |
| 112 | + } |
115 | 113 |
|
116 |
| - @Override |
| 114 | + @Override |
117 | 115 | public void generateClass(ClassVisitor v) {
|
118 |
| - Type sourceType = Type.getType(source); |
119 |
| - Type targetType = Type.getType(target); |
120 |
| - ClassEmitter ce = new ClassEmitter(v); |
121 |
| - ce.begin_class(Constants.V1_8, |
122 |
| - Constants.ACC_PUBLIC, |
123 |
| - getClassName(), |
124 |
| - BEAN_COPIER, |
125 |
| - null, |
126 |
| - Constants.SOURCE_FILE); |
127 |
| - |
128 |
| - EmitUtils.null_constructor(ce); |
129 |
| - CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null); |
130 |
| - PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source); |
131 |
| - PropertyDescriptor[] setters = ReflectUtils.getBeanSetters(target); |
132 |
| - |
133 |
| - Map names = new HashMap(); |
134 |
| - for (PropertyDescriptor getter : getters) { |
135 |
| - names.put(getter.getName(), getter); |
136 |
| - } |
137 |
| - Local targetLocal = e.make_local(); |
138 |
| - Local sourceLocal = e.make_local(); |
139 |
| - if (useConverter) { |
140 |
| - e.load_arg(1); |
141 |
| - e.checkcast(targetType); |
142 |
| - e.store_local(targetLocal); |
143 |
| - e.load_arg(0); |
144 |
| - e.checkcast(sourceType); |
145 |
| - e.store_local(sourceLocal); |
146 |
| - } else { |
147 |
| - e.load_arg(1); |
148 |
| - e.checkcast(targetType); |
149 |
| - e.load_arg(0); |
150 |
| - e.checkcast(sourceType); |
151 |
| - } |
152 |
| - for (PropertyDescriptor setter : setters) { |
153 |
| - PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName()); |
154 |
| - if (getter != null) { |
155 |
| - MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod()); |
156 |
| - MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod()); |
157 |
| - if (useConverter) { |
158 |
| - Type setterType = write.getSignature().getArgumentTypes()[0]; |
159 |
| - e.load_local(targetLocal); |
160 |
| - e.load_arg(2); |
161 |
| - e.load_local(sourceLocal); |
162 |
| - e.invoke(read); |
163 |
| - e.box(read.getSignature().getReturnType()); |
164 |
| - EmitUtils.load_class(e, setterType); |
165 |
| - e.push(write.getSignature().getName()); |
166 |
| - e.invoke_interface(CONVERTER, CONVERT); |
167 |
| - e.unbox_or_zero(setterType); |
168 |
| - e.invoke(write); |
169 |
| - } else if (compatible(getter, setter)) { |
170 |
| - e.dup2(); |
171 |
| - e.invoke(read); |
172 |
| - e.invoke(write); |
173 |
| - } |
174 |
| - } |
175 |
| - } |
176 |
| - e.return_value(); |
177 |
| - e.end_method(); |
178 |
| - ce.end_class(); |
179 |
| - } |
180 |
| - |
181 |
| - private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) { |
182 |
| - // TODO: allow automatic widening conversions? |
183 |
| - return setter.getPropertyType().isAssignableFrom(getter.getPropertyType()); |
184 |
| - } |
185 |
| - |
186 |
| - @Override |
| 116 | + Type sourceType = Type.getType(source); |
| 117 | + Type targetType = Type.getType(target); |
| 118 | + ClassEmitter ce = new ClassEmitter(v); |
| 119 | + ce.begin_class(Constants.V1_8, |
| 120 | + Constants.ACC_PUBLIC, |
| 121 | + getClassName(), |
| 122 | + BEAN_COPIER, |
| 123 | + null, |
| 124 | + Constants.SOURCE_FILE); |
| 125 | + |
| 126 | + EmitUtils.null_constructor(ce); |
| 127 | + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null); |
| 128 | + PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source); |
| 129 | + PropertyDescriptor[] setters = ReflectUtils.getBeanSetters(target); |
| 130 | + |
| 131 | + Map names = new HashMap(); |
| 132 | + for (PropertyDescriptor getter : getters) { |
| 133 | + names.put(getter.getName(), getter); |
| 134 | + } |
| 135 | + Local targetLocal = e.make_local(); |
| 136 | + Local sourceLocal = e.make_local(); |
| 137 | + if (useConverter) { |
| 138 | + e.load_arg(1); |
| 139 | + e.checkcast(targetType); |
| 140 | + e.store_local(targetLocal); |
| 141 | + e.load_arg(0); |
| 142 | + e.checkcast(sourceType); |
| 143 | + e.store_local(sourceLocal); |
| 144 | + } else { |
| 145 | + e.load_arg(1); |
| 146 | + e.checkcast(targetType); |
| 147 | + e.load_arg(0); |
| 148 | + e.checkcast(sourceType); |
| 149 | + } |
| 150 | + for (PropertyDescriptor setter : setters) { |
| 151 | + PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName()); |
| 152 | + if (getter != null) { |
| 153 | + MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod()); |
| 154 | + MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod()); |
| 155 | + if (useConverter) { |
| 156 | + Type setterType = write.getSignature().getArgumentTypes()[0]; |
| 157 | + e.load_local(targetLocal); |
| 158 | + e.load_arg(2); |
| 159 | + e.load_local(sourceLocal); |
| 160 | + e.invoke(read); |
| 161 | + e.box(read.getSignature().getReturnType()); |
| 162 | + EmitUtils.load_class(e, setterType); |
| 163 | + e.push(write.getSignature().getName()); |
| 164 | + e.invoke_interface(CONVERTER, CONVERT); |
| 165 | + e.unbox_or_zero(setterType); |
| 166 | + e.invoke(write); |
| 167 | + } else if (compatible(getter, setter)) { |
| 168 | + e.dup2(); |
| 169 | + e.invoke(read); |
| 170 | + e.invoke(write); |
| 171 | + } |
| 172 | + } |
| 173 | + } |
| 174 | + e.return_value(); |
| 175 | + e.end_method(); |
| 176 | + ce.end_class(); |
| 177 | + } |
| 178 | + |
| 179 | + private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) { |
| 180 | + // TODO: allow automatic widening conversions? |
| 181 | + return setter.getPropertyType().isAssignableFrom(getter.getPropertyType()); |
| 182 | + } |
| 183 | + |
| 184 | + @Override |
187 | 185 | protected Object firstInstance(Class type) {
|
188 |
| - return ReflectUtils.newInstance(type); |
189 |
| - } |
| 186 | + return ReflectUtils.newInstance(type); |
| 187 | + } |
190 | 188 |
|
191 |
| - @Override |
| 189 | + @Override |
192 | 190 | protected Object nextInstance(Object instance) {
|
193 |
| - return instance; |
194 |
| - } |
195 |
| - } |
| 191 | + return instance; |
| 192 | + } |
| 193 | + } |
196 | 194 | }
|
0 commit comments