You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Aj.java 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*******************************************************************************
  2. * Copyright (c) 2005 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Alexandre Vasseur initial implementation
  11. *******************************************************************************/
  12. package org.aspectj.weaver.loadtime;
  13. import java.util.Map;
  14. import java.util.WeakHashMap;
  15. import org.aspectj.weaver.tools.Trace;
  16. import org.aspectj.weaver.tools.TraceFactory;
  17. import org.aspectj.weaver.tools.WeavingAdaptor;
  18. /**
  19. * Adapter between the generic class pre processor interface and the AspectJ weaver
  20. * Load time weaving consistency relies on Bcel.setRepository
  21. *
  22. * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  23. */
  24. public class Aj implements ClassPreProcessor {
  25. private IWeavingContext weavingContext;
  26. private static Trace trace = TraceFactory.getTraceFactory().getTrace(Aj.class);
  27. public Aj(){
  28. this(null);
  29. }
  30. public Aj(IWeavingContext context){
  31. if (trace.isTraceEnabled()) trace.enter("<init>",this,new Object[] {context});
  32. this.weavingContext = context;
  33. if (trace.isTraceEnabled()) trace.exit("<init>");
  34. }
  35. /**
  36. * Initialization
  37. */
  38. public void initialize() {
  39. ;
  40. }
  41. /**
  42. * Weave
  43. *
  44. * @param className
  45. * @param bytes
  46. * @param loader
  47. * @return weaved bytes
  48. */
  49. public byte[] preProcess(String className, byte[] bytes, ClassLoader loader) {
  50. if (trace.isTraceEnabled()) trace.enter("preProcess",this,new Object[] {className,bytes,loader});
  51. //TODO AV needs to doc that
  52. if (loader == null || className == null) {
  53. // skip boot loader or null classes (hibernate)
  54. if (trace.isTraceEnabled()) trace.exit("preProcess",bytes);
  55. return bytes;
  56. }
  57. try {
  58. WeavingAdaptor weavingAdaptor = WeaverContainer.getWeaver(loader, weavingContext);
  59. if (weavingAdaptor == null) {
  60. if (trace.isTraceEnabled()) trace.exit("preProcess",bytes);
  61. return bytes;
  62. }
  63. return weavingAdaptor.weaveClass(className, bytes);
  64. } catch (Exception t) {
  65. trace.error("preProcess",t);
  66. //FIXME AV wondering if we should have the option to fail (throw runtime exception) here
  67. // would make sense at least in test f.e. see TestHelper.handleMessage()
  68. t.printStackTrace();
  69. if (trace.isTraceEnabled()) trace.exit("preProcess",bytes);
  70. return bytes;
  71. }
  72. }
  73. /**
  74. * Cache of weaver
  75. * There is one weaver per classloader
  76. */
  77. static class WeaverContainer {
  78. private static Map weavingAdaptors = new WeakHashMap();
  79. static WeavingAdaptor getWeaver(ClassLoader loader, IWeavingContext weavingContext) {
  80. ExplicitlyInitializedClassLoaderWeavingAdaptor adaptor = null;
  81. synchronized(weavingAdaptors) {
  82. adaptor = (ExplicitlyInitializedClassLoaderWeavingAdaptor) weavingAdaptors.get(loader);
  83. if (adaptor == null) {
  84. String loaderClassName = loader.getClass().getName();
  85. if (loaderClassName.equals("sun.reflect.DelegatingClassLoader")) {
  86. // we don't weave reflection generated types at all!
  87. return null;
  88. } else {
  89. // create it and put it back in the weavingAdaptors map but avoid any kind of instantiation
  90. // within the synchronized block
  91. ClassLoaderWeavingAdaptor weavingAdaptor = new ClassLoaderWeavingAdaptor(loader, weavingContext);
  92. adaptor = new ExplicitlyInitializedClassLoaderWeavingAdaptor(weavingAdaptor);
  93. weavingAdaptors.put(loader, adaptor);
  94. }
  95. }
  96. }
  97. // perform the initialization
  98. return adaptor.getWeavingAdaptor(loader, weavingContext);
  99. // old version
  100. // synchronized(loader) {//FIXME AV - temp fix for #99861
  101. // synchronized (weavingAdaptors) {
  102. // WeavingAdaptor weavingAdaptor = (WeavingAdaptor) weavingAdaptors.get(loader);
  103. // if (weavingAdaptor == null) {
  104. // weavingAdaptor = new ClassLoaderWeavingAdaptor(loader, weavingContext);
  105. // weavingAdaptors.put(loader, weavingAdaptor);
  106. // }
  107. // return weavingAdaptor;
  108. // }
  109. // }
  110. }
  111. }
  112. static class ExplicitlyInitializedClassLoaderWeavingAdaptor {
  113. private final ClassLoaderWeavingAdaptor weavingAdaptor;
  114. private boolean isInitialized;
  115. public ExplicitlyInitializedClassLoaderWeavingAdaptor(ClassLoaderWeavingAdaptor weavingAdaptor) {
  116. this.weavingAdaptor = weavingAdaptor;
  117. this.isInitialized = false;
  118. }
  119. private void initialize(ClassLoader loader, IWeavingContext weavingContext) {
  120. if (!isInitialized) {
  121. isInitialized = true;
  122. weavingAdaptor.initialize(loader, weavingContext);
  123. }
  124. }
  125. public ClassLoaderWeavingAdaptor getWeavingAdaptor(ClassLoader loader, IWeavingContext weavingContext) {
  126. initialize(loader, weavingContext);
  127. return weavingAdaptor;
  128. }
  129. }
  130. /**
  131. * Returns a namespace based on the contest of the aspects available
  132. */
  133. public String getNamespace (ClassLoader loader) {
  134. ClassLoaderWeavingAdaptor weavingAdaptor = (ClassLoaderWeavingAdaptor)WeaverContainer.getWeaver(loader, weavingContext);
  135. return weavingAdaptor.getNamespace();
  136. }
  137. /**
  138. * Check to see if any classes have been generated for a particular classes loader.
  139. * Calls ClassLoaderWeavingAdaptor.generatedClassesExist()
  140. * @param loader the class cloder
  141. * @return true if classes have been generated.
  142. */
  143. public boolean generatedClassesExist(ClassLoader loader){
  144. return ((ClassLoaderWeavingAdaptor)WeaverContainer.getWeaver(loader, weavingContext)).generatedClassesExistFor(null);
  145. }
  146. public void flushGeneratedClasses(ClassLoader loader){
  147. ((ClassLoaderWeavingAdaptor)WeaverContainer.getWeaver(loader, weavingContext)).flushGeneratedClasses();
  148. }
  149. }