1 package org.apache.maven.surefire.booter;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.PrintStream;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25
26 import org.apache.maven.surefire.providerapi.SurefireProvider;
27 import org.apache.maven.surefire.suite.RunResult;
28 import org.apache.maven.surefire.testset.TestSetFailedException;
29
30 import static org.apache.maven.surefire.util.ReflectionUtils.getMethod;
31 import static org.apache.maven.surefire.util.ReflectionUtils.invokeGetter;
32 import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray;
33 import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray2;
34
35
36
37
38
39
40
41 public class ProviderFactory
42 {
43 private final StartupConfiguration startupConfiguration;
44
45 private final ProviderConfiguration providerConfiguration;
46
47 private final ClassLoader classLoader;
48
49 private final SurefireReflector surefireReflector;
50
51 private final Object reporterManagerFactory;
52
53 private static final Class[] INVOKE_PARAMETERS = { Object.class };
54
55 private static final Class[] INVOKE_EMPTY_PARAMETER_TYPES = { };
56
57 private static final Class[] INVOKE_EMPTY_PARAMETERS = { };
58
59 public ProviderFactory( StartupConfiguration startupConfiguration, ProviderConfiguration providerConfiguration,
60 ClassLoader testsClassLoader, Object reporterManagerFactory )
61 {
62 this.providerConfiguration = providerConfiguration;
63 this.startupConfiguration = startupConfiguration;
64 this.surefireReflector = new SurefireReflector( testsClassLoader );
65 this.classLoader = testsClassLoader;
66 this.reporterManagerFactory = reporterManagerFactory;
67 }
68
69 public static RunResult invokeProvider( Object testSet, ClassLoader testsClassLoader, Object factory,
70 ProviderConfiguration providerConfiguration, boolean insideFork,
71 StartupConfiguration startupConfig, boolean restoreStreams )
72 throws TestSetFailedException, InvocationTargetException
73 {
74 final PrintStream orgSystemOut = System.out;
75 final PrintStream orgSystemErr = System.err;
76
77
78
79 try
80 {
81 return new ProviderFactory( startupConfig, providerConfiguration, testsClassLoader, factory )
82 .createProvider( insideFork )
83 .invoke( testSet );
84 }
85 finally
86 {
87 if ( restoreStreams && System.getSecurityManager() == null )
88 {
89 System.setOut( orgSystemOut );
90 System.setErr( orgSystemErr );
91 }
92 }
93 }
94
95 public SurefireProvider createProvider( boolean isInsideFork )
96 {
97 final Thread currentThread = Thread.currentThread();
98 final ClassLoader systemClassLoader = currentThread.getContextClassLoader();
99 currentThread.setContextClassLoader( classLoader );
100
101 Object o = surefireReflector.createBooterConfiguration( classLoader, reporterManagerFactory, isInsideFork );
102 surefireReflector.setTestSuiteDefinitionAware( o, providerConfiguration.getTestSuiteDefinition() );
103 surefireReflector.setProviderPropertiesAware( o, providerConfiguration.getProviderProperties() );
104 surefireReflector.setReporterConfigurationAware( o, providerConfiguration.getReporterConfiguration() );
105 surefireReflector.setTestClassLoaderAware( o, classLoader );
106 surefireReflector.setTestArtifactInfoAware( o, providerConfiguration.getTestArtifact() );
107 surefireReflector.setRunOrderParameters( o, providerConfiguration.getRunOrderParameters() );
108 surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
109 surefireReflector.setMainCliOptions( o, providerConfiguration.getMainCliOptions() );
110 surefireReflector.setSkipAfterFailureCount( o, providerConfiguration.getSkipAfterFailureCount() );
111 surefireReflector.setShutdown( o, providerConfiguration.getShutdown() );
112
113 Object provider = surefireReflector.instantiateProvider( startupConfiguration.getActualClassName(), o );
114 currentThread.setContextClassLoader( systemClassLoader );
115
116 return new ProviderProxy( provider, classLoader );
117 }
118
119
120 private final class ProviderProxy
121 implements SurefireProvider
122 {
123 private final Object providerInOtherClassLoader;
124
125 private final ClassLoader testsClassLoader;
126
127
128 private ProviderProxy( Object providerInOtherClassLoader, ClassLoader testsClassLoader )
129 {
130 this.providerInOtherClassLoader = providerInOtherClassLoader;
131 this.testsClassLoader = testsClassLoader;
132 }
133
134 @SuppressWarnings( "unchecked" )
135 public Iterable<Class<?>> getSuites()
136 {
137 ClassLoader current = swapClassLoader( testsClassLoader );
138 try
139 {
140 return (Iterable<Class<?>>) invokeGetter( providerInOtherClassLoader, "getSuites" );
141 }
142 finally
143 {
144 Thread.currentThread().setContextClassLoader( current );
145 }
146 }
147
148 public RunResult invoke( Object forkTestSet )
149 throws TestSetFailedException, InvocationTargetException
150 {
151 ClassLoader current = swapClassLoader( testsClassLoader );
152 try
153 {
154 Method invoke = getMethod( providerInOtherClassLoader.getClass(), "invoke", INVOKE_PARAMETERS );
155 Object result = invokeMethodWithArray2( providerInOtherClassLoader, invoke, forkTestSet );
156 return (RunResult) surefireReflector.convertIfRunResult( result );
157 }
158 finally
159 {
160 if ( System.getSecurityManager() == null )
161 {
162 Thread.currentThread().setContextClassLoader( current );
163 }
164 }
165
166 }
167
168 private ClassLoader swapClassLoader( ClassLoader newClassLoader )
169 {
170 ClassLoader current = Thread.currentThread().getContextClassLoader();
171 Thread.currentThread().setContextClassLoader( newClassLoader );
172 return current;
173 }
174
175 public void cancel()
176 {
177 Class<?> providerType = providerInOtherClassLoader.getClass();
178 Method invoke = getMethod( providerType, "cancel", INVOKE_EMPTY_PARAMETER_TYPES );
179 invokeMethodWithArray( providerInOtherClassLoader, invoke, INVOKE_EMPTY_PARAMETERS );
180 }
181 }
182 }