1 4 package com.tc.aspectwerkz.aspect.container; 5 6 import com.tc.asm.ClassWriter; 7 import com.tc.asm.MethodVisitor; 8 import com.tc.asm.Opcodes; 9 10 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo; 11 import com.tc.aspectwerkz.reflect.ClassInfo; 12 import com.tc.aspectwerkz.reflect.ConstructorInfo; 13 import com.tc.aspectwerkz.transform.Properties; 14 import com.tc.aspectwerkz.transform.TransformationConstants; 15 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 16 import com.tc.aspectwerkz.util.Strings; 17 18 import java.io.IOException ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.Map ; 22 23 43 public abstract class AbstractAspectFactoryCompiler implements Opcodes, TransformationConstants { 44 45 final static Artifact[] EMPTY_ARTIFACT_ARRAY = new Artifact[0]; 46 47 private final ClassLoader m_loader; 48 49 protected String m_aspectFactoryClassName; 50 protected String [] m_interfaces = null; 51 protected final String m_aspectQualifiedName; 52 protected final String m_aspectClassName; 53 protected final String m_aspectClassSignature; 54 protected final String m_aspectContainerClassName; 55 protected final boolean m_hasAspectContainer; 56 57 private final String m_uuid; 58 private boolean m_hasParameters; 59 private String m_rawParameters; 60 private Map m_parametersLazy; 61 62 protected ClassWriter m_cw; 63 protected MethodVisitor m_clinit; 64 65 public AbstractAspectFactoryCompiler(String uuid, 66 String aspectClassName, 67 String aspectQualifiedName, 68 String containerClassName, 69 String rawParameters, 70 ClassLoader loader) { 71 m_uuid = uuid; 72 m_aspectClassName = aspectClassName.replace('.', '/'); 73 m_aspectClassSignature = 'L' + m_aspectClassName + ';'; 74 m_aspectQualifiedName = aspectQualifiedName; 75 m_aspectFactoryClassName = AspectFactoryManager.getAspectFactoryClassName( 76 m_aspectClassName, m_aspectQualifiedName 77 ); 78 if (containerClassName != null) { 79 m_aspectContainerClassName = containerClassName.replace('.', '/'); 80 m_hasAspectContainer = true; 81 } else { 82 m_aspectContainerClassName = null; 83 m_hasAspectContainer = false; 84 } 85 if (rawParameters != null) { 86 m_rawParameters = rawParameters; 87 m_hasParameters = true; 88 } else { 89 m_rawParameters = null; 90 m_hasParameters = false; 91 } 92 m_loader = loader; 93 } 94 95 private Map getParameters() { 96 if (m_parametersLazy == null) { 97 Map map; 98 if (m_rawParameters != null) { 99 map = new HashMap (); 100 String [] raw = Strings.splitString(m_rawParameters, DELIMITER); 101 for (int i = 0; i < raw.length; i++) { 102 if (i < raw.length) { 103 map.put(raw[i], raw[++i]); 104 } 105 } 106 } else { 107 map = new HashMap (0); 108 } 109 m_parametersLazy = map; 110 } 111 return m_parametersLazy; 112 } 113 114 public Artifact compile() { 115 m_cw = AsmHelper.newClassWriter(true); 116 117 m_cw.visit( 118 AsmHelper.JAVA_VERSION, 119 ACC_PUBLIC, 120 m_aspectFactoryClassName, 121 null, 122 OBJECT_CLASS_NAME, 123 m_interfaces 124 ); 125 126 m_cw.visitField( 128 ACC_STATIC + ACC_PRIVATE, 129 FACTORY_CLASS_FIELD_NAME, 130 CLASS_CLASS_SIGNATURE, 131 null, 132 null 133 ); 134 135 m_clinit = m_cw.visitMethod( 137 ACC_STATIC, 138 CLINIT_METHOD_NAME, 139 CLINIT_METHOD_SIGNATURE, 140 null, 141 null 142 ); 143 144 m_clinit.visitLdcInsn(m_aspectFactoryClassName.replace('/', '.')); 146 m_clinit.visitMethodInsn( 147 INVOKESTATIC, 148 CLASS_CLASS, 149 FOR_NAME_METHOD_NAME, 150 FOR_NAME_METHOD_SIGNATURE 151 ); 152 m_clinit.visitFieldInsn( 153 PUTSTATIC, 154 m_aspectFactoryClassName, 155 FACTORY_CLASS_FIELD_NAME, 156 CLASS_CLASS_SIGNATURE 157 ); 158 159 if (m_hasParameters) { 160 createParametersFieldAndClinit(); 161 } 162 if (m_hasAspectContainer) { 163 createAspectContainerFieldAndClinit(); 164 } 165 166 createAspectOf(); 167 createHasAspect(); 168 createOtherArtifacts(); 169 170 m_clinit.visitInsn(RETURN); 171 m_clinit.visitMaxs(0, 0); 172 173 Artifact artifact = new Artifact(m_aspectFactoryClassName, m_cw.toByteArray()); 174 175 if (Properties.DUMP_JIT_FACTORIES) try { 176 AsmHelper.dumpClass(Properties.DUMP_DIR_FACTORIES, artifact.className, artifact.bytecode); 177 } catch (IOException e) { 178 } 179 return artifact; 180 } 181 182 protected abstract void createAspectOf(); 183 184 protected abstract void createHasAspect(); 185 186 protected abstract void createOtherArtifacts(); 187 188 private void createParametersFieldAndClinit() { 189 m_cw.visitField( 190 ACC_PRIVATE + ACC_STATIC + ACC_FINAL, 191 FACTORY_PARAMS_FIELD_NAME, 192 MAP_CLASS_SIGNATURE, 193 null, 194 null 195 ); 196 197 m_clinit.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME); 198 m_clinit.visitInsn(DUP); 199 m_clinit.visitMethodInsn(INVOKESPECIAL, HASH_MAP_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE); 200 for (Iterator iterator = getParameters().entrySet().iterator(); iterator.hasNext();) { 201 m_clinit.visitInsn(DUP); 202 Map.Entry entry = (Map.Entry ) iterator.next(); 203 m_clinit.visitLdcInsn(entry.getKey()); 204 m_clinit.visitLdcInsn(entry.getValue()); 205 m_clinit.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, PUT_METHOD_NAME, PUT_METHOD_SIGNATURE); 206 m_clinit.visitInsn(POP); 207 } 208 m_clinit.visitFieldInsn(PUTSTATIC, m_aspectFactoryClassName, FACTORY_PARAMS_FIELD_NAME, MAP_CLASS_SIGNATURE); 209 } 210 211 private void createAspectContainerFieldAndClinit() { 212 m_cw.visitField( 213 ACC_PRIVATE + ACC_STATIC, 214 FACTORY_CONTAINER_FIELD_NAME, 215 ASPECT_CONTAINER_CLASS_SIGNATURE, 216 null, 217 null 218 ); 219 220 ClassInfo containerClassInfo = AsmClassInfo.getClassInfo( 222 m_aspectContainerClassName, 223 m_loader 224 ); 225 boolean hasConstructor = false; 226 for (int i = 0; i < containerClassInfo.getConstructors().length; i++) { 227 ConstructorInfo constructorInfo = containerClassInfo.getConstructors()[i]; 228 if (ASPECT_CONTAINER_OPTIONAL_INIT_SIGNATURE.equals(constructorInfo.getSignature())) { 229 hasConstructor = true; 230 break; 231 } 232 } 234 m_clinit.visitTypeInsn(NEW, m_aspectContainerClassName); 235 m_clinit.visitInsn(DUP); 236 if (hasConstructor) { 237 m_clinit.visitLdcInsn(m_aspectClassName.replace('/', '.')); 238 m_clinit.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE); 239 m_clinit.visitFieldInsn( 241 GETSTATIC, m_aspectFactoryClassName, FACTORY_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE 242 ); 243 m_clinit.visitMethodInsn( 244 INVOKEVIRTUAL, 245 CLASS_CLASS, 246 GETCLASSLOADER_METHOD_NAME, 247 CLASS_CLASS_GETCLASSLOADER_METHOD_SIGNATURE 248 ); 249 m_clinit.visitLdcInsn(m_uuid); 250 m_clinit.visitLdcInsn(m_aspectQualifiedName); 251 if (m_hasParameters) { 252 m_clinit.visitFieldInsn( 253 GETSTATIC, m_aspectFactoryClassName, FACTORY_PARAMS_FIELD_NAME, MAP_CLASS_SIGNATURE 254 ); 255 } else { 256 m_clinit.visitInsn(ACONST_NULL); 257 } 258 m_clinit.visitMethodInsn( 259 INVOKESPECIAL, 260 m_aspectContainerClassName, 261 INIT_METHOD_NAME, 262 ASPECT_CONTAINER_OPTIONAL_INIT_SIGNATURE 263 ); 264 } else { 265 m_clinit.visitMethodInsn( 266 INVOKESPECIAL, m_aspectContainerClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE 267 ); 268 } 269 m_clinit.visitFieldInsn( 270 PUTSTATIC, m_aspectFactoryClassName, FACTORY_CONTAINER_FIELD_NAME, ASPECT_CONTAINER_CLASS_SIGNATURE 271 ); 272 } 273 } 274 | Popular Tags |