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
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
70
71 klass = Class.forName(s, true, ClassLoader.getSystemClassLoader());
72
73
74
75
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
109
110
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
131 return obyte;
132 }
133 }
134 }
135 }