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.cflow;
008:
009: import org.codehaus.aspectwerkz.expression.ExpressionInfo;
010: import org.codehaus.aspectwerkz.definition.SystemDefinition;
011: import org.codehaus.aspectwerkz.definition.AspectDefinition;
012: import org.codehaus.aspectwerkz.definition.AdviceDefinition;
013: import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo;
014: import org.codehaus.aspectwerkz.reflect.ClassInfo;
015: import org.codehaus.aspectwerkz.reflect.MethodInfo;
016: import org.codehaus.aspectwerkz.aspect.AdviceType;
017:
018: import java.util.List;
019: import java.util.ArrayList;
020:
021: /**
022: * A Cflow binding represents an extracted cflow or cflowbelow subexpression
023: * <p/>
024: * For a given pointcut "pcA and cflowA or cflowbelowB", we will extract two bindings.
025: * The m_cflowID must be unique on a per cflow sub expresion basis ie JVM wide.
026: * <p/>
027: * Note: CflowBinding hashcode depends on Cflow_ID (sub expr) + isCflowBelow only.
028: *
029: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
030: */
031: public class CflowBinding {
032:
033: /**
034: * the base implementation that hosts the cflow advices
035: */
036: private final static ClassInfo ABSTRACT_CFLOWCLASS = JavaClassInfo
037: .getClassInfo(AbstractCflowSystemAspect.class);
038: private final static MethodInfo CFLOW_ENTER_ADVICE;
039: private final static MethodInfo CFLOW_EXIT_ADVICE;
040: static {
041: MethodInfo enter = null;
042: MethodInfo exit = null;
043: for (int i = 0; i < ABSTRACT_CFLOWCLASS.getMethods().length; i++) {
044: MethodInfo methodInfo = ABSTRACT_CFLOWCLASS.getMethods()[i];
045: if (methodInfo.getName().equals("enter")) {
046: enter = methodInfo;
047: } else if (methodInfo.getName().equals("exit")) {
048: exit = methodInfo;
049: }
050: }
051: if (enter == null || exit == null) {
052: throw new Error("Could not gather cflow advices from "
053: + AbstractCflowSystemAspect.class);
054: } else {
055: CFLOW_ENTER_ADVICE = enter;
056: CFLOW_EXIT_ADVICE = exit;
057: }
058: }
059:
060: /**
061: * cflow unique id
062: */
063: private int m_cflowID;
064:
065: /**
066: * pointcut that represents this cflow sub-expression
067: */
068: private ExpressionInfo m_cflowSubExpression;
069:
070: /**
071: * pointcut that represents the containing expression
072: */
073: private ExpressionInfo m_outerExpression;
074:
075: /**
076: * marker if this binding is a cflow below, not used at the moment
077: */
078: private boolean m_isCflowBelow;
079:
080: /**
081: * Cosntructs a new cflow binding
082: *
083: * @param cflowID
084: * @param cflowSubExpression
085: * @param isCflowBelow
086: */
087: public CflowBinding(int cflowID, ExpressionInfo cflowSubExpression,
088: ExpressionInfo outerExpression, boolean isCflowBelow) {
089: m_cflowID = cflowID;
090: m_cflowSubExpression = cflowSubExpression;
091: m_outerExpression = outerExpression;
092: m_isCflowBelow = isCflowBelow;
093: }
094:
095: /**
096: * @return the sub expression
097: */
098: public ExpressionInfo getExpression() {
099: return m_cflowSubExpression;
100: }
101:
102: /**
103: * Extract the cflow bindings from any pointcut
104: * This includes both cflow and cflowbelow
105: *
106: * @param expressionInfo the pointcut expression frow where to extract the cflow bindings
107: * @return a list of CflowBinding, can be empty
108: */
109: public static List getCflowBindingsForCflowOf(
110: ExpressionInfo expressionInfo) {
111: List cflowBindings = new ArrayList();
112: if (expressionInfo != null) {
113: expressionInfo.getCflowAspectExpression()
114: .populateCflowAspectBindings(cflowBindings);
115: }
116: return cflowBindings;
117: }
118:
119: /**
120: * Create an aspect definition for this cflow binding in the given system.
121: * The cflow jit aspects will gets compiled and loaded
122: *
123: * @param systemDefinition
124: * @param loader
125: * @return the cflow aspect definition
126: */
127: public AspectDefinition getAspectDefinition(
128: SystemDefinition systemDefinition, ClassLoader loader) {
129: String aspectName = CflowCompiler
130: .getCflowAspectClassName(m_cflowID);
131:
132: // check if we have already register this aspect
133: // TODO: it may happen that the aspect gets register somewhere up in the hierarchy ??
134: // it is optim only
135:
136: // TODO: how to do this class define lazyly and not pass in a classloader ?
137: // could be done in the JIT jp clinit when 1+ advice has a cflow binding
138: Class aspectClass = CflowCompiler
139: .compileCflowAspectAndAttachToClassLoader(loader,
140: m_cflowID);
141: ClassInfo cflowAspectInfo = JavaClassInfo
142: .getClassInfo(aspectClass);
143:
144: AspectDefinition aspectDef = new AspectDefinition(aspectName
145: .replace('/', '.'), cflowAspectInfo, systemDefinition);
146: aspectDef.addBeforeAdviceDefinition(new AdviceDefinition(
147: CFLOW_ENTER_ADVICE.getName(), AdviceType.BEFORE, null,
148: aspectName, aspectName, m_cflowSubExpression,
149: CFLOW_ENTER_ADVICE, aspectDef));
150: aspectDef.addAfterAdviceDefinition(new AdviceDefinition(
151: CFLOW_EXIT_ADVICE.getName(), AdviceType.AFTER_FINALLY,
152: null, aspectName, aspectName, m_cflowSubExpression,
153: CFLOW_EXIT_ADVICE, aspectDef));
154:
155: return aspectDef;
156: }
157:
158: public boolean isCflowBelow() {
159: return m_isCflowBelow;
160: }
161:
162: public int getCflowID() {
163: return m_cflowID;
164: }
165:
166: public boolean equals(Object o) {
167: if (this == o)
168: return true;
169: if (!(o instanceof CflowBinding))
170: return false;
171:
172: final CflowBinding cflowBinding = (CflowBinding) o;
173:
174: if (m_cflowID != cflowBinding.m_cflowID)
175: return false;
176: if (m_isCflowBelow != cflowBinding.m_isCflowBelow)
177: return false;
178:
179: return true;
180: }
181:
182: public int hashCode() {
183: int result;
184: result = m_cflowID;
185: result = 29 * result + (m_isCflowBelow ? 1 : 0);
186: return result;
187: }
188: }
|