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.ClassLoaderPatcher;
11 import org.codehaus.aspectwerkz.hook.ClassLoaderPreProcessor;
12
13 import java.io.InputStream;
14
15 import javassist.CannotCompileException;
16 import javassist.ClassPool;
17 import javassist.CtClass;
18 import javassist.expr.ExprEditor;
19 import javassist.expr.MethodCall;
20
21 /***
22 * Instruments the java.lang.ClassLoader to plug in the Class PreProcessor mechanism using Javassist. <p/>We are using a
23 * lazy initialization of the class preprocessor to allow all class pre processor logic to be in system classpath and
24 * not in bootclasspath. <p/>This implementation should support IBM custom JRE
25 *
26 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
27 */
28 public class ClassLoaderPreProcessorImpl implements ClassLoaderPreProcessor {
29 public ClassLoaderPreProcessorImpl() {
30 }
31
32 public byte[] preProcess(final byte[] b) {
33 try {
34 ClassPool pool = ClassPool.getDefault();
35 CtClass klass = pool.get("java.lang.ClassLoader");
36
37
38
39
40
41
42 ExprEditor defineClass0Pre = new ExprEditor() {
43 public void edit(MethodCall m) throws CannotCompileException {
44 if ("defineClass0".equals(m.getMethodName())) {
45 int argsCount = 5;
46
47
48
49 try {
50 argsCount = m.getMethod().getParameterTypes().length;
51 } catch (Throwable t) {
52 throw new RuntimeException(t.toString());
53 }
54 if (argsCount == 5) {
55 m.replace(
56 '{'
57 +
58 " byte[] newBytes = org.codehaus.aspectwerkz.hook.impl.ClassPreProcessorHelper.defineClass0Pre($0, $$);"
59 + " $_ = $proceed($1, newBytes, 0, newBytes.length, $5);"
60 + '}'
61 );
62 } else if (argsCount == 7) {
63 m.replace(
64 '{'
65 +
66 " byte[] newBytes = org.codehaus.aspectwerkz.hook.impl.ClassPreProcessorHelper.defineClass0Pre($0, $1, $2, $3, $4, $5);"
67 + " $_ = $proceed($1, newBytes, 0, newBytes.length, $5, $6, $7);"
68 + '}'
69 );
70 }
71 }
72 }
73 };
74 klass.instrument(defineClass0Pre);
75
76
77
78
79 return klass.toBytecode();
80
81
82 } catch (Exception e) {
83 System.err.println("failed to patch ClassLoader:");
84 e.printStackTrace();
85 return b;
86 }
87 }
88
89 /***
90 * main test
91 */
92 public static void main(String[] args) throws Exception {
93 ClassLoaderPreProcessor me = new ClassLoaderPreProcessorImpl();
94 InputStream is = ClassLoader.getSystemClassLoader().getParent().getResourceAsStream(
95 "java/lang/ClassLoader.class"
96 );
97 me.preProcess(ClassLoaderPatcher.inputStreamToByteArray(is));
98 is.close();
99 }
100 }