View Javadoc

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          // if we have cflow advice then let it run first, then check if we are in cflow
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 }