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.aspect.management;
9
10 import org.codehaus.aspectwerkz.DeploymentModel;
11 import org.codehaus.aspectwerkz.expression.ExpressionContext;
12
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Iterator;
16 import java.util.List;
17
18 /***
19 * Manages pointcuts and introductions defined by a specfic aspect.
20 *
21 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
22 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
23 */
24 public class PointcutManager {
25 /***
26 * Holds references to all the pointcuts.
27 */
28 protected final List m_pointcuts = new ArrayList();
29
30 /***
31 * Holds references to all the pointcuts that has a cflow pointcut.
32 */
33 protected final List m_cflowPointcuts = new ArrayList();
34
35 /***
36 * Holds references to all the the introductions.
37 */
38 protected String[] m_introductions = new String[0];
39
40 /***
41 * The name of the aspect.
42 */
43 protected final String m_name;
44
45 /***
46 * The deployment model for the aspect.
47 */
48 protected final int m_deploymentModel;
49
50 /***
51 * Creates a new aspect.
52 *
53 * @param name the name of the aspect
54 */
55 public PointcutManager(final String name) {
56 this(name, DeploymentModel.PER_JVM);
57 }
58
59 /***
60 * Creates a new aspect.
61 *
62 * @param name the name of the aspect
63 * @param deploymentModel the deployment model for the aspect
64 */
65 public PointcutManager(final String name, final int deploymentModel) {
66 if (name == null) {
67 throw new IllegalArgumentException("name can not be null");
68 }
69 if (deploymentModel < 0) {
70 throw new IllegalArgumentException(deploymentModel + " is not a valid deployement model type");
71 }
72 m_name = name;
73 m_deploymentModel = deploymentModel;
74 }
75
76 /***
77 * Returns the name of the aspect.
78 *
79 * @return the aspect name
80 */
81 public String getName() {
82 return m_name;
83 }
84
85 /***
86 * Returns the deployment model for the aspect.
87 *
88 * @return the deployment model
89 */
90 public int getDeploymentModel() {
91 return m_deploymentModel;
92 }
93
94 /***
95 * Returns the deployment model for the aspect.
96 *
97 * @return the deployment model
98 */
99 public String getDeploymentModelAsString() {
100 return DeploymentModel.getDeploymentModelAsString(m_deploymentModel);
101 }
102
103 /***
104 * Adds an introduction to the open class.
105 *
106 * @param introduction the name of the introduction to add
107 */
108 public final void addIntroduction(final String introduction) {
109 synchronized (m_introductions) {
110 final String[] tmp = new String[m_introductions.length + 1];
111 java.lang.System.arraycopy(m_introductions, 0, tmp, 0, m_introductions.length);
112 tmp[m_introductions.length] = introduction;
113 m_introductions = new String[m_introductions.length + 1];
114 java.lang.System.arraycopy(tmp, 0, m_introductions, 0, tmp.length);
115 }
116 }
117
118 /***
119 * Adds an array with introductions to the open class. <br/>
120 *
121 * @param introductions the introductions to add
122 */
123 public final void addIntroductions(final String[] introductions) {
124 synchronized (m_introductions) {
125 final String[] clone = new String[introductions.length];
126 java.lang.System.arraycopy(introductions, 0, clone, 0, introductions.length);
127 final String[] tmp = new String[m_introductions.length + introductions.length];
128 int i;
129 for (i = 0; i < m_introductions.length; i++) {
130 tmp[i] = m_introductions[i];
131 }
132 for (int j = 0; j < clone.length; i++, j++) {
133 tmp[i] = clone[j];
134 }
135 m_introductions = new String[tmp.length];
136 java.lang.System.arraycopy(tmp, 0, m_introductions, 0, tmp.length);
137 }
138 }
139
140 /***
141 * Adds a new pointcut.
142 *
143 * @param pointcut the pointcut to add
144 */
145 public void addPointcut(final Pointcut pointcut) {
146 synchronized (m_pointcuts) {
147 synchronized (m_cflowPointcuts) {
148 m_pointcuts.add(pointcut);
149 if (pointcut.getExpressionInfo().hasCflowPointcut()) {
150 m_cflowPointcuts.add(new Pointcut(pointcut.getAspectManager(), pointcut.getExpressionInfo()));
151 }
152 }
153 }
154 }
155
156 /***
157 * Returns the introductions for the open class.
158 *
159 * @return an array with the introductions for the class
160 */
161 public String[] getIntroductions() {
162 return m_introductions;
163 }
164
165 /***
166 * Returns the pointcut for a specific expression.
167 *
168 * @param expression the expression
169 * @return the pointcut, or null
170 */
171 public Pointcut getPointcut(final String expression) {
172 for (Iterator it = m_pointcuts.iterator(); it.hasNext();) {
173 Pointcut pointcut = (Pointcut) it.next();
174 if (pointcut.getExpressionInfo().getExpressionAsString().equals(expression)) {
175 return pointcut;
176 }
177 }
178 return null;
179 }
180
181 /***
182 * Returns the cflow pointcut for a specific expression.
183 *
184 * @param expression the expression
185 * @return the pointcut, or null
186 */
187 public Pointcut getCflowPointcut(final String expression) {
188 for (Iterator it = m_cflowPointcuts.iterator(); it.hasNext();) {
189 Pointcut pointcut = (Pointcut) it.next();
190 if (pointcut.getExpressionInfo().getExpressionAsString().equals(expression)) {
191 return pointcut;
192 }
193 }
194 return null;
195 }
196
197 /***
198 * Returns all the pointcuts defined by a specific aspect.
199 *
200 * @return the pointcuts
201 */
202 public List getPointcuts() {
203 return m_pointcuts;
204 }
205
206 /***
207 * Returns all the pointcuts defined by a specific aspect that has a cflow pointcut referenced.
208 *
209 * @return the pointcuts
210 */
211 public List getCflowPointcuts() {
212 return m_cflowPointcuts;
213 }
214
215 /***
216 * Returns all the pointcuts for the join point specified.
217 *
218 * @param ctx the expression context
219 * @return the pointcuts that parse
220 */
221 public List getPointcuts(final ExpressionContext ctx) {
222 if (ctx == null) {
223 throw new IllegalArgumentException("context can not be null");
224 }
225 List pointcutList = new ArrayList();
226 for (Iterator it = m_pointcuts.iterator(); it.hasNext();) {
227 Pointcut pointcut = (Pointcut) it.next();
228 if (pointcut.getExpressionInfo().getExpression().match(ctx)) {
229 pointcutList.add(pointcut);
230 }
231 }
232 return pointcutList;
233 }
234
235 /***
236 * Returns all the cflow pointcuts for the join point specified.
237 *
238 * @param ctx the expression context
239 * @return the pointcuts that parse
240 */
241 public List getCflowPointcuts(final ExpressionContext ctx) {
242 if (ctx == null) {
243 throw new IllegalArgumentException("context can not be null");
244 }
245 List pointcutList = new ArrayList();
246 for (Iterator it = m_cflowPointcuts.iterator(); it.hasNext();) {
247 Pointcut pointcut = (Pointcut) it.next();
248 if (pointcut.getExpressionInfo().getCflowExpression().match(ctx)) {
249 pointcutList.add(pointcut);
250 }
251 }
252 return pointcutList;
253 }
254
255 public boolean equals(Object o) {
256 if (this == o) {
257 return true;
258 }
259 if (!(o instanceof PointcutManager)) {
260 return false;
261 }
262 final PointcutManager pointcutManager = (PointcutManager) o;
263 if (m_deploymentModel != pointcutManager.m_deploymentModel) {
264 return false;
265 }
266 if (!Arrays.equals(m_introductions, pointcutManager.m_introductions)) {
267 return false;
268 }
269 if (!m_name.equals(pointcutManager.m_name)) {
270 return false;
271 }
272 if (!m_pointcuts.equals(pointcutManager.m_pointcuts)) {
273 return false;
274 }
275 if (!m_cflowPointcuts.equals(pointcutManager.m_cflowPointcuts)) {
276 return false;
277 }
278 return true;
279 }
280
281 public int hashCode() {
282 int result;
283 result = m_pointcuts.hashCode();
284 result = m_cflowPointcuts.hashCode();
285 result = (29 * result) + m_name.hashCode();
286 result = (29 * result) + m_deploymentModel;
287 return result;
288 }
289 }