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.hook.impl;
9   
10  import org.codehaus.aspectwerkz.hook.ClassPreProcessor;
11  
12  import java.security.ProtectionDomain;
13  
14  /***
15   * Helper class called by the modified java.lang.ClassLoader. <p/>This class is called at different points by the
16   * modified java.lang.ClassLoader of the org.codehaus.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl implemention.
17   * <br/>This class must reside in the -Xbootclasspath when AspectWerkz layer 1 is used, but the effective implementation
18   * of the class preprocessor (AspectWerkz layer 2) can be in standard system classpath (-cp).
19   * 
20   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
21   */
22  public class ClassPreProcessorHelper {
23      /***
24       * ClassPreProcessor used if aspectwerkz.classloader.preprocessor property is defined to full qualified class name
25       */
26      private static ClassPreProcessor preProcessor;
27  
28      /***
29       * true if preProcesor already initalized
30       */
31      private static boolean preProcessorInitialized;
32  
33      /***
34       * option used to defined the class preprocessor
35       */
36      private static String PRE_PROCESSOR_CLASSNAME_PROPERTY = "aspectwerkz.classloader.preprocessor";
37  
38      /***
39       * default class preprocessor
40       */
41      private static String PRE_PROCESSOR_CLASSNAME_DEFAULT = "org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor";
42  
43      static {
44          initializePreProcessor();
45      }
46  
47      /***
48       * Returns the configured class preprocessor Should be called after initialization only
49       * 
50       * @return the preprocessor or null if not initialized
51       */
52      public static ClassPreProcessor getClassPreProcessor() {
53          return preProcessor;
54      }
55  
56      /***
57       * Initialization of the ClassPreProcessor The ClassPreProcessor implementation is lazy loaded. This allow to put it
58       * in the regular classpath whereas the instrumentation layer (layer 1) is in the bootclasspath
59       */
60      public static synchronized void initializePreProcessor() {
61          //@todo review log statement according to log layer
62          if (preProcessorInitialized) {
63              return;
64          }
65          preProcessorInitialized = true;
66          Class klass = null;
67          String s = System.getProperty(PRE_PROCESSOR_CLASSNAME_PROPERTY, PRE_PROCESSOR_CLASSNAME_DEFAULT);
68          try {
69              // force loading thru System class loader to allow
70              // preprocessor implementation to be in standard classpath
71              klass = Class.forName(s, true, ClassLoader.getSystemClassLoader());
72  
73              // special hidden option to allow testing of HotSwap weaving when WeavingCL is used
74              // in such a case the CLPP must be in the WeavingCL hierarchy, which is parrallel
75              // to the regulare SystemCL
76              if (System.getProperty("aspectwerkz.transform.forceWCL") != null) {
77                  klass = Class.forName(s, true, Thread.currentThread().getContextClassLoader());
78              }
79          } catch (ClassNotFoundException _ex) {
80              System.err.println("AspectWerkz - WARN - Pre-processor class '" + s + "' not found");
81          }
82          if (klass != null) {
83              try {
84                  preProcessor = (ClassPreProcessor) klass.newInstance();
85                  preProcessor.initialize(null);
86                  System.out.println("AspectWerkz - INFO - Pre-processor " + s + " loaded and initialized");
87              } catch (Throwable throwable) {
88                  System.err.println("AspectWerkz - WARN - Error initializing pre-processor class " + s + ':');
89                  throwable.printStackTrace();
90              }
91          }
92      }
93  
94      /***
95       * byte code instrumentation of class loaded
96       */
97      public static byte[] defineClass0Pre(
98          ClassLoader caller,
99          String name,
100         byte[] b,
101         int off,
102         int len,
103         ProtectionDomain pd) {
104         if (!preProcessorInitialized) {
105             initializePreProcessor();
106         }
107         if (preProcessor == null) {
108             // we need to check this due to reentrancy when ClassPreProcessorHelper is beeing
109             // initialized
110             // since it tries to load a ClassPreProcessor implementation
111             byte[] obyte = new byte[len];
112             System.arraycopy(b, off, obyte, 0, len);
113             return obyte;
114         } else {
115             try {
116                 byte[] ibyte = new byte[len];
117                 byte[] obyte = new byte[] {};
118                 System.arraycopy(b, off, ibyte, 0, len);
119                 obyte = preProcessor.preProcess(name, ibyte, caller);
120                 return obyte;
121             } catch (Throwable throwable) {
122                 System.err.println("AspectWerkz - WARN - Error pre-processing class "
123                     + name
124                     + " in "
125                     + Thread.currentThread());
126                 throwable.printStackTrace();
127                 byte[] obyte = new byte[len];
128                 System.arraycopy(b, off, obyte, 0, len);
129 
130                 //abyte = preProcessor.preProcess(name, abyte, caller);
131                 return obyte;
132             }
133         }
134     }
135 }