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 }