BeanCopier sets name prefix for public classes as well

Includes consistent formatting of Spring-patched files.

Closes gh-28699

(cherry picked from commit 7a60e2024b)
This commit is contained in:
Juergen Hoeller
2023-10-15 16:09:17 +02:00
parent cb28e2a701
commit 2dc4fe0857
9 changed files with 791 additions and 689 deletions

View File

@@ -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;
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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 <code>BeanMap</code>. For finer
* control over the generated instance, use a new instance of
* <code>BeanMap.Generator</code> instead of this static method.
* @param bean the JavaBean underlying the map
* @return a new <code>BeanMap</code> 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 <code>BeanMap</code>. For finer
* control over the generated instance, use a new instance of
* <code>BeanMap.Generator</code> instead of this static method.
* @param bean the JavaBean underlying the map
* @return a new <code>BeanMap</code> 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 <code>BeanMap</code>. 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 <code>BeanMap</code>. 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 <code>BeanMap</code> 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 <code>BeanMap</code> instance
*/
abstract public BeanMap newInstance(Object bean);
/**
* Create a new <code>BeanMap</code> 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 <code>BeanMap</code> 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 <code>BeanMap</code>
* 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 <code>BeanMap</code>
* @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 <code>BeanMap</code>
* 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 <code>BeanMap</code>
* @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 <code>BeanMap</code>
* 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 <code>BeanMap</code>
* 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();
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}
}

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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());
}
}
}