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 }