KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > hook > impl > ClassPreProcessorHelper


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 JavaDoc;
13 import java.lang.reflect.Method JavaDoc;
14
15 /**
16  * Helper class called by the modified java.lang.ClassLoader. <p/>This class is called at different points by the
17  * modified java.lang.ClassLoader of the org.codehaus.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl implemention.
18  * <br/>This class must reside in the -Xbootclasspath when AspectWerkz layer 1 is used, but the effective implementation
19  * of the class preprocessor (AspectWerkz layer 2) can be in standard system classpath (-cp).
20  *
21  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
22  */

23 public class ClassPreProcessorHelper {
24     /**
25      * ClassPreProcessor used if aspectwerkz.classloader.preprocessor property is defined to full qualified class name
26      */

27     private static ClassPreProcessor preProcessor;
28
29     /**
30      * true if preProcesor already initalized
31      */

32     private static boolean preProcessorInitialized;
33
34     /**
35      * option used to defined the class preprocessor
36      */

37     private static String JavaDoc PRE_PROCESSOR_CLASSNAME_PROPERTY = "aspectwerkz.classloader.preprocessor";
38
39     /**
40      * default class preprocessor
41      */

42     private static String JavaDoc PRE_PROCESSOR_CLASSNAME_DEFAULT = "org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor";
43
44     static {
45         initializePreProcessor();
46     }
47
48     /**
49      * Returns the configured class preprocessor Should be called after initialization only
50      *
51      * @return the preprocessor or null if not initialized
52      */

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

61     public static synchronized void initializePreProcessor() {
62         if (preProcessorInitialized) {
63             return;
64         }
65         preProcessorInitialized = true;
66         Class JavaDoc klass = null;
67         String JavaDoc 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         } catch (ClassNotFoundException JavaDoc _ex) {
73             System.err.println("AspectWerkz - WARN - Pre-processor class '" + s + "' not found");
74         }
75         if (klass != null) {
76             try {
77                 preProcessor = (ClassPreProcessor) klass.newInstance();
78                 preProcessor.initialize();
79                 System.out.println("AspectWerkz - INFO - Pre-processor " + s + " loaded and initialized");
80             } catch (Throwable JavaDoc throwable) {
81                 System.err.println("AspectWerkz - WARN - Error initializing pre-processor class " + s + ':');
82                 throwable.printStackTrace();
83             }
84         }
85     }
86
87     /**
88      * byte code instrumentation of class loaded
89      */

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

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

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

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