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.api.provider.SurefireProvider;
27 import org.apache.maven.surefire.api.report.ReporterException;
28 import org.apache.maven.surefire.api.suite.RunResult;
29 import org.apache.maven.surefire.api.testset.TestSetFailedException;
30
31 import static org.apache.maven.surefire.api.util.ReflectionUtils.getMethod;
32 import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeGetter;
33 import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
34 import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray2;
35 import static org.apache.maven.surefire.api.util.internal.ObjectUtils.isSecurityManagerSupported;
36
37
38
39
40
41
42
43 public class ProviderFactory
44 {
45 private final StartupConfiguration startupConfiguration;
46
47 private final ProviderConfiguration providerConfiguration;
48
49 private final ClassLoader classLoader;
50
51 private final SurefireReflector surefireReflector;
52
53 private final Object reporterManagerFactory;
54
55 private static final Class<?>[] INVOKE_PARAMETERS = { Object.class };
56
57 private static final Class<?>[] INVOKE_EMPTY_PARAMETER_TYPES = { };
58
59 private static final Object[] INVOKE_EMPTY_PARAMETERS = { };
60
61 public ProviderFactory( StartupConfiguration startupConfiguration, ProviderConfiguration providerConfiguration,
62 ClassLoader testsClassLoader, Object reporterManagerFactory )
63 {
64 this.providerConfiguration = providerConfiguration;
65 this.startupConfiguration = startupConfiguration;
66 this.surefireReflector = new SurefireReflector( testsClassLoader );
67 this.classLoader = testsClassLoader;
68 this.reporterManagerFactory = reporterManagerFactory;
69 }
70
71 public static RunResult invokeProvider( Object testSet, ClassLoader testsClassLoader, Object factory,
72 ProviderConfiguration providerConfiguration, boolean insideFork,
73 StartupConfiguration startupConfig, boolean restoreStreams )
74 throws TestSetFailedException, InvocationTargetException
75 {
76 final PrintStream orgSystemOut = System.out;
77 final PrintStream orgSystemErr = System.err;
78
79
80
81 try
82 {
83 return new ProviderFactory( startupConfig, providerConfiguration, testsClassLoader, factory )
84 .createProvider( insideFork )
85 .invoke( testSet );
86 }
87 finally
88 {
89 if ( restoreStreams && ( !isSecurityManagerSupported() || System.getSecurityManager() == null ) )
90 {
91 System.setOut( orgSystemOut );
92 System.setErr( orgSystemErr );
93 }
94 }
95 }
96
97 public SurefireProvider createProvider( boolean isInsideFork )
98 {
99 final Thread currentThread = Thread.currentThread();
100 final ClassLoader systemClassLoader = currentThread.getContextClassLoader();
101 currentThread.setContextClassLoader( classLoader );
102
103 Object o = surefireReflector.createBooterConfiguration( classLoader, isInsideFork );
104 surefireReflector.setReporterFactoryAware( o, reporterManagerFactory );
105 surefireReflector.setTestSuiteDefinitionAware( o, providerConfiguration.getTestSuiteDefinition() );
106 surefireReflector.setProviderPropertiesAware( o, providerConfiguration.getProviderProperties() );
107 surefireReflector.setReporterConfigurationAware( o, providerConfiguration.getReporterConfiguration() );
108 surefireReflector.setTestClassLoaderAware( o, classLoader );
109 surefireReflector.setTestArtifactInfoAware( o, providerConfiguration.getTestArtifact() );
110 surefireReflector.setRunOrderParameters( o, providerConfiguration.getRunOrderParameters() );
111 surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
112 surefireReflector.setMainCliOptions( o, providerConfiguration.getMainCliOptions() );
113 surefireReflector.setSkipAfterFailureCount( o, providerConfiguration.getSkipAfterFailureCount() );
114 if ( isInsideFork )
115 {
116 surefireReflector.setSystemExitTimeout( o, providerConfiguration.getSystemExitTimeout() );
117 }
118
119 Object provider = surefireReflector.instantiateProvider( startupConfiguration.getActualClassName(), o );
120 currentThread.setContextClassLoader( systemClassLoader );
121
122 return new ProviderProxy( provider, classLoader );
123 }
124
125 private final class ProviderProxy
126 implements SurefireProvider
127 {
128 private final Object providerInOtherClassLoader;
129
130 private final ClassLoader testsClassLoader;
131
132
133 private ProviderProxy( Object providerInOtherClassLoader, ClassLoader testsClassLoader )
134 {
135 this.providerInOtherClassLoader = providerInOtherClassLoader;
136 this.testsClassLoader = testsClassLoader;
137 }
138
139 @Override
140 public Iterable<Class<?>> getSuites()
141 {
142 ClassLoader current = swapClassLoader( testsClassLoader );
143 try
144 {
145 return 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 }