1 16 package net.sf.cglib.transform.impl; 17 18 import net.sf.cglib.transform.*; 19 import java.util.*; 20 import net.sf.cglib.core.*; 21 import org.objectweb.asm.Attribute; 22 import org.objectweb.asm.Label; 23 import org.objectweb.asm.Type; 24 25 public class FieldProviderTransformer extends ClassEmitterTransformer { 26 27 private static final String FIELD_NAMES = "CGLIB$FIELD_NAMES"; 28 private static final String FIELD_TYPES = "CGLIB$FIELD_TYPES"; 29 30 private static final Type FIELD_PROVIDER = 31 TypeUtils.parseType("net.sf.cglib.transform.impl.FieldProvider"); 32 private static final Type ILLEGAL_ARGUMENT_EXCEPTION = 33 TypeUtils.parseType("IllegalArgumentException"); 34 private static final Signature PROVIDER_GET = 35 TypeUtils.parseSignature("Object getField(String)"); 36 private static final Signature PROVIDER_SET = 37 TypeUtils.parseSignature("void setField(String, Object)"); 38 private static final Signature PROVIDER_SET_BY_INDEX = 39 TypeUtils.parseSignature("void setField(int, Object)"); 40 private static final Signature PROVIDER_GET_BY_INDEX = 41 TypeUtils.parseSignature("Object getField(int)"); 42 private static final Signature PROVIDER_GET_TYPES = 43 TypeUtils.parseSignature("Class[] getFieldTypes()"); 44 private static final Signature PROVIDER_GET_NAMES = 45 TypeUtils.parseSignature("String[] getFieldNames()"); 46 47 private int access; 48 private Map fields; 49 50 public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) { 51 if (!TypeUtils.isAbstract(access)) { 52 interfaces = TypeUtils.add(interfaces, FIELD_PROVIDER); 53 } 54 this.access = access; 55 fields = new HashMap(); 56 super.begin_class(version, access, className, superType, interfaces, sourceFile); 57 } 58 59 public void declare_field(int access, String name, Type type, Object value) { 60 super.declare_field(access, name, type, value); 61 62 if (!TypeUtils.isStatic(access)) { 63 fields.put(name, type); 64 } 65 } 66 67 public void end_class() { 68 if (!TypeUtils.isInterface(access)) { 69 try { 70 generate(); 71 } catch (RuntimeException e) { 72 throw e; 73 } catch (Exception e) { 74 throw new CodeGenerationException(e); 75 } 76 } 77 super.end_class(); 78 } 79 80 private void generate() throws Exception { 81 final String [] names = (String [])fields.keySet().toArray(new String [fields.size()]); 82 83 int indexes[] = new int[names.length]; 84 for (int i = 0; i < indexes.length; i++) { 85 indexes[i] = i; 86 } 87 88 super.declare_field(Constants.PRIVATE_FINAL_STATIC, FIELD_NAMES, Constants.TYPE_STRING_ARRAY, null); 89 super.declare_field(Constants.PRIVATE_FINAL_STATIC, FIELD_TYPES, Constants.TYPE_CLASS_ARRAY, null); 90 91 initFieldProvider(names); 93 getNames(); 94 getTypes(); 95 getField(names); 96 setField(names); 97 setByIndex(names, indexes); 98 getByIndex(names, indexes); 99 } 100 101 private void initFieldProvider(String [] names) { 102 CodeEmitter e = getStaticHook(); 103 EmitUtils.push_object(e, names); 104 e.putstatic(getClassType(), FIELD_NAMES, Constants.TYPE_STRING_ARRAY); 105 106 e.push(names.length); 107 e.newarray(Constants.TYPE_CLASS); 108 e.dup(); 109 for(int i = 0; i < names.length; i++ ){ 110 e.dup(); 111 e.push(i); 112 Type type = (Type)fields.get(names[i]); 113 EmitUtils.load_class(e, type); 114 e.aastore(); 115 } 116 e.putstatic(getClassType(), FIELD_TYPES, Constants.TYPE_CLASS_ARRAY); 117 } 118 119 private void getNames() { 120 CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_NAMES, null); 121 e.getstatic(getClassType(), FIELD_NAMES, Constants.TYPE_STRING_ARRAY); 122 e.return_value(); 123 e.end_method(); 124 } 125 126 private void getTypes() { 127 CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_TYPES, null); 128 e.getstatic(getClassType(), FIELD_TYPES, Constants.TYPE_CLASS_ARRAY); 129 e.return_value(); 130 e.end_method(); 131 } 132 133 private void setByIndex(final String [] names, final int[] indexes) throws Exception { 134 final CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_SET_BY_INDEX, null); 135 e.load_this(); 136 e.load_arg(1); 137 e.load_arg(0); 138 e.process_switch(indexes, new ProcessSwitchCallback() { 139 public void processCase(int key, Label end) throws Exception { 140 Type type = (Type)fields.get(names[key]); 141 e.unbox(type); 142 e.putfield(names[key]); 143 e.return_value(); 144 } 145 public void processDefault() throws Exception { 146 e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field index"); 147 } 148 }); 149 e.end_method(); 150 } 151 152 private void getByIndex(final String [] names, final int[] indexes) throws Exception { 153 final CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_BY_INDEX, null); 154 e.load_this(); 155 e.load_arg(0); 156 e.process_switch(indexes, new ProcessSwitchCallback() { 157 public void processCase(int key, Label end) throws Exception { 158 Type type = (Type)fields.get(names[key]); 159 e.getfield(names[key]); 160 e.box(type); 161 e.return_value(); 162 } 163 public void processDefault() throws Exception { 164 e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field index"); 165 } 166 }); 167 e.end_method(); 168 } 169 170 private void getField(String [] names) throws Exception { 173 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, PROVIDER_GET, null); 174 e.load_this(); 175 e.load_arg(0); 176 EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 177 public void processCase(Object key, Label end) { 178 Type type = (Type)fields.get(key); 179 e.getfield((String )key); 180 e.box(type); 181 e.return_value(); 182 } 183 public void processDefault() { 184 e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field name"); 185 } 186 }); 187 e.end_method(); 188 } 189 190 private void setField(String [] names) throws Exception { 191 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, PROVIDER_SET, null); 192 e.load_this(); 193 e.load_arg(1); 194 e.load_arg(0); 195 EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 196 public void processCase(Object key, Label end) { 197 Type type = (Type)fields.get(key); 198 e.unbox(type); 199 e.putfield((String )key); 200 e.return_value(); 201 } 202 public void processDefault() { 203 e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field name"); 204 } 205 }); 206 e.end_method(); 207 } 208 } 209 | Popular Tags |