1 4 package com.tc.aspectwerkz.proxy; 5 6 import com.tc.asm.ClassReader; 7 import com.tc.asm.ClassVisitor; 8 import com.tc.asm.ClassWriter; 9 import com.tc.asm.MethodVisitor; 10 import com.tc.asm.Opcodes; 11 import com.tc.asm.Type; 12 13 import com.tc.aspectwerkz.exception.WrappedRuntimeException; 14 import com.tc.aspectwerkz.transform.TransformationConstants; 15 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 16 import com.tc.aspectwerkz.transform.inlining.AsmNullAdapter; 17 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.util.HashSet ; 21 import java.util.Set ; 22 23 31 public class ProxyDelegationCompiler implements TransformationConstants { 32 33 41 public static byte[] compileProxyFor( 42 final ClassLoader loader, final Class [] interfaces, final String proxyClassName) { 43 final ClassWriter proxyWriter = AsmHelper.newClassWriter(true); 44 45 final Set methodSignatures = new HashSet (); 46 final String [] interfaceClassNames = new String [interfaces.length]; 47 final String [] interfaceSignatures = new String [interfaces.length]; 48 for (int i = 0; i < interfaces.length; i++) { 49 interfaceClassNames[i] = interfaces[i].getName().replace('.', '/'); 50 interfaceSignatures[i] = 'L' + interfaceClassNames[i] + ';'; 51 } 52 53 ProxyCompilerClassVisitor createProxy = new ProxyDelegationCompiler.ProxyCompilerClassVisitor( 55 proxyWriter, 56 proxyClassName.replace('.', '/'), 57 methodSignatures, 58 interfaceClassNames, 59 interfaceSignatures 60 ); 61 62 for (int i = 0; i < interfaces.length; i++) { 64 Class anInterface = interfaces[i]; 65 final String interfaceClassName = anInterface.getName().replace('.', '/'); 66 67 InputStream in = null; 68 final ClassReader classReader; 69 try { 70 if (loader != null) { 71 in = loader.getResourceAsStream(interfaceClassName + ".class"); 72 } else { 73 in = ClassLoader.getSystemClassLoader().getResourceAsStream(interfaceClassName + ".class"); 74 } 75 classReader = new ClassReader(in); 76 } catch (IOException e) { 77 throw new WrappedRuntimeException("Cannot compile proxy for " + anInterface, e); 78 } finally { 79 try { 80 in.close(); 81 } catch (Throwable t) { 82 ; 83 } 84 } 85 classReader.accept(createProxy, true); } 87 return proxyWriter.toByteArray(); 88 } 89 90 94 public static class ProxyCompilerClassVisitor extends AsmNullAdapter.NullClassAdapter implements Opcodes, TransformationConstants { 95 final ClassVisitor m_proxyCv; 96 final String m_proxyClassName; 97 final Set m_signatures; 98 private int currentInterfaceIndex = 0; 99 final String [] m_interfaceClassNames; 100 final String [] m_interfaceSignatures; 101 102 110 public ProxyCompilerClassVisitor(final ClassVisitor proxyCv, final String proxyClassName, final Set signatures, final String [] interfaceClassNames, final String [] interfaceSignatures) { 111 m_proxyCv = proxyCv; 112 m_proxyClassName = proxyClassName; 113 m_signatures = signatures; 114 m_interfaceClassNames = interfaceClassNames; 115 m_interfaceSignatures = interfaceSignatures; 116 117 m_proxyCv.visit( 118 AsmHelper.JAVA_VERSION, 119 ACC_PUBLIC + ACC_SYNTHETIC + ACC_SUPER, 120 m_proxyClassName, 121 null, 122 OBJECT_CLASS_NAME, 123 interfaceClassNames 124 ); 125 126 for (int i = 0; i < interfaceClassNames.length; i++) { 128 m_interfaceSignatures[i] = 'L' + interfaceClassNames[i] + ';'; 129 m_proxyCv.visitField( 130 ACC_PRIVATE + ACC_SYNTHETIC + ACC_FINAL, 131 "DELEGATE_" + i, 132 m_interfaceSignatures[i], 133 null, 134 null 135 ); 136 } 137 138 StringBuffer ctorDesc = new StringBuffer ("("); 140 for (int i = 0; i < interfaceClassNames.length; i++) { 141 ctorDesc.append(m_interfaceSignatures[i]); 142 } 143 ctorDesc.append(")V"); 144 MethodVisitor init = m_proxyCv.visitMethod( 145 ACC_PUBLIC + ACC_SYNTHETIC, 146 INIT_METHOD_NAME, 147 ctorDesc.toString(), 148 null, 149 null 150 ); 151 init.visitVarInsn(ALOAD, 0); 152 init.visitMethodInsn(INVOKESPECIAL, OBJECT_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE); 153 for (int i = 0; i < interfaceClassNames.length; i++) { 154 init.visitVarInsn(ALOAD, 0); 155 init.visitVarInsn(ALOAD, 1 + i); 156 init.visitFieldInsn(PUTFIELD, m_proxyClassName, "DELEGATE_" + i, m_interfaceSignatures[i]); 157 } 158 init.visitInsn(RETURN); 159 init.visitMaxs(0, 0); 160 } 161 162 172 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String [] exceptions) { 173 if (m_signatures.contains(name + desc)) { 174 return super.visitMethod(access, name, desc, signature, exceptions); 175 } 176 m_signatures.add(name + desc); 177 178 MethodVisitor cv = m_proxyCv.visitMethod( 179 access & ~ACC_ABSTRACT, 180 name, 181 desc, 182 signature, 183 exceptions 184 ); 185 186 cv.visitVarInsn(ALOAD, 0); 187 cv.visitFieldInsn( 188 GETFIELD, 189 m_proxyClassName, 190 "DELEGATE_" + currentInterfaceIndex, 191 m_interfaceSignatures[currentInterfaceIndex] 192 ); 193 AsmHelper.loadArgumentTypes(cv, Type.getArgumentTypes(desc), false); 194 cv.visitMethodInsn( 195 INVOKEINTERFACE, 196 m_interfaceClassNames[currentInterfaceIndex], 197 name, 198 desc 199 ); 200 AsmHelper.addReturnStatement(cv, Type.getReturnType(desc)); 201 cv.visitMaxs(0, 0); 202 203 return cv; 206 } 207 208 211 public void visitEnd() { 212 currentInterfaceIndex++; 213 super.visitEnd(); 214 } 215 } 216 217 } 218 | Popular Tags |