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 Angela Nicoara. Portions
017: // created by Angela Nicoara are Copyright (C) 2002 Angela Nicoara.
018: // All Rights Reserved.
019: //
020: // Contributor(s):
021: // $Id$
022: // =====================================================================
023: //
024: // (history at end)
025: //
026:
027: package ch.ethz.prose.jvmai.jikesrvm.advice_weaver;
028:
029: import java.lang.reflect.Field;
030: import java.lang.reflect.Method;
031: import java.util.*;
032:
033: import com.ibm.JikesRVM.classloader.*;
034:
035: /**
036: * Remembers the fields where a callback should be inserted. For each method
037: * that references the specified field, a callback is woven using the
038: * MethodWeaver class.
039: *
040: * @version $Revision$
041: * @author Johann Gyger
042: * @author Angela Nicoara
043: */
044: public class FieldWeaver {
045:
046: /**
047: * Collection of all field weavers. For each field there exists exactly one
048: * field weaver in the system.
049: */
050: protected static Map weavers = new HashMap();
051:
052: /**
053: * Get a unique field weaver for `target'.
054: *
055: * @param target field that will be woven
056: */
057: public static synchronized FieldWeaver getWeaver(Field target) {
058: if (target == null)
059: throw new NullPointerException(
060: "Parameter `target' must not be null.");
061:
062: FieldWeaver result = (FieldWeaver) weavers.get(target
063: .toString());
064: if (result == null) {
065: result = new FieldWeaver(target);
066: weavers.put(target.toString(), result);
067: }
068:
069: return result;
070: };
071:
072: /**
073: * Re-weave all modified f and activate them in the VM.
074: */
075: public static synchronized void commit() {
076: Iterator it = weavers.values().iterator();
077: while (it.hasNext()) {
078: FieldWeaver fw = (FieldWeaver) it.next();
079: if (fw.modified) {
080: //System.out.println("FieldWeaver.commit(): " + fw.debugString());
081: fw.weave();
082: }
083: }
084: }
085:
086: /**
087: * Reset all field weavers.
088: */
089: public static synchronized void resetAll() {
090: weavers = new HashMap();
091: }
092:
093: /**
094: * Field bound to this weaver.
095: */
096: protected Field target;
097:
098: /**
099: * Is field access join point activated?
100: */
101: protected boolean fieldAccessEnabled;
102:
103: /**
104: * Is field modificatin join point activated?
105: */
106: protected boolean fieldModificationEnabled;
107:
108: /**
109: * Is a re-weaving of the callbacks for the field in this weaver necessary?
110: */
111: protected boolean modified;
112:
113: /**
114: * Create a new field weaver.
115: *
116: * @param target target field for which callbacks will be woven
117: */
118: protected FieldWeaver(Field target) {
119: this .target = target;
120: }
121:
122: /**
123: * Enable field access join point.
124: *
125: * @param flag enable/disable
126: */
127: public void setFieldAccessEnabled(boolean flag) {
128: fieldAccessEnabled = flag;
129: modified = true;
130: }
131:
132: /**
133: * Enable field modification join point.
134: *
135: * @param flag enable/disable
136: */
137: public void setFieldModificationEnabled(boolean flag) {
138: fieldModificationEnabled = flag;
139: modified = true;
140: }
141:
142: public String debugString() {
143: StringBuffer sb = new StringBuffer();
144:
145: sb.append("FieldWeaver for: ");
146: sb.append(target);
147: sb.append("\n\tfieldAccessEnabled: ");
148: sb.append(fieldAccessEnabled);
149: sb.append("\n\tfieldModificationEnabled: ");
150: sb.append(fieldModificationEnabled);
151: sb.append("\n\tmodified: ");
152: sb.append(modified);
153:
154: return sb.toString();
155: }
156:
157: /**
158: * Weave advice that are associated with the field in this weaver. The
159: * weaving is actually done by the MethodWeaver. This method only informs the
160: * MethodWeaver instances that are involved.
161: */
162: protected void weave() {
163: VM_Field f = java.lang.reflect.JikesRVMSupport
164: .getFieldOf(target);
165: VM_FieldReference fr = f.getMemberRef().asFieldReference();
166:
167: Iterator it = fr.accessors.iterator();
168: while (it.hasNext()) {
169: Method m = getMethod(((Integer) it.next()).intValue());
170:
171: if (fieldAccessEnabled)
172: MethodWeaver.getWeaver(m).addFieldAccessor(target);
173: else
174: MethodWeaver.getWeaver(m).removeFieldAccessor(target);
175: }
176:
177: it = fr.modifiers.iterator();
178: while (it.hasNext()) {
179: Method m = getMethod(((Integer) it.next()).intValue());
180:
181: if (fieldModificationEnabled)
182: MethodWeaver.getWeaver(m).addFieldModifier(target);
183: else
184: MethodWeaver.getWeaver(m).removeFieldModifier(target);
185: }
186:
187: modified = false;
188: }
189:
190: /**
191: * Get the method with id `id'
192: *
193: * @param id method id
194: * @return method
195: */
196: protected Method getMethod(int id) {
197: VM_MethodReference mr = VM_MemberReference.getMemberRef(id)
198: .asMethodReference();
199: VM_Method m = (VM_NormalMethod) mr.resolve();
200:
201: return java.lang.reflect.JikesRVMSupport.createMethod(m);
202: }
203:
204: }
205:
206: //======================================================================
207: //
208: // $Log$
209: //
|