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