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