1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.surefire.booter;
20
21 import java.io.File;
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.Method;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.apache.maven.surefire.api.booter.BaseProviderFactory;
30 import org.apache.maven.surefire.api.cli.CommandLineOption;
31 import org.apache.maven.surefire.api.provider.ProviderParameters;
32 import org.apache.maven.surefire.api.report.ReporterConfiguration;
33 import org.apache.maven.surefire.api.report.ReporterFactory;
34 import org.apache.maven.surefire.api.suite.RunResult;
35 import org.apache.maven.surefire.api.testset.DirectoryScannerParameters;
36 import org.apache.maven.surefire.api.testset.RunOrderParameters;
37 import org.apache.maven.surefire.api.testset.TestArtifactInfo;
38 import org.apache.maven.surefire.api.testset.TestListResolver;
39 import org.apache.maven.surefire.api.testset.TestRequest;
40 import org.apache.maven.surefire.api.util.RunOrder;
41 import org.apache.maven.surefire.api.util.SurefireReflectionException;
42
43 import static java.util.Collections.checkedList;
44 import static org.apache.maven.surefire.api.util.ReflectionUtils.getConstructor;
45 import static org.apache.maven.surefire.api.util.ReflectionUtils.getMethod;
46 import static org.apache.maven.surefire.api.util.ReflectionUtils.instantiateOneArg;
47 import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeGetter;
48 import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
49 import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeSetter;
50 import static org.apache.maven.surefire.api.util.ReflectionUtils.newInstance;
51
52
53
54
55
56
57
58
59 public final class SurefireReflector {
60 private final ClassLoader surefireClassLoader;
61
62 private final Class<?> reporterConfiguration;
63
64 private final Class<?> testRequest;
65
66 private final Class<?> testArtifactInfo;
67
68 private final Class<?> directoryScannerParameters;
69
70 private final Class<?> runOrderParameters;
71
72 private final Class<?> baseProviderFactory;
73
74 private final Class<?> runResult;
75
76 private final Class<?> booterParameters;
77
78 private final Class<?> reporterFactory;
79
80 private final Class<?> testListResolver;
81
82 private final Class<Enum<?>> commandLineOptionsClass;
83
84 @SuppressWarnings("unchecked")
85 public SurefireReflector(ClassLoader surefireClassLoader) {
86 this.surefireClassLoader = surefireClassLoader;
87 try {
88 reporterConfiguration = surefireClassLoader.loadClass(ReporterConfiguration.class.getName());
89 testRequest = surefireClassLoader.loadClass(TestRequest.class.getName());
90 testArtifactInfo = surefireClassLoader.loadClass(TestArtifactInfo.class.getName());
91 directoryScannerParameters = surefireClassLoader.loadClass(DirectoryScannerParameters.class.getName());
92 runOrderParameters = surefireClassLoader.loadClass(RunOrderParameters.class.getName());
93 baseProviderFactory = surefireClassLoader.loadClass(BaseProviderFactory.class.getName());
94 reporterFactory = surefireClassLoader.loadClass(ReporterFactory.class.getName());
95 runResult = surefireClassLoader.loadClass(RunResult.class.getName());
96 booterParameters = surefireClassLoader.loadClass(ProviderParameters.class.getName());
97 testListResolver = surefireClassLoader.loadClass(TestListResolver.class.getName());
98 commandLineOptionsClass = (Class<Enum<?>>) surefireClassLoader.loadClass(CommandLineOption.class.getName());
99 } catch (ClassNotFoundException e) {
100 throw new SurefireReflectionException(e);
101 }
102 }
103
104 public Object convertIfRunResult(Object result) {
105 if (result == null || !isRunResult(result)) {
106 return result;
107 }
108 int getCompletedCount1 = invokeGetter(result, "getCompletedCount");
109 int getErrors = invokeGetter(result, "getErrors");
110 int getSkipped = invokeGetter(result, "getSkipped");
111 int getFailures = invokeGetter(result, "getFailures");
112 return new RunResult(getCompletedCount1, getErrors, getFailures, getSkipped);
113 }
114
115 private Object createTestRequest(TestRequest suiteDefinition) {
116 if (suiteDefinition == null) {
117 return null;
118 } else {
119 Object resolver = createTestListResolver(suiteDefinition.getTestListResolver());
120 Class<?>[] arguments = {List.class, File.class, testListResolver, int.class};
121 Constructor<?> constructor = getConstructor(testRequest, arguments);
122 return newInstance(
123 constructor,
124 suiteDefinition.getSuiteXmlFiles(),
125 suiteDefinition.getTestSourceDirectory(),
126 resolver,
127 suiteDefinition.getRerunFailingTestsCount());
128 }
129 }
130
131 private Object createTestListResolver(TestListResolver resolver) {
132 if (resolver == null) {
133 return null;
134 } else {
135 Constructor<?> constructor = getConstructor(testListResolver, String.class);
136 return newInstance(constructor, resolver.getPluginParameterTest());
137 }
138 }
139
140 private Object createDirectoryScannerParameters(DirectoryScannerParameters directoryScannerParameters) {
141 if (directoryScannerParameters == null) {
142 return null;
143 }
144
145 Class<?>[] arguments = {File.class, List.class, List.class, List.class, String.class};
146 Constructor<?> constructor = getConstructor(this.directoryScannerParameters, arguments);
147 return newInstance(
148 constructor,
149 directoryScannerParameters.getTestClassesDirectory(),
150 directoryScannerParameters.getIncludes(),
151 directoryScannerParameters.getExcludes(),
152 directoryScannerParameters.getSpecificTests(),
153 RunOrder.asString(directoryScannerParameters.getRunOrder()));
154 }
155
156 private Object createRunOrderParameters(RunOrderParameters runOrderParameters) {
157 if (runOrderParameters == null) {
158 return null;
159 }
160
161 Class<?>[] arguments = {String.class, File.class, Long.class};
162 Constructor<?> constructor = getConstructor(this.runOrderParameters, arguments);
163 File runStatisticsFile = runOrderParameters.getRunStatisticsFile();
164 return newInstance(
165 constructor,
166 RunOrder.asString(runOrderParameters.getRunOrder()),
167 runStatisticsFile,
168 runOrderParameters.getRunOrderRandomSeed());
169 }
170
171 private Object createTestArtifactInfo(TestArtifactInfo testArtifactInfo) {
172 if (testArtifactInfo == null) {
173 return null;
174 }
175 Class<?>[] arguments = {String.class, String.class};
176 Constructor<?> constructor = getConstructor(this.testArtifactInfo, arguments);
177 return newInstance(constructor, testArtifactInfo.getVersion(), testArtifactInfo.getClassifier());
178 }
179
180 private Object createReporterConfiguration(ReporterConfiguration reporterConfig) {
181 Constructor<?> constructor = getConstructor(reporterConfiguration, File.class, boolean.class);
182 return newInstance(constructor, reporterConfig.getReportsDirectory(), reporterConfig.isTrimStackTrace());
183 }
184
185 public Object createBooterConfiguration(ClassLoader surefireClassLoader, boolean insideFork) {
186 return instantiateOneArg(surefireClassLoader, BaseProviderFactory.class.getName(), boolean.class, insideFork);
187 }
188
189 public Object instantiateProvider(String providerClassName, Object booterParameters) {
190 return instantiateOneArg(surefireClassLoader, providerClassName, this.booterParameters, booterParameters);
191 }
192
193 public void setIfDirScannerAware(Object o, DirectoryScannerParameters dirScannerParams) {
194 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
195 setDirectoryScannerParameters(o, dirScannerParams);
196 }
197 }
198
199 public void setMainCliOptions(Object o, List<CommandLineOption> options) {
200 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
201 List<Enum<?>> newOptions = checkedList(new ArrayList<>(options.size()), commandLineOptionsClass);
202 Collection<Integer> ordinals = toOrdinals(options);
203 for (Enum<?> e : commandLineOptionsClass.getEnumConstants()) {
204 if (ordinals.contains(e.ordinal())) {
205 newOptions.add(e);
206 }
207 }
208 invokeSetter(o, "setMainCliOptions", List.class, newOptions);
209 }
210 }
211
212 public void setSkipAfterFailureCount(Object o, int skipAfterFailureCount) {
213 invokeSetter(o, "setSkipAfterFailureCount", int.class, skipAfterFailureCount);
214 }
215
216 public void setSystemExitTimeout(Object o, Integer systemExitTimeout) {
217 invokeSetter(o, "setSystemExitTimeout", Integer.class, systemExitTimeout);
218 }
219
220 void setDirectoryScannerParameters(Object o, DirectoryScannerParameters dirScannerParams) {
221 Object param = createDirectoryScannerParameters(dirScannerParams);
222 invokeSetter(o, "setDirectoryScannerParameters", directoryScannerParameters, param);
223 }
224
225 public void setRunOrderParameters(Object o, RunOrderParameters runOrderParameters) {
226 Object param = createRunOrderParameters(runOrderParameters);
227 invokeSetter(o, "setRunOrderParameters", this.runOrderParameters, param);
228 }
229
230 public void setTestSuiteDefinitionAware(Object o, TestRequest testSuiteDefinition2) {
231 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
232 setTestSuiteDefinition(o, testSuiteDefinition2);
233 }
234 }
235
236 void setTestSuiteDefinition(Object o, TestRequest testSuiteDefinition1) {
237 Object param = createTestRequest(testSuiteDefinition1);
238 invokeSetter(o, "setTestRequest", testRequest, param);
239 }
240
241 public void setProviderPropertiesAware(Object o, Map<String, String> properties) {
242 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
243 setProviderProperties(o, properties);
244 }
245 }
246
247 void setProviderProperties(Object o, Map<String, String> providerProperties) {
248 invokeSetter(o, "setProviderProperties", Map.class, providerProperties);
249 }
250
251 public void setReporterConfigurationAware(Object o, ReporterConfiguration reporterConfiguration1) {
252 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
253 setReporterConfiguration(o, reporterConfiguration1);
254 }
255 }
256
257 private void setReporterConfiguration(Object o, ReporterConfiguration reporterConfiguration) {
258 Object param = createReporterConfiguration(reporterConfiguration);
259 invokeSetter(o, "setReporterConfiguration", this.reporterConfiguration, param);
260 }
261
262 public void setTestClassLoaderAware(Object o, ClassLoader testClassLoader) {
263 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
264 setTestClassLoader(o, testClassLoader);
265 }
266 }
267
268 void setTestClassLoader(Object o, ClassLoader testClassLoader) {
269 Method setter = getMethod(o, "setClassLoaders", ClassLoader.class);
270 invokeMethodWithArray(o, setter, testClassLoader);
271 }
272
273 public void setTestArtifactInfoAware(Object o, TestArtifactInfo testArtifactInfo1) {
274 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
275 setTestArtifactInfo(o, testArtifactInfo1);
276 }
277 }
278
279 void setTestArtifactInfo(Object o, TestArtifactInfo testArtifactInfo) {
280 Object param = createTestArtifactInfo(testArtifactInfo);
281 invokeSetter(o, "setTestArtifactInfo", this.testArtifactInfo, param);
282 }
283
284 public void setReporterFactoryAware(Object o, Object reporterFactory) {
285 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
286 setReporterFactory(o, reporterFactory);
287 }
288 }
289
290 void setReporterFactory(Object o, Object reporterFactory) {
291 invokeSetter(o, "setReporterFactory", this.reporterFactory, reporterFactory);
292 }
293
294 private boolean isRunResult(Object o) {
295 return runResult.isAssignableFrom(o.getClass());
296 }
297
298 private static Collection<Integer> toOrdinals(Collection<? extends Enum<?>> enums) {
299 Collection<Integer> ordinals = new ArrayList<>(enums.size());
300 for (Enum<?> e : enums) {
301 ordinals.add(e.ordinal());
302 }
303 return ordinals;
304 }
305 }