View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.transform.inlining;
9   
10  import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer;
11  import org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor;
12  import org.codehaus.aspectwerkz.transform.Context;
13  import org.objectweb.asm.Label;
14  
15  import java.io.File;
16  import java.io.FileOutputStream;
17  import java.util.HashMap;
18  import java.util.List;
19  import java.util.Map;
20  import java.util.ArrayList;
21  import java.util.Set;
22  
23  import gnu.trove.TObjectIntHashMap;
24  
25  /***
26   * Implementation of the transformation context interface for the delegation weaving.
27   *
28   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
29   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
30   */
31  public class ContextImpl implements Context {
32      /***
33       * The name of the class.
34       */
35      private final String m_className;
36  
37      /***
38       * The initial bytecode of the class
39       */
40      private final byte[] m_initialBytecode;
41  
42      /***
43       * The current bytecode of the class
44       */
45      private byte[] m_currentBytecode;
46  
47      /***
48       * The class loader for the class being transformed.
49       */
50      private final ClassLoader m_loader;
51  
52      /***
53       * Marks the class being transformed as advised.
54       */
55      private boolean m_advised = false;
56  
57      /***
58       * Marks the class being transformed as made advisable for interceptor support.
59       */
60      private boolean m_madeAdvisable = false;
61  
62      /***
63       * Marks the context as read-only.
64       */
65      private boolean m_readOnly = false;
66  
67      /***
68       * Meta-data for the transformation.
69       */
70      private Map m_metaData = new HashMap();
71  
72      /***
73       * The contextual set of SystemDefinitions
74       */
75      private final Set m_definitions;
76  
77      /***
78       * The emitted join points.
79       */
80      private final List m_emittedJoinPoints = new ArrayList();
81  
82      /***
83       * A map of line number per label.
84       * Note: labels are valid in the scope of one single ASM accept() only (one phase)
85       */
86      private final TObjectIntHashMap m_labelTolineNumbers = new TObjectIntHashMap();
87  
88      private long m_serialVerUid;
89      /***
90       * Creates a new context.
91       *
92       * @param loader the class loader
93       */
94      public ContextImpl(final String className, final byte[] bytecode, final ClassLoader loader) {
95          m_className = className.replace('.', '/');
96          m_loader = loader;
97          m_initialBytecode = bytecode;
98          m_currentBytecode = bytecode;
99          m_definitions = SystemDefinitionContainer.getDefinitionsFor(m_loader);
100     }
101 
102     public String getClassName() {
103         return m_className;
104     }
105 
106     /***
107      * Returns the initial bytecode.
108      *
109      * @return bytecode
110      */
111     public byte[] getInitialBytecode() {
112         return m_initialBytecode;
113     }
114 
115     /***
116      * Returns the current bytecode.
117      *
118      * @return bytecode
119      */
120     public byte[] getCurrentBytecode() {
121         return m_currentBytecode;
122     }
123 
124     /***
125      * Sets the current bytecode.
126      *
127      * @param bytecode
128      */
129     public void setCurrentBytecode(final byte[] bytecode) {
130         m_currentBytecode = bytecode;
131     }
132 
133     /***
134      * Returns the class loader.
135      *
136      * @return the class loader
137      */
138     public ClassLoader getLoader() {
139         return m_loader;
140     }
141 
142     /***
143      * The definitions context (with hierarchical structure)
144      *
145      * @return
146      */
147     public Set getDefinitions() {
148         return m_definitions;
149     }
150 
151     /***
152      * Marks the class being transformed as advised. The marker can at most be set once per class per transformer
153      */
154     public void markAsAdvised() {
155         m_advised = true;
156     }
157 
158     /***
159      * Marks the class as made advisable.
160      */
161     public void markMadeAdvisable() {
162         m_madeAdvisable = true;
163     }
164 
165     /***
166      * Resets the isAdviced flag.
167      */
168     public void resetAdvised() {
169         m_advised = false;
170     }
171 
172     /***
173      * Checks if the class being transformed has beed advised.
174      *
175      * @return boolean
176      */
177     public boolean isAdvised() {
178         return m_advised;
179     }
180 
181     /***
182      * Checks if the class has been made advisable.
183      *
184      * @return
185      */
186     public boolean isMadeAdvisable() {
187         return m_madeAdvisable;
188     }
189 
190     /***
191      * Marks the context as read-only.
192      */
193     public void markAsReadOnly() {
194         m_readOnly = true;
195     }
196 
197     /***
198      * Checks if the context is read-only.
199      *
200      * @return boolean
201      */
202     public boolean isReadOnly() {
203         return m_readOnly;
204     }
205 
206     /***
207      * Returns meta-data for the transformation.
208      *
209      * @param key the key
210      * @return the value
211      */
212     public Object getMetaData(final Object key) {
213         return m_metaData.get(key);
214     }
215 
216     /***
217      * Adds new meta-data for the transformation.
218      *
219      * @param key   the key
220      * @param value the value
221      */
222     public void addMetaData(final Object key, final Object value) {
223         if (m_readOnly) {
224             throw new IllegalStateException("context is read only");
225         }
226         m_metaData.put(key, value);
227     }
228 
229     /***
230      * Dumps the class to specific directory.
231      *
232      * @param dumpDir
233      */
234     public void dump(final String dumpDir) {
235         try {
236             int lastSegmentIndex = m_className.lastIndexOf('/');
237             if (lastSegmentIndex < 0) {
238                 lastSegmentIndex = 0;
239             }
240             File dir = new File(dumpDir + File.separator + m_className.substring(0, lastSegmentIndex));
241             dir.mkdirs();
242             FileOutputStream os = new FileOutputStream(
243                     dumpDir
244                     + File.separator
245                     + m_className.replace('.', '/')
246                     + ".class"
247             );
248             os.write(m_currentBytecode);
249             os.close();
250         } catch (Exception e) {
251             AspectWerkzPreProcessor.log("failed to dump " + m_className);
252             e.printStackTrace();
253         }
254     }
255 
256     /***
257      * Adds a new EmittedJoinPoint
258      *
259      * @param jp
260      */
261     public void addEmittedJoinPoint(final EmittedJoinPoint jp) {
262         m_emittedJoinPoints.add(jp);
263     }
264 
265     /***
266      * Returns all the EmittedJoinPoints
267      *
268      * @return
269      */
270     public List getEmittedJoinPoints() {
271         return m_emittedJoinPoints;
272     }
273 
274     public void setSerialVerUid(long initialSerialVerUid) {
275         m_serialVerUid = initialSerialVerUid;
276     }
277 
278     public long getSerialVerUid() {
279         return m_serialVerUid;
280     }
281 
282     public void addLineNumberInfo(Label label, int lineNumber) {
283         m_labelTolineNumbers.put(label, lineNumber);
284     }
285 
286     /***
287      * Tries to resolve the line number from the given label
288      *
289      * @param label
290      * @return
291      */
292     public int resolveLineNumberInfo(Label label) {
293        if (m_labelTolineNumbers.containsKey(label)) {
294            return m_labelTolineNumbers.get(label);
295        } else {
296            return 0;
297        }
298     }
299 
300 }