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.perx;
005:
006: import com.tc.aspectwerkz.AspectContext;
007: import com.tc.aspectwerkz.DeploymentModel;
008: import com.tc.aspectwerkz.expression.ExpressionInfo;
009: import com.tc.aspectwerkz.aspect.AdviceType;
010: import com.tc.aspectwerkz.aspect.management.HasInstanceLevelAspect;
011: import com.tc.aspectwerkz.definition.AdviceDefinition;
012: import com.tc.aspectwerkz.definition.AspectDefinition;
013: import com.tc.aspectwerkz.definition.SystemDefinition;
014: import com.tc.aspectwerkz.reflect.impl.java.JavaClassInfo;
015: import com.tc.aspectwerkz.reflect.MethodInfo;
016: import com.tc.aspectwerkz.reflect.ClassInfo;
017: import com.tc.aspectwerkz.transform.TransformationConstants;
018:
019: /**
020: * Generic aspect used by perX deployment modes to initialize the aspect instance.
021: * It gets registered programatically when finding perX aspects.
022: * fake
023: *
024: * @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
025: */
026: public class PerObjectAspect {
027:
028: /**
029: * PerObjectAspect class name
030: */
031: public static final String PEROBJECT_ASPECT_NAME = PerObjectAspect.class
032: .getName().replace('/', '.');
033:
034: /**
035: * Name of system advice that will bind the aspect to the perX X instance.
036: * This advice is bound to the "X && target(aw_instance)" pointcut for pertarget(X)
037: * and "X && this(aw_instance)" pointcut for perthis(X) and thus its signature
038: * is a beforePerObjecr(HasInstanceLevelAspect aw_instance).
039: */
040: private static final String BEFORE_ADVICE_NAME = "beforePerObject";
041:
042: /**
043: * Name of the advice argument where we bound the perX X instance.
044: */
045: public static final String ADVICE_ARGUMENT_NAME = "aw_Instance";
046:
047: /**
048: * ClassInfo and method Info for the PerObjectAspect
049: */
050: private static final ClassInfo PEROBJECT_CLASSINFO = JavaClassInfo
051: .getClassInfo(PerObjectAspect.class);
052: private static MethodInfo BEFORE_ADVICE_METHOD_INFO;
053:
054: static {
055: MethodInfo[] methods = PEROBJECT_CLASSINFO.getMethods();
056: for (int i = 0; i < methods.length; i++) {
057: if (PerObjectAspect.BEFORE_ADVICE_NAME.equals(methods[i]
058: .getName())) {
059: BEFORE_ADVICE_METHOD_INFO = methods[i];
060: break;
061: }
062: }
063: if (BEFORE_ADVICE_METHOD_INFO == null) {
064: throw new Error("Could not find PerObjectAspect."
065: + BEFORE_ADVICE_NAME);
066: }
067: }
068:
069: /**
070: * One PerObjectAspect instance gets created for each X of perthis(X) / pertarget(X) and
071: * is passed as aspect context parameters the Qname of the perX aspect for which it acts
072: * and the container class name of that one.
073: */
074: private static final String ASPECT_QNAME_PARAM = "perobject.aspect.qname";
075: private static final String CONTAINER_CLASSNAME_PARAM = "perobject.container.classname";
076:
077: private static final String ADVICE_ARGUMENT_TYPE = TransformationConstants.HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME
078: .replace('/', '.');
079:
080: private static final String ADVICE_SIGNATURE = BEFORE_ADVICE_NAME
081: + "(" + ADVICE_ARGUMENT_TYPE + " " + ADVICE_ARGUMENT_NAME
082: + ")";
083:
084: private final String m_aspectQName;
085:
086: private final String m_containerClassName;
087:
088: /**
089: * PerObjectAspect constructor.
090: * We keep track of the aspectQname and container class name to further call Aspects.aspectOf
091: *
092: * @param ctx
093: */
094: public PerObjectAspect(AspectContext ctx) {
095: m_aspectQName = ctx.getParameter(ASPECT_QNAME_PARAM);
096: m_containerClassName = ctx
097: .getParameter(CONTAINER_CLASSNAME_PARAM);
098: }
099:
100: /**
101: * Before perPointcut && this/target(targetInstance) bound that will associate the aspect and the instance.
102: * Note: do not refactor the names here without refactoring the constants.
103: */
104: public void beforePerObject(HasInstanceLevelAspect aw_instance) {
105: if (aw_instance == null) {
106: return;
107: }
108: aw_instance.aw$getAspect(getClass());
109: }
110:
111: /**
112: * Creates the generic AspectDefinition for the PerObjectAspect
113: *
114: * @param systemDefinition
115: * @param aspectDefinition
116: * @return definition for the perObjectAspect for the given perX aspect
117: */
118: public static AspectDefinition getAspectDefinition(
119: SystemDefinition systemDefinition,
120: AspectDefinition aspectDefinition) {
121: DeploymentModel.PointcutControlledDeploymentModel deploymentModel = (DeploymentModel.PointcutControlledDeploymentModel) aspectDefinition
122: .getDeploymentModel();
123:
124: AspectDefinition perXSystemAspectDef = new AspectDefinition(
125: getAspectName(aspectDefinition.getQualifiedName(),
126: deploymentModel), PEROBJECT_CLASSINFO,
127: systemDefinition);
128:
129: perXSystemAspectDef.setDeploymentModel(DeploymentModel.PER_JVM);
130: perXSystemAspectDef.addParameter(
131: PerObjectAspect.ASPECT_QNAME_PARAM, aspectDefinition
132: .getQualifiedName());
133: perXSystemAspectDef.addParameter(
134: PerObjectAspect.CONTAINER_CLASSNAME_PARAM,
135: aspectDefinition.getContainerClassName());
136:
137: ExpressionInfo expressionInfo = createExpressionInfo(
138: deploymentModel, aspectDefinition.getQualifiedName(),
139: PEROBJECT_CLASSINFO.getClassLoader());
140:
141: perXSystemAspectDef
142: .addBeforeAdviceDefinition(new AdviceDefinition(
143: PerObjectAspect.ADVICE_SIGNATURE,
144: AdviceType.BEFORE, null, perXSystemAspectDef
145: .getName(), PEROBJECT_ASPECT_NAME,
146: expressionInfo, BEFORE_ADVICE_METHOD_INFO,
147: perXSystemAspectDef));
148:
149: return perXSystemAspectDef;
150: }
151:
152: /**
153: * Naming strategy depends on the perX(X) X pointcut.
154: * One definition is created per perX X pointcut hashcode, thus perthis(X) and pertarget(X)
155: * are sharing the same system aspect perObjectAspect definition.
156: * Note: depends on perX aspect Qname to support pointcut references of the same name in 2 different aspect.
157: *
158: * @param perXAspectQName Qname of the perX deployed aspect
159: * @param deploymentModel
160: * @return
161: */
162: private static String getAspectName(
163: String perXAspectQName,
164: DeploymentModel.PointcutControlledDeploymentModel deploymentModel) {
165: return PEROBJECT_ASPECT_NAME + '_' + perXAspectQName.hashCode()
166: + '_' + deploymentModel.hashCode();
167: }
168:
169: /**
170: * Create the expression info where to bind the perObjectAspect for the given perX model
171: *
172: * @param deployModel
173: * @param qualifiedName of the perX Aspect
174: * @param cl
175: * @return
176: */
177: public static ExpressionInfo createExpressionInfo(
178: final DeploymentModel.PointcutControlledDeploymentModel deployModel,
179: final String qualifiedName, final ClassLoader cl) {
180: ExpressionInfo expressionInfo = new ExpressionInfo(deployModel
181: .getDeploymentExpression(), qualifiedName);
182: expressionInfo.addArgument(
183: PerObjectAspect.ADVICE_ARGUMENT_NAME,
184: PerObjectAspect.ADVICE_ARGUMENT_TYPE, cl);
185:
186: return expressionInfo;
187: }
188:
189: }
|