001: /**************************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.definition;
008:
009: import org.codehaus.aspectwerkz.expression.ExpressionInfo;
010: import org.codehaus.aspectwerkz.aspect.AdviceType;
011: import org.codehaus.aspectwerkz.reflect.MethodInfo;
012: import org.codehaus.aspectwerkz.util.Strings;
013: import org.codehaus.aspectwerkz.DeploymentModel;
014: import org.codehaus.aspectwerkz.cflow.CflowBinding;
015:
016: import java.util.List;
017:
018: /**
019: * Holds the meta-data for the advices.
020: *
021: * @author <a href="mailto:jboner@codehaus.org">Jonas Boner </a>
022: */
023: public class AdviceDefinition {
024:
025: /**
026: * The name of the advice.
027: * It is the advice method name and optionnaly the call signature.
028: * e.g. advice or advice() or advice(JoinPoint jp) or myadvice(JoinPoint myJp , java.lang.String foo) ...
029: */
030: private String m_name;
031:
032: /**
033: * The type of the advice.
034: */
035: private AdviceType m_type;
036:
037: /**
038: * The aspect class name.
039: */
040: private final String m_aspectClassName;
041:
042: /**
043: * The aspect name.
044: */
045: private final String m_aspectName;
046:
047: /**
048: * The pointcut expression.
049: */
050: private ExpressionInfo m_expressionInfo;
051:
052: /**
053: * The method for the advice.
054: */
055: private final MethodInfo m_method;
056:
057: /**
058: * The attribute for the advice.
059: */
060: private String m_attribute = "";
061:
062: /**
063: * The aspect definition holding this advice definition.
064: */
065: private AspectDefinition m_aspectDefinition;
066:
067: /**
068: * The special arg type, such as returning(TYPE) or throwing(TYPE).
069: */
070: private String m_specialArgumentType;
071:
072: /**
073: * Indicates if this advice will need a cflow or cflowbelow runtime check
074: */
075: private boolean m_hasCflowOrCflowBelow = false;
076:
077: /**
078: * TODO only use this method and make ctor private?
079: * <p/>
080: * Creates a new advice definition.
081: *
082: * @param adviceName the advice name
083: * @param adviceType the advice type
084: * @param expression the advice expression
085: * @param specialArgumentType the arg
086: * @param aspectName the aspect name
087: * @param aspectClassName the aspect class name
088: * @param method the advice method
089: * @param aspectDef the aspect definition
090: * @return the new advice definition
091: */
092: public static AdviceDefinition newInstance(final String adviceName,
093: final AdviceType adviceType, final String expression,
094: final String specialArgumentType, final String aspectName,
095: final String aspectClassName, final MethodInfo method,
096: final AspectDefinition aspectDef) {
097: ExpressionInfo expressionInfo = new ExpressionInfo(expression,
098: aspectDef.getQualifiedName());
099:
100: // support for pointcut signature
101: String adviceCallSignature = null;
102: String resolvedSpecialArgumentType = specialArgumentType;
103: if (adviceName.indexOf('(') > 0) {
104: adviceCallSignature = adviceName.substring(adviceName
105: .indexOf('(') + 1, adviceName.lastIndexOf(')'));
106: String[] parameters = Strings.splitString(
107: adviceCallSignature, ",");
108: for (int i = 0; i < parameters.length; i++) {
109: String[] parameterInfo = Strings.splitString(Strings
110: .replaceSubString(parameters[i].trim(), " ",
111: " "), " ");
112: // skip the parameter if this ones is a after returning / throwing binding
113: if (parameterInfo[1].equals(specialArgumentType)) {
114: resolvedSpecialArgumentType = parameterInfo[0];
115: expressionInfo
116: .setSpecialArgumentName(parameterInfo[1]);
117: } else {
118: expressionInfo.addArgument(parameterInfo[1],
119: parameterInfo[0], aspectDef.getClassInfo()
120: .getClassLoader());
121: }
122: }
123: }
124:
125: return new AdviceDefinition(adviceName, adviceType,
126: resolvedSpecialArgumentType, aspectName,
127: aspectClassName, expressionInfo, method, aspectDef);
128: }
129:
130: /**
131: * Creates a new advice meta-data instance.
132: *
133: * @param name the name of the expressionInfo
134: * @param type the type of the advice
135: * @param specialArgumentType the special arg type, such as returning(TYPE) or throwing(TYPE)
136: * @param aspectName the name of the aspect
137: * @param aspectClassName the class name of the aspect
138: * @param expressionInfo the expressionInfo
139: * @param methodInfo the methodInfo
140: */
141: public AdviceDefinition(final String name, final AdviceType type,
142: final String specialArgumentType, final String aspectName,
143: final String aspectClassName,
144: final ExpressionInfo expressionInfo,
145: final MethodInfo methodInfo,
146: final AspectDefinition aspectDef) {
147: if (name == null) {
148: throw new IllegalArgumentException("name can not be null");
149: }
150: if (type == null) {
151: throw new IllegalArgumentException("illegal advice type");
152: }
153: if (aspectName == null) {
154: throw new IllegalArgumentException(
155: "aspect name can not be null");
156: }
157: if (aspectClassName == null) {
158: throw new IllegalArgumentException(
159: "class name can not be null");
160: }
161: if (methodInfo == null) {
162: throw new IllegalArgumentException(
163: "methodInfo can not be null");
164: }
165: if (aspectDef == null) {
166: throw new IllegalArgumentException(
167: "aspect definition can not be null");
168: }
169: m_name = name;
170: m_type = type;
171: m_specialArgumentType = specialArgumentType;
172: m_aspectName = aspectName;
173: m_aspectClassName = aspectClassName;
174: m_expressionInfo = expressionInfo;
175: m_method = methodInfo;
176: m_aspectDefinition = aspectDef;
177:
178: // get the cflow Advice bindings to know if this advice binding is using cflow or cflowbelow
179: List cflowBindings = CflowBinding
180: .getCflowBindingsForCflowOf(m_expressionInfo);
181: m_hasCflowOrCflowBelow = (cflowBindings.size() > 0);
182: }
183:
184: /**
185: * Returns the advice type.
186: *
187: * @return the advice type
188: */
189: public AdviceType getType() {
190: return m_type;
191: }
192:
193: /**
194: * Returns the name of the advice.
195: *
196: * @return the name
197: */
198: public String getName() {
199: return m_name;
200: }
201:
202: /**
203: * Returns the fully qualified name for the advice
204: *
205: * @return the fully qualified name
206: */
207: public String getQualifiedName() {
208: return m_aspectDefinition.getQualifiedName() + '.' + m_name;
209: }
210:
211: /**
212: * Sets the name of the advice.
213: *
214: * @param name the name
215: */
216: public void setName(final String name) {
217: m_name = name.trim();
218: }
219:
220: /**
221: * Returns the expression.
222: * <p/>
223: * TODO should return NULL object if null
224: *
225: * @return the expression
226: */
227: public ExpressionInfo getExpressionInfo() {
228: return m_expressionInfo;
229: }
230:
231: /**
232: * Sets the expression info.
233: *
234: * @param newExpression the new expression info
235: */
236: public void setExpressionInfo(final ExpressionInfo newExpression) {
237: m_expressionInfo = newExpression;
238: // update the hasCflow caracteristic
239: List cflowBindings = CflowBinding
240: .getCflowBindingsForCflowOf(m_expressionInfo);
241: m_hasCflowOrCflowBelow = (cflowBindings.size() > 0);
242: }
243:
244: /**
245: * Returns the class name.
246: *
247: * @return the class name
248: */
249: public String getAspectClassName() {
250: return m_aspectClassName;
251: }
252:
253: /**
254: * Returns the aspect name.
255: *
256: * @return the aspect name
257: */
258: public String getAspectName() {
259: return m_aspectName;
260: }
261:
262: /**
263: * Returns the special arg type, such as returning(TYPE) or throwing(TYPE).
264: *
265: * @return
266: */
267: public String getSpecialArgumentType() {
268: return m_specialArgumentType;
269: }
270:
271: /**
272: * Returns the method.
273: *
274: * @return the method
275: */
276: public MethodInfo getMethodInfo() {
277: return m_method;
278: }
279:
280: /**
281: * Returns the the deployment model for the advice
282: *
283: * @return the deployment model
284: */
285: public DeploymentModel getDeploymentModel() {
286: return m_aspectDefinition.getDeploymentModel();
287: }
288:
289: /**
290: * Returns the attribute.
291: *
292: * @return the attribute
293: */
294: public String getAttribute() {
295: return m_attribute;
296: }
297:
298: /**
299: * Sets the attribute.
300: *
301: * @param attribute the attribute
302: */
303: public void setAttribute(final String attribute) {
304: m_attribute = attribute;
305: }
306:
307: /**
308: * Returns the definition for the aspect that defines this advice.
309: *
310: * @return the aspect definition
311: */
312: public AspectDefinition getAspectDefinition() {
313: return m_aspectDefinition;
314: }
315:
316: /**
317: * Check if the advice is bound to a pointcut with cflow or cflowbelow
318: *
319: * @return
320: */
321: public boolean hasCflowOrCflowBelow() {
322: return m_hasCflowOrCflowBelow;
323: }
324:
325: /**
326: * Deep copy of the definition.
327: *
328: * @param expressionInfo
329: * @return
330: */
331: public AdviceDefinition copyAt(final ExpressionInfo expressionInfo) {
332: return new AdviceDefinition(getName(), getType(),
333: getSpecialArgumentType(), getAspectName(),
334: getAspectClassName(), expressionInfo, getMethodInfo(),
335: m_aspectDefinition);
336: }
337:
338: /**
339: * Equals and hashcode means we have the same advice if the aspect qualified name (not classname) and
340: * advice name (may include signature) are the same. [AW-439 fix]
341: *
342: * @param o
343: * @return
344: */
345: public boolean equals(Object o) {
346: if (this == o)
347: return true;
348: if (!(o instanceof AdviceDefinition))
349: return false;
350:
351: final AdviceDefinition adviceDefinition = (AdviceDefinition) o;
352:
353: if (!m_aspectName.equals(adviceDefinition.m_aspectName))
354: return false;
355: if (!m_name.equals(adviceDefinition.m_name))
356: return false;
357:
358: return true;
359: }
360:
361: public int hashCode() {
362: int result;
363: result = m_name.hashCode();
364: result = 29 * result + m_aspectName.hashCode();
365: return result;
366: }
367: }
|