1 21 package com.db4o.j2me.bloat; 22 23 import java.lang.reflect.*; 24 import java.util.*; 25 26 import EDU.purdue.cs.bloat.editor.*; 27 import EDU.purdue.cs.bloat.editor.Type; 28 import EDU.purdue.cs.bloat.file.*; 29 import EDU.purdue.cs.bloat.reflect.*; 30 import EDU.purdue.cs.bloat.reflect.FieldInfo; 31 32 import com.db4o.reflect.self.*; 33 import com.db4o.reflect.self.ClassInfo; 34 35 public class RegistryEnhancer { 36 private static final String COMPONENTTYPE_METHODNAME = "componentType"; 37 38 private static final String ARRAYFOR_METHODNAME = "arrayFor"; 39 40 private static final String INFOFOR_METHODNAME = "infoFor"; 41 42 private static final String CLASSINFO_CONSTNAME = "CLASSINFO"; 43 44 private ClassEditor _ce; 45 46 private Class [] _clazzes; 47 48 private BloatContext _context; 49 50 public RegistryEnhancer(BloatContext context, ClassEditor ce, Class clazz) { 51 this._ce = ce; 52 this._clazzes = createClasses(clazz); 53 this._context = context; 54 } 55 56 private static Class [] createClasses(Class concrete) { 57 List list = new ArrayList(); 58 Class cur = concrete; 59 while (cur != Object .class) { 60 list.add(cur); 61 cur = cur.getSuperclass(); 62 } 63 return (Class []) list.toArray(new Class [list.size()]); 64 } 65 66 public void generate() { 67 _context.addNoArgConstructor(_ce); 68 generateCLASSINFOField(); 69 generateInfoForMethod(); 70 generateArrayForMethod(); 71 generateComponentTypeMethod(); 72 } 73 74 private void generateCLASSINFOField() { 75 FieldEditor fe = _context.createField(_ce, 26, Type 76 .getType(Hashtable.class), CLASSINFO_CONSTNAME); 77 78 MethodBuilder builder = new MethodBuilder(_context, _ce, 79 Modifiers.STATIC, void.class, "<clinit>", new Class [0], 80 new Class [0]); 81 builder.newRef(Hashtable.class); 82 builder.dup(); 83 builder.invokeSpecial(_context.getType(Hashtable.class), BloatContext.INIT_METHODNAME, 84 new Type[0], Type.VOID); 85 builder.putstatic(_ce.type(), Hashtable.class, CLASSINFO_CONSTNAME); 86 for (int classIdx = 0; classIdx < _clazzes.length; classIdx++) { 87 builder.getstatic(_ce.type(), Hashtable.class, CLASSINFO_CONSTNAME); 88 generateInfoForClass(builder, _clazzes[classIdx]); 89 } 90 91 builder.returnInstruction(); 92 builder.commit(); 93 fe.commit(); 94 95 } 96 97 private void generateInfoForClass(MethodBuilder builder, Class clazz) { 98 builder.invokeLoadClassConstMethod(clazz); 99 builder.newRef(com.db4o.reflect.self.ClassInfo.class); 100 builder.dup(); 101 FieldInfo[] fieldsInf = collectFieldsOfClass(clazz); 102 builder.ldc(isAbstractClass(clazz)); 103 builder.invokeLoadClassConstMethod(clazz 104 .getSuperclass()); 105 builder.ldc(fieldsInf.length); 106 builder.anewarray(com.db4o.reflect.self.FieldInfo.class); 107 for (int i = 0; i < fieldsInf.length; i++) { 108 generateInfoForField(builder, _context.fieldEditor(clazz, fieldsInf[i]), i); 109 } 110 builder.invokeSpecial(_context.getType(ClassInfo.class), BloatContext.INIT_METHODNAME, 111 new Type[] { Type.BOOLEAN, Type.CLASS, 112 _context.getType(com.db4o.reflect.self.FieldInfo[].class) }, 113 Type.VOID); 114 builder.invokeVirtual(_context.getType(Hashtable.class), "put", 115 new Type[] { Type.OBJECT, Type.OBJECT }, Type.OBJECT); 116 } 117 118 private void generateInfoForField(MethodBuilder builder, FieldEditor fieldEditor, int arrIdx) { 119 builder.dup(); 120 builder.ldc(arrIdx); 121 builder.newRef(com.db4o.reflect.self.FieldInfo.class); 122 builder.dup(); 123 builder.ldc(fieldEditor.name()); 124 Class wrapper = PrimitiveUtil.wrapper(fieldEditor.type()); 125 if (wrapper != null) { 126 builder.getstatic(wrapper, Class .class, "TYPE"); 127 } else { 128 builder.invokeLoadClassConstMethod(fieldEditor.type().className()); 129 } 130 builder.ldc(fieldEditor.isPublic()); 131 builder.ldc(fieldEditor.isStatic()); 132 builder.ldc(fieldEditor.isTransient()); 133 builder.invokeSpecial( 134 _context.getType(com.db4o.reflect.self.FieldInfo.class), BloatContext.INIT_METHODNAME, 135 new Type[] { Type.STRING, Type.CLASS, Type.BOOLEAN, 136 Type.BOOLEAN, Type.BOOLEAN }, Type.VOID); 137 builder.aastore(); 138 } 139 140 141 private FieldInfo[] collectFieldsOfClass(Class clazz) { 142 ClassEditor ce = null; 143 FieldInfo[] fields = null; 144 try { 145 ce = new ClassEditor(null, new ClassFileLoader().loadClass(clazz 146 .getName())); 147 fields = ce.fields(); 148 } catch (ClassNotFoundException e) { 149 e.printStackTrace(); 150 } 151 return fields; 152 } 153 154 private boolean isAbstractClass(Class clazz) { 155 return Modifier.isAbstract(clazz.getModifiers()); 156 } 157 158 private void generateInfoForMethod() { 159 MethodBuilder builder = new MethodBuilder(_context, _ce, 160 Modifiers.PUBLIC, com.db4o.reflect.self.ClassInfo.class, 161 INFOFOR_METHODNAME, new Class [] { Class .class }, null); 162 builder.getstatic(_ce.type(), Hashtable.class, CLASSINFO_CONSTNAME); 163 builder.aload(1); 164 builder.invokeVirtual(_context.getType(Hashtable.class), "get", 165 new Type[] { Type.OBJECT }, Type.OBJECT); 166 builder.checkcast(ClassInfo.class); 167 builder.areturn(); 168 builder.commit(); 169 170 } 171 172 private void generateArrayForMethod() { 173 MethodBuilder builder = new MethodBuilder(_context, _ce, 174 Modifiers.PUBLIC, Object .class, ARRAYFOR_METHODNAME, new Class [] { 175 Class .class, Integer.TYPE }, null); 176 int labelIdx = 1; 177 for (int classIdx = 0; classIdx < _clazzes.length; classIdx++) { 178 builder.invokeLoadClassConstMethod(_clazzes[classIdx]); 179 builder.aload(1); 180 builder.invokeVirtual(Type.CLASS, 181 "isAssignableFrom", new Type[] { Type.CLASS }, 182 Type.BOOLEAN); 183 builder.ifeq(labelIdx); 184 builder.iload(2); 185 builder.newarray(_clazzes[classIdx]); 186 builder.areturn(); 187 builder.label(labelIdx); 188 labelIdx++; 189 } 190 builder.aload(0); 191 builder.aload(1); 192 builder.iload(2); 193 builder.invokeSpecial(_context.getType(SelfReflectionRegistry.class), 194 ARRAYFOR_METHODNAME, new Type[] { Type.CLASS, Type.INTEGER }, 195 Type.OBJECT); 196 builder.areturn(); 197 builder.commit(); 198 } 199 200 private void generateComponentTypeMethod() { 201 MethodBuilder builder = new MethodBuilder(_context, _ce, 202 Modifiers.PUBLIC, Class .class, COMPONENTTYPE_METHODNAME, 203 new Class [] { Class .class }, new Class [0]); 204 int labelId = 1; 205 for (int classIdx = 0; classIdx < _clazzes.length; classIdx++) { 206 builder 207 .invokeLoadClassConstMethod(convertToArray(_clazzes[classIdx])); 208 builder.aload(1); 209 builder.invokeVirtual(Type.CLASS, 210 "isAssignableFrom", new Type[] { Type.CLASS }, 211 Type.BOOLEAN); 212 builder.ifeq(labelId); 213 builder.invokeLoadClassConstMethod(_clazzes[classIdx]); 214 builder.areturn(); 215 builder.label(labelId); 216 labelId++; 217 } 218 builder.aload(0); 219 builder.aload(1); 220 builder.invokeSpecial( 221 _context.getType(com.db4o.reflect.self.SelfReflectionRegistry.class), 222 COMPONENTTYPE_METHODNAME, new Type[] { Type.CLASS }, Type.CLASS); 223 builder.areturn(); 224 builder.commit(); 225 226 } 227 228 private Class convertToArray(Class clazz) { 229 return Array.newInstance(clazz, new int[1]).getClass(); 230 } 231 232 233 234 } 235 | Popular Tags |