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 test.aopc;
9   
10  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
11  
12  import java.io.File;
13  import java.lang.reflect.Array;
14  import java.lang.reflect.Method;
15  import java.net.MalformedURLException;
16  import java.net.URL;
17  import java.net.URLClassLoader;
18  
19  import javassist.ClassPool;
20  import javassist.CtClass;
21  import javassist.CtMethod;
22  import javassist.LoaderClassPath;
23  import javassist.Modifier;
24  
25  /***
26   * Test helper for AspectContainer, emulates a ClassLoader hierarchy sys/sub/ sys/sub/a sys/sub/b
27   * 
28   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
29   */
30  public class ClassCreator {
31      /***
32       * ClassLoader.defineClass(name, bytes, from, to)
33       */
34      private static Method CLASSLOADER_DEFINECLASS_METHOD;
35  
36      static {
37          try {
38              Object b = Array.newInstance(byte.class, 1);
39              CLASSLOADER_DEFINECLASS_METHOD = ClassLoader.class.getDeclaredMethod(
40                  "defineClass",
41                  new Class[] {
42                      String.class, b.getClass(), int.class, int.class
43                  });
44              CLASSLOADER_DEFINECLASS_METHOD.setAccessible(true);
45          } catch (Throwable t) {
46              t.printStackTrace();
47          }
48      }
49  
50      public static Object createInstance(String name, Class classPrototype, ClassLoader loader) {
51          try {
52              return createClass(name, classPrototype, loader).newInstance();
53          } catch (Throwable t) {
54              throw new WrappedRuntimeException(t);
55          }
56      }
57  
58      public static Class createClass(String name, Class classPrototype, ClassLoader loader) {
59          try {
60              ClassPool cp = new ClassPool(null);
61              cp.appendClassPath(new LoaderClassPath(loader));
62              CtClass prototype = cp.get(classPrototype.getName());
63              prototype.setName(name);
64              return define(prototype.toBytecode(), name, loader);
65          } catch (Throwable throwable) {
66              throw new WrappedRuntimeException(throwable);
67          }
68      }
69  
70      public static void main(String[] a) throws Throwable {
71          ClassLoader myCL = new URLClassLoader(new URL[] {
72              getPathFor(Callable.class.getResource("META-INF/aop.xml"))
73          }, ClassLoader.getSystemClassLoader());
74          ClassLoader mySubCLA = new URLClassLoader(new URL[] {
75              getPathFor(Callable.class.getResource("a/META-INF/aop.xml"))
76          }, myCL);
77          Callable ca = (Callable) (createClass("test.aopc.a.Callee", CallablePrototype.class,  mySubCLA)).newInstance();
78          ca.methodAround();
79          ca.debug();
80          ClassLoader mySubCLB = new URLClassLoader(new URL[] {}, myCL);
81          Callable cb = (Callable) (createClass("test.aopc.b.Callee", CallablePrototype.class, mySubCLB)).newInstance();
82          cb.methodAround();
83          cb.debug();
84      }
85  
86      public static URL getPathFor(URL definition) {
87          try {
88              System.out.println(definition);
89              System.out.println(definition.getFile());
90              File f = new File(definition.getFile());
91              if (!f.exists()) {
92                  System.err.println("<WARN> could not find " + f);
93              }
94              String path = new File(f.getParent()).getParent();
95              File testExists = new File(path);
96              if (!testExists.isDirectory()) {
97                  System.err.println("<WARN> could not find " + path);
98              }
99              return new File(path).toURL();
100         } catch (MalformedURLException e) {
101             throw new WrappedRuntimeException(e);
102         }
103     }
104 
105     /***
106      * Helper to define a Class within a specific ClassLoader
107      * 
108      * @param b
109      * @param name
110      * @param loader
111      * @return @throws Throwable
112      */
113     public static Class define(byte[] b, String name, ClassLoader loader) throws Throwable {
114         Object k = CLASSLOADER_DEFINECLASS_METHOD.invoke(loader, new Object[] {
115             name, b, new Integer(0), new Integer(b.length)
116         });
117         return (Class) k;
118     }
119 }