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.joinpoint.management;
9
10 import org.codehaus.aspectwerkz.AdviceInfo;
11 import org.codehaus.aspectwerkz.aspect.AspectContainer;
12
13 import java.io.Serializable;
14
15 /***
16 * Handles the execution of the around advices.
17 *
18 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
19 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
20 */
21 public class AroundAdviceExecutor implements Serializable {
22 /***
23 * The index of the current advice.
24 */
25 private int m_currentAdviceIndex = -1;
26
27 /***
28 * The stack index.
29 */
30 private int m_stackIndex = -1;
31
32 /***
33 * The advices indexes.
34 */
35 private final AdviceInfo[] m_adviceIndexes;
36
37 /***
38 * The join point type.
39 */
40 private final int m_joinPointType;
41
42 /***
43 * Creates a new around advice executor.
44 *
45 * @param adviceIndexes
46 * @param joinPointType
47 */
48 public AroundAdviceExecutor(final AdviceInfo[] adviceIndexes, final int joinPointType) {
49 m_adviceIndexes = adviceIndexes;
50 m_joinPointType = joinPointType;
51 }
52
53 /***
54 * Executes its advices one by one. After the last advice has been executed, the original method is invoked.
55 *
56 * @param joinPoint the current join point
57 * @return the result from the next advice in the chain or the invocation of the target method
58 */
59 public Object proceed(final JoinPointBase joinPoint) throws Throwable {
60
61 if (!joinPoint.isInCflow()) {
62 return JoinPointBase.invokeJoinPoint(joinPoint, m_joinPointType);
63 }
64 m_stackIndex++;
65 try {
66 if (m_stackIndex == 0) {
67 if (joinPoint.m_beforeAdviceExecutor.hasAdvices()) {
68 joinPoint.m_beforeAdviceExecutor.proceed(joinPoint);
69 }
70 }
71 Object result = null;
72 if (m_currentAdviceIndex == (m_adviceIndexes.length - 1)) {
73 m_currentAdviceIndex = -1;
74 try {
75 result = JoinPointBase.invokeJoinPoint(joinPoint, m_joinPointType);
76 } finally {
77 m_currentAdviceIndex = m_adviceIndexes.length - 1;
78 }
79 } else {
80 m_currentAdviceIndex++;
81 try {
82 AdviceInfo index = m_adviceIndexes[m_currentAdviceIndex];
83 AspectContainer container = index.getAspectManager().getAspectContainer(index.getAspectIndex());
84 result = container.invokeAdvice(index.getMethodIndex(), joinPoint, index.getMethodToArgIndexes());
85 } finally {
86 m_currentAdviceIndex--;
87 }
88 }
89 if (m_stackIndex == 0) {
90 if (joinPoint.m_afterAdviceExecutor.hasAdvices()) {
91 joinPoint.m_afterAdviceExecutor.proceed(joinPoint);
92 }
93 }
94 return result;
95 } finally {
96 m_stackIndex--;
97 }
98 }
99
100 /***
101 * Checks if the executor has any advices.
102 *
103 * @return true if it has advices
104 */
105 public boolean hasAdvices() {
106 return m_adviceIndexes.length != 0;
107 }
108
109 /***
110 * Resets the invocation flow. <p/>Will restart the execution chain of advice.
111 */
112 public void reset() {
113 m_currentAdviceIndex = -1;
114 m_stackIndex = -1;
115 }
116 }