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