1 22 package org.jboss.aop.advice; 23 24 import javassist.ClassPool; 25 import javassist.CtClass; 26 import javassist.CtField; 27 import javassist.CtMethod; 28 import javassist.CtNewMethod; 29 import org.jboss.aop.AspectManager; 30 import org.jboss.aop.instrument.OptimizedMethodInvocations; 31 import org.jboss.aop.instrument.TransformerCommon; 32 import org.jboss.aop.joinpoint.Invocation; 33 import org.jboss.aop.joinpoint.Joinpoint; 34 import org.jboss.aop.joinpoint.MethodJoinpoint; 35 36 import java.lang.reflect.Field ; 37 import java.lang.reflect.Method ; 38 import java.util.ArrayList ; 39 40 46 public class PerVmAdvice 47 { 48 private static long counter = 0; 49 50 public static synchronized Interceptor generateOptimized(Joinpoint joinpoint, AspectManager manager, String adviceName, AspectDefinition a) throws Exception 51 { 52 Object aspect = manager.getPerVMAspect(a); 53 return generateInterceptor(joinpoint, aspect, adviceName); 54 55 } 56 57 public static Interceptor generateInterceptor(Joinpoint joinpoint, Object aspect, String adviceName) throws Exception 58 { 59 ClassLoader cl = aspect.getClass().getClassLoader(); 60 String name = "org.jboss.aop.advice." + aspect.getClass().getName() + "_z_" + adviceName + "_" + System.identityHashCode(cl); 61 Class iclass = null; 62 63 if (cl == null) 64 { 65 cl = Thread.currentThread().getContextClassLoader(); 67 } 68 synchronized (PerVmAdvice.class) 69 { 70 try 71 { 72 iclass = cl.loadClass(name); 73 } 74 catch(Exception e) 75 { 76 } 77 78 ClassPool pool; 79 try 80 { 81 pool = AspectManager.instance().findClassPool(cl); 82 } 83 catch (RuntimeException e) 84 { 85 throw new RuntimeException (e); 87 } 88 89 if (iclass == null) 90 { 91 Method[] methods = aspect.getClass().getMethods(); 92 ArrayList matches = new ArrayList (); 93 for (int i = 0; i < methods.length; i++) 94 { 95 if (methods[i].getName().equals(adviceName)) matches.add(methods[i]); 96 } 97 98 if (matches.size() == 1) 100 { 101 Method method = (Method) matches.get(0); 102 if (joinpoint instanceof MethodJoinpoint) 103 { 104 if (method.getParameterTypes().length == 0 || method.getParameterTypes().length > 1 || !Invocation.class.isAssignableFrom(method.getParameterTypes()[0])) 105 { 106 return generateArgsInterceptor(aspect, method, joinpoint); 107 } 108 } 109 } 110 111 CtClass clazz = TransformerCommon.makeClass(pool, name); 113 114 CtClass interceptorInterface = pool.get("org.jboss.aop.advice.Interceptor"); 116 CtClass abstractAdviceClass = pool.get("org.jboss.aop.advice.AbstractAdvice"); 117 clazz.setSuperclass(abstractAdviceClass); 118 119 CtClass aspectClass = pool.get(aspect.getClass().getName()); 121 CtField field = new CtField(aspectClass, "aspectField", clazz); 122 field.setModifiers(javassist.Modifier.PUBLIC); 123 clazz.addField(field); 124 CtMethod getNameTemplate = interceptorInterface.getDeclaredMethod("getName"); 126 String getNameBody = 127 "{ " + 128 " return \"" + aspect.getClass().getName() + "." + adviceName + "\"; " + 129 "}"; 130 CtMethod getName = CtNewMethod.make(getNameTemplate.getReturnType(), "getName", getNameTemplate.getParameterTypes(), getNameTemplate.getExceptionTypes(), getNameBody, clazz); 131 getName.setModifiers(javassist.Modifier.PUBLIC); 132 clazz.addMethod(getName); 133 134 CtMethod invokeTemplate = interceptorInterface.getDeclaredMethod("invoke"); 136 StringBuffer invokeBody = new StringBuffer (); 137 invokeBody.append("{ "); 138 if (matches.size() > 1) 139 { 140 for (int i = 0; i < matches.size(); i++) 141 { 142 Method advice = (Method) matches.get(i); 143 String param = advice.getParameterTypes()[0].getName(); 144 invokeBody.append(" if ($1 instanceof " + param + ") return aspectField." + adviceName + "((" + param + ")$1); "); 145 } 146 invokeBody.append(" return (org.jboss.aop.joinpoint.Invocation)null; "); 147 } 148 else 149 { 150 Method advice = (Method) matches.get(0); 151 String param = advice.getParameterTypes()[0].getName(); 152 invokeBody.append("return aspectField." + adviceName + "((" + param + ")$1); "); 153 } 154 invokeBody.append("}"); 155 CtMethod invoke = CtNewMethod.make(invokeTemplate.getReturnType(), "invoke", invokeTemplate.getParameterTypes(), invokeTemplate.getExceptionTypes(), invokeBody.toString(), clazz); 156 invoke.setModifiers(javassist.Modifier.PUBLIC); 157 clazz.addMethod(invoke); 158 159 iclass = TransformerCommon.toClass(clazz, cl); 160 } 161 } 162 Interceptor rtn = (Interceptor) iclass.newInstance(); 163 Field f = iclass.getField("aspectField"); 164 f.set(rtn, aspect); 165 return rtn; 166 } 167 168 public static Interceptor generateArgsInterceptor(Object aspect, Method advice, Joinpoint joinpoint) throws Exception 169 { 170 Method method = ((MethodJoinpoint) joinpoint).getMethod(); 171 String optimized = OptimizedMethodInvocations.getOptimizedInvocationClassName(method); 172 173 174 ClassPool pool = AspectManager.instance().findClassPool(aspect.getClass().getClassLoader()); 175 CtClass clazz = TransformerCommon.makeClass(pool, "org.jboss.aop.advice." + aspect.getClass().getName() + counter++); 176 177 CtClass interceptorInterface = pool.get("org.jboss.aop.advice.Interceptor"); 179 clazz.addInterface(interceptorInterface); 180 181 CtClass aspectClass = pool.get(aspect.getClass().getName()); 183 CtField field = new CtField(aspectClass, "aspectField", clazz); 184 field.setModifiers(javassist.Modifier.PUBLIC); 185 clazz.addField(field); 186 CtMethod getNameTemplate = interceptorInterface.getDeclaredMethod("getName"); 188 String getNameBody = 189 "{ " + 190 " return \"" + aspect.getClass().getName() + "." + advice.getName() + "\"; " + 191 "}"; 192 CtMethod getName = CtNewMethod.make(getNameTemplate.getReturnType(), "getName", getNameTemplate.getParameterTypes(), getNameTemplate.getExceptionTypes(), getNameBody, clazz); 193 getName.setModifiers(javassist.Modifier.PUBLIC); 194 clazz.addMethod(getName); 195 196 String invokeBody = null; 198 if (Invocation.class.isAssignableFrom(advice.getParameterTypes()[0])) 199 { 200 invokeBody = getInvocationBody(optimized, advice, method); 201 } 202 else 203 { 204 invokeBody = getThreadStackBody(optimized, advice, method); 205 } 206 CtMethod invoke = CtNewMethod.make(invokeBody, clazz); 207 invoke.setModifiers(javassist.Modifier.PUBLIC); 208 clazz.addMethod(invoke); 209 Class iclass = TransformerCommon.toClass(clazz); 210 211 Interceptor rtn = (Interceptor) iclass.newInstance(); 212 Field f = iclass.getField("aspectField"); 213 f.set(rtn, aspect); 214 return rtn; 215 } 216 217 private static String getThreadStackBody(String optimized, Method advice, Method method) 218 { 219 String invokeBody = 220 "public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws java.lang.Throwable " + 221 "{ " + 222 " " + optimized + " optimized = (" + optimized + ")invocation; " + 223 " org.jboss.aop.joinpoint.CurrentInvocation.push(invocation); " + 224 " try {"; 225 invokeBody += "return ($w)aspectField." + advice.getName() + "("; 226 Class [] adviceParams = advice.getParameterTypes(); 227 Class [] params = method.getParameterTypes(); 228 boolean first = true; 229 if (adviceParams.length > 0) 230 { 231 int adviceParam = 0; 232 for (int i = 0; i < params.length && adviceParam < adviceParams.length; i++) 233 { 234 if (adviceParams[adviceParam].equals(params[i])) 235 { 236 adviceParam++; 237 if (first) 238 { 239 first = false; 240 } 241 else 242 { 243 invokeBody += ", "; 244 } 245 invokeBody += "optimized.arg" + i; 246 } 247 } 248 } 249 invokeBody += "); "; 250 invokeBody += 251 " } finally { org.jboss.aop.joinpoint.CurrentInvocation.pop(); }"; 252 invokeBody += 253 "}"; 254 return invokeBody; 255 } 256 257 private static String getInvocationBody(String optimized, Method advice, Method method) 258 { 259 String invokeBody = 260 "public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws java.lang.Throwable " + 261 "{ " + 262 " " + optimized + " optimized = (" + optimized + ")invocation; " + 263 " return ($w)aspectField." + advice.getName() + "(optimized"; 264 Class [] adviceParams = advice.getParameterTypes(); 265 Class [] params = method.getParameterTypes(); 266 if (adviceParams.length > 0) 267 { 268 int adviceParam = 1; 269 for (int i = 0; i < params.length && adviceParam < adviceParams.length; i++) 270 { 271 if (adviceParams[adviceParam].equals(params[i])) 272 { 273 adviceParam++; 274 invokeBody += ", "; 275 invokeBody += "optimized.arg" + i; 276 } 277 } 278 } 279 invokeBody += "); "; 280 invokeBody += 281 "}"; 282 return invokeBody; 283 } 284 } 285 | Popular Tags |