1 4 package com.tc.aspectwerkz.proxy; 5 6 import com.tc.asm.*; 7 8 import com.tc.aspectwerkz.exception.WrappedRuntimeException; 9 import com.tc.aspectwerkz.transform.TransformationConstants; 10 import com.tc.aspectwerkz.transform.inlining.AsmCopyAdapter; 11 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 12 import com.tc.aspectwerkz.transform.inlining.AsmNullAdapter; 13 14 import java.io.IOException ; 15 import java.io.InputStream ; 16 import java.lang.reflect.Modifier ; 17 18 29 public class ProxySubclassingCompiler implements TransformationConstants { 30 31 38 public static byte[] compileProxyFor(final Class clazz, final String proxyClassName) { 39 return compileProxyFor(clazz.getClassLoader(), clazz.getName(), proxyClassName); 40 } 41 42 50 public static byte[] compileProxyFor(final ClassLoader loader, final String className, final String proxyClassName) { 51 52 final String targetClassName = className.replace('.', '/'); 53 final ClassWriter proxyWriter = AsmHelper.newClassWriter(true); 54 55 InputStream in = null; 56 final ClassReader classReader; 57 try { 58 if (loader != null) { 59 in = loader.getResourceAsStream(targetClassName + ".class"); 60 } else { 61 in = ClassLoader.getSystemClassLoader().getResourceAsStream(targetClassName + ".class"); 62 } 63 classReader = new ClassReader(in); 64 } catch (IOException e) { 65 throw new WrappedRuntimeException("Cannot compile proxy for " + className, e); 66 } finally { 67 try { 68 in.close(); 69 } catch (Throwable t) { 70 ; 71 } 72 } 73 74 ClassVisitor createProxy = new ProxyCompilerClassVisitor(proxyWriter, proxyClassName.replace('.', '/')); 75 classReader.accept(createProxy, true); return proxyWriter.toByteArray(); 77 } 78 79 84 private static class ProxyCompilerClassVisitor extends AsmNullAdapter.NullClassAdapter { 85 86 final private ClassVisitor m_proxyCv; 87 final private String m_proxyClassName; 88 private String m_className; 89 90 public ProxyCompilerClassVisitor(final ClassVisitor proxyCv, final String proxyClassName) { 91 m_proxyCv = proxyCv; 92 m_proxyClassName = proxyClassName; 93 } 94 95 104 public void visit(final int version, 105 final int access, 106 final String name, 107 final String signature, 108 final String superName, 109 final String [] interfaces) { 110 if (Modifier.isFinal(access)) { 111 throw new RuntimeException ("Cannot create a proxy from final class " + name); 112 } 113 m_className = name; 114 m_proxyCv.visit( 115 version, 116 ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC, 117 m_proxyClassName.replace('.', '/'), 118 signature, 119 name, 120 interfaces 121 ); 122 } 123 124 134 public MethodVisitor visitMethod(final int access, 135 final String name, 136 final String desc, 137 final String signature, 138 final String [] exceptions) { 139 final MethodVisitor proxyCode; 140 final boolean copyAnnotation; 141 if (Modifier.isFinal(access) || Modifier.isPrivate(access) || Modifier.isNative(access)) { 142 proxyCode = AsmNullAdapter.NullMethodAdapter.NULL_METHOD_ADAPTER; 145 copyAnnotation = false; 146 } else if (CLINIT_METHOD_NAME.equals(name)) { 147 proxyCode = AsmNullAdapter.NullMethodAdapter.NULL_METHOD_ADAPTER; 149 copyAnnotation = false; 150 } else if (INIT_METHOD_NAME.equals(name)) { 151 proxyCode = m_proxyCv.visitMethod( 153 access + ACC_SYNTHETIC, 154 INIT_METHOD_NAME, 155 desc, 156 signature, 157 exceptions 158 ); 159 160 proxyCode.visitVarInsn(ALOAD, 0); 161 AsmHelper.loadArgumentTypes(proxyCode, Type.getArgumentTypes(desc), false); 162 proxyCode.visitMethodInsn(INVOKESPECIAL, m_className, INIT_METHOD_NAME, desc); 163 proxyCode.visitInsn(RETURN); 164 proxyCode.visitMaxs(0, 0); 165 copyAnnotation = true; 166 } else { 167 proxyCode = m_proxyCv.visitMethod( 169 access + ACC_SYNTHETIC, 170 name, 171 desc, 172 signature, 173 exceptions 174 ); 175 176 if (Modifier.isStatic(access)) { 177 AsmHelper.loadArgumentTypes(proxyCode, Type.getArgumentTypes(desc), true); 178 proxyCode.visitMethodInsn(INVOKESTATIC, m_className, name, desc); 179 AsmHelper.addReturnStatement(proxyCode, Type.getReturnType(desc)); 180 proxyCode.visitMaxs(0, 0); 181 } else { 182 proxyCode.visitVarInsn(ALOAD, 0); 183 AsmHelper.loadArgumentTypes(proxyCode, Type.getArgumentTypes(desc), false); 184 proxyCode.visitMethodInsn(INVOKESPECIAL, m_className, name, desc); 185 AsmHelper.addReturnStatement(proxyCode, Type.getReturnType(desc)); 186 proxyCode.visitMaxs(0, 0); 187 } 188 copyAnnotation = true; 189 } 190 191 if (copyAnnotation) { 193 return new AsmCopyAdapter.CopyMethodAnnotationElseNullAdapter(proxyCode); 194 } else { 195 return AsmNullAdapter.NullMethodAdapter.NULL_METHOD_ADAPTER; 196 } 197 } 198 199 206 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 207 return new AsmCopyAdapter.CopyAnnotationAdapter( 208 super.visitAnnotation(desc, visible), 209 m_proxyCv.visitAnnotation(desc, visible) 210 ); 211 } 212 213 218 public void visitAttribute(Attribute attribute) { 219 m_proxyCv.visitAttribute(attribute); 220 } 221 } 222 } 223 | Popular Tags |