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.cflow;
9
10 import org.codehaus.aspectwerkz.expression.ExpressionInfo;
11 import org.codehaus.aspectwerkz.definition.SystemDefinition;
12 import org.codehaus.aspectwerkz.definition.AspectDefinition;
13 import org.codehaus.aspectwerkz.definition.AdviceDefinition;
14 import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo;
15 import org.codehaus.aspectwerkz.reflect.ClassInfo;
16 import org.codehaus.aspectwerkz.reflect.MethodInfo;
17 import org.codehaus.aspectwerkz.aspect.AdviceType;
18
19 import java.util.List;
20 import java.util.ArrayList;
21
22 /***
23 * A Cflow binding represents an extracted cflow or cflowbelow subexpression
24 * <p/>
25 * For a given pointcut "pcA and cflowA or cflowbelowB", we will extract two bindings.
26 * The m_cflowID must be unique on a per cflow sub expresion basis ie JVM wide.
27 * <p/>
28 * Note: CflowBinding hashcode depends on Cflow_ID (sub expr) + isCflowBelow only.
29 *
30 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
31 */
32 public class CflowBinding {
33
34 /***
35 * the base implementation that hosts the cflow advices
36 */
37 private final static ClassInfo ABSTRACT_CFLOWCLASS = JavaClassInfo.getClassInfo(AbstractCflowSystemAspect.class);
38 private final static MethodInfo CFLOW_ENTER_ADVICE;
39 private final static MethodInfo CFLOW_EXIT_ADVICE;
40 static {
41 MethodInfo enter = null;
42 MethodInfo exit = null;
43 for (int i = 0; i < ABSTRACT_CFLOWCLASS.getMethods().length; i++) {
44 MethodInfo methodInfo = ABSTRACT_CFLOWCLASS.getMethods()[i];
45 if (methodInfo.getName().equals("enter")) {
46 enter = methodInfo;
47 } else if (methodInfo.getName().equals("exit")) {
48 exit = methodInfo;
49 }
50 }
51 if (enter == null || exit == null) {
52 throw new Error("Could not gather cflow advices from " + AbstractCflowSystemAspect.class);
53 } else {
54 CFLOW_ENTER_ADVICE = enter;
55 CFLOW_EXIT_ADVICE = exit;
56 }
57 }
58
59 /***
60 * cflow unique id
61 */
62 private int m_cflowID;
63
64 /***
65 * pointcut that represents this cflow sub-expression
66 */
67 private ExpressionInfo m_cflowSubExpression;
68
69 /***
70 * pointcut that represents the containing expression
71 */
72 private ExpressionInfo m_outerExpression;
73
74 /***
75 * marker if this binding is a cflow below, not used at the moment
76 */
77 private boolean m_isCflowBelow;
78
79 /***
80 * Cosntructs a new cflow binding
81 *
82 * @param cflowID
83 * @param cflowSubExpression
84 * @param isCflowBelow
85 */
86 public CflowBinding(int cflowID, ExpressionInfo cflowSubExpression, ExpressionInfo outerExpression, boolean isCflowBelow) {
87 m_cflowID = cflowID;
88 m_cflowSubExpression = cflowSubExpression;
89 m_outerExpression = outerExpression;
90 m_isCflowBelow = isCflowBelow;
91 }
92
93 /***
94 * @return the sub expression
95 */
96 public ExpressionInfo getExpression() {
97 return m_cflowSubExpression;
98 }
99
100 /***
101 * Extract the cflow bindings from any pointcut
102 * This includes both cflow and cflowbelow
103 *
104 * @param expressionInfo the pointcut expression frow where to extract the cflow bindings
105 * @return a list of CflowBinding, can be empty
106 */
107 public static List getCflowBindingsForCflowOf(ExpressionInfo expressionInfo) {
108 List cflowBindings = new ArrayList();
109 if (expressionInfo != null) {
110 expressionInfo.getCflowAspectExpression().populateCflowAspectBindings(cflowBindings);
111 }
112 return cflowBindings;
113 }
114
115 /***
116 * Create an aspect definition for this cflow binding in the given system.
117 * The cflow jit aspects will gets compiled and loaded
118 *
119 * @param systemDefinition
120 * @param loader
121 * @return the cflow aspect definition
122 */
123 public AspectDefinition getAspectDefinition(SystemDefinition systemDefinition, ClassLoader loader) {
124 String aspectName = CflowCompiler.getCflowAspectClassName(m_cflowID);
125
126
127
128
129
130
131
132 Class aspectClass = CflowCompiler.compileCflowAspectAndAttachToClassLoader(loader, m_cflowID);
133 ClassInfo cflowAspectInfo = JavaClassInfo.getClassInfo(aspectClass);
134
135 AspectDefinition aspectDef = new AspectDefinition(
136 aspectName.replace('/', '.'),
137 cflowAspectInfo,
138 systemDefinition
139 );
140 aspectDef.addBeforeAdviceDefinition(
141 new AdviceDefinition(
142 CFLOW_ENTER_ADVICE.getName(),
143 AdviceType.BEFORE,
144 null,
145 aspectName,
146 aspectName,
147 m_cflowSubExpression,
148 CFLOW_ENTER_ADVICE,
149 aspectDef
150 )
151 );
152 aspectDef.addAfterAdviceDefinition(
153 new AdviceDefinition(
154 CFLOW_EXIT_ADVICE.getName(),
155 AdviceType.AFTER_FINALLY,
156 null,
157 aspectName,
158 aspectName,
159 m_cflowSubExpression,
160 CFLOW_EXIT_ADVICE,
161 aspectDef
162 )
163 );
164
165 return aspectDef;
166 }
167
168 public boolean isCflowBelow() {
169 return m_isCflowBelow;
170 }
171
172 public int getCflowID() {
173 return m_cflowID;
174 }
175
176 public boolean equals(Object o) {
177 if (this == o) return true;
178 if (!(o instanceof CflowBinding)) return false;
179
180 final CflowBinding cflowBinding = (CflowBinding) o;
181
182 if (m_cflowID != cflowBinding.m_cflowID) return false;
183 if (m_isCflowBelow != cflowBinding.m_isCflowBelow) return false;
184
185 return true;
186 }
187
188 public int hashCode() {
189 int result;
190 result = m_cflowID;
191 result = 29 * result + (m_isCflowBelow ? 1 : 0);
192 return result;
193 }
194 }