/************************************************************************************** * Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. * * http://aspectwerkz.codehaus.org * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the LGPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package org.codehaus.aspectwerkz.transform.inlining; import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer; import org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor; import org.codehaus.aspectwerkz.transform.Context; import org.objectweb.asm.Label; import java.io.File; import java.io.FileOutputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ArrayList; import java.util.Set; import gnu.trove.TObjectIntHashMap; /** * Implementation of the transformation context interface for the delegation weaving. * * @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a> * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a> */ public class ContextImpl implements Context { /** * The name of the class. */ private final String m_className; /** * The initial bytecode of the class */ private final byte[] m_initialBytecode; /** * The current bytecode of the class */ private byte[] m_currentBytecode; /** * The class loader for the class being transformed. */ private final ClassLoader m_loader; /** * Marks the class being transformed as advised. */ private boolean m_advised = false; /** * Marks the class being transformed as made advisable for interceptor support. */ private boolean m_madeAdvisable = false; /** * Marks the context as read-only. */ private boolean m_readOnly = false; /** * Meta-data for the transformation. */ private Map m_metaData = new HashMap(); /** * The contextual set of SystemDefinitions */ private final Set m_definitions; /** * The emitted join points. */ private final List m_emittedJoinPoints = new ArrayList(); /** * A map of line number per label. * Note: labels are valid in the scope of one single ASM accept() only (one phase) */ private final TObjectIntHashMap m_labelTolineNumbers = new TObjectIntHashMap(); private long m_serialVerUid; /** * Creates a new context. * * @param loader the class loader */ public ContextImpl(final String className, final byte[] bytecode, final ClassLoader loader) { m_className = className.replace('.', '/'); m_loader = loader; m_initialBytecode = bytecode; m_currentBytecode = bytecode; m_definitions = SystemDefinitionContainer.getDefinitionsFor(m_loader); } public String getClassName() { return m_className; } /** * Returns the initial bytecode. * * @return bytecode */ public byte[] getInitialBytecode() { return m_initialBytecode; } /** * Returns the current bytecode. * * @return bytecode */ public byte[] getCurrentBytecode() { return m_currentBytecode; } /** * Sets the current bytecode. * * @param bytecode */ public void setCurrentBytecode(final byte[] bytecode) { m_currentBytecode = bytecode; } /** * Returns the class loader. * * @return the class loader */ public ClassLoader getLoader() { return m_loader; } /** * The definitions context (with hierarchical structure) * * @return */ public Set getDefinitions() { return m_definitions; } /** * Marks the class being transformed as advised. The marker can at most be set once per class per transformer */ public void markAsAdvised() { m_advised = true; } /** * Marks the class as made advisable. */ public void markMadeAdvisable() { m_madeAdvisable = true; } /** * Resets the isAdviced flag. */ public void resetAdvised() { m_advised = false; } /** * Checks if the class being transformed has beed advised. * * @return boolean */ public boolean isAdvised() { return m_advised; } /** * Checks if the class has been made advisable. * * @return */ public boolean isMadeAdvisable() { return m_madeAdvisable; } /** * Marks the context as read-only. */ public void markAsReadOnly() { m_readOnly = true; } /** * Checks if the context is read-only. * * @return boolean */ public boolean isReadOnly() { return m_readOnly; } /** * Returns meta-data for the transformation. * * @param key the key * @return the value */ public Object getMetaData(final Object key) { return m_metaData.get(key); } /** * Adds new meta-data for the transformation. * * @param key the key * @param value the value */ public void addMetaData(final Object key, final Object value) { if (m_readOnly) { throw new IllegalStateException("context is read only"); } m_metaData.put(key, value); } /** * Dumps the class to specific directory. * * @param dumpDir */ public void dump(final String dumpDir) { try { int lastSegmentIndex = m_className.lastIndexOf('/'); if (lastSegmentIndex < 0) { lastSegmentIndex = 0; } File dir = new File(dumpDir + File.separator + m_className.substring(0, lastSegmentIndex)); dir.mkdirs(); FileOutputStream os = new FileOutputStream( dumpDir + File.separator + m_className.replace('.', '/') + ".class" ); os.write(m_currentBytecode); os.close(); } catch (Exception e) { AspectWerkzPreProcessor.log("failed to dump " + m_className); e.printStackTrace(); } } /** * Adds a new EmittedJoinPoint * * @param jp */ public void addEmittedJoinPoint(final EmittedJoinPoint jp) { m_emittedJoinPoints.add(jp); } /** * Returns all the EmittedJoinPoints * * @return */ public List getEmittedJoinPoints() { return m_emittedJoinPoints; } public void setSerialVerUid(long initialSerialVerUid) { m_serialVerUid = initialSerialVerUid; } public long getSerialVerUid() { return m_serialVerUid; } public void addLineNumberInfo(Label label, int lineNumber) { m_labelTolineNumbers.put(label, lineNumber); } /** * Tries to resolve the line number from the given label * * @param label * @return */ public int resolveLineNumberInfo(Label label) { if (m_labelTolineNumbers.containsKey(label)) { return m_labelTolineNumbers.get(label); } else { return 0; } } }