KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > hook > impl > ClassPreProcessorHelper


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.aspectwerkz.hook.impl;
5
6 import com.tc.aspectwerkz.hook.ClassPreProcessor;
7
8 import java.security.ProtectionDomain JavaDoc;
9 import java.lang.reflect.Method JavaDoc;
10
11 /**
12  * Helper class called by the modified java.lang.ClassLoader. <p/>This class is called at different points by the
13  * modified java.lang.ClassLoader of the com.tc.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl implemention.
14  * <br/>This class must reside in the -Xbootclasspath when AspectWerkz layer 1 is used, but the effective implementation
15  * of the class preprocessor (AspectWerkz layer 2) can be in standard system classpath (-cp).
16  *
17  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
18  */

19 public class ClassPreProcessorHelper {
20   /**
21    * ClassPreProcessor used if aspectwerkz.classloader.preprocessor property is defined to full qualified class name
22    */

23   private static ClassPreProcessor preProcessor;
24
25   /**
26    * true if preProcesor already initalized
27    */

28   private static boolean preProcessorInitialized;
29
30   /**
31    * option used to defined the class preprocessor
32    */

33   private static String JavaDoc PRE_PROCESSOR_CLASSNAME_PROPERTY = "aspectwerkz.classloader.preprocessor";
34
35   /**
36    * default class preprocessor
37    */

38   private static String JavaDoc PRE_PROCESSOR_CLASSNAME_DEFAULT = "com.tc.aspectwerkz.transform.AspectWerkzPreProcessor";
39
40   static {
41     initializePreProcessor();
42   }
43
44   /**
45    * Returns the configured class preprocessor Should be called after initialization only
46    *
47    * @return the preprocessor or null if not initialized
48    */

49   public static ClassPreProcessor getClassPreProcessor() {
50     return preProcessor;
51   }
52
53   /**
54    * Initialization of the ClassPreProcessor The ClassPreProcessor implementation is lazy loaded. This allow to put it
55    * in the regular classpath whereas the instrumentation layer (layer 1) is in the bootclasspath
56    */

57   public static synchronized void initializePreProcessor() {
58     if (preProcessorInitialized) {
59       return;
60     }
61     preProcessorInitialized = true;
62     Class JavaDoc klass = null;
63     String JavaDoc s = System.getProperty(PRE_PROCESSOR_CLASSNAME_PROPERTY, PRE_PROCESSOR_CLASSNAME_DEFAULT);
64     try {
65       // force loading thru System class loader to allow
66
// preprocessor implementation to be in standard classpath
67
klass = Class.forName(s, true, ClassLoader.getSystemClassLoader());
68     } catch (ClassNotFoundException JavaDoc _ex) {
69       System.err.println("AspectWerkz - WARN - Pre-processor class '" + s + "' not found");
70     }
71     if (klass != null) {
72       try {
73         preProcessor = (ClassPreProcessor) klass.newInstance();
74         preProcessor.initialize();
75         System.err.println("AspectWerkz - INFO - Pre-processor " + s + " loaded and initialized");
76       } catch (Throwable JavaDoc throwable) {
77         System.err.println("AspectWerkz - WARN - Error initializing pre-processor class " + s + ':');
78         throwable.printStackTrace();
79       }
80     }
81   }
82
83   /**
84    * byte code instrumentation of class loaded
85    */

86   public static byte[] defineClass0Pre(ClassLoader JavaDoc caller,
87                                        String JavaDoc name,
88                                        byte[] b,
89                                        int off,
90                                        int len,
91                                        ProtectionDomain JavaDoc pd) {
92     if (preProcessor == null) {
93       // we need to check this due to reentrancy when ClassPreProcessorHelper is beeing
94
// initialized
95
// since it tries to load a ClassPreProcessor implementation
96
byte[] obyte = new byte[len];
97       System.arraycopy(b, off, obyte, 0, len);
98       return obyte;
99     } else {
100       try {
101         byte[] ibyte = new byte[len];
102         System.arraycopy(b, off, ibyte, 0, len);
103         return preProcessor.preProcess(name, ibyte, caller);
104       } catch (Throwable JavaDoc throwable) {
105         System.err.println(
106                 "AspectWerkz - WARN - Error pre-processing class "
107                         + name
108                         + " in "
109                         + Thread.currentThread()
110         );
111         throwable.printStackTrace();
112         // fallback to unweaved bytecode
113
byte[] obyte = new byte[len];
114         System.arraycopy(b, off, obyte, 0, len);
115         return obyte;
116       }
117     }
118   }
119
120   /**
121    * Byte code instrumentation of class loaded using Java 5 style thru NIO
122    * Since Java 5 comes with JVMTI this helper should be rarely used.
123    * We do no reference ByteBuffer directly to allow Java 1.3 compilation, though
124    * this helper will be really slow
125    *
126    * @param caller
127    * @param name
128    * @param byteBuffer Object that is instance of Java 1.4 NIO ButeBuffer
129    * @param off
130    * @param len
131    * @param pd
132    * @return Object instance of Java 1.4 NIO ByteBuffer
133    */

134   public static Object JavaDoc/*java.nio.ByteBuffer*/ defineClass0Pre(ClassLoader JavaDoc caller,
135                                                               String JavaDoc name,
136                                                               Object JavaDoc/*java.nio.ByteBuffer*/ byteBuffer,
137                                                               int off,
138                                                               int len,
139                                                               ProtectionDomain JavaDoc pd) {
140     byte[] bytes = new byte[len];
141     //Java 1.4 : byteBuffer.getDefault(bytes, off, len);
142
byteBufferGet(byteBuffer, bytes, off, len);
143     byte[] newbytes = defineClass0Pre(caller, name, bytes, 0, bytes.length, pd);
144     //Java 1.4 : ByteBuffer newBuffer = ByteBuffer.wrap(newbytes);
145
Object JavaDoc newBuffer = byteBufferWrap(newbytes);
146     return newBuffer;
147   }
148
149   /**
150    * Equivalent to Java 1.4 NIO aByteBuffer.getDefault(bytes, offset, length) to populate
151    * the bytes array from the aByteBuffer.
152    *
153    * @param byteBuffer
154    * @param dest
155    * @param offset
156    * @param length
157    */

158   private static void byteBufferGet(Object JavaDoc byteBuffer, byte[] dest, int offset, int length) {
159     try {
160       Class JavaDoc cByteBuffer = Class.forName("java.nio.ByteBuffer");
161       Method JavaDoc mGet = cByteBuffer.getDeclaredMethod("getDefault", new Class JavaDoc[]{BYTE_ARRAY_CLASS, int.class, int.class});
162       mGet.invoke(byteBuffer, new Object JavaDoc[]{dest, new Integer JavaDoc(offset), new Integer JavaDoc(length)});
163     } catch (Throwable JavaDoc t) {
164       System.err.println("AW : java.nio not supported");
165       throw new RuntimeException JavaDoc(t.toString());
166     }
167   }
168
169   /**
170    * Equivalent to Java 1.4 NIO static ByteBuffer.wrap(bytes) to create
171    * a new byteBuffer instance.
172    *
173    * @param bytes
174    * @return a ByteBuffer
175    */

176   private static Object JavaDoc/*java.nio.ByteBuffer*/ byteBufferWrap(byte[] bytes) {
177     try {
178       Class JavaDoc cByteBuffer = Class.forName("java.nio.ByteBuffer");
179       Method JavaDoc mGet = cByteBuffer.getDeclaredMethod("wrap", new Class JavaDoc[]{BYTE_ARRAY_CLASS});
180       Object JavaDoc byteBuffer = mGet.invoke(null, new Object JavaDoc[]{bytes});
181       return byteBuffer;
182     } catch (Throwable JavaDoc t) {
183       System.err.println("AW : java.nio not supported");
184       throw new RuntimeException JavaDoc(t.toString());
185     }
186   }
187
188   private final static byte[] EMPTY_BYTEARRAY = new byte[0];
189   private final static Class JavaDoc BYTE_ARRAY_CLASS = EMPTY_BYTEARRAY.getClass();
190
191 }
Popular Tags