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 if ( isInsideFork )
113 {
114 surefireReflector.setSystemExitTimeout( o, providerConfiguration.getSystemExitTimeout() );
115 }
116
117 Object provider = surefireReflector.instantiateProvider( startupConfiguration.getActualClassName(), o );
118 currentThread.setContextClassLoader( systemClassLoader );
119
120 return new ProviderProxy( provider, classLoader );
121 }
122
123 private final class ProviderProxy
124 implements SurefireProvider
125 {
126 private final Object providerInOtherClassLoader;
127
128 private final ClassLoader testsClassLoader;
129
130
131 private ProviderProxy( Object providerInOtherClassLoader, ClassLoader testsClassLoader )
132 {
133 this.providerInOtherClassLoader = providerInOtherClassLoader;
134 this.testsClassLoader = testsClassLoader;
135 }
136
137 @SuppressWarnings( "unchecked" )
138 public Iterable<Class<?>> getSuites()
139 {
140 ClassLoader current = swapClassLoader( testsClassLoader );
141 try
142 {
143 return (Iterable<Class<?>>) invokeGetter( providerInOtherClassLoader, "getSuites" );
144 }
145 finally
146 {
147 Thread.currentThread().setContextClassLoader( current );
148 }
149 }
150
151 public RunResult invoke( Object forkTestSet )
152 throws TestSetFailedException, InvocationTargetException
153 {
154 ClassLoader current = swapClassLoader( testsClassLoader );
155 try
156 {
157 Method invoke = getMethod( providerInOtherClassLoader.getClass(), "invoke", INVOKE_PARAMETERS );
158 Object result = invokeMethodWithArray2( providerInOtherClassLoader, invoke, forkTestSet );
159 return (RunResult) surefireReflector.convertIfRunResult( result );
160 }
161 finally
162 {
163 if ( System.getSecurityManager() == null )
164 {
165 Thread.currentThread().setContextClassLoader( current );
166 }
167 }
168
169 }
170
171 private ClassLoader swapClassLoader( ClassLoader newClassLoader )
172 {
173 ClassLoader current = Thread.currentThread().getContextClassLoader();
174 Thread.currentThread().setContextClassLoader( newClassLoader );
175 return current;
176 }
177
178 public void cancel()
179 {
180 Class<?> providerType = providerInOtherClassLoader.getClass();
181 Method invoke = getMethod( providerType, "cancel", INVOKE_EMPTY_PARAMETER_TYPES );
182 invokeMethodWithArray( providerInOtherClassLoader, invoke, INVOKE_EMPTY_PARAMETERS );
183 }
184 }
185 }