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.transform.inlining;
008:
009: import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer;
010: import org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor;
011: import org.codehaus.aspectwerkz.transform.Context;
012: import org.objectweb.asm.Label;
013:
014: import java.io.File;
015: import java.io.FileOutputStream;
016: import java.util.HashMap;
017: import java.util.List;
018: import java.util.Map;
019: import java.util.ArrayList;
020: import java.util.Set;
021:
022: import gnu.trove.TObjectIntHashMap;
023:
024: /**
025: * Implementation of the transformation context interface for the delegation weaving.
026: *
027: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
028: * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
029: */
030: public class ContextImpl implements Context {
031: /**
032: * The name of the class.
033: */
034: private final String m_className;
035:
036: /**
037: * The initial bytecode of the class
038: */
039: private final byte[] m_initialBytecode;
040:
041: /**
042: * The current bytecode of the class
043: */
044: private byte[] m_currentBytecode;
045:
046: /**
047: * The class loader for the class being transformed.
048: */
049: private final ClassLoader m_loader;
050:
051: /**
052: * Marks the class being transformed as advised.
053: */
054: private boolean m_advised = false;
055:
056: /**
057: * Marks the class being transformed as made advisable for interceptor support.
058: */
059: private boolean m_madeAdvisable = false;
060:
061: /**
062: * Marks the context as read-only.
063: */
064: private boolean m_readOnly = false;
065:
066: /**
067: * Meta-data for the transformation.
068: */
069: private Map m_metaData = new HashMap();
070:
071: /**
072: * The contextual set of SystemDefinitions
073: */
074: private final Set m_definitions;
075:
076: /**
077: * The emitted join points.
078: */
079: private final List m_emittedJoinPoints = new ArrayList();
080:
081: /**
082: * A map of line number per label.
083: * Note: labels are valid in the scope of one single ASM accept() only (one phase)
084: */
085: private final TObjectIntHashMap m_labelTolineNumbers = new TObjectIntHashMap();
086:
087: private long m_serialVerUid;
088:
089: /**
090: * Creates a new context.
091: *
092: * @param loader the class loader
093: */
094: public ContextImpl(final String className, final byte[] bytecode,
095: final ClassLoader loader) {
096: m_className = className.replace('.', '/');
097: m_loader = loader;
098: m_initialBytecode = bytecode;
099: m_currentBytecode = bytecode;
100: m_definitions = SystemDefinitionContainer
101: .getDefinitionsFor(m_loader);
102: }
103:
104: public String getClassName() {
105: return m_className;
106: }
107:
108: /**
109: * Returns the initial bytecode.
110: *
111: * @return bytecode
112: */
113: public byte[] getInitialBytecode() {
114: return m_initialBytecode;
115: }
116:
117: /**
118: * Returns the current bytecode.
119: *
120: * @return bytecode
121: */
122: public byte[] getCurrentBytecode() {
123: return m_currentBytecode;
124: }
125:
126: /**
127: * Sets the current bytecode.
128: *
129: * @param bytecode
130: */
131: public void setCurrentBytecode(final byte[] bytecode) {
132: m_currentBytecode = bytecode;
133: }
134:
135: /**
136: * Returns the class loader.
137: *
138: * @return the class loader
139: */
140: public ClassLoader getLoader() {
141: return m_loader;
142: }
143:
144: /**
145: * The definitions context (with hierarchical structure)
146: *
147: * @return
148: */
149: public Set getDefinitions() {
150: return m_definitions;
151: }
152:
153: /**
154: * Marks the class being transformed as advised. The marker can at most be set once per class per transformer
155: */
156: public void markAsAdvised() {
157: m_advised = true;
158: }
159:
160: /**
161: * Marks the class as made advisable.
162: */
163: public void markMadeAdvisable() {
164: m_madeAdvisable = true;
165: }
166:
167: /**
168: * Resets the isAdviced flag.
169: */
170: public void resetAdvised() {
171: m_advised = false;
172: }
173:
174: /**
175: * Checks if the class being transformed has beed advised.
176: *
177: * @return boolean
178: */
179: public boolean isAdvised() {
180: return m_advised;
181: }
182:
183: /**
184: * Checks if the class has been made advisable.
185: *
186: * @return
187: */
188: public boolean isMadeAdvisable() {
189: return m_madeAdvisable;
190: }
191:
192: /**
193: * Marks the context as read-only.
194: */
195: public void markAsReadOnly() {
196: m_readOnly = true;
197: }
198:
199: /**
200: * Checks if the context is read-only.
201: *
202: * @return boolean
203: */
204: public boolean isReadOnly() {
205: return m_readOnly;
206: }
207:
208: /**
209: * Returns meta-data for the transformation.
210: *
211: * @param key the key
212: * @return the value
213: */
214: public Object getMetaData(final Object key) {
215: return m_metaData.get(key);
216: }
217:
218: /**
219: * Adds new meta-data for the transformation.
220: *
221: * @param key the key
222: * @param value the value
223: */
224: public void addMetaData(final Object key, final Object value) {
225: if (m_readOnly) {
226: throw new IllegalStateException("context is read only");
227: }
228: m_metaData.put(key, value);
229: }
230:
231: /**
232: * Dumps the class to specific directory.
233: *
234: * @param dumpDir
235: */
236: public void dump(final String dumpDir) {
237: try {
238: int lastSegmentIndex = m_className.lastIndexOf('/');
239: if (lastSegmentIndex < 0) {
240: lastSegmentIndex = 0;
241: }
242: File dir = new File(dumpDir + File.separator
243: + m_className.substring(0, lastSegmentIndex));
244: dir.mkdirs();
245: FileOutputStream os = new FileOutputStream(dumpDir
246: + File.separator + m_className.replace('.', '/')
247: + ".class");
248: os.write(m_currentBytecode);
249: os.close();
250: } catch (Exception e) {
251: AspectWerkzPreProcessor
252: .log("failed to dump " + m_className);
253: e.printStackTrace();
254: }
255: }
256:
257: /**
258: * Adds a new EmittedJoinPoint
259: *
260: * @param jp
261: */
262: public void addEmittedJoinPoint(final EmittedJoinPoint jp) {
263: m_emittedJoinPoints.add(jp);
264: }
265:
266: /**
267: * Returns all the EmittedJoinPoints
268: *
269: * @return
270: */
271: public List getEmittedJoinPoints() {
272: return m_emittedJoinPoints;
273: }
274:
275: public void setSerialVerUid(long initialSerialVerUid) {
276: m_serialVerUid = initialSerialVerUid;
277: }
278:
279: public long getSerialVerUid() {
280: return m_serialVerUid;
281: }
282:
283: public void addLineNumberInfo(Label label, int lineNumber) {
284: m_labelTolineNumbers.put(label, lineNumber);
285: }
286:
287: /**
288: * Tries to resolve the line number from the given label
289: *
290: * @param label
291: * @return
292: */
293: public int resolveLineNumberInfo(Label label) {
294: if (m_labelTolineNumbers.containsKey(label)) {
295: return m_labelTolineNumbers.get(label);
296: } else {
297: return 0;
298: }
299: }
300:
301: }
|