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