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;
9   
10  import junit.framework.TestCase;
11  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
12  import org.codehaus.aspectwerkz.hook.impl.WeavingClassLoader;
13  
14  import java.io.File;
15  import java.io.IOException;
16  import java.lang.reflect.Constructor;
17  import java.lang.reflect.Method;
18  import java.net.URL;
19  import java.util.ArrayList;
20  import java.util.StringTokenizer;
21  
22  /***
23   * Transparently runs TestCase with an embedded online mode Write a JUnit test case and extends
24   * WeaverTestCase.
25   * 
26   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
27   */
28  public class WeavedTestCase extends TestCase {
29      /***
30       * the test runner that runs the test thru reflection in a weaving ClassLoader
31       */
32      private static WeaverTestRunner s_runner = new WeaverTestRunner();
33  
34      public WeavedTestCase() {
35          super();
36      }
37  
38      public WeavedTestCase(String name) {
39          super(name);
40      }
41  
42      /***
43       * Overrides JUnit runBare() to run thru the weaverTestRunner This allow WeaverTestCase to be
44       * regular TestCase
45       * 
46       * @throws Throwable
47       */
48      public void runBare() throws Throwable {
49          s_runner.runTest(this.getClass().getName(), getName());
50      }
51  
52      /***
53       * Callback the regulare JUnit runBare()
54       * 
55       * @throws Throwable
56       */
57      public void runBareAfterWeaving() throws Throwable {
58          super.runBare();
59      }
60  
61      /***
62       * Allow to run WeaverTestCase thru a weaving ClassLoader
63       */
64      public static class WeaverTestRunner {
65          /***
66           * Weaving classloader
67           */
68          private WeavingClassLoader cl;
69  
70          /***
71           * Build weavin classloader with system class path and ext. classloader as parent
72           */
73          public WeaverTestRunner() {
74              try {
75                  String path = System.getProperty("java.class.path");
76                  ArrayList paths = new ArrayList();
77                  StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
78                  while (st.hasMoreTokens()) {
79                      paths.add((new File(st.nextToken())).getCanonicalFile().toURL());
80                  }
81                  cl = new WeavingClassLoader((URL[]) paths.toArray(new URL[] {}), ClassLoader
82                          .getSystemClassLoader().getParent());
83              } catch (IOException e) {
84                  throw new WrappedRuntimeException(e);
85              }
86          }
87  
88          /***
89           * Runs a single test (testXX) Takes care of not using the weaving class loader is online
90           * mode or weavingClassLoader.main() is already used (might fail under JRockit MAPI)
91           * 
92           * @param testClassName test class
93           * @param testMethodName test method
94           * @throws Throwable
95           */
96          public void runTest(String testClassName, String testMethodName) throws Throwable {
97              // skip test embedded weaving if online mode / weavingClassLoader.main() is already used
98              if ((cl.getClass().getClassLoader() == null)
99                  || (cl.getClass().getClassLoader().getClass().getName()
100                         .indexOf("hook.impl.Weaving") > 0)) {
101                 ;
102             } else {
103                 Thread.currentThread().setContextClassLoader(cl); // needed for Aspect loading
104             }
105             Class testClass = Class.forName(testClassName, true, Thread.currentThread()
106                     .getContextClassLoader());
107 
108             //)cl.loadClass(testClassName);
109             Constructor ctor = null;
110             Object testInstance = null;
111             try {
112                 // new junit style
113                 ctor = testClass.getConstructor(new Class[] {});
114                 testInstance = ctor.newInstance(new Object[] {});
115                 Method setNameMethod = testClass.getMethod("setExpression", new Class[] {
116                     String.class
117                 });
118                 setNameMethod.invoke(testInstance, new Object[] {
119                     testMethodName
120                 });
121             } catch (NoSuchMethodException e) {
122                 ctor = testClass.getConstructor(new Class[] {
123                     String.class
124                 });
125                 testInstance = ctor.newInstance(new Object[] {
126                     testMethodName
127                 });
128             }
129             Method runAfterWeavingMethod = testClass.getMethod(
130                 "runBareAfterWeaving",
131                 new Class[] {});
132             runAfterWeavingMethod.invoke(testInstance, new Object[] {});
133         }
134     }
135 }