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: GetCut.java,v 1.3 2003/11/07 22:34:57 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.FieldAccessJoinPoint;
032:
033: /**
034: * Class GetCut is a crosscut which cuts field gets.
035: *
036: *
037: *
038: * The advice method is <code>GET_ARGS</code>. The join-point
039: * where the advice method is executted depend on:
040: * <ol>
041: * <li> the signature of <code>GET_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: *
050: * @version $Revision: 1.3 $
051: * @author Andrei Popovici
052: */
053: public abstract class GetCut extends AbstractCrosscut {
054: private static class SetGetArgs {
055: Object[] cc;
056: Object[] cw;
057: Object[] wc;
058: Object[] ww;
059:
060: SetGetArgs() {
061: cc = new Object[2];
062: cw = new Object[2];
063: cw[1] = new ANY();
064: wc = new Object[2];
065: wc[0] = new ANY();
066: ww = new Object[2];
067: ww[0] = new ANY();
068: ww[1] = new ANY();
069: }
070: }
071:
072: private ThreadLocal threadLocalArgs;
073:
074: /** This method must be defined by subclasses. It will be called
075: * each time one of the selected fields is
076: *
077: */
078: protected void GET_ARGS() {
079: }
080:
081: private transient SetGetSignaturePattern advicePattern;
082:
083: static class SetGetThreadLocal extends ThreadLocal implements
084: java.io.Serializable {
085: protected Object initialValue() {
086: return new SetGetArgs();
087: }
088: };
089:
090: protected GetCut() {
091: threadLocalArgs = new SetGetThreadLocal();
092: initState();
093: }
094:
095: private void initState() {
096: if (advicePattern == null) {
097: advicePattern = new SetGetSignaturePattern(this );
098: toStringSignature = advicePattern.toString();
099: }
100: }
101:
102: String toStringSignature = null;
103:
104: public void insertionAction(boolean isBeforeInsertion) {
105: if (isBeforeInsertion)
106: initState();
107: }
108:
109: protected void joinPointAction(FieldAccessJoinPoint ev) {
110: Object[] args = null;
111: SetGetArgs setGetArgs = (SetGetArgs) threadLocalArgs.get();
112:
113: switch (advicePattern.signatureCathegory) {
114: case SignaturePattern.SIGNATURE__EMPTY: //GET_ARGS(); //BUGFIX: the advice method is executed twice
115: break;
116: case SignaturePattern.SIGNATURE__CONCRETE__CONCRETE:
117: args = setGetArgs.cc;
118: args[0] = ev.getTarget();
119: args[1] = ev.getValue();
120: break;
121: case SignaturePattern.SIGNATURE__WILDCARD__CONCRETE:
122: args = setGetArgs.wc;
123: ((ANY) args[0]).setObject(ev.getTarget());
124: args[1] = ev.getValue();
125: break;
126: case SignaturePattern.SIGNATURE__CONCRETE__WILDCARD:
127: args = setGetArgs.cw;
128: args[0] = ev.getTarget();
129: ((ANY) args[1]).setObject(ev.getValue());
130: break;
131: case SignaturePattern.SIGNATURE__WILDCARD__WILDCARD:
132: args = setGetArgs.ww;
133: ((ANY) args[0]).setObject(ev.getTarget());
134: ((ANY) args[1]).setObject(ev.getValue());
135: break;
136: default:
137: throw new Error("Wrong pattern signature in " + this );
138: }
139: try {
140: advicePattern.methodObj.invoke(this , args);
141: } catch (IllegalAccessException e) {
142: throw new RuntimeException();
143: } catch (java.lang.reflect.InvocationTargetException e) {
144: throw new RuntimeException();
145: }
146:
147: }
148:
149: /**
150: * Create a new CrosscutRequest consisting of FieldAccessRequests
151: * and FieldModificationRequests for every field (public, protected,
152: * private or package-scoped) declared in class <code>c</code>. (No
153: * request is generated for inherited fields!)
154: */
155: protected CrosscutRequest doCreateRequest(Class c)
156: throws SecurityException {
157: // retrieve all fields of this class and install
158: // a field access and a field modification watch.
159: Field[] declaredFields = null;
160: CrosscutRequest result = new CrosscutRequest();
161:
162: try {
163: declaredFields = c.getDeclaredFields();
164: } catch (NoClassDefFoundError e) {
165: return result;
166: }
167: for (int i = 0; i < declaredFields.length; i++) {
168: if (advicePattern
169: .matchesOperationOnField(declaredFields[i]))
170: result.add(requestFactory.createJoinPointRequest(
171: FieldAccessJoinPoint.KIND, declaredFields[i]));
172: }
173:
174: return result;
175: }
176:
177: /**
178: *
179: */
180: public String toString() {
181: return " Crosscut: 'GetCut' \n" + " Advice:"
182: + toStringSignature + "\n" + " PointCutter: "
183: + getSpecializer() + "\n";
184: }
185: }
186:
187: //======================================================================
188: //
189: // $Log: GetCut.java,v $
190: // Revision 1.3 2003/11/07 22:34:57 anicoara
191: // GetCut bugfix: the advice method has been executed twice
192: //
193: // Revision 1.2 2003/07/11 12:27:43 apopovic
194: // Bug fix for rare cases. Some classed loaded late may throw a 'NoClassDefError' when
195: // trying to retrieve the declared methods; The crosscut for such cases is now an empty listt
196: //
197: // Revision 1.1.1.1 2003/07/02 15:30:51 apopovic
198: // Imported from ETH Zurich
199: //
200: // Revision 1.3 2003/05/26 13:28:52 popovici
201: // Documentation Improvements
202: //
203: // Revision 1.2 2003/05/25 11:46:44 popovici
204: // Improved 'toString' presentation of aspects
205: //
206: // Revision 1.1 2003/05/05 13:58:18 popovici
207: // renaming from runes to prose
208: //
209: // Revision 1.13 2003/04/29 17:34:46 pfalcari
210: // Serialization problem fixed
211: //
212: // Revision 1.12 2003/04/26 18:51:33 popovici
213: // 1 Bug fix which lead to a refactoring step:
214: // 1. the bug: 'JoinPointRequests' used to write to a static list, which survived a startup/teardown;
215: // now this list belongs to the JoinPointManager;
216: // 2. the refactoring: the JoinPointManager now creates (and shares state) with join-points.
217: //
218: // Revision 1.11 2003/04/17 12:49:25 popovici
219: // Refactoring of the crosscut package
220: // ExceptionCut renamed to ThrowCut
221: // McutSignature is now SignaturePattern
222: //
223: // Revision 1.10 2003/04/17 08:47:20 popovici
224: // Important functionality additions
225: // - Cflow specializers
226: // - Restructuring of the MethodCut, SetCut, ThrowCut, and GetCut (they are much smaller)
227: // - Transactional capabilities
228: // - Total refactoring of Specializer evaluation, which permits fine-grained distinction
229: // between static and dynamic specializers.
230: // - Functionality pulled up in abstract classes
231: // - Uniformization of advice methods patterns and names
232: //
233: // Revision 1.9 2003/04/07 13:17:26 popovici
234: // Bug fix in serialization: Local hash maps were not static.
235: // > Deserialized join-points used to hit on a null when looking for their 'threadLocalJoinPoint'
236: //
237: // Revision 1.8 2003/03/04 18:36:34 popovici
238: // Organization of imprts
239: //
240: // Revision 1.7 2003/03/04 11:27:18 popovici
241: // Important refactorization step (march):
242: // - removal of 'JoinPointEvents'; JoinPoints now have the same function as events
243: // - reimplementation of the JVMAIDebuggerAspectInterface (better performance, coding conventions, removal of ProseVM
244: // structures
245: //
246: // Revision 1.6 2003/01/27 12:49:04 pschoch
247: // new toString() implementation
248: //
249: // Revision 1.5 2002/10/31 18:26:50 pschoch
250: // Capability of crosscutting Exceptions added to prose.
251: //
252: // Revision 1.4 2002/10/25 07:42:34 popovici
253: // Undo Chnages Phillippe
254: //
255: // Revision 1.2 2002/06/07 15:30:51 popovici
256: // Documentation updates of FunctionalCrosscut/ClasseS refactorings
257: //
258: // Revision 1.1 2002/06/05 09:27:59 popovici
259: // thisJoinPoint() introduced in Abstract Crosscut and subclasses;
260: //
261: // Revision 1.5 2002/03/28 13:48:41 popovici
262: // Mozilla-ified
263: //
264: // Revision 1.4 2002/03/06 13:48:37 popovici
265: // joinPointAction now in 4 flavours, depending on the join point type
266: //
267: // Revision 1.3 2002/02/21 12:39:20 popovici
268: // Crosscut efficiency issues:
269: // - joinPointAction dispatch based on static optimization
270: // (->doesEventSpecialization, 'setSpecializer' modified)
271: // (->calculation of 'adviceMethodOptimization', in Func.Crossc)
272: // - joinPointAction now uses JoinPoints (not Events)
273: // - JoinPointListeners (including crosscuts) now use joinPointReached(XXXJoinPoint) to avoid casting
274: // Crosscut architectural issues:
275: // - AbstractCrosscut now insertable.
276: // - AbstractCrosscuts owns referecnces to JVMAI
277: //
278: // Revision 1.2 2002/02/05 09:47:12 smarkwal
279: // JVMDI-specific code replaced by JVMAI. Prose-implementation classes and reflection package removed.
280: //
281: // Revision 1.1.1.1 2001/11/29 18:13:17 popovici
282: // Sources from runes
283: //
284: // Revision 1.1.2.1 2000/11/28 16:39:38 groos
285: // Initial revision.
286: //
|