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