1 19 package org.apache.cayenne.enhancer; 20 21 import org.objectweb.asm.ClassVisitor; 22 import org.objectweb.asm.FieldVisitor; 23 import org.objectweb.asm.Label; 24 import org.objectweb.asm.MethodVisitor; 25 import org.objectweb.asm.Opcodes; 26 import org.objectweb.asm.Type; 27 28 35 public class EnhancementHelper { 36 37 41 public static boolean isGeneratedField(String name) { 42 return name != null && name.startsWith(fieldPrefix); 43 } 44 45 private static String fieldPrefix = "$cay_"; 46 private ClassVisitor classVisitor; 47 private Type currentClass; 48 49 public EnhancementHelper(ClassVisitor classVisitor) { 50 this.classVisitor = classVisitor; 51 } 52 53 public Type getCurrentClass() { 54 return currentClass; 55 } 56 57 public String getPropertyField(String propertyName) { 58 return fieldPrefix + propertyName; 59 } 60 61 public void reset(String className) { 62 this.currentClass = Type.getType("L" + className + ";"); 64 } 65 66 public String [] addInterface(String [] interfaces, Class newInterface) { 67 68 String name = Type.getInternalName(newInterface); 69 if (interfaces == null || interfaces.length == 0) { 70 return new String [] { 71 name 72 }; 73 } 74 75 String [] expandedInterfaces = new String [interfaces.length + 1]; 76 expandedInterfaces[0] = name; 77 System.arraycopy(interfaces, 0, expandedInterfaces, 1, interfaces.length); 78 79 return expandedInterfaces; 80 } 81 82 86 public void createField(Class fieldType, String name) { 87 createField(fieldType, name, false); 88 } 89 90 94 public void createField(Class fieldType, String name, boolean isTransient) { 95 Type asmType = Type.getType(fieldType); 96 int access = Opcodes.ACC_PROTECTED; 97 if (isTransient) { 98 access += Opcodes.ACC_TRANSIENT; 99 } 100 101 createField(name, asmType, access); 102 } 103 104 public void createProperty(Class propertyType, String name) { 105 createProperty(propertyType, name, false); 106 } 107 108 public void createProperty(Class propertyType, String name, boolean isTransient) { 109 Type asmType = Type.getType(propertyType); 110 111 int access = Opcodes.ACC_PROTECTED; 112 if (isTransient) { 113 access += Opcodes.ACC_TRANSIENT; 114 } 115 116 createField(name, asmType, access); 117 createGetter(name, asmType); 118 createSetter(name, asmType); 119 } 120 121 private void createSetter(String propertyName, Type asmType) { 122 123 String methodName = "set" + Character.toUpperCase(propertyName.charAt(0)); 124 if (propertyName.length() > 1) { 125 methodName += propertyName.substring(1); 126 } 127 128 MethodVisitor mv = classVisitor.visitMethod(Opcodes.ACC_PUBLIC, methodName, "(" 129 + asmType.getDescriptor() 130 + ")V", null, null); 131 mv.visitCode(); 132 Label l0 = new Label(); 133 mv.visitLabel(l0); 134 mv.visitVarInsn(Opcodes.ALOAD, 0); 135 136 if ("I".equals(asmType.getDescriptor())) { 138 mv.visitVarInsn(Opcodes.ILOAD, 1); 139 } 140 else { 141 mv.visitVarInsn(Opcodes.ALOAD, 1); 142 } 143 144 mv.visitFieldInsn( 145 Opcodes.PUTFIELD, 146 currentClass.getInternalName(), 147 getPropertyField(propertyName), 148 asmType.getDescriptor()); 149 mv.visitInsn(Opcodes.RETURN); 150 Label l1 = new Label(); 151 mv.visitLabel(l1); 152 mv.visitLocalVariable("this", currentClass.getDescriptor(), null, l0, l1, 0); 153 mv.visitLocalVariable(propertyName, asmType.getDescriptor(), null, l0, l1, 1); 154 mv.visitMaxs(2, 2); 155 mv.visitEnd(); 156 } 157 158 private void createGetter(String propertyName, Type asmType) { 159 160 String prefix = "boolean".equals(asmType.getClassName()) ? "is" : "get"; 161 String methodName = prefix + Character.toUpperCase(propertyName.charAt(0)); 162 if (propertyName.length() > 1) { 163 methodName += propertyName.substring(1); 164 } 165 166 MethodVisitor mv = classVisitor.visitMethod(Opcodes.ACC_PUBLIC, methodName, "()" 167 + asmType.getDescriptor(), null, null); 168 mv.visitCode(); 169 Label l0 = new Label(); 170 mv.visitLabel(l0); 171 mv.visitVarInsn(Opcodes.ALOAD, 0); 172 mv.visitFieldInsn( 173 Opcodes.GETFIELD, 174 currentClass.getInternalName(), 175 getPropertyField(propertyName), 176 asmType.getDescriptor()); 177 178 if ("I".equals(asmType.getDescriptor())) { 180 mv.visitInsn(Opcodes.IRETURN); 181 } 182 else { 183 mv.visitInsn(Opcodes.ARETURN); 184 } 185 186 Label l1 = new Label(); 187 mv.visitLabel(l1); 188 mv.visitLocalVariable("this", currentClass.getDescriptor(), null, l0, l1, 0); 189 mv.visitMaxs(1, 1); 190 mv.visitEnd(); 191 } 192 193 private void createField(String propertyName, Type asmType, int access) { 194 FieldVisitor fv = classVisitor.visitField( 195 access, 196 getPropertyField(propertyName), 197 asmType.getDescriptor(), 198 null, 199 null); 200 fv.visitEnd(); 201 } 202 } 203 | Popular Tags |