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 = {File.class, testListResolver, int.class};
121 Constructor<?> constructor = getConstructor(testRequest, arguments);
122 return newInstance(
123 constructor,
124 suiteDefinition.getTestSourceDirectory(),
125 resolver,
126 suiteDefinition.getRerunFailingTestsCount());
127 }
128 }
129
130 private Object createTestListResolver(TestListResolver resolver) {
131 if (resolver == null) {
132 return null;
133 } else {
134 Constructor<?> constructor = getConstructor(testListResolver, String.class);
135 return newInstance(constructor, resolver.getPluginParameterTest());
136 }
137 }
138
139 private Object createDirectoryScannerParameters(DirectoryScannerParameters directoryScannerParameters) {
140 if (directoryScannerParameters == null) {
141 return null;
142 }
143
144 Class<?>[] arguments = {File.class, List.class, List.class, List.class, String.class};
145 Constructor<?> constructor = getConstructor(this.directoryScannerParameters, arguments);
146 return newInstance(
147 constructor,
148 directoryScannerParameters.getTestClassesDirectory(),
149 directoryScannerParameters.getIncludes(),
150 directoryScannerParameters.getExcludes(),
151 directoryScannerParameters.getSpecificTests(),
152 RunOrder.asString(directoryScannerParameters.getRunOrder()));
153 }
154
155 private Object createRunOrderParameters(RunOrderParameters runOrderParameters) {
156 if (runOrderParameters == null) {
157 return null;
158 }
159
160 Class<?>[] arguments = {String.class, File.class, Long.class};
161 Constructor<?> constructor = getConstructor(this.runOrderParameters, arguments);
162 File runStatisticsFile = runOrderParameters.getRunStatisticsFile();
163 return newInstance(
164 constructor,
165 RunOrder.asString(runOrderParameters.getRunOrder()),
166 runStatisticsFile,
167 runOrderParameters.getRunOrderRandomSeed());
168 }
169
170 private Object createTestArtifactInfo(TestArtifactInfo testArtifactInfo) {
171 if (testArtifactInfo == null) {
172 return null;
173 }
174 Class<?>[] arguments = {String.class, String.class};
175 Constructor<?> constructor = getConstructor(this.testArtifactInfo, arguments);
176 return newInstance(constructor, testArtifactInfo.getVersion(), testArtifactInfo.getClassifier());
177 }
178
179 private Object createReporterConfiguration(ReporterConfiguration reporterConfig) {
180 Constructor<?> constructor = getConstructor(reporterConfiguration, File.class, boolean.class);
181 return newInstance(constructor, reporterConfig.getReportsDirectory(), reporterConfig.isTrimStackTrace());
182 }
183
184 public Object createBooterConfiguration(ClassLoader surefireClassLoader, boolean insideFork) {
185 return instantiateOneArg(surefireClassLoader, BaseProviderFactory.class.getName(), boolean.class, insideFork);
186 }
187
188 public Object instantiateProvider(String providerClassName, Object booterParameters) {
189 return instantiateOneArg(surefireClassLoader, providerClassName, this.booterParameters, booterParameters);
190 }
191
192 public void setIfDirScannerAware(Object o, DirectoryScannerParameters dirScannerParams) {
193 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
194 setDirectoryScannerParameters(o, dirScannerParams);
195 }
196 }
197
198 public void setMainCliOptions(Object o, List<CommandLineOption> options) {
199 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
200 List<Enum<?>> newOptions = checkedList(new ArrayList<>(options.size()), commandLineOptionsClass);
201 Collection<Integer> ordinals = toOrdinals(options);
202 for (Enum<?> e : commandLineOptionsClass.getEnumConstants()) {
203 if (ordinals.contains(e.ordinal())) {
204 newOptions.add(e);
205 }
206 }
207 invokeSetter(o, "setMainCliOptions", List.class, newOptions);
208 }
209 }
210
211 public void setSkipAfterFailureCount(Object o, int skipAfterFailureCount) {
212 invokeSetter(o, "setSkipAfterFailureCount", int.class, skipAfterFailureCount);
213 }
214
215 public void setSystemExitTimeout(Object o, Integer systemExitTimeout) {
216 invokeSetter(o, "setSystemExitTimeout", Integer.class, systemExitTimeout);
217 }
218
219 void setDirectoryScannerParameters(Object o, DirectoryScannerParameters dirScannerParams) {
220 Object param = createDirectoryScannerParameters(dirScannerParams);
221 invokeSetter(o, "setDirectoryScannerParameters", directoryScannerParameters, param);
222 }
223
224 public void setRunOrderParameters(Object o, RunOrderParameters runOrderParameters) {
225 Object param = createRunOrderParameters(runOrderParameters);
226 invokeSetter(o, "setRunOrderParameters", this.runOrderParameters, param);
227 }
228
229 public void setTestSuiteDefinitionAware(Object o, TestRequest testSuiteDefinition2) {
230 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
231 setTestSuiteDefinition(o, testSuiteDefinition2);
232 }
233 }
234
235 void setTestSuiteDefinition(Object o, TestRequest testSuiteDefinition1) {
236 Object param = createTestRequest(testSuiteDefinition1);
237 invokeSetter(o, "setTestRequest", testRequest, param);
238 }
239
240 public void setProviderPropertiesAware(Object o, Map<String, String> properties) {
241 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
242 setProviderProperties(o, properties);
243 }
244 }
245
246 void setProviderProperties(Object o, Map<String, String> providerProperties) {
247 invokeSetter(o, "setProviderProperties", Map.class, providerProperties);
248 }
249
250 public void setReporterConfigurationAware(Object o, ReporterConfiguration reporterConfiguration1) {
251 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
252 setReporterConfiguration(o, reporterConfiguration1);
253 }
254 }
255
256 private void setReporterConfiguration(Object o, ReporterConfiguration reporterConfiguration) {
257 Object param = createReporterConfiguration(reporterConfiguration);
258 invokeSetter(o, "setReporterConfiguration", this.reporterConfiguration, param);
259 }
260
261 public void setTestClassLoaderAware(Object o, ClassLoader testClassLoader) {
262 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
263 setTestClassLoader(o, testClassLoader);
264 }
265 }
266
267 void setTestClassLoader(Object o, ClassLoader testClassLoader) {
268 Method setter = getMethod(o, "setClassLoaders", ClassLoader.class);
269 invokeMethodWithArray(o, setter, testClassLoader);
270 }
271
272 public void setTestArtifactInfoAware(Object o, TestArtifactInfo testArtifactInfo1) {
273 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
274 setTestArtifactInfo(o, testArtifactInfo1);
275 }
276 }
277
278 void setTestArtifactInfo(Object o, TestArtifactInfo testArtifactInfo) {
279 Object param = createTestArtifactInfo(testArtifactInfo);
280 invokeSetter(o, "setTestArtifactInfo", this.testArtifactInfo, param);
281 }
282
283 public void setReporterFactoryAware(Object o, Object reporterFactory) {
284 if (baseProviderFactory.isAssignableFrom(o.getClass())) {
285 setReporterFactory(o, reporterFactory);
286 }
287 }
288
289 void setReporterFactory(Object o, Object reporterFactory) {
290 invokeSetter(o, "setReporterFactory", this.reporterFactory, reporterFactory);
291 }
292
293 private boolean isRunResult(Object o) {
294 return runResult.isAssignableFrom(o.getClass());
295 }
296
297 private static Collection<Integer> toOrdinals(Collection<? extends Enum<?>> enums) {
298 Collection<Integer> ordinals = new ArrayList<>(enums.size());
299 for (Enum<?> e : enums) {
300 ordinals.add(e.ordinal());
301 }
302 return ordinals;
303 }
304 }