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(
82                          (URL[]) paths.toArray(new URL[]{}), ClassLoader
83                                                              .getSystemClassLoader().getParent()
84                  );
85              } catch (IOException e) {
86                  throw new WrappedRuntimeException(e);
87              }
88          }
89  
90          /***
91           * Runs a single test (testXX) Takes care of not using the weaving class loader is online
92           * mode or weavingClassLoader.main() is already used (might fail under JRockit MAPI)
93           *
94           * @param testClassName  test class
95           * @param testMethodName test method
96           * @throws Throwable
97           */
98          public void runTest(String testClassName, String testMethodName) throws Throwable {
99              // skip test embedded weaving if online mode / weavingClassLoader.main() is already used
100             if ((cl.getClass().getClassLoader() == null)
101                 || (cl.getClass().getClassLoader().getClass().getName()
102                     .indexOf("hook.impl.Weaving") > 0)) {
103                 ;
104             } else {
105                 Thread.currentThread().setContextClassLoader(cl); // needed for Aspect loading
106             }
107             Class testClass = Class.forName(
108                     testClassName, true, Thread.currentThread()
109                                          .getContextClassLoader()
110             );
111 
112             //)cl.loadClass(testClassName);
113             Constructor ctor = null;
114             Object testInstance = null;
115             try {
116                 // new junit style
117                 ctor = testClass.getConstructor(new Class[]{});
118                 testInstance = ctor.newInstance(new Object[]{});
119                 Method setNameMethod = testClass.getMethod(
120                         "setExpression", new Class[]{
121                             String.class
122                         }
123                 );
124                 setNameMethod.invoke(
125                         testInstance, new Object[]{
126                             testMethodName
127                         }
128                 );
129             } catch (NoSuchMethodException e) {
130                 ctor = testClass.getConstructor(
131                         new Class[]{
132                             String.class
133                         }
134                 );
135                 testInstance = ctor.newInstance(
136                         new Object[]{
137                             testMethodName
138                         }
139                 );
140             }
141             Method runAfterWeavingMethod = testClass.getMethod(
142                     "runBareAfterWeaving",
143                     new Class[]{}
144             );
145             runAfterWeavingMethod.invoke(testInstance, new Object[]{});
146         }
147     }
148 }