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