001: //
002: // This file is part of the prose package.
003: //
004: // The contents of this file are subject to the Mozilla Public License
005: // Version 1.1 (the "License"); you may not use this file except in
006: // compliance with the License. You may obtain a copy of the License at
007: // http://www.mozilla.org/MPL/
008: //
009: // Software distributed under the License is distributed on an "AS IS" basis,
010: // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011: // for the specific language governing rights and limitations under the
012: // License.
013: //
014: // The Original Code is prose.
015: //
016: // The Initial Developer of the Original Code is Andrei Popovici. Portions
017: // created by Andrei Popovici are Copyright (C) 2002 Andrei Popovici.
018: // All Rights Reserved.
019: //
020: // Contributor(s):
021: // $Id: SetCut.java,v 1.3 2003/11/07 22:32:37 anicoara Exp $
022: // =====================================================================
023: //
024: // (history at end)
025: //
026:
027: package ch.ethz.prose.crosscut;
028:
029: // used packages
030: import java.lang.reflect.Field;
031: import ch.ethz.jvmai.FieldModificationJoinPoint;
032:
033: /**
034: * Class SetCut is a crosscut which cuts field sets.
035: *
036: *
037: *
038: * The advice method is <code>SET_ARGS</code>. The join-point
039: * where the advice method is executted depend on:
040: * <ol>
041: * <li> the signature of <code>SET_ARGS</code>
042: * <li> the value returned by <code>pointCutter</code>.
043: * </ol>
044: *
045: * Within an advice method, the <code>thisJoinPoint()</code> method
046: * can be called to obtain a reference to the currently executing
047: * join-point.
048: *
049: * @version $Revision: 1.3 $
050: * @author Andrei Popovici
051: */
052: public abstract class SetCut extends AbstractCrosscut {
053:
054: private static class SetGetArgs {
055:
056: Object[] cc;
057: Object[] cw;
058: Object[] wc;
059: Object[] ww;
060:
061: SetGetArgs() {
062: cc = new Object[2];
063: cw = new Object[2];
064: cw[1] = new ANY();
065: wc = new Object[2];
066: wc[0] = new ANY();
067: ww = new Object[2];
068: ww[0] = new ANY();
069: ww[1] = new ANY();
070: }
071: }
072:
073: private ThreadLocal threadLocalArgs;
074: private transient SetGetSignaturePattern advicePattern;
075:
076: protected void SET_ARGS() {
077: }
078:
079: static class SetGetThreadLocal extends ThreadLocal implements
080: java.io.Serializable {
081: private static final long serialVersionUID = 3256441412991071543L;
082:
083: protected Object initialValue() {
084: return new SetGetArgs();
085: }
086: };
087:
088: protected SetCut() {
089: initState();
090: threadLocalArgs = new SetGetThreadLocal();
091: }
092:
093: public void insertionAction(boolean isBeforeInsertion) {
094: if (isBeforeInsertion)
095: initState();
096: }
097:
098: String toStringSignature;
099:
100: private void initState() {
101: if (advicePattern == null) {
102: advicePattern = new SetGetSignaturePattern(this );
103: toStringSignature = advicePattern.toString();
104: }
105: }
106:
107: /**
108: * Note that Field f does <em>not</em> contain the current (old)
109: * value of the field. If you want to retrieve the old value, do
110: * it by invoking <code>f.get(owner)</code>. The old value is
111: * only accessible at the moment this method is called. After that,
112: * invokation of <code>f.get(owner)</code> returns the new value.
113: *
114: */
115:
116: /** Extracts the field owner and passes this to <code>fieldAccessAdvice</code>
117: */
118: protected void joinPointAction(FieldModificationJoinPoint ev) {
119:
120: Object[] args = null;
121: SetGetArgs setGetArgs = (SetGetArgs) threadLocalArgs.get();
122:
123: switch (advicePattern.signatureCathegory) {
124: case SignaturePattern.SIGNATURE__EMPTY: //SET_ARGS(); //BUGFIX: the advice method is executed twice
125: break;
126: case SignaturePattern.SIGNATURE__CONCRETE__CONCRETE:
127: args = setGetArgs.cc;
128: args[0] = ev.getTarget();
129: args[1] = ev.getValue();
130: break;
131: case SignaturePattern.SIGNATURE__WILDCARD__CONCRETE:
132: args = setGetArgs.wc;
133: ((ANY) args[0]).setObject(ev.getTarget());
134: args[1] = ev.getValue();
135: break;
136: case SignaturePattern.SIGNATURE__CONCRETE__WILDCARD:
137: args = setGetArgs.cw;
138: args[0] = ev.getTarget();
139: ((ANY) args[1]).setObject(ev.getValue());
140: break;
141: case SignaturePattern.SIGNATURE__WILDCARD__WILDCARD:
142: args = setGetArgs.ww;
143: ((ANY) args[0]).setObject(ev.getTarget());
144: ((ANY) args[1]).setObject(ev.getValue());
145: break;
146: default:
147: throw new Error("Wrong pattern signature in " + this );
148: }
149: try {
150: advicePattern.methodObj.invoke(this , args);
151: } catch (IllegalAccessException e) {
152: throw new RuntimeException();
153: } catch (java.lang.reflect.InvocationTargetException e) {
154: throw new RuntimeException(e.getTargetException());
155: }
156:
157: }
158:
159: /**
160: * Create a new CrosscutRequest consisting of FieldAccessRequests
161: * and FieldModificationRequests for every field (public, protected,
162: * private or package-scoped) declared in class <code>c</code>. (No
163: * request is generated for inherited fields!)
164: */
165: protected CrosscutRequest doCreateRequest(Class c)
166: throws SecurityException {
167: // retrieve all fields of this class and install
168: // a field access and a field modification watch.
169: Field[] declaredFields = null;
170: CrosscutRequest result = new CrosscutRequest();
171:
172: if (null == advicePattern)
173: return result;
174:
175: try {
176: declaredFields = c.getDeclaredFields();
177: } catch (NoClassDefFoundError e) {
178: return result;
179: }
180:
181: for (int i = 0; i < declaredFields.length; i++) {
182: if (advicePattern
183: .matchesOperationOnField(declaredFields[i]))
184: result.add(requestFactory.createJoinPointRequest(
185: FieldModificationJoinPoint.KIND,
186: declaredFields[i]));
187: }
188:
189: return result;
190: }
191:
192: /**
193: *
194: */
195: public String toString() {
196: return " Crosscut: 'SetCut' \n" + " Advice:"
197: + toStringSignature + "\n" + " PointCutter: "
198: + getSpecializer() + "\n";
199: }
200:
201: }
202:
203: //======================================================================
204: //
205: // $Log: SetCut.java,v $
206: // Revision 1.3 2003/11/07 22:32:37 anicoara
207: // SetCut bugfixes: threadLocalArgs has been transient, the advice method was executed twice
208: //
209: // Revision 1.2 2003/07/11 12:27:43 apopovic
210: // Bug fix for rare cases. Some classed loaded late may throw a 'NoClassDefError' when
211: // trying to retrieve the declared methods; The crosscut for such cases is now an empty listt
212: //
213: // Revision 1.1.1.1 2003/07/02 15:30:51 apopovic
214: // Imported from ETH Zurich
215: //
216: // Revision 1.3 2003/05/26 13:28:53 popovici
217: // Documentation Improvements
218: //
219: // Revision 1.2 2003/05/25 11:46:45 popovici
220: // Improved 'toString' presentation of aspects
221: //
222: // Revision 1.1 2003/05/05 13:58:16 popovici
223: // renaming from runes to prose
224: //
225: // Revision 1.8 2002/06/06 12:01:50 popovici
226: // fieldAccessAdvice removed from SetCut; tests and usage of SetCut's
227: // ability to intercept gets moved to 'GetCut'
228: // Minor bug fixes;
229: //
230: // Revision 1.7 2002/06/05 12:03:49 popovici
231: // thisJoinPoint() updated everywhere. The 'fieldModificationAdvice is now parameterless'; older implemnentations now
232: // use 'thisJoinPoint()'
233: //
234: // Revision 1.6 2002/06/05 09:27:58 popovici
235: // thisJoinPoint() introduced in Abstract Crosscut and subclasses;
236: //
237: // Revision 1.5 2002/03/28 13:48:41 popovici
238: // Mozilla-ified
239: //
240: // Revision 1.4 2002/03/06 13:48:37 popovici
241: // joinPointAction now in 4 flavours, depending on the join point type
242: //
243: // Revision 1.3 2002/02/21 12:39:20 popovici
244: // Crosscut efficiency issues:
245: // - joinPointAction dispatch based on static optimization
246: // (->doesEventSpecialization, 'setSpecializer' modified)
247: // (->calculation of 'adviceMethodOptimization', in Func.Crossc)
248: // - joinPointAction now uses JoinPoints (not Events)
249: // - JoinPointListeners (including crosscuts) now use joinPointReached(XXXJoinPoint) to avoid casting
250: // Crosscut architectural issues:
251: // - AbstractCrosscut now insertable.
252: // - AbstractCrosscuts owns referecnces to JVMAI
253: //
254: // Revision 1.2 2002/02/05 09:47:12 smarkwal
255: // JVMDI-specific code replaced by JVMAI. Prose-implementation classes and reflection package removed.
256: //
257: // Revision 1.1.1.1 2001/11/29 18:13:17 popovici
258: // Sources from runes
259: //
260: // Revision 1.1.2.1 2000/11/28 16:39:38 groos
261: // Initial revision.
262: //
|