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