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 }