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