1 8 package org.codehaus.aspectwerkz.proxy; 9 10 import java.lang.reflect.Method ; 11 import java.lang.reflect.Modifier ; 12 import java.lang.reflect.Constructor ; 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.io.BufferedInputStream ; 16 import java.io.ByteArrayInputStream ; 17 18 import org.codehaus.aspectwerkz.transform.TransformationConstants; 19 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper; 20 import org.codehaus.aspectwerkz.reflect.ReflectHelper; 21 import org.codehaus.aspectwerkz.util.ContextClassLoader; 22 import org.codehaus.aspectwerkz.exception.WrappedRuntimeException; 23 import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper; 24 import org.objectweb.asm.ClassWriter; 25 import org.objectweb.asm.CodeVisitor; 26 import org.objectweb.asm.Type; 27 import org.objectweb.asm.ClassReader; 28 import org.objectweb.asm.ClassAdapter; 29 import org.objectweb.asm.ClassVisitor; 30 import org.objectweb.asm.Attribute; 31 import org.objectweb.asm.attrs.Attributes; 32 33 44 public class ProxyCompiler implements TransformationConstants { 45 private final static String [] EMPTY_STRING_ARRAY = new String [0]; 46 47 55 public static InputStream getProxyResourceAsStream(final ClassLoader loader, final String proxyClassName) { 56 String className = Proxy.getUniqueClassNameFromProxy(proxyClassName); 57 if (className != null) { 58 byte[] proxy = compileProxyFor(loader, className, proxyClassName); 59 return new BufferedInputStream (new ByteArrayInputStream (proxy)); 60 } else { 61 return null; 62 } 63 } 64 65 72 public static byte[] compileProxyFor(final Class clazz, final String proxyClassName) { 73 return compileProxyFor(clazz.getClassLoader(), clazz.getName(), proxyClassName); 74 } 75 76 84 public static byte[] compileProxyFor(final ClassLoader loader, final String className, final String proxyClassName) { 85 86 final String targetClassName = className.replace('.', '/'); 87 final ClassWriter proxyWriter = AsmHelper.newClassWriter(true); 88 89 InputStream in = null; 90 final ClassReader classReader; 91 try { 92 if (loader != null) { 93 in = loader.getResourceAsStream(targetClassName + ".class"); 94 } else { 95 in = ClassLoader.getSystemClassLoader().getResourceAsStream(targetClassName + ".class"); 96 } 97 classReader = new ClassReader(in); 98 } catch (IOException e) { 99 throw new WrappedRuntimeException("Cannot compile proxy for " + className, e); 100 } finally { 101 try { 102 in.close(); 103 } catch (Throwable t) { 104 ; 105 } 106 } 107 108 ClassVisitor createProxy = new ProxyCompilerClassVisitor(proxyWriter, proxyClassName.replace('.', '/')); 109 classReader.accept(createProxy, Attributes.getDefaultAttributes(), true); return proxyWriter.toByteArray(); 111 } 112 113 118 private static class ProxyCompilerClassVisitor extends AsmAnnotationHelper.NullClassAdapter { 119 120 final private ClassVisitor m_proxyCv; 121 final private String m_proxyClassName; 122 private String m_className; 123 124 public ProxyCompilerClassVisitor(final ClassVisitor proxyCv, final String proxyClassName) { 125 m_proxyCv = proxyCv; 126 m_proxyClassName = proxyClassName; 127 } 128 129 138 public void visit(final int version, 139 final int access, 140 final String name, 141 final String superName, 142 final String [] interfaces, 143 final String sourceFile) { 144 if (Modifier.isFinal(access)) { 145 throw new RuntimeException ("Cannot create a proxy from final class " + name); 146 } 147 m_className = name; 148 m_proxyCv.visit( 149 version, 150 ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC, 151 m_proxyClassName.replace('.', '/'), 152 name, 153 interfaces, 154 null 155 ); 156 } 157 158 168 public CodeVisitor visitMethod(final int access, 169 final String name, 170 final String desc, 171 final String [] exceptions, 172 final Attribute attrs) { 173 if (Modifier.isFinal(access) || Modifier.isPrivate(access) || Modifier.isNative(access)) { 174 ; 177 } else if (CLINIT_METHOD_NAME.equals(name)) { 178 ; 180 } else if (INIT_METHOD_NAME.equals(name)) { 181 CodeVisitor proxyCode = m_proxyCv.visitMethod( 183 access + ACC_SYNTHETIC, 184 INIT_METHOD_NAME, 185 desc, 186 exceptions, 187 attrs 188 ); 189 190 proxyCode.visitVarInsn(ALOAD, 0); 191 AsmHelper.loadArgumentTypes(proxyCode, Type.getArgumentTypes(desc), false); 192 proxyCode.visitMethodInsn(INVOKESPECIAL, m_className, INIT_METHOD_NAME, desc); 193 proxyCode.visitInsn(RETURN); 194 proxyCode.visitMaxs(0, 0); 195 } else { 196 CodeVisitor proxyCode = m_proxyCv.visitMethod( 198 access + ACC_SYNTHETIC, 199 name, 200 desc, 201 exceptions, 202 attrs 203 ); 204 205 if (Modifier.isStatic(access)) { 206 AsmHelper.loadArgumentTypes(proxyCode, Type.getArgumentTypes(desc), true); 207 proxyCode.visitMethodInsn(INVOKESTATIC, m_className, name, desc); 208 AsmHelper.addReturnStatement(proxyCode, Type.getReturnType(desc)); 209 proxyCode.visitMaxs(0, 0); 210 } else { 211 proxyCode.visitVarInsn(ALOAD, 0); 212 AsmHelper.loadArgumentTypes(proxyCode, Type.getArgumentTypes(desc), false); 213 proxyCode.visitMethodInsn(INVOKESPECIAL, m_className, name, desc); 214 AsmHelper.addReturnStatement(proxyCode, Type.getReturnType(desc)); 215 proxyCode.visitMaxs(0, 0); 216 } 217 } 218 219 return AsmAnnotationHelper.NullCodeAdapter.NULL_CODE_ADAPTER; 220 } 221 } 222 223 } 314 | Popular Tags |