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.expression;
9
10 import org.codehaus.aspectwerkz.expression.ast.ASTRoot;
11 import org.codehaus.aspectwerkz.expression.ast.ASTPointcutReference;
12 import org.codehaus.aspectwerkz.expression.ast.ASTArgParameter;
13 import org.codehaus.aspectwerkz.expression.ast.ASTArgs;
14 import org.codehaus.aspectwerkz.util.Strings;
15 import org.codehaus.aspectwerkz.exception.DefinitionException;
16
17 import java.util.Iterator;
18
19 import gnu.trove.TIntIntHashMap;
20
21 /***
22 * A visitor to compute the args index of the target (matching) method/constructor which match the advice args. Note:
23 * extends the ExpressionVisitor. We should allow for optimization (all=TRUE) by assuming that args(..) does not depends
24 * of the matching context. The "(String a, String b):methodX && args(a,b) -OR- methodY && args(b,a)" expression should
25 * not be allowed then. TODO check support for anonymous pc
26 *
27 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
28 */
29 public class ArgsIndexVisitor extends ExpressionVisitor {
30
31 public ArgsIndexVisitor(final ExpressionInfo expressionInfo,
32 final String expression,
33 final String namespace,
34 final ASTRoot root) {
35 super(expressionInfo, expression, namespace, root);
36 }
37
38
39
40 public Object visit(ASTPointcutReference node, Object data) {
41
42 ExpressionContext context = (ExpressionContext) data;
43 ExpressionNamespace namespace = ExpressionNamespace.getNamespace(m_namespace);
44 ArgsIndexVisitor expression = namespace.getExpressionInfo(node.getName()).getArgsIndexMapper();
45 if (expression == null) {
46 throw new DefinitionException("Could not find pointcut reference " + node.getName() +
47 " in namespace " + m_namespace);
48 }
49 Boolean match = new Boolean(expression.match(context));
50
51
52
53 if (!context.m_exprIndexToTargetIndex.isEmpty()) {
54 TIntIntHashMap sourceToTargetArgIndexes = new TIntIntHashMap();
55 int index = 0;
56 for (Iterator it = m_expressionInfo.getArgumentNames().iterator(); it.hasNext(); index++) {
57 String adviceParamName = (String) it.next();
58
59 int exprArgIndex = ArgsIndexVisitor.getExprArgIndex(m_expression, adviceParamName);
60 if (exprArgIndex < 0) {
61
62 continue;
63 }
64 int adviceArgIndex = m_expressionInfo.getArgumentIndex(adviceParamName);
65 int targetArgIndex = context.m_exprIndexToTargetIndex.get(exprArgIndex);
66
67
68 sourceToTargetArgIndexes.put(adviceArgIndex, targetArgIndex);
69 }
70 context.m_exprIndexToTargetIndex = sourceToTargetArgIndexes;
71
72
73
74
75
76
77
78
79
80
81
82 }
83 return match;
84 }
85
86 public Object visit(ASTArgs node, Object data) {
87 return super.visit(node, data);
88 }
89
90 public Object visit(ASTArgParameter node, Object data) {
91
92 Boolean match = (Boolean) super.visit(node, data);
93
94
95 int pointcutArgIndex = -1;
96 if (node.getTypePattern().getPattern().indexOf(".") < 0) {
97 pointcutArgIndex = m_expressionInfo.getArgumentIndex(node.getTypePattern().getPattern());
98 }
99
100
101 if (pointcutArgIndex >= 0 && Boolean.TRUE.equals(match)) {
102 ExpressionContext ctx = (ExpressionContext) data;
103
104
105
106 ctx.m_exprIndexToTargetIndex.put(pointcutArgIndex, ctx.getCurrentTargetArgsIndex());
107 }
108 return match;
109 }
110
111 /***
112 * Get the parameter index from a "call side" like signature like pc(a, b) => index(a) = 0, or -1 if not found
113 *
114 * @param expression
115 * @param adviceParamName
116 * @return
117 */
118 private static int getExprArgIndex(String expression, String adviceParamName) {
119
120 int paren = expression.indexOf('(');
121 if (paren > 0) {
122 String params = expression.substring(paren + 1, expression.lastIndexOf(')')).trim();
123 String[] parameters = Strings.splitString(params, ",");
124 int paramIndex = 0;
125 for (int i = 0; i < parameters.length; i++) {
126 String parameter = parameters[i].trim();
127 if (parameter.length() > 0) {
128 if (adviceParamName.equals(parameter)) {
129 return paramIndex;
130 } else {
131 paramIndex++;
132 }
133 }
134 }
135 }
136 return -1;
137 }
138
139 }