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 org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
23 import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerDecorator;
24 import org.apache.maven.surefire.cli.CommandLineOption;
25 import org.apache.maven.surefire.providerapi.ProviderParameters;
26 import org.apache.maven.surefire.report.ReporterConfiguration;
27 import org.apache.maven.surefire.report.ReporterFactory;
28 import org.apache.maven.surefire.suite.RunResult;
29 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
30 import org.apache.maven.surefire.testset.RunOrderParameters;
31 import org.apache.maven.surefire.testset.TestArtifactInfo;
32 import org.apache.maven.surefire.testset.TestListResolver;
33 import org.apache.maven.surefire.testset.TestRequest;
34 import org.apache.maven.surefire.util.RunOrder;
35 import org.apache.maven.surefire.util.SurefireReflectionException;
36
37 import java.io.File;
38 import java.lang.reflect.Constructor;
39 import java.lang.reflect.Method;
40 import java.util.ArrayList;
41 import java.util.Collection;
42 import java.util.List;
43 import java.util.Map;
44
45 import static java.util.Collections.checkedList;
46 import static org.apache.maven.surefire.util.ReflectionUtils.getConstructor;
47 import static org.apache.maven.surefire.util.ReflectionUtils.getMethod;
48 import static org.apache.maven.surefire.util.ReflectionUtils.instantiateOneArg;
49 import static org.apache.maven.surefire.util.ReflectionUtils.instantiateTwoArgs;
50 import static org.apache.maven.surefire.util.ReflectionUtils.invokeGetter;
51 import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray;
52 import static org.apache.maven.surefire.util.ReflectionUtils.invokeSetter;
53 import static org.apache.maven.surefire.util.ReflectionUtils.newInstance;
54
55
56
57
58
59
60
61
62 public class SurefireReflector
63 {
64 private final ClassLoader surefireClassLoader;
65
66 private final Class<?> reporterConfiguration;
67
68 private final Class<?> testRequest;
69
70 private final Class<?> testArtifactInfo;
71
72 private final Class<?> testArtifactInfoAware;
73
74 private final Class<?> directoryScannerParameters;
75
76 private final Class<?> runOrderParameters;
77
78 private final Class<?> directoryScannerParametersAware;
79
80 private final Class<?> testSuiteDefinitionAware;
81
82 private final Class<?> testClassLoaderAware;
83
84 private final Class<?> reporterConfigurationAware;
85
86 private final Class<?> providerPropertiesAware;
87
88 private final Class<?> runResult;
89
90 private final Class<?> booterParameters;
91
92 private final Class<?> reporterFactory;
93
94 private final Class<?> testListResolver;
95
96 private final Class<?> mainCliOptions;
97
98 private final Class<Enum> commandLineOptionsClass;
99
100 private final Class<?> shutdownAwareClass;
101
102 private final Class<Enum> shutdownClass;
103
104 @SuppressWarnings( "unchecked" )
105 public SurefireReflector( ClassLoader surefireClassLoader )
106 {
107 this.surefireClassLoader = surefireClassLoader;
108 try
109 {
110 reporterConfiguration = surefireClassLoader.loadClass( ReporterConfiguration.class.getName() );
111 testRequest = surefireClassLoader.loadClass( TestRequest.class.getName() );
112 testArtifactInfo = surefireClassLoader.loadClass( TestArtifactInfo.class.getName() );
113 testArtifactInfoAware = surefireClassLoader.loadClass( TestArtifactInfoAware.class.getName() );
114 directoryScannerParameters = surefireClassLoader.loadClass( DirectoryScannerParameters.class.getName() );
115 runOrderParameters = surefireClassLoader.loadClass( RunOrderParameters.class.getName() );
116 directoryScannerParametersAware =
117 surefireClassLoader.loadClass( DirectoryScannerParametersAware.class.getName() );
118 testSuiteDefinitionAware = surefireClassLoader.loadClass( TestRequestAware.class.getName() );
119 testClassLoaderAware = surefireClassLoader.loadClass( SurefireClassLoadersAware.class.getName() );
120 reporterConfigurationAware = surefireClassLoader.loadClass( ReporterConfigurationAware.class.getName() );
121 providerPropertiesAware = surefireClassLoader.loadClass( ProviderPropertiesAware.class.getName() );
122 reporterFactory = surefireClassLoader.loadClass( ReporterFactory.class.getName() );
123 runResult = surefireClassLoader.loadClass( RunResult.class.getName() );
124 booterParameters = surefireClassLoader.loadClass( ProviderParameters.class.getName() );
125 testListResolver = surefireClassLoader.loadClass( TestListResolver.class.getName() );
126 mainCliOptions = surefireClassLoader.loadClass( MainCliOptionsAware.class.getName() );
127 commandLineOptionsClass = (Class<Enum>) surefireClassLoader.loadClass( CommandLineOption.class.getName() );
128 shutdownAwareClass = surefireClassLoader.loadClass( ShutdownAware.class.getName() );
129 shutdownClass = (Class<Enum>) surefireClassLoader.loadClass( Shutdown.class.getName() );
130 }
131 catch ( ClassNotFoundException e )
132 {
133 throw new SurefireReflectionException( e );
134 }
135 }
136
137 public Object convertIfRunResult( Object result )
138 {
139 if ( result == null || !isRunResult( result ) )
140 {
141 return result;
142 }
143 int getCompletedCount1 = (Integer) invokeGetter( result, "getCompletedCount" );
144 int getErrors = (Integer) invokeGetter( result, "getErrors" );
145 int getSkipped = (Integer) invokeGetter( result, "getSkipped" );
146 int getFailures = (Integer) invokeGetter( result, "getFailures" );
147 return new RunResult( getCompletedCount1, getErrors, getFailures, getSkipped );
148 }
149
150 private Object createTestRequest( TestRequest suiteDefinition )
151 {
152 if ( suiteDefinition == null )
153 {
154 return null;
155 }
156 else
157 {
158 Object resolver = createTestListResolver( suiteDefinition.getTestListResolver() );
159 Class<?>[] arguments = { List.class, File.class, testListResolver, int.class };
160 Constructor constructor = getConstructor( testRequest, arguments );
161 return newInstance( constructor,
162 suiteDefinition.getSuiteXmlFiles(),
163 suiteDefinition.getTestSourceDirectory(),
164 resolver,
165 suiteDefinition.getRerunFailingTestsCount() );
166 }
167 }
168
169 private Object createTestListResolver( TestListResolver resolver )
170 {
171 if ( resolver == null )
172 {
173 return null;
174 }
175 else
176 {
177 Constructor constructor = getConstructor( testListResolver, String.class );
178 return newInstance( constructor, resolver.getPluginParameterTest() );
179 }
180 }
181
182 private Object createDirectoryScannerParameters( DirectoryScannerParameters directoryScannerParameters )
183 {
184 if ( directoryScannerParameters == null )
185 {
186 return null;
187 }
188
189 Class<?>[] arguments = { File.class, List.class, List.class, List.class, boolean.class, String.class };
190 Constructor constructor = getConstructor( this.directoryScannerParameters, arguments );
191 return newInstance( constructor,
192 directoryScannerParameters.getTestClassesDirectory(),
193 directoryScannerParameters.getIncludes(),
194 directoryScannerParameters.getExcludes(),
195 directoryScannerParameters.getSpecificTests(),
196 directoryScannerParameters.isFailIfNoTests(),
197 RunOrder.asString( directoryScannerParameters.getRunOrder() ) );
198 }
199
200 private Object createRunOrderParameters( RunOrderParameters runOrderParameters )
201 {
202 if ( runOrderParameters == null )
203 {
204 return null;
205 }
206
207 Class<?>[] arguments = { String.class, File.class };
208 Constructor constructor = getConstructor( this.runOrderParameters, arguments );
209 File runStatisticsFile = runOrderParameters.getRunStatisticsFile();
210 return newInstance( constructor, RunOrder.asString( runOrderParameters.getRunOrder() ), runStatisticsFile );
211 }
212
213 private Object createTestArtifactInfo( TestArtifactInfo testArtifactInfo )
214 {
215 if ( testArtifactInfo == null )
216 {
217 return null;
218 }
219 Class<?>[] arguments = { String.class, String.class };
220 Constructor constructor = getConstructor( this.testArtifactInfo, arguments );
221 return newInstance( constructor, testArtifactInfo.getVersion(), testArtifactInfo.getClassifier() );
222 }
223
224 private Object createReporterConfiguration( ReporterConfiguration reporterConfig )
225 {
226 Constructor constructor = getConstructor( reporterConfiguration, File.class, boolean.class );
227 return newInstance( constructor, reporterConfig.getReportsDirectory(), reporterConfig.isTrimStackTrace() );
228 }
229
230 public Object createBooterConfiguration( ClassLoader surefireClassLoader, Object factoryInstance,
231 boolean insideFork )
232 {
233 return instantiateTwoArgs( surefireClassLoader, BaseProviderFactory.class.getName(),
234 reporterFactory, factoryInstance, boolean.class, insideFork );
235 }
236
237 public Object instantiateProvider( String providerClassName, Object booterParameters )
238 {
239 return instantiateOneArg( surefireClassLoader, providerClassName, this.booterParameters, booterParameters );
240 }
241
242 public void setIfDirScannerAware( Object o, DirectoryScannerParameters dirScannerParams )
243 {
244 if ( directoryScannerParametersAware.isAssignableFrom( o.getClass() ) )
245 {
246 setDirectoryScannerParameters( o, dirScannerParams );
247 }
248 }
249
250 public void setMainCliOptions( Object o, List<CommandLineOption> options )
251 {
252 if ( mainCliOptions.isAssignableFrom( o.getClass() ) )
253 {
254 List<Enum> newOptions = checkedList( new ArrayList<Enum>( options.size() ), commandLineOptionsClass );
255 Collection<Integer> ordinals = toOrdinals( options );
256 for ( Enum e : commandLineOptionsClass.getEnumConstants() )
257 {
258 if ( ordinals.contains( e.ordinal() ) )
259 {
260 newOptions.add( e );
261 }
262 }
263 invokeSetter( o, "setMainCliOptions", List.class, newOptions );
264 }
265 }
266
267 public void setSkipAfterFailureCount( Object o, int skipAfterFailureCount )
268 {
269 invokeSetter( o, "setSkipAfterFailureCount", int.class, skipAfterFailureCount );
270 }
271
272 public void setShutdown( Object o, Shutdown shutdown )
273 {
274 if ( shutdownAwareClass.isAssignableFrom( o.getClass() ) )
275 {
276 for ( Enum e : shutdownClass.getEnumConstants() )
277 {
278 if ( shutdown.ordinal() == e.ordinal() )
279 {
280 invokeSetter( o, "setShutdown", shutdownClass, e );
281 break;
282 }
283 }
284 }
285 }
286
287 public void setSystemExitTimeout( Object o, Integer systemExitTimeout )
288 {
289 invokeSetter( o, "setSystemExitTimeout", Integer.class, systemExitTimeout );
290 }
291
292 void setDirectoryScannerParameters( Object o, DirectoryScannerParameters dirScannerParams )
293 {
294 Object param = createDirectoryScannerParameters( dirScannerParams );
295 invokeSetter( o, "setDirectoryScannerParameters", directoryScannerParameters, param );
296 }
297
298 public void setRunOrderParameters( Object o, RunOrderParameters runOrderParameters )
299 {
300 Object param = createRunOrderParameters( runOrderParameters );
301 invokeSetter( o, "setRunOrderParameters", this.runOrderParameters, param );
302 }
303
304 public void setTestSuiteDefinitionAware( Object o, TestRequest testSuiteDefinition2 )
305 {
306 if ( testSuiteDefinitionAware.isAssignableFrom( o.getClass() ) )
307 {
308 setTestSuiteDefinition( o, testSuiteDefinition2 );
309 }
310 }
311
312 void setTestSuiteDefinition( Object o, TestRequest testSuiteDefinition1 )
313 {
314 Object param = createTestRequest( testSuiteDefinition1 );
315 invokeSetter( o, "setTestRequest", testRequest, param );
316 }
317
318 public void setProviderPropertiesAware( Object o, Map<String, String> properties )
319 {
320 if ( providerPropertiesAware.isAssignableFrom( o.getClass() ) )
321 {
322 setProviderProperties( o, properties );
323 }
324 }
325
326 void setProviderProperties( Object o, Map<String, String> providerProperties )
327 {
328 invokeSetter( o, "setProviderProperties", Map.class, providerProperties );
329 }
330
331 public void setReporterConfigurationAware( Object o, ReporterConfiguration reporterConfiguration1 )
332 {
333 if ( reporterConfigurationAware.isAssignableFrom( o.getClass() ) )
334 {
335 setReporterConfiguration( o, reporterConfiguration1 );
336 }
337 }
338
339 private void setReporterConfiguration( Object o, ReporterConfiguration reporterConfiguration )
340 {
341 Object param = createReporterConfiguration( reporterConfiguration );
342 invokeSetter( o, "setReporterConfiguration", this.reporterConfiguration, param );
343 }
344
345 public void setTestClassLoaderAware( Object o, ClassLoader testClassLoader )
346 {
347 if ( testClassLoaderAware.isAssignableFrom( o.getClass() ) )
348 {
349 setTestClassLoader( o, testClassLoader );
350 }
351 }
352
353 void setTestClassLoader( Object o, ClassLoader testClassLoader )
354 {
355 Method setter = getMethod( o, "setClassLoaders", ClassLoader.class );
356 invokeMethodWithArray( o, setter, testClassLoader );
357 }
358
359 public void setTestArtifactInfoAware( Object o, TestArtifactInfo testArtifactInfo1 )
360 {
361 if ( testArtifactInfoAware.isAssignableFrom( o.getClass() ) )
362 {
363 setTestArtifactInfo( o, testArtifactInfo1 );
364 }
365 }
366
367 void setTestArtifactInfo( Object o, TestArtifactInfo testArtifactInfo )
368 {
369 Object param = createTestArtifactInfo( testArtifactInfo );
370 invokeSetter( o, "setTestArtifactInfo", this.testArtifactInfo, param );
371 }
372
373 private boolean isRunResult( Object o )
374 {
375 return runResult.isAssignableFrom( o.getClass() );
376 }
377
378 private static Collection<Integer> toOrdinals( Collection<? extends Enum> enums )
379 {
380 Collection<Integer> ordinals = new ArrayList<>( enums.size() );
381 for ( Enum e : enums )
382 {
383 ordinals.add( e.ordinal() );
384 }
385 return ordinals;
386 }
387
388 public static Object createConsoleLogger( ConsoleLogger consoleLogger, ClassLoader cl )
389 {
390 try
391 {
392 Class<?> decoratorClass = cl.loadClass( ConsoleLoggerDecorator.class.getName() );
393 return getConstructor( decoratorClass, Object.class ).newInstance( consoleLogger );
394 }
395 catch ( Exception e )
396 {
397 throw new SurefireReflectionException( e );
398 }
399 }
400 }