1 22 package org.jboss.proxy.compiler; 23 24 import java.lang.reflect.Method ; 25 26 import org.apache.bcel.Constants; 27 import org.apache.bcel.classfile.JavaClass; 28 import org.apache.bcel.generic.ClassGen; 29 import org.apache.bcel.generic.BasicType; 30 import org.apache.bcel.generic.Type; 31 32 import org.jboss.logging.Logger; 33 34 41 public class ProxyCompiler 42 { 43 44 private static final Logger log = Logger.getLogger(ProxyCompiler.class); 45 46 47 public final static String CLASS_DUMP_PATH = 48 System.getProperty(ProxyCompiler.class.getName() + ".dumpPath", null); 49 50 51 public final static String IMPL_SUFFIX = "$Proxy"; 52 53 54 Runtime runtime; 55 56 57 Class superclass; 58 59 60 Class targetTypes[]; 61 62 63 Method methods[]; 64 65 66 Class proxyType; 67 68 76 public ProxyCompiler(final ClassLoader parent, 77 final Class superclass, 78 final Class targetTypes[], 79 final Method methods[]) 80 throws Exception 81 { 82 this.superclass = superclass; 83 this.targetTypes = targetTypes; 84 this.methods = methods; 85 86 this.runtime = new Runtime (parent); 87 this.runtime.targetTypes = targetTypes; 88 this.runtime.methods = methods; 89 90 runtime.makeProxyType(this); 91 } 92 93 public Class getProxyType() { 94 return proxyType; 95 } 96 97 public String getProxyClassName() { 98 106 return targetTypes[0].getName() + IMPL_SUFFIX; 107 } 108 109 114 public byte[] getCode() 115 { 116 boolean trace = log.isTraceEnabled(); 117 118 final String proxyClassName = getProxyClassName(); 119 final String superClassName = superclass.getName(); 120 121 int icount = 1; for (int i = 0; i < targetTypes.length; i++) { 123 Class targetType = targetTypes[i]; 124 if (targetType.isInterface()) { 125 icount++; 126 } 127 } 128 129 String interfaceNames[] = new String [icount]; 130 interfaceNames[0] = Proxies.ProxyTarget.class.getName(); 131 icount = 1; 132 for (int i = 0; i < targetTypes.length; i++) { 133 Class targetType = targetTypes[i]; 134 if (targetType.isInterface()) { 135 interfaceNames[icount++] = targetType.getName(); 136 } 137 else if (!superclass.isAssignableFrom(targetType)) { 138 throw new RuntimeException ("unexpected: " + targetType); 139 } 140 } 141 142 ClassGen cg = new ClassGen(proxyClassName, 143 superClassName, 144 "<generated>", 145 Constants.ACC_PUBLIC | Constants.ACC_FINAL, 146 interfaceNames); 147 148 ProxyImplementationFactory factory = 149 new ProxyImplementationFactory(superClassName, proxyClassName, cg); 150 151 cg.addField(factory.createInvocationHandlerField()); 152 cg.addField(factory.createRuntimeField()); 153 cg.addMethod(factory.createConstructor()); 154 155 157 cg.addMethod(factory.createGetInvocationHandler()); 158 cg.addMethod(factory.createGetTargetTypes()); 159 160 boolean haveToString = false; 161 162 if (trace) log.trace("Creating proxy methods..."); 163 164 for (int i = 0; i < methods.length; i++) 166 { 167 Method m = methods[i]; 168 if (trace) log.trace("Reflected method: " + m); 169 170 String name = m.getName(); 171 Class rTypeClass = m.getReturnType(); 172 String rTypeName = rTypeClass.getName(); 173 Type rType = Utility.getType(rTypeClass); 174 Type[] pTypes = Utility.getTypes(m.getParameterTypes()); 175 String [] exceptionNames = getNames(m.getExceptionTypes()); 176 177 if (name.equals("toString") && pTypes.length == 0) { 178 haveToString = true; 179 } 180 181 org.apache.bcel.classfile.Method proxyMethod = 182 factory.createProxyMethod(name, i, rType, pTypes, exceptionNames); 183 184 if (trace) log.trace("Created proxy method: " + proxyMethod); 185 186 cg.addMethod(proxyMethod); 187 } 188 189 if (!haveToString) { 190 cg.addMethod(factory.createToString()); 191 } 192 193 JavaClass jclass = cg.getJavaClass(); 194 if (trace) log.trace("Generated Java class: " + jclass); 195 196 if (CLASS_DUMP_PATH != null) { 198 try { 199 String filename = CLASS_DUMP_PATH + java.io.File.separator + proxyClassName + ".class"; 200 log.info("Dumping generated proxy class to " + filename); 201 jclass.dump(filename); 202 } 203 catch (Exception e) { 204 log.error("Failed to dump class file", e); 205 } 206 } 207 208 return jclass.getBytes(); 209 } 210 211 215 private String [] getNames(Class [] classes) { 216 String [] names = new String [classes.length]; 217 for ( int i = 0; i < classes.length; i++ ) { 218 names[i] = classes[i].getName(); 219 } 220 221 return names; 222 } 223 } 224 | Popular Tags |