/* */ package org.jboss.aop.instrument;
/* */
/* */ import java.io.PrintStream;
/* */ import java.util.Collection;
/* */ import java.util.HashMap;
/* */ import java.util.Iterator;
/* */ import java.util.List;
/* */ import java.util.Map;
/* */ import javassist.CannotCompileException;
/* */ import javassist.CtBehavior;
/* */ import javassist.CtClass;
/* */ import javassist.CtConstructor;
/* */ import javassist.CtMethod;
/* */ import javassist.Modifier;
/* */ import javassist.NotFoundException;
/* */ import javassist.expr.ExprEditor;
/* */ import javassist.expr.MethodCall;
/* */ import javassist.expr.NewExpr;
/* */ import org.jboss.aop.AspectManager;
/* */ import org.jboss.aop.ClassAdvisor;
/* */ import org.jboss.aop.ConByConInfo;
/* */ import org.jboss.aop.ConByMethodInfo;
/* */ import org.jboss.aop.MethodByConInfo;
/* */ import org.jboss.aop.MethodByMethodInfo;
/* */ import org.jboss.aop.pointcut.Pointcut;
/* */ import org.jboss.aop.util.Advisable;
/* */ import org.jboss.aop.util.JavassistMethodHashing;
/* */ import org.jboss.aop.util.logging.AOPLogger;
/* */ import org.jboss.logging.Logger;
/* */
/* */ public abstract class CallerTransformer
/* */ {
/* 56 */ private static final Logger logger = AOPLogger.getLogger(CallerTransformer.class);
/* */
/* 58 */ public static final String CON_BY_CON_INFO_CLASS_NAME = ConByConInfo.class.getName();
/* 59 */ public static final String CON_BY_METHOD_INFO_CLASS_NAME = ConByMethodInfo.class.getName();
/* 60 */ public static final String METHOD_BY_CON_INFO_CLASS_NAME = MethodByConInfo.class.getName();
/* 61 */ public static final String METHOD_BY_METHOD_INFO_CLASS_NAME = MethodByMethodInfo.class.getName();
/* */ Instrumentor instrumentor;
/* */ boolean optimize;
/* */ AspectManager manager;
/* */ CallerInfoAdder callerInfoAdder;
/* */
/* */ protected CallerTransformer(Instrumentor instrumentor, AspectManager manager, boolean optimize, CallerInfoAdder callerInfoAdder)
/* */ {
/* 77 */ this.instrumentor = instrumentor;
/* 78 */ this.optimize = optimize;
/* 79 */ this.manager = manager;
/* 80 */ this.callerInfoAdder = callerInfoAdder;
/* */ }
/* */
/* */ protected abstract CallerExprEditor callerExprEditorFactory(ClassAdvisor paramClassAdvisor, CtClass paramCtClass);
/* */
/* */ public boolean applyCallerPointcuts(CtClass clazz, ClassAdvisor advisor) throws CannotCompileException {
/* 87 */ if ((!advisor.getManager().isWithin()) && (!advisor.getManager().isCall()) && (!advisor.getManager().isWithincode()))
/* */ {
/* 89 */ if ((AspectManager.verbose) && (logger.isDebugEnabled())) logger.debug("There are no caller pointcuts!");
/* 90 */ return false;
/* */ }
/* 92 */ CallerExprEditor expr = callerExprEditorFactory(advisor, clazz);
/* 93 */ CtMethod[] methods = clazz.getDeclaredMethods();
/* 94 */ for (int i = 0; i < methods.length; i++)
/* */ {
/* 96 */ if (!Advisable.isAdvisable(methods[i]))
/* */ continue;
/* 98 */ methods[i].instrument(expr);
/* */ }
/* */
/* 102 */ CtConstructor[] cons = clazz.getDeclaredConstructors();
/* 103 */ for (int i = 0; i < cons.length; i++)
/* */ {
/* 105 */ cons[i].instrument(expr);
/* */ }
/* */
/* 108 */ return expr.appliedCallerBinding;
/* */ }
/* */
/* */ private boolean isTargetConstructorAdvised(CtConstructor calledConstructor)
/* */ {
/* */ try
/* */ {
/* 115 */ ClassAdvisor adv = this.manager.getTempClassAdvisor(calledConstructor.getDeclaringClass());
/* 116 */ return ConstructorExecutionTransformer.isAdvisableConstructor(calledConstructor, adv);
/* */ }
/* */ catch (Exception e) {
/* */ }
/* 120 */ throw new RuntimeException(e);
/* */ }
/* */
/* */ private static String getHashString(long hash)
/* */ {
/* 127 */ if (hash < 0L)
/* */ {
/* 129 */ return "_N_" + -1L * hash;
/* */ }
/* */
/* 133 */ return "_" + hash;
/* */ }
/* */
/* */ protected static String getUniqueInvocationFieldname(long callingHash, String classname, long calledHash)
/* */ {
/* 139 */ classname = classname.replace('.', '_');
/* 140 */ classname = classname.replace('/', '_');
/* */
/* 142 */ return getHashString(callingHash) + classname + getHashString(calledHash);
/* */ }
/* */
/* */ protected static String getConByConInfoName(long callingIndex, String classname, long calledHash)
/* */ {
/* 147 */ return "aop$constructorCall_con_" + getUniqueInvocationFieldname(callingIndex, classname, calledHash);
/* */ }
/* */
/* */ protected static String getConByMethodInfoName(long callingHash, String classname, long calledHash)
/* */ {
/* 152 */ return "aop$constructorCall_" + getUniqueInvocationFieldname(callingHash, classname, calledHash);
/* */ }
/* */
/* */ protected static String getMethodByConInfoName(int index, String classname, long calledHash)
/* */ {
/* 157 */ return "aop$methodCall_con_" + getUniqueInvocationFieldname(index, classname, calledHash);
/* */ }
/* */
/* */ protected static String getMethodByMethodInfoName(long callingHash, String classname, long calledHash)
/* */ {
/* 162 */ return "aop$methodCall_" + getUniqueInvocationFieldname(callingHash, classname, calledHash);
/* */ }
/* */
/* */ protected static String conByConInfoFromWeakReference(String localName, String infoName)
/* */ {
/* 167 */ return TransformerCommon.infoFromWeakReference(CON_BY_CON_INFO_CLASS_NAME, localName, infoName);
/* */ }
/* */
/* */ protected static String conByMethodInfoFromWeakReference(String localName, String infoName)
/* */ {
/* 172 */ return TransformerCommon.infoFromWeakReference(CON_BY_METHOD_INFO_CLASS_NAME, localName, infoName);
/* */ }
/* */
/* */ protected static String methodByMethodInfoFromWeakReference(String localName, String infoName)
/* */ {
/* 177 */ return TransformerCommon.infoFromWeakReference(METHOD_BY_METHOD_INFO_CLASS_NAME, localName, infoName);
/* */ }
/* */
/* */ protected static String methodByConInfoFromWeakReference(String localName, String infoName)
/* */ {
/* 182 */ return TransformerCommon.infoFromWeakReference(METHOD_BY_CON_INFO_CLASS_NAME, localName, infoName);
/* */ }
/* */
/* */ abstract class CallerExprEditor extends ExprEditor
/* */ {
/* */ CtClass callingClass;
/* */ ClassAdvisor advisor;
/* */ List constructors;
/* 284 */ public boolean appliedCallerBinding = false;
/* */
/* 286 */ HashMap callerInfos = new HashMap();
/* 287 */ int invocationCounter = 0;
/* */
/* */ public CallerExprEditor(ClassAdvisor advisor, CtClass callingClass)
/* */ {
/* 291 */ this.advisor = advisor;
/* 292 */ this.callingClass = callingClass;
/* 293 */ this.constructors = CallerTransformer.this.instrumentor.getConstructors(callingClass);
/* */ }
/* */
/* */ private synchronized String getUniqueInvocationClassname(String classname)
/* */ {
/* 298 */ return classname + "_" + ++this.invocationCounter + "_";
/* */ }
/* */
/* */ protected String getOptimizedConCalledByMethodInvocationClassName(long callingHash, String classname, long calledHash)
/* */ {
/* 303 */ return getUniqueInvocationClassname(classname) + "ConByMInvocation";
/* */ }
/* */
/* */ protected String getOptimizedConCalledByConInvocationClassName(long callingIndex, String classname, long calledHash)
/* */ {
/* 308 */ return getUniqueInvocationClassname(classname) + "ConByConInvocation";
/* */ }
/* */
/* */ protected String getOptimizedMethodCalledByMethodClassName(long callingHash, String classname, long calledHash)
/* */ {
/* 313 */ return getUniqueInvocationClassname(classname) + "MByMInvocation";
/* */ }
/* */
/* */ protected String getOptimizedMethodCalledByConstructorClassName(int callingIndex, String classname, long calledHash)
/* */ {
/* 318 */ return getUniqueInvocationClassname(classname) + "MByConInvocation";
/* */ }
/* */
/* */ public void edit(MethodCall call) throws CannotCompileException
/* */ {
/* 323 */ String classname = call.getClassName();
/* 324 */ String methodName = call.getMethodName();
/* */ try
/* */ {
/* 327 */ if ((ClassAdvisor.isWithoutAdvisement(methodName)) || (methodName.startsWith("_")) || (classname.startsWith("org.jboss.aop")) || (call.getMethodName().equals("class$")) || (!Instrumentor.isTransformable(this.callingClass)))
/* */ {
/* 334 */ return;
/* */ }
/* */
/* 337 */ CtBehavior behavior = call.where();
/* */
/* 339 */ boolean hasPointcut = false;
/* */
/* 341 */ DeclareChecker.checkDeclares(CallerTransformer.this.manager, call, this.advisor);
/* */
/* 344 */ Map pointcuts = CallerTransformer.this.manager.getPointcuts();
/* 345 */ synchronized (pointcuts)
/* */ {
/* 347 */ Iterator it = pointcuts.values().iterator();
/* 348 */ while (it.hasNext())
/* */ {
/* 350 */ Pointcut p = (Pointcut)it.next();
/* 351 */ if (p.matchesCall(this.advisor, call))
/* */ {
/* 353 */ hasPointcut = true;
/* 354 */ break;
/* */ }
/* */
/* 358 */ if ((AspectManager.verbose) && (CallerTransformer.logger.isDebugEnabled())) CallerTransformer.logger.debug("MethodCall does not match: " + p.getExpr());
/* */ }
/* */ }
/* */
/* 362 */ if (hasPointcut)
/* */ {
/* 364 */ if ((behavior instanceof CtMethod))
/* 365 */ modifyMethod(call, classname);
/* 366 */ else if ((behavior instanceof CtConstructor)) modifyConstructor(call, classname);
/* */ }
/* */ }
/* */ catch (Exception ex)
/* */ {
/* 371 */ System.err.println("error getting:" + classname + ". '" + methodName + "'");
/* 372 */ ex.printStackTrace();
/* 373 */ throw new CannotCompileException(ex);
/* */ }
/* */ }
/* */
/* */ private void modifyConstructor(MethodCall call, String classname)
/* */ throws NotFoundException, CannotCompileException
/* */ {
/* 380 */ CallerTransformer.this.instrumentor.setupBasics(this.callingClass);
/* 381 */ CallerTransformer.ConstructorDetail cd = new CallerTransformer.ConstructorDetail(CallerTransformer.this, this, call, classname);
/* 382 */ setupConstructor(cd);
/* 383 */ replaceMethodCallInCon(cd);
/* 384 */ this.appliedCallerBinding = true;
/* */ }
/* */
/* */ protected void replaceMethodCallInCon(CallerTransformer.ConstructorDetail cd)
/* */ throws CannotCompileException, NotFoundException
/* */ {
/* 391 */ String replaced = CallerTransformer.methodByConInfoFromWeakReference("info", cd.callerInfoField) + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { " + "$_ = ($r)aop$classAdvisor$aop.invokeConstructorCaller(info, this, $0, $args);" + "} else { " + "$_ = $proceed($$); " + "}";
/* */
/* 399 */ cd.call.replace(replaced);
/* */ }
/* */
/* */ private void modifyMethod(MethodCall call, String classname) throws NotFoundException, CannotCompileException
/* */ {
/* 404 */ CallerTransformer.this.instrumentor.setupBasics(this.callingClass);
/* 405 */ CallerTransformer.MethodDetail md = new CallerTransformer.MethodDetail(CallerTransformer.this, this, call, classname);
/* 406 */ setupMethod(md);
/* 407 */ replaceMethodCallInMethod(md);
/* 408 */ this.appliedCallerBinding = true;
/* */ }
/* */
/* */ protected void replaceMethodCallInMethod(CallerTransformer.MethodDetail md)
/* */ throws NotFoundException, CannotCompileException
/* */ {
/* 415 */ String callingObject = ", null";
/* 416 */ if (!Modifier.isStatic(md.where.getModifiers()))
/* */ {
/* 418 */ callingObject = ", this";
/* */ }
/* 420 */ String replaced = CallerTransformer.methodByMethodInfoFromWeakReference("info", md.callerInfoField) + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { " + "$_ = ($r)aop$classAdvisor$aop.invokeCaller(info" + callingObject + ", $0, $args);" + "} else { " + "$_ = $proceed($$); " + "}";
/* */
/* 428 */ md.call.replace(replaced);
/* */ }
/* */
/* */ public void edit(NewExpr call)
/* */ throws CannotCompileException
/* */ {
/* */ try
/* */ {
/* 436 */ String classname = call.getClassName();
/* 437 */ if ((classname.startsWith("org.jboss.aop")) || (!Instrumentor.isTransformable(this.callingClass)))
/* */ {
/* 439 */ return;
/* */ }
/* */
/* 442 */ DeclareChecker.checkDeclares(CallerTransformer.this.manager, call, this.advisor);
/* */
/* 444 */ boolean hasPointcut = false;
/* */
/* 447 */ Map pointcuts = CallerTransformer.this.manager.getPointcuts();
/* 448 */ synchronized (pointcuts)
/* */ {
/* 450 */ Iterator it = pointcuts.values().iterator();
/* 451 */ while (it.hasNext())
/* */ {
/* 453 */ Pointcut p = (Pointcut)it.next();
/* 454 */ if (p.matchesCall(this.advisor, call))
/* */ {
/* 456 */ hasPointcut = true;
/* 457 */ break;
/* */ }
/* */ }
/* */ }
/* 461 */ if (hasPointcut)
/* */ {
/* 463 */ CtBehavior behavior = call.where();
/* 464 */ if ((behavior instanceof CtMethod))
/* 465 */ modifyMethod(call, classname);
/* 466 */ else if ((behavior instanceof CtConstructor)) modifyConstructor(call, classname);
/* */ }
/* */ }
/* */ catch (Exception ex)
/* */ {
/* 471 */ CallerTransformer.logger.error(ex.getMessage());
/* 472 */ throw new CannotCompileException(ex);
/* */ }
/* */ }
/* */
/* */ private void modifyMethod(NewExpr call, String classname) throws Exception, NotFoundException, CannotCompileException
/* */ {
/* 478 */ CallerTransformer.this.instrumentor.setupBasics(this.callingClass);
/* 479 */ CallerTransformer.ConByMethodDetail cd = new CallerTransformer.ConByMethodDetail(CallerTransformer.this, this, call, classname);
/* 480 */ setupMethod(cd);
/* 481 */ replaceConCallInMethod(cd);
/* 482 */ this.appliedCallerBinding = true;
/* */ }
/* */
/* */ protected void replaceConCallInMethod(CallerTransformer.ConByMethodDetail cd)
/* */ throws NotFoundException, CannotCompileException
/* */ {
/* 489 */ String callingObject = "null";
/* 490 */ if (!Modifier.isStatic(cd.where.getModifiers()))
/* */ {
/* 492 */ callingObject = "this";
/* */ }
/* */
/* 495 */ String replaced = CallerTransformer.conByMethodInfoFromWeakReference("info", cd.callerInfoField) + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { " + "java.lang.Object callingObject = " + callingObject + "; " + "$_ = ($r)aop$classAdvisor$aop.invokeConCalledByMethod(info, " + callingObject + ", $args);" + "} else { " + "$_ = $proceed($$); " + "}";
/* */
/* 505 */ cd.call.replace(replaced);
/* */ }
/* */
/* */ private void modifyConstructor(NewExpr call, String classname) throws Exception, NotFoundException, CannotCompileException
/* */ {
/* 510 */ CallerTransformer.this.instrumentor.setupBasics(this.callingClass);
/* 511 */ CallerTransformer.ConByConDetail cd = new CallerTransformer.ConByConDetail(CallerTransformer.this, this, call, classname);
/* 512 */ setupConstructor(cd);
/* 513 */ replaceConCallInCon(cd);
/* 514 */ this.appliedCallerBinding = true;
/* */ }
/* */
/* */ protected void replaceConCallInCon(CallerTransformer.ConByConDetail cd)
/* */ throws CannotCompileException, NotFoundException
/* */ {
/* 521 */ String replaced = CallerTransformer.conByConInfoFromWeakReference("info", cd.callerInfoField) + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { " + "$_ = ($r)aop$classAdvisor$aop.invokeConCalledByCon(info, this, $args);" + "} else { " + "$_ = $proceed($$); " + "}";
/* */
/* 530 */ cd.call.replace(replaced);
/* */ }
/* */
/* */ protected abstract void setupConstructor(CallerTransformer.ConstructorDetail paramConstructorDetail)
/* */ throws NotFoundException, CannotCompileException;
/* */
/* */ protected abstract void setupMethod(CallerTransformer.MethodDetail paramMethodDetail)
/* */ throws NotFoundException, CannotCompileException;
/* */
/* */ protected abstract void setupMethod(CallerTransformer.ConByMethodDetail paramConByMethodDetail)
/* */ throws NotFoundException, CannotCompileException;
/* */
/* */ protected abstract void setupConstructor(CallerTransformer.ConByConDetail paramConByConDetail)
/* */ throws NotFoundException, CannotCompileException;
/* */ }
/* */
/* */ protected class ConByConDetail
/* */ {
/* */ NewExpr call;
/* */ boolean isTgtConAdvised;
/* */ CtConstructor con;
/* */ int callingIndex;
/* */ long calledHash;
/* */ String callerInfoField;
/* */ CtConstructor calledConstructor;
/* */ String classname;
/* */
/* */ ConByConDetail(CallerTransformer.CallerExprEditor editor, NewExpr call, String classname)
/* */ throws NotFoundException
/* */ {
/* 268 */ this.call = call;
/* 269 */ this.con = ((CtConstructor)call.where());
/* 270 */ this.callingIndex = editor.constructors.indexOf(this.con);
/* 271 */ this.calledHash = JavassistMethodHashing.constructorHash(call.getConstructor());
/* 272 */ this.callerInfoField = CallerTransformer.getConByConInfoName(this.callingIndex, classname, this.calledHash);
/* 273 */ this.calledConstructor = call.getConstructor();
/* 274 */ this.classname = classname;
/* 275 */ this.isTgtConAdvised = CallerTransformer.this.isTargetConstructorAdvised(this.calledConstructor);
/* */ }
/* */ }
/* */
/* */ protected class ConByMethodDetail
/* */ {
/* */ NewExpr call;
/* */ boolean isTgtConAdvised;
/* */ CtMethod where;
/* */ long callingHash;
/* */ long calledHash;
/* */ String callerInfoField;
/* */ CtConstructor calledConstructor;
/* */ String classname;
/* */
/* */ ConByMethodDetail(CallerTransformer.CallerExprEditor editor, NewExpr call, String classname)
/* */ throws NotFoundException
/* */ {
/* 244 */ this.call = call;
/* 245 */ this.where = ((CtMethod)call.where());
/* 246 */ this.callingHash = JavassistMethodHashing.methodHash(this.where);
/* 247 */ this.calledHash = JavassistMethodHashing.constructorHash(call.getConstructor());
/* 248 */ this.callerInfoField = CallerTransformer.getConByMethodInfoName(this.callingHash, classname, this.calledHash);
/* 249 */ this.calledConstructor = call.getConstructor();
/* 250 */ this.classname = classname;
/* 251 */ this.isTgtConAdvised = CallerTransformer.this.isTargetConstructorAdvised(this.calledConstructor);
/* */ }
/* */ }
/* */
/* */ protected class MethodDetail
/* */ {
/* */ MethodCall call;
/* */ CtMethod where;
/* */ long callingHash;
/* */ long calledHash;
/* */ String callerInfoField;
/* */ CtMethod calledMethod;
/* */ String classname;
/* */
/* */ MethodDetail(CallerTransformer.CallerExprEditor editor, MethodCall call, String classname)
/* */ throws NotFoundException
/* */ {
/* 220 */ this.call = call;
/* 221 */ this.where = ((CtMethod)call.where());
/* 222 */ this.callingHash = JavassistMethodHashing.methodHash(this.where);
/* 223 */ this.calledHash = JavassistMethodHashing.methodHash(call.getMethod());
/* 224 */ this.callerInfoField = CallerTransformer.getMethodByMethodInfoName(this.callingHash, classname, this.calledHash);
/* 225 */ this.calledMethod = call.getMethod();
/* */
/* 227 */ this.classname = classname;
/* */ }
/* */ }
/* */
/* */ protected class ConstructorDetail
/* */ {
/* */ MethodCall call;
/* */ CtConstructor con;
/* */ int callingIndex;
/* */ long calledHash;
/* */ String callerInfoField;
/* */ CtMethod calledMethod;
/* */ String classname;
/* */
/* */ ConstructorDetail(CallerTransformer.CallerExprEditor editor, MethodCall call, String classname)
/* */ throws NotFoundException
/* */ {
/* 198 */ this.call = call;
/* 199 */ this.con = ((CtConstructor)call.where());
/* 200 */ this.callingIndex = editor.constructors.indexOf(this.con);
/* 201 */ this.calledHash = JavassistMethodHashing.methodHash(call.getMethod());
/* 202 */ this.callerInfoField = CallerTransformer.getMethodByConInfoName(this.callingIndex, classname, this.calledHash);
/* 203 */ this.calledMethod = call.getMethod();
/* 204 */ this.classname = classname;
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.aop.instrument.CallerTransformer
* JD-Core Version: 0.6.0
*/