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