From 2dc4fe0857b4001a45063d98651bbe979172333d Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 15 Oct 2023 16:09:17 +0200 Subject: [PATCH] BeanCopier sets name prefix for public classes as well Includes consistent formatting of Spring-patched files. Closes gh-28699 (cherry picked from commit 7a60e2024b1d99ed07613b184279f24d2d9d63e7) --- .../cglib/beans/BeanCopier.java | 279 +++++----- .../cglib/beans/BeanGenerator.java | 225 ++++---- .../springframework/cglib/beans/BeanMap.java | 513 +++++++++--------- .../cglib/beans/BeanMapEmitter.java | 45 +- .../springframework/cglib/beans/BulkBean.java | 202 +++---- .../cglib/beans/BulkBeanEmitter.java | 16 +- .../cglib/beans/BulkBeanException.java | 7 +- .../cglib/beans/FixedKeySet.java | 13 +- .../cglib/beans/ImmutableBean.java | 180 +++--- 9 files changed, 791 insertions(+), 689 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/BeanCopier.java b/spring-core/src/main/java/org/springframework/cglib/beans/BeanCopier.java index 30a00e8d1d..52b94fd5d8 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/BeanCopier.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/BeanCopier.java @@ -16,12 +16,24 @@ package org.springframework.cglib.beans; import java.beans.PropertyDescriptor; -import java.lang.reflect.*; import java.security.ProtectionDomain; -import org.springframework.cglib.core.*; +import java.util.HashMap; +import java.util.Map; + import org.springframework.asm.ClassVisitor; import org.springframework.asm.Type; -import java.util.*; +import org.springframework.cglib.core.AbstractClassGenerator; +import org.springframework.cglib.core.ClassEmitter; +import org.springframework.cglib.core.CodeEmitter; +import org.springframework.cglib.core.Constants; +import org.springframework.cglib.core.Converter; +import org.springframework.cglib.core.EmitUtils; +import org.springframework.cglib.core.KeyFactory; +import org.springframework.cglib.core.Local; +import org.springframework.cglib.core.MethodInfo; +import org.springframework.cglib.core.ReflectUtils; +import org.springframework.cglib.core.Signature; +import org.springframework.cglib.core.TypeUtils; /** * @author Chris Nokleberg @@ -29,151 +41,154 @@ import java.util.*; @SuppressWarnings({"rawtypes", "unchecked"}) abstract public class BeanCopier { - private static final BeanCopierKey KEY_FACTORY = - (BeanCopierKey)KeyFactory.create(BeanCopierKey.class); - private static final Type CONVERTER = - TypeUtils.parseType("org.springframework.cglib.core.Converter"); - private static final Type BEAN_COPIER = - TypeUtils.parseType("org.springframework.cglib.beans.BeanCopier"); - private static final Signature COPY = - new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER }); - private static final Signature CONVERT = - TypeUtils.parseSignature("Object convert(Object, Class, Object)"); - - interface BeanCopierKey { - public Object newInstance(String source, String target, boolean useConverter); - } + private static final BeanCopierKey KEY_FACTORY = + (BeanCopierKey)KeyFactory.create(BeanCopierKey.class); + private static final Type CONVERTER = + TypeUtils.parseType("org.springframework.cglib.core.Converter"); + private static final Type BEAN_COPIER = + TypeUtils.parseType("org.springframework.cglib.beans.BeanCopier"); + private static final Signature COPY = + new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER }); + private static final Signature CONVERT = + TypeUtils.parseSignature("Object convert(Object, Class, Object)"); - public static BeanCopier create(Class source, Class target, boolean useConverter) { - Generator gen = new Generator(); - gen.setSource(source); - gen.setTarget(target); - gen.setUseConverter(useConverter); - return gen.create(); - } + interface BeanCopierKey { + public Object newInstance(String source, String target, boolean useConverter); + } - abstract public void copy(Object from, Object to, Converter converter); + public static BeanCopier create(Class source, Class target, boolean useConverter) { + Generator gen = new Generator(); + gen.setSource(source); + gen.setTarget(target); + gen.setUseConverter(useConverter); + return gen.create(); + } - public static class Generator extends AbstractClassGenerator { - private static final Source SOURCE = new Source(BeanCopier.class.getName()); - private Class source; - private Class target; - private boolean useConverter; + abstract public void copy(Object from, Object to, Converter converter); - public Generator() { - super(SOURCE); - } + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(BeanCopier.class.getName()); + private Class source; + private Class target; + private boolean useConverter; - public void setSource(Class source) { - if(!Modifier.isPublic(source.getModifiers())){ - setNamePrefix(source.getName()); - } - this.source = source; - } - - public void setTarget(Class target) { - if(!Modifier.isPublic(target.getModifiers())){ - setNamePrefix(target.getName()); - } - this.target = target; + public Generator() { + super(SOURCE); + } + + public void setSource(Class source) { + this.source = source; + // SPRING PATCH BEGIN + setContextClass(source); + setNamePrefix(source.getName()); + // SPRING PATCH END + } + + public void setTarget(Class target) { + this.target = target; // SPRING PATCH BEGIN setContextClass(target); + setNamePrefix(target.getName()); // SPRING PATCH END - } + } - public void setUseConverter(boolean useConverter) { - this.useConverter = useConverter; - } + public void setUseConverter(boolean useConverter) { + this.useConverter = useConverter; + } - protected ClassLoader getDefaultClassLoader() { - return source.getClassLoader(); - } + @Override + protected ClassLoader getDefaultClassLoader() { + return source.getClassLoader(); + } - protected ProtectionDomain getProtectionDomain() { - return ReflectUtils.getProtectionDomain(source); - } + @Override + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(source); + } - public BeanCopier create() { - Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter); - return (BeanCopier)super.create(key); - } + public BeanCopier create() { + Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter); + return (BeanCopier)super.create(key); + } - public void generateClass(ClassVisitor v) { - Type sourceType = Type.getType(source); - Type targetType = Type.getType(target); - ClassEmitter ce = new ClassEmitter(v); - ce.begin_class(Constants.V1_8, - Constants.ACC_PUBLIC, - getClassName(), - BEAN_COPIER, - null, - Constants.SOURCE_FILE); + @Override + public void generateClass(ClassVisitor v) { + Type sourceType = Type.getType(source); + Type targetType = Type.getType(target); + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_8, + Constants.ACC_PUBLIC, + getClassName(), + BEAN_COPIER, + null, + Constants.SOURCE_FILE); - EmitUtils.null_constructor(ce); - CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null); - PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source); - PropertyDescriptor[] setters = ReflectUtils.getBeanSetters(target); + EmitUtils.null_constructor(ce); + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null); + PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source); + PropertyDescriptor[] setters = ReflectUtils.getBeanSetters(target); - Map names = new HashMap(); - for (int i = 0; i < getters.length; i++) { - names.put(getters[i].getName(), getters[i]); - } - Local targetLocal = e.make_local(); - Local sourceLocal = e.make_local(); - if (useConverter) { - e.load_arg(1); - e.checkcast(targetType); - e.store_local(targetLocal); - e.load_arg(0); - e.checkcast(sourceType); - e.store_local(sourceLocal); - } else { - e.load_arg(1); - e.checkcast(targetType); - e.load_arg(0); - e.checkcast(sourceType); - } - for (int i = 0; i < setters.length; i++) { - PropertyDescriptor setter = setters[i]; - PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName()); - if (getter != null) { - MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod()); - MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod()); - if (useConverter) { - Type setterType = write.getSignature().getArgumentTypes()[0]; - e.load_local(targetLocal); - e.load_arg(2); - e.load_local(sourceLocal); - e.invoke(read); - e.box(read.getSignature().getReturnType()); - EmitUtils.load_class(e, setterType); - e.push(write.getSignature().getName()); - e.invoke_interface(CONVERTER, CONVERT); - e.unbox_or_zero(setterType); - e.invoke(write); - } else if (compatible(getter, setter)) { - e.dup2(); - e.invoke(read); - e.invoke(write); - } - } - } - e.return_value(); - e.end_method(); - ce.end_class(); - } + Map names = new HashMap(); + for (PropertyDescriptor getter : getters) { + names.put(getter.getName(), getter); + } + Local targetLocal = e.make_local(); + Local sourceLocal = e.make_local(); + if (useConverter) { + e.load_arg(1); + e.checkcast(targetType); + e.store_local(targetLocal); + e.load_arg(0); + e.checkcast(sourceType); + e.store_local(sourceLocal); + } else { + e.load_arg(1); + e.checkcast(targetType); + e.load_arg(0); + e.checkcast(sourceType); + } + for (PropertyDescriptor setter : setters) { + PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName()); + if (getter != null) { + MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod()); + MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod()); + if (useConverter) { + Type setterType = write.getSignature().getArgumentTypes()[0]; + e.load_local(targetLocal); + e.load_arg(2); + e.load_local(sourceLocal); + e.invoke(read); + e.box(read.getSignature().getReturnType()); + EmitUtils.load_class(e, setterType); + e.push(write.getSignature().getName()); + e.invoke_interface(CONVERTER, CONVERT); + e.unbox_or_zero(setterType); + e.invoke(write); + } else if (compatible(getter, setter)) { + e.dup2(); + e.invoke(read); + e.invoke(write); + } + } + } + e.return_value(); + e.end_method(); + ce.end_class(); + } - private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) { - // TODO: allow automatic widening conversions? - return setter.getPropertyType().isAssignableFrom(getter.getPropertyType()); - } + private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) { + // TODO: allow automatic widening conversions? + return setter.getPropertyType().isAssignableFrom(getter.getPropertyType()); + } - protected Object firstInstance(Class type) { - return ReflectUtils.newInstance(type); - } + @Override + protected Object firstInstance(Class type) { + return ReflectUtils.newInstance(type); + } - protected Object nextInstance(Object instance) { - return instance; - } - } + @Override + protected Object nextInstance(Object instance) { + return instance; + } + } } diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/BeanGenerator.java b/spring-core/src/main/java/org/springframework/cglib/beans/BeanGenerator.java index d4f5e7af9a..f303350f7d 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/BeanGenerator.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/BeanGenerator.java @@ -17,10 +17,18 @@ package org.springframework.cglib.beans; import java.beans.PropertyDescriptor; import java.security.ProtectionDomain; -import java.util.*; -import org.springframework.cglib.core.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + import org.springframework.asm.ClassVisitor; import org.springframework.asm.Type; +import org.springframework.cglib.core.AbstractClassGenerator; +import org.springframework.cglib.core.ClassEmitter; +import org.springframework.cglib.core.Constants; +import org.springframework.cglib.core.EmitUtils; +import org.springframework.cglib.core.KeyFactory; +import org.springframework.cglib.core.ReflectUtils; /** * @author Juozas Baliuka, Chris Nokleberg @@ -28,126 +36,131 @@ import org.springframework.asm.Type; @SuppressWarnings({"rawtypes", "unchecked"}) public class BeanGenerator extends AbstractClassGenerator { - private static final Source SOURCE = new Source(BeanGenerator.class.getName()); - private static final BeanGeneratorKey KEY_FACTORY = - (BeanGeneratorKey)KeyFactory.create(BeanGeneratorKey.class); - - interface BeanGeneratorKey { - public Object newInstance(String superclass, Map props); - } + private static final Source SOURCE = new Source(BeanGenerator.class.getName()); + private static final BeanGeneratorKey KEY_FACTORY = + (BeanGeneratorKey)KeyFactory.create(BeanGeneratorKey.class); - private Class superclass; - private Map props = new HashMap(); - private boolean classOnly; + interface BeanGeneratorKey { + public Object newInstance(String superclass, Map props); + } - public BeanGenerator() { - super(SOURCE); - } + private Class superclass; + private Map props = new HashMap(); + private boolean classOnly; - /** - * Set the class which the generated class will extend. The class - * must not be declared as final, and must have a non-private - * no-argument constructor. - * @param superclass class to extend, or null to extend Object - */ - public void setSuperclass(Class superclass) { - if (superclass != null && superclass.equals(Object.class)) { - superclass = null; - } - this.superclass = superclass; + public BeanGenerator() { + super(SOURCE); + } + + /** + * Set the class which the generated class will extend. The class + * must not be declared as final, and must have a non-private + * no-argument constructor. + * @param superclass class to extend, or null to extend Object + */ + public void setSuperclass(Class superclass) { + if (superclass != null && superclass.equals(Object.class)) { + superclass = null; + } + this.superclass = superclass; // SPRING PATCH BEGIN setContextClass(superclass); // SPRING PATCH END - } + } - public void addProperty(String name, Class type) { - if (props.containsKey(name)) { - throw new IllegalArgumentException("Duplicate property name \"" + name + "\""); - } - props.put(name, Type.getType(type)); - } + public void addProperty(String name, Class type) { + if (props.containsKey(name)) { + throw new IllegalArgumentException("Duplicate property name \"" + name + "\""); + } + props.put(name, Type.getType(type)); + } - protected ClassLoader getDefaultClassLoader() { - if (superclass != null) { - return superclass.getClassLoader(); - } else { - return null; - } - } + @Override + protected ClassLoader getDefaultClassLoader() { + if (superclass != null) { + return superclass.getClassLoader(); + } else { + return null; + } + } - protected ProtectionDomain getProtectionDomain() { - return ReflectUtils.getProtectionDomain(superclass); - } + @Override + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(superclass); + } - public Object create() { - classOnly = false; - return createHelper(); - } + public Object create() { + classOnly = false; + return createHelper(); + } - public Object createClass() { - classOnly = true; - return createHelper(); - } + public Object createClass() { + classOnly = true; + return createHelper(); + } - private Object createHelper() { - if (superclass != null) { - setNamePrefix(superclass.getName()); - } - String superName = (superclass != null) ? superclass.getName() : "java.lang.Object"; - Object key = KEY_FACTORY.newInstance(superName, props); - return super.create(key); - } + private Object createHelper() { + if (superclass != null) { + setNamePrefix(superclass.getName()); + } + String superName = (superclass != null) ? superclass.getName() : "java.lang.Object"; + Object key = KEY_FACTORY.newInstance(superName, props); + return super.create(key); + } - public void generateClass(ClassVisitor v) throws Exception { - int size = props.size(); - String[] names = (String[])props.keySet().toArray(new String[size]); - Type[] types = new Type[size]; - for (int i = 0; i < size; i++) { - types[i] = (Type)props.get(names[i]); - } - ClassEmitter ce = new ClassEmitter(v); - ce.begin_class(Constants.V1_8, - Constants.ACC_PUBLIC, - getClassName(), - superclass != null ? Type.getType(superclass) : Constants.TYPE_OBJECT, - null, - null); - EmitUtils.null_constructor(ce); - EmitUtils.add_properties(ce, names, types); - ce.end_class(); - } + @Override + public void generateClass(ClassVisitor v) throws Exception { + int size = props.size(); + String[] names = (String[])props.keySet().toArray(new String[size]); + Type[] types = new Type[size]; + for (int i = 0; i < size; i++) { + types[i] = (Type)props.get(names[i]); + } + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_8, + Constants.ACC_PUBLIC, + getClassName(), + superclass != null ? Type.getType(superclass) : Constants.TYPE_OBJECT, + null, + null); + EmitUtils.null_constructor(ce); + EmitUtils.add_properties(ce, names, types); + ce.end_class(); + } - protected Object firstInstance(Class type) { - if (classOnly) { - return type; - } else { - return ReflectUtils.newInstance(type); - } - } + @Override + protected Object firstInstance(Class type) { + if (classOnly) { + return type; + } else { + return ReflectUtils.newInstance(type); + } + } - protected Object nextInstance(Object instance) { - Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass(); - if (classOnly) { - return protoclass; - } else { - return ReflectUtils.newInstance(protoclass); - } - } + @Override + protected Object nextInstance(Object instance) { + Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass(); + if (classOnly) { + return protoclass; + } else { + return ReflectUtils.newInstance(protoclass); + } + } - public static void addProperties(BeanGenerator gen, Map props) { - for (Iterator it = props.keySet().iterator(); it.hasNext();) { - String name = (String)it.next(); - gen.addProperty(name, (Class)props.get(name)); - } - } + public static void addProperties(BeanGenerator gen, Map props) { + for (Iterator it = props.keySet().iterator(); it.hasNext();) { + String name = (String)it.next(); + gen.addProperty(name, (Class)props.get(name)); + } + } - public static void addProperties(BeanGenerator gen, Class type) { - addProperties(gen, ReflectUtils.getBeanProperties(type)); - } + public static void addProperties(BeanGenerator gen, Class type) { + addProperties(gen, ReflectUtils.getBeanProperties(type)); + } - public static void addProperties(BeanGenerator gen, PropertyDescriptor[] descriptors) { - for (int i = 0; i < descriptors.length; i++) { - gen.addProperty(descriptors[i].getName(), descriptors[i].getPropertyType()); - } - } + public static void addProperties(BeanGenerator gen, PropertyDescriptor[] descriptors) { + for (PropertyDescriptor descriptor : descriptors) { + gen.addProperty(descriptor.getName(), descriptor.getPropertyType()); + } + } } diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/BeanMap.java b/spring-core/src/main/java/org/springframework/cglib/beans/BeanMap.java index f73e7e34fb..9a7dbf68b5 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/BeanMap.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/BeanMap.java @@ -41,293 +41,310 @@ import org.springframework.cglib.core.ReflectUtils; */ @SuppressWarnings({"rawtypes", "unchecked"}) abstract public class BeanMap implements Map { - /** - * Limit the properties reflected in the key set of the map - * to readable properties. - * @see BeanMap.Generator#setRequire - */ - public static final int REQUIRE_GETTER = 1; + /** + * Limit the properties reflected in the key set of the map + * to readable properties. + * @see BeanMap.Generator#setRequire + */ + public static final int REQUIRE_GETTER = 1; - /** - * Limit the properties reflected in the key set of the map - * to writable properties. - * @see BeanMap.Generator#setRequire - */ - public static final int REQUIRE_SETTER = 2; - - /** - * Helper method to create a new BeanMap. For finer - * control over the generated instance, use a new instance of - * BeanMap.Generator instead of this static method. - * @param bean the JavaBean underlying the map - * @return a new BeanMap instance - */ - public static BeanMap create(Object bean) { - Generator gen = new Generator(); - gen.setBean(bean); - return gen.create(); - } + /** + * Limit the properties reflected in the key set of the map + * to writable properties. + * @see BeanMap.Generator#setRequire + */ + public static final int REQUIRE_SETTER = 2; - public static class Generator extends AbstractClassGenerator { - private static final Source SOURCE = new Source(BeanMap.class.getName()); + /** + * Helper method to create a new BeanMap. For finer + * control over the generated instance, use a new instance of + * BeanMap.Generator instead of this static method. + * @param bean the JavaBean underlying the map + * @return a new BeanMap instance + */ + public static BeanMap create(Object bean) { + Generator gen = new Generator(); + gen.setBean(bean); + return gen.create(); + } - private static final BeanMapKey KEY_FACTORY = - (BeanMapKey)KeyFactory.create(BeanMapKey.class, KeyFactory.CLASS_BY_NAME); + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(BeanMap.class.getName()); - interface BeanMapKey { - public Object newInstance(Class type, int require); - } - - private Object bean; - private Class beanClass; - private int require; - - public Generator() { - super(SOURCE); - } + private static final BeanMapKey KEY_FACTORY = + (BeanMapKey)KeyFactory.create(BeanMapKey.class, KeyFactory.CLASS_BY_NAME); - /** - * Set the bean that the generated map should reflect. The bean may be swapped - * out for another bean of the same type using {@link #setBean}. - * Calling this method overrides any value previously set using {@link #setBeanClass}. - * You must call either this method or {@link #setBeanClass} before {@link #create}. - * @param bean the initial bean - */ - public void setBean(Object bean) { - this.bean = bean; - if (bean != null) { + interface BeanMapKey { + public Object newInstance(Class type, int require); + } + + private Object bean; + private Class beanClass; + private int require; + + public Generator() { + super(SOURCE); + } + + /** + * Set the bean that the generated map should reflect. The bean may be swapped + * out for another bean of the same type using {@link #setBean}. + * Calling this method overrides any value previously set using {@link #setBeanClass}. + * You must call either this method or {@link #setBeanClass} before {@link #create}. + * @param bean the initial bean + */ + public void setBean(Object bean) { + this.bean = bean; + if (bean != null) { beanClass = bean.getClass(); // SPRING PATCH BEGIN setContextClass(beanClass); // SPRING PATCH END } - } + } - /** - * Set the class of the bean that the generated map should support. - * You must call either this method or {@link #setBeanClass} before {@link #create}. - * @param beanClass the class of the bean - */ - public void setBeanClass(Class beanClass) { - this.beanClass = beanClass; - } + /** + * Set the class of the bean that the generated map should support. + * You must call either this method or {@link #setBeanClass} before {@link #create}. + * @param beanClass the class of the bean + */ + public void setBeanClass(Class beanClass) { + this.beanClass = beanClass; + } - /** - * Limit the properties reflected by the generated map. - * @param require any combination of {@link #REQUIRE_GETTER} and - * {@link #REQUIRE_SETTER}; default is zero (any property allowed) - */ - public void setRequire(int require) { - this.require = require; - } + /** + * Limit the properties reflected by the generated map. + * @param require any combination of {@link #REQUIRE_GETTER} and + * {@link #REQUIRE_SETTER}; default is zero (any property allowed) + */ + public void setRequire(int require) { + this.require = require; + } - protected ClassLoader getDefaultClassLoader() { - return beanClass.getClassLoader(); - } + @Override + protected ClassLoader getDefaultClassLoader() { + return beanClass.getClassLoader(); + } - protected ProtectionDomain getProtectionDomain() { - return ReflectUtils.getProtectionDomain(beanClass); - } + @Override + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(beanClass); + } - /** - * Create a new instance of the BeanMap. An existing - * generated class will be reused if possible. - */ - public BeanMap create() { - if (beanClass == null) - throw new IllegalArgumentException("Class of bean unknown"); - setNamePrefix(beanClass.getName()); - return (BeanMap)super.create(KEY_FACTORY.newInstance(beanClass, require)); - } + /** + * Create a new instance of the BeanMap. An existing + * generated class will be reused if possible. + */ + public BeanMap create() { + if (beanClass == null) { + throw new IllegalArgumentException("Class of bean unknown"); + } + setNamePrefix(beanClass.getName()); + return (BeanMap)super.create(KEY_FACTORY.newInstance(beanClass, require)); + } - public void generateClass(ClassVisitor v) throws Exception { - new BeanMapEmitter(v, getClassName(), beanClass, require); - } + @Override + public void generateClass(ClassVisitor v) throws Exception { + new BeanMapEmitter(v, getClassName(), beanClass, require); + } - protected Object firstInstance(Class type) { - return ((BeanMap)ReflectUtils.newInstance(type)).newInstance(bean); - } + @Override + protected Object firstInstance(Class type) { + return ((BeanMap)ReflectUtils.newInstance(type)).newInstance(bean); + } - protected Object nextInstance(Object instance) { - return ((BeanMap)instance).newInstance(bean); - } - } + @Override + protected Object nextInstance(Object instance) { + return ((BeanMap)instance).newInstance(bean); + } + } - /** - * Create a new BeanMap instance using the specified bean. - * This is faster than using the {@link #create} static method. - * @param bean the JavaBean underlying the map - * @return a new BeanMap instance - */ - abstract public BeanMap newInstance(Object bean); + /** + * Create a new BeanMap instance using the specified bean. + * This is faster than using the {@link #create} static method. + * @param bean the JavaBean underlying the map + * @return a new BeanMap instance + */ + abstract public BeanMap newInstance(Object bean); - /** - * Get the type of a property. - * @param name the name of the JavaBean property - * @return the type of the property, or null if the property does not exist - */ - abstract public Class getPropertyType(String name); + /** + * Get the type of a property. + * @param name the name of the JavaBean property + * @return the type of the property, or null if the property does not exist + */ + abstract public Class getPropertyType(String name); - protected Object bean; + protected Object bean; - protected BeanMap() { - } + protected BeanMap() { + } - protected BeanMap(Object bean) { - setBean(bean); - } + protected BeanMap(Object bean) { + setBean(bean); + } - public Object get(Object key) { - return get(bean, key); - } + @Override + public Object get(Object key) { + return get(bean, key); + } - public Object put(Object key, Object value) { - return put(bean, key, value); - } + @Override + public Object put(Object key, Object value) { + return put(bean, key, value); + } - /** - * Get the property of a bean. This allows a BeanMap - * to be used statically for multiple beans--the bean instance tied to the - * map is ignored and the bean passed to this method is used instead. - * @param bean the bean to query; must be compatible with the type of - * this BeanMap - * @param key must be a String - * @return the current value, or null if there is no matching property - */ - abstract public Object get(Object bean, Object key); + /** + * Get the property of a bean. This allows a BeanMap + * to be used statically for multiple beans--the bean instance tied to the + * map is ignored and the bean passed to this method is used instead. + * @param bean the bean to query; must be compatible with the type of + * this BeanMap + * @param key must be a String + * @return the current value, or null if there is no matching property + */ + abstract public Object get(Object bean, Object key); - /** - * Set the property of a bean. This allows a BeanMap - * to be used statically for multiple beans--the bean instance tied to the - * map is ignored and the bean passed to this method is used instead. - * @param key must be a String - * @return the old value, if there was one, or null - */ - abstract public Object put(Object bean, Object key, Object value); + /** + * Set the property of a bean. This allows a BeanMap + * to be used statically for multiple beans--the bean instance tied to the + * map is ignored and the bean passed to this method is used instead. + * @param key must be a String + * @return the old value, if there was one, or null + */ + abstract public Object put(Object bean, Object key, Object value); - /** - * Change the underlying bean this map should use. - * @param bean the new JavaBean - * @see #getBean - */ - public void setBean(Object bean) { - this.bean = bean; - } + /** + * Change the underlying bean this map should use. + * @param bean the new JavaBean + * @see #getBean + */ + public void setBean(Object bean) { + this.bean = bean; + } - /** - * Return the bean currently in use by this map. - * @return the current JavaBean - * @see #setBean - */ - public Object getBean() { - return bean; - } + /** + * Return the bean currently in use by this map. + * @return the current JavaBean + * @see #setBean + */ + public Object getBean() { + return bean; + } - public void clear() { - throw new UnsupportedOperationException(); - } + @Override + public void clear() { + throw new UnsupportedOperationException(); + } - public boolean containsKey(Object key) { - return keySet().contains(key); - } + @Override + public boolean containsKey(Object key) { + return keySet().contains(key); + } - public boolean containsValue(Object value) { - for (Iterator it = keySet().iterator(); it.hasNext();) { - Object v = get(it.next()); - if (((value == null) && (v == null)) || (value != null && value.equals(v))) - return true; - } - return false; - } + @Override + public boolean containsValue(Object value) { + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object v = get(it.next()); + if (((value == null) && (v == null)) || (value != null && value.equals(v))) { + return true; + } + } + return false; + } - public int size() { - return keySet().size(); - } + @Override + public int size() { + return keySet().size(); + } - public boolean isEmpty() { - return size() == 0; - } + @Override + public boolean isEmpty() { + return size() == 0; + } - public Object remove(Object key) { - throw new UnsupportedOperationException(); - } + @Override + public Object remove(Object key) { + throw new UnsupportedOperationException(); + } - public void putAll(Map t) { - for (Iterator it = t.keySet().iterator(); it.hasNext();) { - Object key = it.next(); - put(key, t.get(key)); - } - } + @Override + public void putAll(Map t) { + for (Object key : t.keySet()) { + put(key, t.get(key)); + } + } - public boolean equals(Object o) { - if (o == null || !(o instanceof Map)) { - return false; - } - Map other = (Map)o; - if (size() != other.size()) { - return false; - } - for (Iterator it = keySet().iterator(); it.hasNext();) { - Object key = it.next(); - if (!other.containsKey(key)) { - return false; - } - Object v1 = get(key); - Object v2 = other.get(key); - if (!((v1 == null) ? v2 == null : v1.equals(v2))) { - return false; - } - } - return true; - } + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof Map)) { + return false; + } + Map other = (Map)o; + if (size() != other.size()) { + return false; + } + for (Object key : keySet()) { + if (!other.containsKey(key)) { + return false; + } + Object v1 = get(key); + Object v2 = other.get(key); + if (!((v1 == null) ? v2 == null : v1.equals(v2))) { + return false; + } + } + return true; + } - public int hashCode() { - int code = 0; - for (Iterator it = keySet().iterator(); it.hasNext();) { - Object key = it.next(); - Object value = get(key); - code += ((key == null) ? 0 : key.hashCode()) ^ - ((value == null) ? 0 : value.hashCode()); - } - return code; - } + @Override + public int hashCode() { + int code = 0; + for (Object key : keySet()) { + Object value = get(key); + code += ((key == null) ? 0 : key.hashCode()) ^ + ((value == null) ? 0 : value.hashCode()); + } + return code; + } - // TODO: optimize - public Set entrySet() { - HashMap copy = new HashMap(); - for (Iterator it = keySet().iterator(); it.hasNext();) { - Object key = it.next(); - copy.put(key, get(key)); - } - return Collections.unmodifiableMap(copy).entrySet(); - } + // TODO: optimize + @Override + public Set entrySet() { + HashMap copy = new HashMap(); + for (Object key : keySet()) { + copy.put(key, get(key)); + } + return Collections.unmodifiableMap(copy).entrySet(); + } - public Collection values() { - Set keys = keySet(); - List values = new ArrayList(keys.size()); - for (Iterator it = keys.iterator(); it.hasNext();) { - values.add(get(it.next())); - } - return Collections.unmodifiableCollection(values); - } + @Override + public Collection values() { + Set keys = keySet(); + List values = new ArrayList(keys.size()); + for (Iterator it = keys.iterator(); it.hasNext();) { + values.add(get(it.next())); + } + return Collections.unmodifiableCollection(values); + } - /* - * @see java.util.AbstractMap#toString - */ - public String toString() - { - StringBuffer sb = new StringBuffer(); - sb.append('{'); - for (Iterator it = keySet().iterator(); it.hasNext();) { - Object key = it.next(); - sb.append(key); - sb.append('='); - sb.append(get(key)); - if (it.hasNext()) { - sb.append(", "); - } - } - sb.append('}'); - return sb.toString(); - } + /* + * @see java.util.AbstractMap#toString + */ + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append('{'); + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + sb.append(key); + sb.append('='); + sb.append(get(key)); + if (it.hasNext()) { + sb.append(", "); + } + } + sb.append('}'); + return sb.toString(); + } } diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/BeanMapEmitter.java b/spring-core/src/main/java/org/springframework/cglib/beans/BeanMapEmitter.java index 986aa02fd6..b1e3596f8f 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/BeanMapEmitter.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/BeanMapEmitter.java @@ -15,12 +15,23 @@ */ package org.springframework.cglib.beans; -import java.beans.*; -import java.util.*; -import org.springframework.cglib.core.*; +import java.beans.PropertyDescriptor; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + import org.springframework.asm.ClassVisitor; import org.springframework.asm.Label; import org.springframework.asm.Type; +import org.springframework.cglib.core.ClassEmitter; +import org.springframework.cglib.core.CodeEmitter; +import org.springframework.cglib.core.Constants; +import org.springframework.cglib.core.EmitUtils; +import org.springframework.cglib.core.MethodInfo; +import org.springframework.cglib.core.ObjectSwitchCallback; +import org.springframework.cglib.core.ReflectUtils; +import org.springframework.cglib.core.Signature; +import org.springframework.cglib.core.TypeUtils; @SuppressWarnings({"rawtypes", "unchecked"}) class BeanMapEmitter extends ClassEmitter { @@ -50,7 +61,7 @@ class BeanMapEmitter extends ClassEmitter { EmitUtils.null_constructor(this); EmitUtils.factory_method(this, NEW_INSTANCE); generateConstructor(); - + Map getters = makePropertyMap(ReflectUtils.getBeanGetters(type)); Map setters = makePropertyMap(ReflectUtils.getBeanSetters(type)); Map allProps = new HashMap(); @@ -79,8 +90,8 @@ class BeanMapEmitter extends ClassEmitter { private Map makePropertyMap(PropertyDescriptor[] props) { Map names = new HashMap(); - for (int i = 0; i < props.length; i++) { - names.put(props[i].getName(), props[i]); + for (PropertyDescriptor prop : props) { + names.put(prop.getName(), prop); } return names; } @@ -97,7 +108,7 @@ class BeanMapEmitter extends ClassEmitter { e.return_value(); e.end_method(); } - + private void generateGet(Class type, final Map getters) { final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null); e.load_arg(0); @@ -105,14 +116,16 @@ class BeanMapEmitter extends ClassEmitter { e.load_arg(1); e.checkcast(Constants.TYPE_STRING); EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { - public void processCase(Object key, Label end) { + @Override + public void processCase(Object key, Label end) { PropertyDescriptor pd = (PropertyDescriptor)getters.get(key); MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod()); e.invoke(method); e.box(method.getSignature().getReturnType()); e.return_value(); } - public void processDefault() { + @Override + public void processDefault() { e.aconst_null(); e.return_value(); } @@ -127,7 +140,8 @@ class BeanMapEmitter extends ClassEmitter { e.load_arg(1); e.checkcast(Constants.TYPE_STRING); EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { - public void processCase(Object key, Label end) { + @Override + public void processCase(Object key, Label end) { PropertyDescriptor pd = (PropertyDescriptor)setters.get(key); if (pd.getReadMethod() == null) { e.aconst_null(); @@ -144,7 +158,8 @@ class BeanMapEmitter extends ClassEmitter { e.invoke(write); e.return_value(); } - public void processDefault() { + @Override + public void processDefault() { // fall-through } }); @@ -152,7 +167,7 @@ class BeanMapEmitter extends ClassEmitter { e.return_value(); e.end_method(); } - + private void generateKeySet(String[] allNames) { // static initializer declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null); @@ -178,12 +193,14 @@ class BeanMapEmitter extends ClassEmitter { final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null); e.load_arg(0); EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { - public void processCase(Object key, Label end) { + @Override + public void processCase(Object key, Label end) { PropertyDescriptor pd = (PropertyDescriptor)allProps.get(key); EmitUtils.load_class(e, Type.getType(pd.getPropertyType())); e.return_value(); } - public void processDefault() { + @Override + public void processDefault() { e.aconst_null(); e.return_value(); } diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/BulkBean.java b/spring-core/src/main/java/org/springframework/cglib/beans/BulkBean.java index 7fdd702dbd..61ae4f076a 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/BulkBean.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/BulkBean.java @@ -16,8 +16,11 @@ package org.springframework.cglib.beans; import java.security.ProtectionDomain; -import org.springframework.cglib.core.*; + import org.springframework.asm.ClassVisitor; +import org.springframework.cglib.core.AbstractClassGenerator; +import org.springframework.cglib.core.KeyFactory; +import org.springframework.cglib.core.ReflectUtils; /** * @author Juozas Baliuka @@ -25,118 +28,123 @@ import org.springframework.asm.ClassVisitor; @SuppressWarnings({"rawtypes", "unchecked"}) abstract public class BulkBean { - private static final BulkBeanKey KEY_FACTORY = - (BulkBeanKey)KeyFactory.create(BulkBeanKey.class); - - interface BulkBeanKey { - public Object newInstance(String target, String[] getters, String[] setters, String[] types); - } - - protected Class target; - protected String[] getters, setters; - protected Class[] types; - - protected BulkBean() { } - - abstract public void getPropertyValues(Object bean, Object[] values); - abstract public void setPropertyValues(Object bean, Object[] values); + private static final BulkBeanKey KEY_FACTORY = + (BulkBeanKey)KeyFactory.create(BulkBeanKey.class); - public Object[] getPropertyValues(Object bean) { - Object[] values = new Object[getters.length]; - getPropertyValues(bean, values); - return values; - } - - public Class[] getPropertyTypes() { - return types.clone(); - } - - public String[] getGetters() { - return getters.clone(); - } - - public String[] getSetters() { - return setters.clone(); - } + interface BulkBeanKey { + public Object newInstance(String target, String[] getters, String[] setters, String[] types); + } - public static BulkBean create(Class target, String[] getters, String[] setters, Class[] types) { - Generator gen = new Generator(); - gen.setTarget(target); - gen.setGetters(getters); - gen.setSetters(setters); - gen.setTypes(types); - return gen.create(); - } + protected Class target; + protected String[] getters, setters; + protected Class[] types; - public static class Generator extends AbstractClassGenerator { - private static final Source SOURCE = new Source(BulkBean.class.getName()); - private Class target; - private String[] getters; - private String[] setters; - private Class[] types; + protected BulkBean() { } - public Generator() { - super(SOURCE); - } + abstract public void getPropertyValues(Object bean, Object[] values); + abstract public void setPropertyValues(Object bean, Object[] values); - public void setTarget(Class target) { - this.target = target; + public Object[] getPropertyValues(Object bean) { + Object[] values = new Object[getters.length]; + getPropertyValues(bean, values); + return values; + } + + public Class[] getPropertyTypes() { + return types.clone(); + } + + public String[] getGetters() { + return getters.clone(); + } + + public String[] getSetters() { + return setters.clone(); + } + + public static BulkBean create(Class target, String[] getters, String[] setters, Class[] types) { + Generator gen = new Generator(); + gen.setTarget(target); + gen.setGetters(getters); + gen.setSetters(setters); + gen.setTypes(types); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(BulkBean.class.getName()); + private Class target; + private String[] getters; + private String[] setters; + private Class[] types; + + public Generator() { + super(SOURCE); + } + + public void setTarget(Class target) { + this.target = target; // SPRING PATCH BEGIN setContextClass(target); // SPRING PATCH END - } + } - public void setGetters(String[] getters) { - this.getters = getters; - } + public void setGetters(String[] getters) { + this.getters = getters; + } - public void setSetters(String[] setters) { - this.setters = setters; - } + public void setSetters(String[] setters) { + this.setters = setters; + } - public void setTypes(Class[] types) { - this.types = types; - } + public void setTypes(Class[] types) { + this.types = types; + } - protected ClassLoader getDefaultClassLoader() { - return target.getClassLoader(); - } + @Override + protected ClassLoader getDefaultClassLoader() { + return target.getClassLoader(); + } - protected ProtectionDomain getProtectionDomain() { - return ReflectUtils.getProtectionDomain(target); - } + @Override + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(target); + } - public BulkBean create() { - setNamePrefix(target.getName()); - String targetClassName = target.getName(); - String[] typeClassNames = ReflectUtils.getNames(types); - Object key = KEY_FACTORY.newInstance(targetClassName, getters, setters, typeClassNames); - return (BulkBean)super.create(key); - } + public BulkBean create() { + setNamePrefix(target.getName()); + String targetClassName = target.getName(); + String[] typeClassNames = ReflectUtils.getNames(types); + Object key = KEY_FACTORY.newInstance(targetClassName, getters, setters, typeClassNames); + return (BulkBean)super.create(key); + } - public void generateClass(ClassVisitor v) throws Exception { - new BulkBeanEmitter(v, getClassName(), target, getters, setters, types); - } + @Override + public void generateClass(ClassVisitor v) throws Exception { + new BulkBeanEmitter(v, getClassName(), target, getters, setters, types); + } - protected Object firstInstance(Class type) { - BulkBean instance = (BulkBean)ReflectUtils.newInstance(type); - instance.target = target; - - int length = getters.length; - instance.getters = new String[length]; - System.arraycopy(getters, 0, instance.getters, 0, length); - - instance.setters = new String[length]; - System.arraycopy(setters, 0, instance.setters, 0, length); - - instance.types = new Class[types.length]; - System.arraycopy(types, 0, instance.types, 0, types.length); + @Override + protected Object firstInstance(Class type) { + BulkBean instance = (BulkBean)ReflectUtils.newInstance(type); + instance.target = target; - return instance; - } + int length = getters.length; + instance.getters = new String[length]; + System.arraycopy(getters, 0, instance.getters, 0, length); - protected Object nextInstance(Object instance) { - return instance; - } - } + instance.setters = new String[length]; + System.arraycopy(setters, 0, instance.setters, 0, length); + + instance.types = new Class[types.length]; + System.arraycopy(types, 0, instance.types, 0, types.length); + + return instance; + } + + @Override + protected Object nextInstance(Object instance) { + return instance; + } + } } diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanEmitter.java b/spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanEmitter.java index 9502c3fa88..8a6198f4c5 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanEmitter.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanEmitter.java @@ -17,9 +17,19 @@ package org.springframework.cglib.beans; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.springframework.cglib.core.*; + import org.springframework.asm.ClassVisitor; import org.springframework.asm.Type; +import org.springframework.cglib.core.Block; +import org.springframework.cglib.core.ClassEmitter; +import org.springframework.cglib.core.CodeEmitter; +import org.springframework.cglib.core.Constants; +import org.springframework.cglib.core.EmitUtils; +import org.springframework.cglib.core.Local; +import org.springframework.cglib.core.MethodInfo; +import org.springframework.cglib.core.ReflectUtils; +import org.springframework.cglib.core.Signature; +import org.springframework.cglib.core.TypeUtils; @SuppressWarnings({"rawtypes", "unchecked"}) class BulkBeanEmitter extends ClassEmitter { @@ -33,7 +43,7 @@ class BulkBeanEmitter extends ClassEmitter { TypeUtils.parseType("org.springframework.cglib.beans.BulkBean"); private static final Type BULK_BEAN_EXCEPTION = TypeUtils.parseType("org.springframework.cglib.beans.BulkBeanException"); - + public BulkBeanEmitter(ClassVisitor v, String className, Class target, @@ -116,7 +126,7 @@ class BulkBeanEmitter extends ClassEmitter { } e.end_method(); } - + private static void validate(Class target, String[] getters, String[] setters, diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanException.java b/spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanException.java index 20887f9383..7325fdebee 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanException.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanException.java @@ -20,7 +20,7 @@ public class BulkBeanException extends RuntimeException { private int index; private Throwable cause; - + public BulkBeanException(String message, int index) { super(message); this.index = index; @@ -35,8 +35,9 @@ public class BulkBeanException extends RuntimeException public int getIndex() { return index; } - - public Throwable getCause() { + + @Override + public Throwable getCause() { return cause; } } diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/FixedKeySet.java b/spring-core/src/main/java/org/springframework/cglib/beans/FixedKeySet.java index 399da30ee5..92b32efe8c 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/FixedKeySet.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/FixedKeySet.java @@ -15,7 +15,12 @@ */ package org.springframework.cglib.beans; -import java.util.*; +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; @SuppressWarnings({"rawtypes", "unchecked"}) public /* need it for class loading */ class FixedKeySet extends AbstractSet { @@ -27,11 +32,13 @@ public /* need it for class loading */ class FixedKeySet extends AbstractSet { set = Collections.unmodifiableSet(new HashSet(Arrays.asList(keys))); } - public Iterator iterator() { + @Override + public Iterator iterator() { return set.iterator(); } - public int size() { + @Override + public int size() { return size; } } diff --git a/spring-core/src/main/java/org/springframework/cglib/beans/ImmutableBean.java b/spring-core/src/main/java/org/springframework/cglib/beans/ImmutableBean.java index dfc0359422..9c023394bd 100644 --- a/spring-core/src/main/java/org/springframework/cglib/beans/ImmutableBean.java +++ b/spring-core/src/main/java/org/springframework/cglib/beans/ImmutableBean.java @@ -18,115 +18,129 @@ package org.springframework.cglib.beans; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.security.ProtectionDomain; -import org.springframework.cglib.core.*; + import org.springframework.asm.ClassVisitor; import org.springframework.asm.Type; +import org.springframework.cglib.core.AbstractClassGenerator; +import org.springframework.cglib.core.ClassEmitter; +import org.springframework.cglib.core.CodeEmitter; +import org.springframework.cglib.core.Constants; +import org.springframework.cglib.core.EmitUtils; +import org.springframework.cglib.core.MethodInfo; +import org.springframework.cglib.core.ReflectUtils; +import org.springframework.cglib.core.Signature; +import org.springframework.cglib.core.TypeUtils; /** * @author Chris Nokleberg */ @SuppressWarnings({"rawtypes", "unchecked"}) public class ImmutableBean { - private static final Type ILLEGAL_STATE_EXCEPTION = - TypeUtils.parseType("IllegalStateException"); - private static final Signature CSTRUCT_OBJECT = - TypeUtils.parseConstructor("Object"); - private static final Class[] OBJECT_CLASSES = { Object.class }; - private static final String FIELD_NAME = "CGLIB$RWBean"; + private static final Type ILLEGAL_STATE_EXCEPTION = + TypeUtils.parseType("IllegalStateException"); + private static final Signature CSTRUCT_OBJECT = + TypeUtils.parseConstructor("Object"); + private static final Class[] OBJECT_CLASSES = { Object.class }; + private static final String FIELD_NAME = "CGLIB$RWBean"; - private ImmutableBean() { - } + private ImmutableBean() { + } - public static Object create(Object bean) { - Generator gen = new Generator(); - gen.setBean(bean); - return gen.create(); - } + public static Object create(Object bean) { + Generator gen = new Generator(); + gen.setBean(bean); + return gen.create(); + } - public static class Generator extends AbstractClassGenerator { - private static final Source SOURCE = new Source(ImmutableBean.class.getName()); - private Object bean; - private Class target; + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(ImmutableBean.class.getName()); + private Object bean; + private Class target; - public Generator() { - super(SOURCE); - } + public Generator() { + super(SOURCE); + } - public void setBean(Object bean) { - this.bean = bean; - target = bean.getClass(); + public void setBean(Object bean) { + this.bean = bean; + target = bean.getClass(); // SPRING PATCH BEGIN setContextClass(target); // SPRING PATCH END - } + } - protected ClassLoader getDefaultClassLoader() { - return target.getClassLoader(); - } + @Override + protected ClassLoader getDefaultClassLoader() { + return target.getClassLoader(); + } - protected ProtectionDomain getProtectionDomain() { - return ReflectUtils.getProtectionDomain(target); - } + @Override + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(target); + } - public Object create() { - String name = target.getName(); - setNamePrefix(name); - return super.create(name); - } + public Object create() { + String name = target.getName(); + setNamePrefix(name); + return super.create(name); + } - public void generateClass(ClassVisitor v) { - Type targetType = Type.getType(target); - ClassEmitter ce = new ClassEmitter(v); - ce.begin_class(Constants.V1_8, - Constants.ACC_PUBLIC, - getClassName(), - targetType, - null, - Constants.SOURCE_FILE); + @Override + public void generateClass(ClassVisitor v) { + Type targetType = Type.getType(target); + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_8, + Constants.ACC_PUBLIC, + getClassName(), + targetType, + null, + Constants.SOURCE_FILE); - ce.declare_field(Constants.ACC_FINAL | Constants.ACC_PRIVATE, FIELD_NAME, targetType, null); + ce.declare_field(Constants.ACC_FINAL | Constants.ACC_PRIVATE, FIELD_NAME, targetType, null); - CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null); - e.load_this(); - e.super_invoke_constructor(); - e.load_this(); - e.load_arg(0); - e.checkcast(targetType); - e.putfield(FIELD_NAME); - e.return_value(); - e.end_method(); + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null); + e.load_this(); + e.super_invoke_constructor(); + e.load_this(); + e.load_arg(0); + e.checkcast(targetType); + e.putfield(FIELD_NAME); + e.return_value(); + e.end_method(); - PropertyDescriptor[] descriptors = ReflectUtils.getBeanProperties(target); - Method[] getters = ReflectUtils.getPropertyMethods(descriptors, true, false); - Method[] setters = ReflectUtils.getPropertyMethods(descriptors, false, true); + PropertyDescriptor[] descriptors = ReflectUtils.getBeanProperties(target); + Method[] getters = ReflectUtils.getPropertyMethods(descriptors, true, false); + Method[] setters = ReflectUtils.getPropertyMethods(descriptors, false, true); - for (int i = 0; i < getters.length; i++) { - MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]); - e = EmitUtils.begin_method(ce, getter, Constants.ACC_PUBLIC); - e.load_this(); - e.getfield(FIELD_NAME); - e.invoke(getter); - e.return_value(); - e.end_method(); - } + for (Method getter2 : getters) { + MethodInfo getter = ReflectUtils.getMethodInfo(getter2); + e = EmitUtils.begin_method(ce, getter, Constants.ACC_PUBLIC); + e.load_this(); + e.getfield(FIELD_NAME); + e.invoke(getter); + e.return_value(); + e.end_method(); + } - for (int i = 0; i < setters.length; i++) { - MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]); - e = EmitUtils.begin_method(ce, setter, Constants.ACC_PUBLIC); - e.throw_exception(ILLEGAL_STATE_EXCEPTION, "Bean is immutable"); - e.end_method(); - } + for (Method setter2 : setters) { + MethodInfo setter = ReflectUtils.getMethodInfo(setter2); + e = EmitUtils.begin_method(ce, setter, Constants.ACC_PUBLIC); + e.throw_exception(ILLEGAL_STATE_EXCEPTION, "Bean is immutable"); + e.end_method(); + } - ce.end_class(); - } + ce.end_class(); + } - protected Object firstInstance(Class type) { - return ReflectUtils.newInstance(type, OBJECT_CLASSES, new Object[]{ bean }); - } + @Override + protected Object firstInstance(Class type) { + return ReflectUtils.newInstance(type, OBJECT_CLASSES, new Object[]{ bean }); + } - // TODO: optimize - protected Object nextInstance(Object instance) { - return firstInstance(instance.getClass()); - } - } + // TODO: optimize + @Override + protected Object nextInstance(Object instance) { + return firstInstance(instance.getClass()); + } + } }