1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.testing;
20
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.Reader;
27 import java.lang.reflect.AccessibleObject;
28 import java.lang.reflect.Field;
29 import java.net.MalformedURLException;
30 import java.net.URL;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Properties;
37
38 import com.google.inject.Module;
39 import org.apache.commons.io.input.XmlStreamReader;
40 import org.apache.maven.artifact.Artifact;
41 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
42 import org.apache.maven.execution.DefaultMavenExecutionRequest;
43 import org.apache.maven.execution.DefaultMavenExecutionResult;
44 import org.apache.maven.execution.MavenExecutionRequest;
45 import org.apache.maven.execution.MavenExecutionResult;
46 import org.apache.maven.execution.MavenSession;
47 import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
48 import org.apache.maven.model.Plugin;
49 import org.apache.maven.plugin.Mojo;
50 import org.apache.maven.plugin.MojoExecution;
51 import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
52 import org.apache.maven.plugin.descriptor.MojoDescriptor;
53 import org.apache.maven.plugin.descriptor.Parameter;
54 import org.apache.maven.plugin.descriptor.PluginDescriptor;
55 import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
56 import org.apache.maven.project.MavenProject;
57 import org.apache.maven.repository.RepositorySystem;
58 import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
59 import org.codehaus.plexus.ContainerConfiguration;
60 import org.codehaus.plexus.DefaultContainerConfiguration;
61 import org.codehaus.plexus.DefaultPlexusContainer;
62 import org.codehaus.plexus.PlexusConstants;
63 import org.codehaus.plexus.PlexusContainer;
64 import org.codehaus.plexus.PlexusContainerException;
65 import org.codehaus.plexus.PlexusTestCase;
66 import org.codehaus.plexus.classworlds.ClassWorld;
67 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
68 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
69 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
70 import org.codehaus.plexus.component.repository.ComponentDescriptor;
71 import org.codehaus.plexus.configuration.PlexusConfiguration;
72 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
73 import org.codehaus.plexus.context.Context;
74 import org.codehaus.plexus.util.InterpolationFilterReader;
75 import org.codehaus.plexus.util.ReaderFactory;
76 import org.codehaus.plexus.util.ReflectionUtils;
77 import org.codehaus.plexus.util.StringUtils;
78 import org.codehaus.plexus.util.xml.Xpp3Dom;
79 import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public abstract class AbstractMojoTestCase extends PlexusTestCase {
94 private static final DefaultArtifactVersion MAVEN_VERSION;
95
96 static {
97 DefaultArtifactVersion version = null;
98 String path = "/META-INF/maven/org.apache.maven/maven-core/pom.properties";
99
100 try (InputStream is = AbstractMojoTestCase.class.getResourceAsStream(path)) {
101 Properties properties = new Properties();
102 if (is != null) {
103 properties.load(is);
104 }
105 String property = properties.getProperty("version");
106 if (property != null) {
107 version = new DefaultArtifactVersion(property);
108 }
109 } catch (IOException e) {
110
111 }
112 MAVEN_VERSION = version;
113 }
114
115 private ComponentConfigurator configurator;
116
117 private PlexusContainer container;
118
119 private Map<String, MojoDescriptor> mojoDescriptors;
120
121
122
123
124
125
126
127 @Override
128 protected void setUp() throws Exception {
129 assertTrue(
130 "Maven 3.2.4 or better is required",
131 MAVEN_VERSION == null || new DefaultArtifactVersion("3.2.3").compareTo(MAVEN_VERSION) < 0);
132
133 configurator = getContainer().lookup(ComponentConfigurator.class, "basic");
134 Context context = container.getContext();
135 Map<Object, Object> map = context.getContextData();
136
137 try (InputStream is = getClass().getResourceAsStream("/" + getPluginDescriptorLocation());
138 Reader reader = new BufferedReader(new XmlStreamReader(is));
139 InterpolationFilterReader interpolationReader = new InterpolationFilterReader(reader, map, "${", "}")) {
140
141 PluginDescriptor pluginDescriptor = new PluginDescriptorBuilder().build(interpolationReader);
142
143 Artifact artifact = lookup(RepositorySystem.class)
144 .createArtifact(
145 pluginDescriptor.getGroupId(),
146 pluginDescriptor.getArtifactId(),
147 pluginDescriptor.getVersion(),
148 ".jar");
149
150 artifact.setFile(getPluginArtifactFile());
151 pluginDescriptor.setPluginArtifact(artifact);
152 pluginDescriptor.setArtifacts(Arrays.asList(artifact));
153
154 for (ComponentDescriptor<?> desc : pluginDescriptor.getComponents()) {
155 getContainer().addComponentDescriptor(desc);
156 }
157
158 mojoDescriptors = new HashMap<>();
159 for (MojoDescriptor mojoDescriptor : pluginDescriptor.getMojos()) {
160 mojoDescriptors.put(mojoDescriptor.getGoal(), mojoDescriptor);
161 }
162 }
163 }
164
165
166
167
168
169
170
171 private File getPluginArtifactFile() throws IOException {
172 final String pluginDescriptorLocation = getPluginDescriptorLocation();
173 final URL resource = getClass().getResource("/" + pluginDescriptorLocation);
174
175 File file = null;
176
177
178 if (resource != null) {
179 if ("file".equalsIgnoreCase(resource.getProtocol())) {
180 String path = resource.getPath();
181 if (path.endsWith(pluginDescriptorLocation)) {
182 file = new File(path.substring(0, path.length() - pluginDescriptorLocation.length()));
183 }
184 } else if ("jar".equalsIgnoreCase(resource.getProtocol())) {
185
186 try {
187 URL jarfile = new URL(resource.getPath());
188 if ("file".equalsIgnoreCase(jarfile.getProtocol())) {
189 String path = jarfile.getPath();
190 if (path.endsWith(pluginDescriptorLocation)) {
191 file = new File(path.substring(0, path.length() - pluginDescriptorLocation.length() - 2));
192 }
193 }
194 } catch (MalformedURLException e) {
195
196 }
197 }
198 }
199
200
201 if (file == null || !file.exists()) {
202 file = new File(getBasedir());
203 }
204
205 return file.getCanonicalFile();
206 }
207
208 protected InputStream getPublicDescriptorStream() throws Exception {
209 return new FileInputStream(new File(getPluginDescriptorPath()));
210 }
211
212 protected String getPluginDescriptorPath() {
213 return getBasedir() + "/target/classes/META-INF/maven/plugin.xml";
214 }
215
216 protected String getPluginDescriptorLocation() {
217 return "META-INF/maven/plugin.xml";
218 }
219
220 @Override
221 protected void setupContainer() {
222 ContainerConfiguration cc = setupContainerConfiguration();
223 try {
224 List<Module> modules = new ArrayList<>();
225 addGuiceModules(modules);
226 container = new DefaultPlexusContainer(cc, modules.toArray(new Module[0]));
227 } catch (PlexusContainerException e) {
228 e.printStackTrace();
229 fail("Failed to create plexus container.");
230 }
231 }
232
233
234
235
236 protected void addGuiceModules(List<Module> modules) {
237
238 }
239
240 protected ContainerConfiguration setupContainerConfiguration() {
241 ClassWorld classWorld =
242 new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader());
243
244 ContainerConfiguration cc = new DefaultContainerConfiguration()
245 .setClassWorld(classWorld)
246 .setClassPathScanning(PlexusConstants.SCANNING_INDEX)
247 .setAutoWiring(true)
248 .setName("maven");
249
250 return cc;
251 }
252
253 @Override
254 protected PlexusContainer getContainer() {
255 if (container == null) {
256 setupContainer();
257 }
258
259 return container;
260 }
261
262
263
264
265
266
267
268
269
270 protected <T extends Mojo> T lookupMojo(String goal, String pluginPom) throws Exception {
271 return lookupMojo(goal, new File(pluginPom));
272 }
273
274
275
276
277
278
279
280
281
282 protected <T extends Mojo> T lookupEmptyMojo(String goal, String pluginPom) throws Exception {
283 return lookupEmptyMojo(goal, new File(pluginPom));
284 }
285
286
287
288
289
290
291
292
293
294 protected <T extends Mojo> T lookupMojo(String goal, File pom) throws Exception {
295 File pluginPom = new File(getBasedir(), "pom.xml");
296
297 Xpp3Dom pluginPomDom = Xpp3DomBuilder.build(ReaderFactory.newXmlReader(pluginPom));
298
299 String artifactId = pluginPomDom.getChild("artifactId").getValue();
300
301 String groupId = resolveFromRootThenParent(pluginPomDom, "groupId");
302
303 String version = resolveFromRootThenParent(pluginPomDom, "version");
304
305 PlexusConfiguration pluginConfiguration = extractPluginConfiguration(artifactId, pom);
306
307 return lookupMojo(groupId, artifactId, version, goal, pluginConfiguration);
308 }
309
310
311
312
313
314
315
316
317
318 protected <T extends Mojo> T lookupEmptyMojo(String goal, File pom) throws Exception {
319 File pluginPom = new File(getBasedir(), "pom.xml");
320
321 Xpp3Dom pluginPomDom = Xpp3DomBuilder.build(ReaderFactory.newXmlReader(pluginPom));
322
323 String artifactId = pluginPomDom.getChild("artifactId").getValue();
324
325 String groupId = resolveFromRootThenParent(pluginPomDom, "groupId");
326
327 String version = resolveFromRootThenParent(pluginPomDom, "version");
328
329 return lookupMojo(groupId, artifactId, version, goal, null);
330 }
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 protected <T extends Mojo> T lookupMojo(
353 String groupId, String artifactId, String version, String goal, PlexusConfiguration pluginConfiguration)
354 throws Exception {
355 validateContainerStatus();
356
357
358
359 T mojo = (T) lookup(Mojo.class, groupId + ":" + artifactId + ":" + version + ":" + goal);
360
361 if (pluginConfiguration != null) {
362
363
364
365
366 ExpressionEvaluator evaluator = new ResolverExpressionEvaluatorStub();
367
368 configurator.configureComponent(
369 mojo, pluginConfiguration, evaluator, getContainer().getContainerRealm());
370 }
371
372 return mojo;
373 }
374
375
376
377
378
379
380
381
382
383 protected <T extends Mojo> T lookupConfiguredMojo(MavenProject project, String goal) throws Exception {
384 return lookupConfiguredMojo(newMavenSession(project), newMojoExecution(goal));
385 }
386
387
388
389
390
391
392
393
394
395
396 protected <T extends Mojo> T lookupConfiguredMojo(MavenSession session, MojoExecution execution)
397 throws Exception, ComponentConfigurationException {
398 MavenProject project = session.getCurrentProject();
399 MojoDescriptor mojoDescriptor = execution.getMojoDescriptor();
400
401 T mojo = (T) lookup(mojoDescriptor.getRole(), mojoDescriptor.getRoleHint());
402
403 ExpressionEvaluator evaluator = new PluginParameterExpressionEvaluator(session, execution);
404
405 Xpp3Dom configuration = null;
406 Plugin plugin = project.getPlugin(mojoDescriptor.getPluginDescriptor().getPluginLookupKey());
407 if (plugin != null) {
408 configuration = (Xpp3Dom) plugin.getConfiguration();
409 }
410 if (configuration == null) {
411 configuration = new Xpp3Dom("configuration");
412 }
413 configuration = Xpp3Dom.mergeXpp3Dom(configuration, execution.getConfiguration());
414
415 PlexusConfiguration pluginConfiguration = new XmlPlexusConfiguration(configuration);
416
417 if (mojoDescriptor.getComponentConfigurator() != null) {
418 configurator =
419 getContainer().lookup(ComponentConfigurator.class, mojoDescriptor.getComponentConfigurator());
420 }
421
422 configurator.configureComponent(
423 mojo, pluginConfiguration, evaluator, getContainer().getContainerRealm());
424
425 return mojo;
426 }
427
428
429
430
431
432
433
434 protected MavenSession newMavenSession(MavenProject project) {
435 MavenExecutionRequest request = new DefaultMavenExecutionRequest();
436 MavenExecutionResult result = new DefaultMavenExecutionResult();
437
438 MavenSession session = new MavenSession(container, MavenRepositorySystemUtils.newSession(), request, result);
439 session.setCurrentProject(project);
440 session.setProjects(Arrays.asList(project));
441 return session;
442 }
443
444
445
446
447
448
449
450 protected MojoExecution newMojoExecution(String goal) {
451 MojoDescriptor mojoDescriptor = mojoDescriptors.get(goal);
452 assertNotNull(String.format("The MojoDescriptor for the goal %s cannot be null.", goal), mojoDescriptor);
453 MojoExecution execution = new MojoExecution(mojoDescriptor);
454 finalizeMojoConfiguration(execution);
455 return execution;
456 }
457
458
459 private void finalizeMojoConfiguration(MojoExecution mojoExecution) {
460 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
461
462 Xpp3Dom executionConfiguration = mojoExecution.getConfiguration();
463 if (executionConfiguration == null) {
464 executionConfiguration = new Xpp3Dom("configuration");
465 }
466
467 Xpp3Dom defaultConfiguration = new Xpp3Dom(MojoDescriptorCreator.convert(mojoDescriptor));
468
469 Xpp3Dom finalConfiguration = new Xpp3Dom("configuration");
470
471 if (mojoDescriptor.getParameters() != null) {
472 for (Parameter parameter : mojoDescriptor.getParameters()) {
473 Xpp3Dom parameterConfiguration = executionConfiguration.getChild(parameter.getName());
474
475 if (parameterConfiguration == null) {
476 parameterConfiguration = executionConfiguration.getChild(parameter.getAlias());
477 }
478
479 Xpp3Dom parameterDefaults = defaultConfiguration.getChild(parameter.getName());
480
481 parameterConfiguration = Xpp3Dom.mergeXpp3Dom(parameterConfiguration, parameterDefaults, Boolean.TRUE);
482
483 if (parameterConfiguration != null) {
484 parameterConfiguration = new Xpp3Dom(parameterConfiguration, parameter.getName());
485
486 if (StringUtils.isEmpty(parameterConfiguration.getAttribute("implementation"))
487 && StringUtils.isNotEmpty(parameter.getImplementation())) {
488 parameterConfiguration.setAttribute("implementation", parameter.getImplementation());
489 }
490
491 finalConfiguration.addChild(parameterConfiguration);
492 }
493 }
494 }
495
496 mojoExecution.setConfiguration(finalConfiguration);
497 }
498
499
500
501
502
503
504
505 protected PlexusConfiguration extractPluginConfiguration(String artifactId, File pom) throws Exception {
506
507 try (Reader reader = ReaderFactory.newXmlReader(pom)) {
508 Xpp3Dom pomDom = Xpp3DomBuilder.build(reader);
509 return extractPluginConfiguration(artifactId, pomDom);
510 }
511 }
512
513
514
515
516
517
518
519 protected PlexusConfiguration extractPluginConfiguration(String artifactId, Xpp3Dom pomDom) throws Exception {
520 Xpp3Dom pluginConfigurationElement = null;
521
522 Xpp3Dom buildElement = pomDom.getChild("build");
523 if (buildElement != null) {
524 Xpp3Dom pluginsRootElement = buildElement.getChild("plugins");
525
526 if (pluginsRootElement != null) {
527 Xpp3Dom[] pluginElements = pluginsRootElement.getChildren();
528
529 for (Xpp3Dom pluginElement : pluginElements) {
530 String pluginElementArtifactId =
531 pluginElement.getChild("artifactId").getValue();
532
533 if (pluginElementArtifactId.equals(artifactId)) {
534 pluginConfigurationElement = pluginElement.getChild("configuration");
535
536 break;
537 }
538 }
539
540 if (pluginConfigurationElement == null) {
541 throw new ConfigurationException("Cannot find a configuration element for a plugin with an "
542 + "artifactId of " + artifactId + ".");
543 }
544 }
545 }
546
547 if (pluginConfigurationElement == null) {
548 throw new ConfigurationException(
549 "Cannot find a configuration element for a plugin with an artifactId of " + artifactId + ".");
550 }
551
552 return new XmlPlexusConfiguration(pluginConfigurationElement);
553 }
554
555
556
557
558
559
560
561
562
563
564 protected <T extends Mojo> T configureMojo(T mojo, String artifactId, File pom) throws Exception {
565 validateContainerStatus();
566
567 PlexusConfiguration pluginConfiguration = extractPluginConfiguration(artifactId, pom);
568
569 ExpressionEvaluator evaluator = new ResolverExpressionEvaluatorStub();
570
571 configurator.configureComponent(
572 mojo, pluginConfiguration, evaluator, getContainer().getContainerRealm());
573
574 return mojo;
575 }
576
577
578
579
580
581
582
583
584
585 protected <T extends Mojo> T configureMojo(T mojo, PlexusConfiguration pluginConfiguration) throws Exception {
586 validateContainerStatus();
587
588 ExpressionEvaluator evaluator = new ResolverExpressionEvaluatorStub();
589
590 configurator.configureComponent(
591 mojo, pluginConfiguration, evaluator, getContainer().getContainerRealm());
592
593 return mojo;
594 }
595
596
597
598
599
600
601
602
603
604
605
606 protected <T> T getVariableValueFromObject(Object object, String variable) throws IllegalAccessException {
607 Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, object.getClass());
608
609 field.setAccessible(true);
610
611 return (T) field.get(object);
612 }
613
614
615
616
617
618
619
620
621
622 protected Map<String, Object> getVariablesAndValuesFromObject(Object object) throws IllegalAccessException {
623 return getVariablesAndValuesFromObject(object.getClass(), object);
624 }
625
626
627
628
629
630
631
632
633
634
635 protected Map<String, Object> getVariablesAndValuesFromObject(Class<?> clazz, Object object)
636 throws IllegalAccessException {
637 Map<String, Object> map = new HashMap<>();
638
639 Field[] fields = clazz.getDeclaredFields();
640
641 AccessibleObject.setAccessible(fields, true);
642
643 for (Field field : fields) {
644 map.put(field.getName(), field.get(object));
645 }
646
647 Class<?> superclass = clazz.getSuperclass();
648
649 if (!Object.class.equals(superclass)) {
650 map.putAll(getVariablesAndValuesFromObject(superclass, object));
651 }
652
653 return map;
654 }
655
656
657
658
659
660
661
662
663
664 protected <T> void setVariableValueToObject(Object object, String variable, T value) throws IllegalAccessException {
665 Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, object.getClass());
666
667 field.setAccessible(true);
668
669 field.set(object, value);
670 }
671
672
673
674
675
676
677
678
679
680
681
682 private String resolveFromRootThenParent(Xpp3Dom pluginPomDom, String element) throws Exception {
683 Xpp3Dom elementDom = pluginPomDom.getChild(element);
684
685
686 if (elementDom == null) {
687 Xpp3Dom pluginParentDom = pluginPomDom.getChild("parent");
688
689 if (pluginParentDom != null) {
690 elementDom = pluginParentDom.getChild(element);
691
692 if (elementDom == null) {
693 throw new Exception("unable to determine " + element);
694 }
695
696 return elementDom.getValue();
697 }
698
699 throw new Exception("unable to determine " + element);
700 }
701
702 return elementDom.getValue();
703 }
704
705
706
707
708
709
710
711
712
713 private void validateContainerStatus() throws Exception {
714 if (getContainer() != null) {
715 return;
716 }
717
718 throw new Exception("container is null, make sure super.setUp() is called");
719 }
720 }