1 16 package net.sf.cglib.beans; 17 18 import java.beans.*; 19 import java.util.*; 20 import net.sf.cglib.core.*; 21 import org.objectweb.asm.ClassVisitor; 22 import org.objectweb.asm.Label; 23 import org.objectweb.asm.Type; 24 25 class BeanMapEmitter extends ClassEmitter { 26 private static final Type BEAN_MAP = 27 TypeUtils.parseType("net.sf.cglib.beans.BeanMap"); 28 private static final Type FIXED_KEY_SET = 29 TypeUtils.parseType("net.sf.cglib.beans.FixedKeySet"); 30 private static final Signature CSTRUCT_OBJECT = 31 TypeUtils.parseConstructor("Object"); 32 private static final Signature CSTRUCT_STRING_ARRAY = 33 TypeUtils.parseConstructor("String[]"); 34 private static final Signature BEAN_MAP_GET = 35 TypeUtils.parseSignature("Object get(Object, Object)"); 36 private static final Signature BEAN_MAP_PUT = 37 TypeUtils.parseSignature("Object put(Object, Object, Object)"); 38 private static final Signature KEY_SET = 39 TypeUtils.parseSignature("java.util.Set keySet()"); 40 private static final Signature NEW_INSTANCE = 41 new Signature("newInstance", BEAN_MAP, new Type[]{ Constants.TYPE_OBJECT }); 42 private static final Signature GET_PROPERTY_TYPE = 43 TypeUtils.parseSignature("Class getPropertyType(String)"); 44 45 public BeanMapEmitter(ClassVisitor v, String className, Class type, int require) { 46 super(v); 47 48 begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE); 49 EmitUtils.null_constructor(this); 50 EmitUtils.factory_method(this, NEW_INSTANCE); 51 generateConstructor(); 52 53 Map getters = makePropertyMap(ReflectUtils.getBeanGetters(type)); 54 Map setters = makePropertyMap(ReflectUtils.getBeanSetters(type)); 55 Map allProps = new HashMap(); 56 allProps.putAll(getters); 57 allProps.putAll(setters); 58 59 if (require != 0) { 60 for (Iterator it = allProps.keySet().iterator(); it.hasNext();) { 61 String name = (String )it.next(); 62 if ((((require & BeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) || 63 (((require & BeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) { 64 it.remove(); 65 getters.remove(name); 66 setters.remove(name); 67 } 68 } 69 } 70 generateGet(type, getters); 71 generatePut(type, setters); 72 73 String [] allNames = getNames(allProps); 74 generateKeySet(allNames); 75 generateGetPropertyType(allProps, allNames); 76 end_class(); 77 } 78 79 private Map makePropertyMap(PropertyDescriptor[] props) { 80 Map names = new HashMap(); 81 for (int i = 0; i < props.length; i++) { 82 names.put(((PropertyDescriptor)props[i]).getName(), props[i]); 83 } 84 return names; 85 } 86 87 private String [] getNames(Map propertyMap) { 88 return (String [])propertyMap.keySet().toArray(new String [propertyMap.size()]); 89 } 90 91 private void generateConstructor() { 92 CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null); 93 e.load_this(); 94 e.load_arg(0); 95 e.super_invoke_constructor(CSTRUCT_OBJECT); 96 e.return_value(); 97 e.end_method(); 98 } 99 100 private void generateGet(Class type, final Map getters) { 101 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null); 102 e.load_arg(0); 103 e.checkcast(Type.getType(type)); 104 e.load_arg(1); 105 e.checkcast(Constants.TYPE_STRING); 106 EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 107 public void processCase(Object key, Label end) { 108 PropertyDescriptor pd = (PropertyDescriptor)getters.get(key); 109 MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod()); 110 e.invoke(method); 111 e.box(method.getSignature().getReturnType()); 112 e.return_value(); 113 } 114 public void processDefault() { 115 e.aconst_null(); 116 e.return_value(); 117 } 118 }); 119 e.end_method(); 120 } 121 122 private void generatePut(Class type, final Map setters) { 123 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null); 124 e.load_arg(0); 125 e.checkcast(Type.getType(type)); 126 e.load_arg(1); 127 e.checkcast(Constants.TYPE_STRING); 128 EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 129 public void processCase(Object key, Label end) { 130 PropertyDescriptor pd = (PropertyDescriptor)setters.get(key); 131 if (pd.getReadMethod() == null) { 132 e.aconst_null(); 133 } else { 134 MethodInfo read = ReflectUtils.getMethodInfo(pd.getReadMethod()); 135 e.dup(); 136 e.invoke(read); 137 e.box(read.getSignature().getReturnType()); 138 } 139 e.swap(); e.load_arg(2); MethodInfo write = ReflectUtils.getMethodInfo(pd.getWriteMethod()); 142 e.unbox(write.getSignature().getArgumentTypes()[0]); 143 e.invoke(write); 144 e.return_value(); 145 } 146 public void processDefault() { 147 } 149 }); 150 e.aconst_null(); 151 e.return_value(); 152 e.end_method(); 153 } 154 155 private void generateKeySet(String [] allNames) { 156 declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null); 158 159 CodeEmitter e = begin_static(); 160 e.new_instance(FIXED_KEY_SET); 161 e.dup(); 162 EmitUtils.push_array(e, allNames); 163 e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY); 164 e.putfield("keys"); 165 e.return_value(); 166 e.end_method(); 167 168 e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null); 170 e.load_this(); 171 e.getfield("keys"); 172 e.return_value(); 173 e.end_method(); 174 } 175 176 private void generateGetPropertyType(final Map allProps, String [] allNames) { 177 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null); 178 e.load_arg(0); 179 EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 180 public void processCase(Object key, Label end) { 181 PropertyDescriptor pd = (PropertyDescriptor)allProps.get(key); 182 EmitUtils.load_class(e, Type.getType(pd.getPropertyType())); 183 e.return_value(); 184 } 185 public void processDefault() { 186 e.aconst_null(); 187 e.return_value(); 188 } 189 }); 190 e.end_method(); 191 } 192 } 193 | Popular Tags |