1 /***************************************************************************************
2 * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.transform.delegation;
9
10 import org.codehaus.aspectwerkz.definition.SystemDefinition;
11 import org.codehaus.aspectwerkz.expression.ExpressionContext;
12 import org.codehaus.aspectwerkz.expression.PointcutType;
13 import org.codehaus.aspectwerkz.reflect.ClassInfo;
14 import org.codehaus.aspectwerkz.reflect.MemberInfo;
15 import org.codehaus.aspectwerkz.reflect.impl.javassist.JavassistClassInfo;
16 import org.codehaus.aspectwerkz.reflect.impl.javassist.JavassistConstructorInfo;
17 import org.codehaus.aspectwerkz.reflect.impl.javassist.JavassistMethodInfo;
18 import org.codehaus.aspectwerkz.transform.Context;
19 import org.codehaus.aspectwerkz.transform.TransformationUtil;
20 import org.codehaus.aspectwerkz.transform.Transformer;
21 import org.codehaus.aspectwerkz.transform.TransformationConstants;
22 import org.codehaus.aspectwerkz.transform.TransformationConstants;
23
24 import java.util.Iterator;
25 import java.util.List;
26
27 import javassist.CannotCompileException;
28 import javassist.CtBehavior;
29 import javassist.CtClass;
30 import javassist.CtConstructor;
31 import javassist.CtMethod;
32 import javassist.Modifier;
33 import javassist.NotFoundException;
34 import javassist.expr.ExprEditor;
35 import javassist.expr.Handler;
36
37 /***
38 * Advises HANDLER join points.
39 *
40 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
41 */
42 public class HandlerTransformer implements Transformer {
43 /***
44 * The join point index.
45 */
46
47
48 /***
49 * Transforms the call side pointcuts.
50 *
51 * @param context the transformation context
52 * @param klass the class set.
53 */
54 public void transform(final Context context, final Klass klass) throws NotFoundException, CannotCompileException {
55 List definitions = context.getDefinitions();
56
57
58
59
60 for (Iterator it = definitions.iterator(); it.hasNext();) {
61 final SystemDefinition definition = (SystemDefinition) it.next();
62 final CtClass ctClass = klass.getCtClass();
63 ClassInfo classInfo = JavassistClassInfo.getClassInfo(ctClass, context.getLoader());
64 if (classFilter(definition, new ExpressionContext(PointcutType.HANDLER, null, classInfo), ctClass)) {
65 continue;
66 }
67 ctClass.instrument(new ExprEditor() {
68 public void edit(Handler handlerExpr) throws CannotCompileException {
69 try {
70 CtClass exceptionClass = null;
71 try {
72 exceptionClass = handlerExpr.getType();
73 } catch (NullPointerException e) {
74 return;
75 }
76 CtBehavior where = null;
77 try {
78 where = handlerExpr.where();
79 } catch (RuntimeException e) {
80
81 where = ctClass.getClassInitializer();
82 }
83 MemberInfo withinMethodInfo = null;
84 if (where instanceof CtMethod) {
85 withinMethodInfo = JavassistMethodInfo.getMethodInfo((CtMethod) where, context.getLoader());
86 } else if (where instanceof CtConstructor) {
87 withinMethodInfo = JavassistConstructorInfo.getConstructorInfo(
88 (CtConstructor) where,
89 context.getLoader());
90 }
91 ClassInfo exceptionClassInfo = JavassistClassInfo.getClassInfo(exceptionClass, context
92 .getLoader());
93 ExpressionContext ctx = new ExpressionContext(
94 PointcutType.HANDLER,
95 exceptionClassInfo,
96 withinMethodInfo);
97 if (definition.hasPointcut(ctx)) {
98
99
100 StringBuffer body = new StringBuffer();
101 body.append(TransformationConstants.JOIN_POINT_MANAGER_FIELD);
102 body.append('.');
103 body.append(TransformationConstants.PROCEED_WITH_HANDLER_JOIN_POINT_METHOD);
104 body.append('(');
105
106
107
108
109 body.append(JavassistHelper.calculateHash(exceptionClass));
110 body.append(',');
111 body.append(klass.getJoinPointIndex());
112 if (Modifier.isStatic(where.getModifiers())) {
113 body.append(", $1, (Object)null, \"");
114 } else {
115 body.append(", $1, this, \"");
116 }
117
118
119 body.append(exceptionClass.getName().replace('/', '.'));
120 body.append("\");");
121 handlerExpr.insertBefore(body.toString());
122 context.markAsAdvised();
123 klass.incrementJoinPointIndex();
124 }
125 } catch (NotFoundException nfe) {
126 nfe.printStackTrace();
127 }
128 }
129 });
130 }
131
132
133
134 klass.flushJoinPointIndex();
135 }
136
137 /***
138 * Filters the classes to be transformed.
139 *
140 * @param definition the definition
141 * @param ctx the context
142 * @param cg the class to filter
143 * @return boolean true if the method should be filtered away
144 */
145 public static boolean classFilter(final SystemDefinition definition, final ExpressionContext ctx, final CtClass cg) {
146 if (cg.isInterface()) {
147 return true;
148 }
149 String className = cg.getName().replace('/', '.');
150 if (definition.inExcludePackage(className)) {
151 return true;
152 }
153 if (!definition.inIncludePackage(className)) {
154 return true;
155 }
156 if (definition.isAdvised(ctx)) {
157 return false;
158 }
159 return true;
160 }
161 }