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