| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.tuscany.sca.itest.bindingsca; |
| |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| /** |
| * A helper class that can be used to run an SCA JUnit test case. The test case will run in an isolated class loader. |
| * |
| * @version $Rev$ $Date$ |
| */ |
| public class TestCaseRunner { |
| |
| private ClassLoader classLoader; |
| private Class<?> testSuiteClass; |
| private Object testSuite; |
| private Class<?> testResultClass; |
| private Class<?> testCaseClass; |
| private Object testCase; |
| |
| private Class<?> beforeAnnotation; |
| private Class<?> beforeClassAnnotation; |
| private Class<?> afterAnnotation; |
| private Class<?> afterClassAnnotation; |
| private Class<?> junit4AdapterClass; |
| private Class<?> junit3TestCaseClass; |
| |
| /** |
| * Constructs a new TestCase runner. |
| * |
| * @param testClass |
| */ |
| public TestCaseRunner(Class<?> testClass, String... isolatedClasses) { |
| try { |
| ClassLoader tccl = setupClassLoader(testClass, isolatedClasses); |
| |
| try { |
| // Thread.currentThread().setContextClassLoader(classLoader); |
| // Allow privileged access to set class loader. Requires RuntimePermission |
| // setContextClassLoader in security policy. |
| final ClassLoader finalClassLoader = classLoader; |
| AccessController.doPrivileged(new PrivilegedAction<Object>() { |
| public Object run() { |
| Thread.currentThread().setContextClassLoader(finalClassLoader); |
| return null; |
| } |
| }); |
| |
| testCaseClass = Class.forName(testClass.getName(), true, classLoader); |
| testCase = testCaseClass.newInstance(); |
| ClassLoader testClassLoader = testCaseClass.getClassLoader(); |
| |
| junit3TestCaseClass = Class.forName("junit.framework.TestCase", true, testClassLoader); |
| |
| testSuiteClass = Class.forName("junit.framework.TestSuite", true, testClassLoader); |
| Constructor<?> testSuiteConstructor = testSuiteClass.getConstructor(Class.class); |
| testSuite = testSuiteConstructor.newInstance(testCaseClass); |
| |
| testResultClass = Class.forName("junit.framework.TestResult", true, testClassLoader); |
| |
| try { |
| beforeAnnotation = Class.forName("org.junit.Before", true, testClassLoader); |
| afterAnnotation = Class.forName("org.junit.After", true, testClassLoader); |
| beforeClassAnnotation = Class.forName("org.junit.BeforeClass", true, testClassLoader); |
| afterClassAnnotation = Class.forName("org.junit.AfterClass", true, testClassLoader); |
| junit4AdapterClass = Class.forName("junit.framework.JUnit4TestAdapter", true, testClassLoader); |
| } catch (Exception e) { |
| // Unexpected |
| throw new AssertionError(e); |
| } |
| } catch (Throwable e) { |
| e.printStackTrace(); |
| } finally { |
| // Thread.currentThread().setContextClassLoader(tccl); |
| // Allow privileged access to set class loader. Requires RuntimePermission |
| // setContextClassLoader in security policy. |
| final ClassLoader finaltccl = tccl; |
| AccessController.doPrivileged(new PrivilegedAction<Object>() { |
| public Object run() { |
| Thread.currentThread().setContextClassLoader(finaltccl); |
| return null; |
| } |
| }); |
| } |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| private ClassLoader setupClassLoader(Class<?> testClass, String... isolatedClasses) { |
| ClassLoader tccl = Thread.currentThread().getContextClassLoader(); |
| classLoader = testClass.getClassLoader(); |
| if (classLoader instanceof URLClassLoader) { |
| URL[] urls = ((URLClassLoader)classLoader).getURLs(); |
| classLoader = new ClassLoaderImpl(urls, classLoader, isolatedClasses); |
| } else if (classLoader == tccl || classLoader.getParent() == tccl) { |
| classLoader = new URLClassLoader(new URL[0], classLoader); |
| } else { |
| classLoader = tccl; |
| } |
| return tccl; |
| } |
| |
| /** |
| * Run the test case |
| */ |
| public void run() { |
| ClassLoader tccl = Thread.currentThread().getContextClassLoader(); |
| try { |
| // Thread.currentThread().setContextClassLoader(classLoader); |
| // Allow privileged access to set class loader. Requires RuntimePermission |
| // setContextClassLoader in security policy. |
| final ClassLoader finalClassLoader = classLoader; |
| AccessController.doPrivileged(new PrivilegedAction<Object>() { |
| public Object run() { |
| Thread.currentThread().setContextClassLoader(finalClassLoader); |
| return null; |
| } |
| }); |
| |
| if (junit3TestCaseClass.isAssignableFrom(testCaseClass)) { |
| Object testResult = testResultClass.newInstance(); |
| Method runMethod = testSuiteClass.getMethod("run", testResultClass); |
| runMethod.invoke(testSuite, testResult); |
| } else { |
| Object junit4Adapter = junit4AdapterClass.getConstructor(Class.class).newInstance(testCaseClass); |
| Object testResult = testResultClass.newInstance(); |
| Method runMethod = junit4AdapterClass.getMethod("run", testResultClass); |
| runMethod.invoke(junit4Adapter, testResult); |
| } |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } finally { |
| // Thread.currentThread().setContextClassLoader(tccl); |
| // Allow privileged access to set class loader. Requires RuntimePermission |
| // setContextClassLoader in security policy. |
| final ClassLoader finaltccl = tccl; |
| AccessController.doPrivileged(new PrivilegedAction<Object>() { |
| public Object run() { |
| Thread.currentThread().setContextClassLoader(finaltccl); |
| return null; |
| } |
| }); |
| } |
| } |
| |
| /** |
| * Invoke the setUp method |
| */ |
| public void setUp() { |
| execute("setUp"); |
| } |
| |
| /** |
| * Invoke the before methods |
| */ |
| public void before() { |
| execute(beforeAnnotation); |
| } |
| |
| /** |
| * Invoke the beforeClass methods |
| */ |
| public void beforeClass() { |
| execute(beforeClassAnnotation); |
| } |
| |
| /** |
| * Invoke the tearDown method |
| */ |
| public void tearDown() { |
| execute("tearDown"); |
| } |
| |
| /** |
| * Invoke the after methods |
| */ |
| public void after() { |
| execute(afterAnnotation); |
| } |
| |
| /** |
| * Invoke the afterClass methods |
| */ |
| public void afterClass() { |
| execute(afterClassAnnotation); |
| } |
| |
| /** |
| * Invoke the specified test method. |
| */ |
| public void run(String methodName) { |
| execute(methodName); |
| } |
| |
| /** |
| * Invoke the methods annotated with the specified annotation. |
| */ |
| private void execute(Class<?> annotationClass) { |
| if (annotationClass == null) { |
| throw new RuntimeException(new NoSuchMethodException()); |
| } |
| ClassLoader tccl = Thread.currentThread().getContextClassLoader(); |
| try { |
| // Thread.currentThread().setContextClassLoader(classLoader); |
| // Allow privileged access to set class loader. Requires RuntimePermission |
| // setContextClassLoader in security policy. |
| final ClassLoader finalClassLoader = classLoader; |
| AccessController.doPrivileged(new PrivilegedAction<Object>() { |
| public Object run() { |
| Thread.currentThread().setContextClassLoader(finalClassLoader); |
| return null; |
| } |
| }); |
| |
| for (Method method : testCaseClass.getDeclaredMethods()) { |
| for (Annotation annotation : method.getAnnotations()) { |
| if (annotation.annotationType() == annotationClass) { |
| method.invoke(testCase); |
| } |
| } |
| } |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } finally { |
| // Thread.currentThread().setContextClassLoader(tccl); |
| // Allow privileged access to set class loader. Requires RuntimePermission |
| // setContextClassLoader in security policy. |
| final ClassLoader finaltccl = tccl; |
| AccessController.doPrivileged(new PrivilegedAction<Object>() { |
| public Object run() { |
| Thread.currentThread().setContextClassLoader(finaltccl); |
| return null; |
| } |
| }); |
| } |
| } |
| |
| /** |
| * Invoke the specified method |
| */ |
| private void execute(String methodName) { |
| ClassLoader tccl = Thread.currentThread().getContextClassLoader(); |
| try { |
| // Thread.currentThread().setContextClassLoader(classLoader); |
| // Allow privileged access to set class loader. Requires RuntimePermission |
| // setContextClassLoader in security policy. |
| final ClassLoader finalClassLoader = classLoader; |
| AccessController.doPrivileged(new PrivilegedAction<Object>() { |
| public Object run() { |
| Thread.currentThread().setContextClassLoader(finalClassLoader); |
| return null; |
| } |
| }); |
| Method setUpMethod = testCaseClass.getDeclaredMethod(methodName); |
| setUpMethod.setAccessible(true); |
| setUpMethod.invoke(testCase); |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } finally { |
| // Thread.currentThread().setContextClassLoader(tccl); |
| // Allow privileged access to set class loader. Requires RuntimePermission |
| // setContextClassLoader in security policy. |
| final ClassLoader finaltccl = tccl; |
| AccessController.doPrivileged(new PrivilegedAction<Object>() { |
| public Object run() { |
| Thread.currentThread().setContextClassLoader(finaltccl); |
| return null; |
| } |
| }); |
| } |
| } |
| |
| public static class ClassLoaderImpl extends URLClassLoader { |
| private Set<String> isolatedClasses = new HashSet<String>(); |
| |
| /** |
| * @param urls |
| * @param parent |
| */ |
| public ClassLoaderImpl(URL[] urls, ClassLoader parent, String... sharedClasses) { |
| super(urls, parent); |
| this.isolatedClasses.addAll(Arrays.asList(sharedClasses)); |
| } |
| |
| @Override |
| protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { |
| if (!isolatedClasses.contains(name)) { |
| return super.loadClass(name, resolve); |
| } else { |
| Class<?> cls = findLoadedClass(name); |
| if (cls == null) { |
| cls = findClass(name); |
| } |
| if (resolve) { |
| resolveClass(cls); |
| } |
| return cls; |
| } |
| } |
| |
| } |
| |
| } |