KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > maven > plugin > DefaultPluginManager


1 package org.apache.maven.plugin;
2
3 /*
4  * Copyright 2001-2005 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import org.apache.maven.MavenArtifactFilterManager;
20 import org.apache.maven.artifact.Artifact;
21 import org.apache.maven.artifact.factory.ArtifactFactory;
22 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
23 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
24 import org.apache.maven.artifact.metadata.ResolutionGroup;
25 import org.apache.maven.artifact.repository.ArtifactRepository;
26 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
27 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
28 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
29 import org.apache.maven.artifact.resolver.ArtifactResolver;
30 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
31 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
32 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
33 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
34 import org.apache.maven.artifact.versioning.VersionRange;
35 import org.apache.maven.execution.MavenSession;
36 import org.apache.maven.execution.RuntimeInformation;
37 import org.apache.maven.model.Plugin;
38 import org.apache.maven.model.ReportPlugin;
39 import org.apache.maven.monitor.event.EventDispatcher;
40 import org.apache.maven.monitor.event.MavenEvents;
41 import org.apache.maven.monitor.logging.DefaultLog;
42 import org.apache.maven.plugin.descriptor.MojoDescriptor;
43 import org.apache.maven.plugin.descriptor.Parameter;
44 import org.apache.maven.plugin.descriptor.PluginDescriptor;
45 import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
46 import org.apache.maven.plugin.logging.Log;
47 import org.apache.maven.plugin.version.PluginVersionManager;
48 import org.apache.maven.plugin.version.PluginVersionNotFoundException;
49 import org.apache.maven.plugin.version.PluginVersionResolutionException;
50 import org.apache.maven.project.MavenProject;
51 import org.apache.maven.project.MavenProjectBuilder;
52 import org.apache.maven.project.ProjectBuildingException;
53 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
54 import org.apache.maven.project.artifact.MavenMetadataSource;
55 import org.apache.maven.project.path.PathTranslator;
56 import org.apache.maven.reporting.MavenReport;
57 import org.apache.maven.settings.Settings;
58 import org.codehaus.plexus.PlexusConstants;
59 import org.codehaus.plexus.PlexusContainer;
60 import org.codehaus.plexus.PlexusContainerException;
61 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
62 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
63 import org.codehaus.plexus.component.configurator.ConfigurationListener;
64 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
65 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
66 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
67 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
68 import org.codehaus.plexus.configuration.PlexusConfiguration;
69 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
70 import org.codehaus.plexus.context.Context;
71 import org.codehaus.plexus.context.ContextException;
72 import org.codehaus.plexus.logging.AbstractLogEnabled;
73 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
74 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
75 import org.codehaus.plexus.util.StringUtils;
76 import org.codehaus.plexus.util.xml.Xpp3Dom;
77
78 import java.io.File JavaDoc;
79 import java.net.URL JavaDoc;
80 import java.util.ArrayList JavaDoc;
81 import java.util.Collection JavaDoc;
82 import java.util.Collections JavaDoc;
83 import java.util.HashMap JavaDoc;
84 import java.util.HashSet JavaDoc;
85 import java.util.Iterator JavaDoc;
86 import java.util.List JavaDoc;
87 import java.util.Map JavaDoc;
88 import java.util.Set JavaDoc;
89
90 public class DefaultPluginManager
91     extends AbstractLogEnabled
92     implements PluginManager, Initializable, Contextualizable
93 {
94     protected PlexusContainer container;
95
96     protected PluginDescriptorBuilder pluginDescriptorBuilder;
97
98     protected ArtifactFilter artifactFilter;
99
100     private Log mojoLogger;
101
102     private Map JavaDoc resolvedCoreArtifactFiles = new HashMap JavaDoc();
103
104     // component requirements
105
protected PathTranslator pathTranslator;
106
107     protected MavenPluginCollector pluginCollector;
108
109     protected PluginVersionManager pluginVersionManager;
110
111     protected ArtifactFactory artifactFactory;
112
113     protected ArtifactResolver artifactResolver;
114
115     protected ArtifactMetadataSource artifactMetadataSource;
116
117     protected RuntimeInformation runtimeInformation;
118
119     protected MavenProjectBuilder mavenProjectBuilder;
120
121     protected PluginMappingManager pluginMappingManager;
122
123     // END component requirements
124

125     public DefaultPluginManager()
126     {
127         pluginDescriptorBuilder = new PluginDescriptorBuilder();
128     }
129
130     // ----------------------------------------------------------------------
131
//
132
// ----------------------------------------------------------------------
133

134     public PluginDescriptor getPluginDescriptorForPrefix( String JavaDoc prefix )
135     {
136         return pluginCollector.getPluginDescriptorForPrefix( prefix );
137     }
138
139     public Plugin getPluginDefinitionForPrefix( String JavaDoc prefix, MavenSession session, MavenProject project )
140     {
141         // TODO: since this is only used in the lifecycle executor, maybe it should be moved there? There is no other
142
// use for the mapping manager in here
143
return pluginMappingManager.getByPrefix( prefix, session.getSettings().getPluginGroups(),
144                                                  project.getPluginArtifactRepositories(),
145                                                  session.getLocalRepository() );
146     }
147
148     public PluginDescriptor verifyPlugin( Plugin plugin, MavenProject project, Settings settings,
149                                           ArtifactRepository localRepository )
150         throws ArtifactResolutionException, PluginVersionResolutionException, ArtifactNotFoundException,
151         InvalidVersionSpecificationException, InvalidPluginException, PluginManagerException, PluginNotFoundException,
152         PluginVersionNotFoundException
153     {
154         // TODO: this should be possibly outside
155
// All version-resolution logic has been moved to DefaultPluginVersionManager.
156
if ( plugin.getVersion() == null )
157         {
158             String JavaDoc version = pluginVersionManager.resolvePluginVersion( plugin.getGroupId(), plugin.getArtifactId(),
159                                                                         project, settings, localRepository );
160             plugin.setVersion( version );
161         }
162
163         return verifyVersionedPlugin( plugin, project, localRepository );
164     }
165
166     private PluginDescriptor verifyVersionedPlugin( Plugin plugin, MavenProject project,
167                                                     ArtifactRepository localRepository )
168         throws PluginVersionResolutionException, ArtifactNotFoundException, ArtifactResolutionException,
169         InvalidVersionSpecificationException, InvalidPluginException, PluginManagerException, PluginNotFoundException
170     {
171         // TODO: this might result in an artifact "RELEASE" being resolved continuously
172
// FIXME: need to find out how a plugin gets marked as 'installed'
173
// and no ChildContainer exists. The check for that below fixes
174
// the 'Can't find plexus container for plugin: xxx' error.
175
try
176         {
177             VersionRange versionRange = VersionRange.createFromVersionSpec( plugin.getVersion() );
178
179             List JavaDoc remoteRepositories = new ArrayList JavaDoc();
180             remoteRepositories.addAll( project.getPluginArtifactRepositories() );
181             remoteRepositories.addAll( project.getRemoteArtifactRepositories() );
182
183             checkRequiredMavenVersion( plugin, localRepository, remoteRepositories );
184
185             Artifact pluginArtifact =
186                 artifactFactory.createPluginArtifact( plugin.getGroupId(), plugin.getArtifactId(), versionRange );
187
188             pluginArtifact = project.replaceWithActiveArtifact( pluginArtifact );
189
190             artifactResolver.resolve( pluginArtifact, project.getPluginArtifactRepositories(), localRepository );
191
192             PlexusContainer pluginContainer = container.getChildContainer( plugin.getKey() );
193
194             File JavaDoc pluginFile = pluginArtifact.getFile();
195
196             if ( !pluginCollector.isPluginInstalled( plugin ) || pluginContainer == null )
197             {
198                 addPlugin( plugin, pluginArtifact, project, localRepository );
199             }
200             else if ( pluginFile.lastModified() > pluginContainer.getCreationDate().getTime() )
201             {
202                 getLogger().info(
203                     "Reloading plugin container for: " + plugin.getKey() + ". The plugin artifact has changed." );
204
205                 pluginContainer.dispose();
206
207                 pluginCollector.flushPluginDescriptor( plugin );
208
209                 addPlugin( plugin, pluginArtifact, project, localRepository );
210             }
211
212             project.addPlugin( plugin );
213         }
214         catch ( ArtifactNotFoundException e )
215         {
216             String JavaDoc groupId = plugin.getGroupId();
217             String JavaDoc artifactId = plugin.getArtifactId();
218             String JavaDoc version = plugin.getVersion();
219
220             if ( groupId == null || artifactId == null || version == null )
221             {
222                 throw new PluginNotFoundException( e );
223             }
224             else if ( groupId.equals( e.getGroupId() ) && artifactId.equals( e.getArtifactId() ) &&
225                 version.equals( e.getVersion() ) && "maven-plugin".equals( e.getType() ) )
226             {
227                 throw new PluginNotFoundException( e );
228             }
229             else
230             {
231                 throw e;
232             }
233         }
234
235         return pluginCollector.getPluginDescriptor( plugin );
236     }
237
238     /**
239      * @todo would be better to store this in the plugin descriptor, but then it won't be available to the version
240      * manager which executes before the plugin is instantiated
241      */

242     private void checkRequiredMavenVersion( Plugin plugin, ArtifactRepository localRepository, List JavaDoc remoteRepositories )
243         throws PluginVersionResolutionException, InvalidPluginException
244     {
245         try
246         {
247             Artifact artifact = artifactFactory.createProjectArtifact( plugin.getGroupId(), plugin.getArtifactId(),
248                                                                        plugin.getVersion() );
249             MavenProject project =
250                 mavenProjectBuilder.buildFromRepository( artifact, remoteRepositories, localRepository, false );
251             // if we don't have the required Maven version, then ignore an update
252
if ( project.getPrerequisites() != null && project.getPrerequisites().getMaven() != null )
253             {
254                 DefaultArtifactVersion requiredVersion =
255                     new DefaultArtifactVersion( project.getPrerequisites().getMaven() );
256                 if ( runtimeInformation.getApplicationVersion().compareTo( requiredVersion ) < 0 )
257                 {
258                     throw new PluginVersionResolutionException( plugin.getGroupId(), plugin.getArtifactId(),
259                                                                 "Plugin requires Maven version " + requiredVersion );
260                 }
261             }
262         }
263         catch ( ProjectBuildingException e )
264         {
265             throw new InvalidPluginException(
266                 "Unable to build project for plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
267         }
268     }
269
270     protected void addPlugin( Plugin plugin, Artifact pluginArtifact, MavenProject project,
271                               ArtifactRepository localRepository )
272         throws PluginManagerException, InvalidPluginException
273     {
274         PlexusContainer child;
275         try
276         {
277             child = container.createChildContainer( plugin.getKey(),
278                                                     Collections.singletonList( pluginArtifact.getFile() ),
279                                                     Collections.EMPTY_MAP,
280                                                     Collections.singletonList( pluginCollector ) );
281         }
282         catch ( PlexusContainerException e )
283         {
284             throw new PluginManagerException(
285                 "Failed to create plugin container for plugin '" + plugin + "': " + e.getMessage(), e );
286         }
287
288         // this plugin's descriptor should have been discovered in the child creation, so we should be able to
289
// circle around and set the artifacts and class realm
290
PluginDescriptor addedPlugin = pluginCollector.getPluginDescriptor( plugin );
291
292         addedPlugin.setClassRealm( child.getContainerRealm() );
293
294         // we're only setting the plugin's artifact itself as the artifact list, to allow it to be retrieved
295
// later when the plugin is first invoked. Retrieving this artifact will in turn allow us to
296
// transitively resolve its dependencies, and add them to the plugin container...
297
addedPlugin.setArtifacts( Collections.singletonList( pluginArtifact ) );
298
299         try
300         {
301             // the only Plugin instance which will have dependencies is the one specified in the project.
302
// We need to look for a Plugin instance there, in case the instance we're using didn't come from
303
// the project.
304
Plugin projectPlugin = (Plugin) project.getBuild().getPluginsAsMap().get( plugin.getKey() );
305
306             if ( projectPlugin == null )
307             {
308                 projectPlugin = plugin;
309             }
310
311             Set JavaDoc artifacts = MavenMetadataSource.createArtifacts( artifactFactory, projectPlugin.getDependencies(), null,
312                                                                  null, project );
313
314 // Set artifacts =
315
// MavenMetadataSource.createArtifacts( artifactFactory, plugin.getDependencies(), null, null, project );
316

317             addedPlugin.setIntroducedDependencyArtifacts( artifacts );
318         }
319         catch ( InvalidDependencyVersionException e )
320         {
321             throw new InvalidPluginException( "Plugin '" + plugin + "' is invalid: " + e.getMessage(), e );
322         }
323     }
324
325     // ----------------------------------------------------------------------
326
// Mojo execution
327
// ----------------------------------------------------------------------
328

329     public void executeMojo( MavenProject project, MojoExecution mojoExecution, MavenSession session )
330         throws ArtifactResolutionException, MojoExecutionException, MojoFailureException, ArtifactNotFoundException,
331         InvalidDependencyVersionException, PluginManagerException, PluginConfigurationException
332     {
333         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
334
335         // NOTE: I'm putting these checks in here, since this is the central point of access for
336
// anything that wants to execute a mojo.
337
if ( mojoDescriptor.isProjectRequired() && !session.isUsingPOMsFromFilesystem() )
338         {
339             throw new MojoExecutionException( "Cannot execute mojo: " + mojoDescriptor.getGoal() +
340                 ". It requires a project with an existing pom.xml, but the build is not using one." );
341         }
342
343         if ( mojoDescriptor.isOnlineRequired() && session.getSettings().isOffline() )
344         {
345             // TODO: Should we error out, or simply warn and skip??
346
throw new MojoExecutionException( "Mojo: " + mojoDescriptor.getGoal() +
347                 " requires online mode for execution. Maven is currently offline." );
348         }
349
350         if ( mojoDescriptor.isDependencyResolutionRequired() != null )
351         {
352             Collection JavaDoc projects;
353
354             if ( mojoDescriptor.isAggregator() )
355             {
356                 projects = session.getSortedProjects();
357             }
358             else
359             {
360                 projects = Collections.singleton( project );
361             }
362
363             for ( Iterator JavaDoc i = projects.iterator(); i.hasNext(); )
364             {
365                 MavenProject p = (MavenProject) i.next();
366                 resolveTransitiveDependencies( session, artifactResolver,
367                                                mojoDescriptor.isDependencyResolutionRequired(), artifactFactory, p );
368             }
369
370             downloadDependencies( project, session, artifactResolver );
371         }
372
373         String JavaDoc goalName = mojoDescriptor.getFullGoalName();
374
375         Mojo plugin;
376
377         PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
378         String JavaDoc goalId = mojoDescriptor.getGoal();
379         String JavaDoc groupId = pluginDescriptor.getGroupId();
380         String JavaDoc artifactId = pluginDescriptor.getArtifactId();
381         String JavaDoc executionId = mojoExecution.getExecutionId();
382         Xpp3Dom dom = project.getGoalConfiguration( groupId, artifactId, executionId, goalId );
383         Xpp3Dom reportDom = project.getReportConfiguration( groupId, artifactId, executionId );
384         dom = Xpp3Dom.mergeXpp3Dom( dom, reportDom );
385         if ( mojoExecution.getConfiguration() != null )
386         {
387             dom = Xpp3Dom.mergeXpp3Dom( dom, mojoExecution.getConfiguration() );
388         }
389
390         plugin = getConfiguredMojo( session, dom, project, false, mojoExecution );
391
392         // Event monitoring.
393
String JavaDoc event = MavenEvents.MOJO_EXECUTION;
394         EventDispatcher dispatcher = session.getEventDispatcher();
395
396         String JavaDoc goalExecId = goalName;
397
398         if ( mojoExecution.getExecutionId() != null )
399         {
400             goalExecId += " {execution: " + mojoExecution.getExecutionId() + "}";
401         }
402
403         dispatcher.dispatchStart( event, goalExecId );
404
405         ClassLoader JavaDoc oldClassLoader = Thread.currentThread().getContextClassLoader();
406
407         try
408         {
409             Thread.currentThread().setContextClassLoader(
410                 mojoDescriptor.getPluginDescriptor().getClassRealm().getClassLoader() );
411
412             plugin.execute();
413
414             dispatcher.dispatchEnd( event, goalExecId );
415         }
416         catch ( MojoExecutionException e )
417         {
418             session.getEventDispatcher().dispatchError( event, goalExecId, e );
419
420             throw e;
421         }
422         catch ( MojoFailureException e )
423         {
424             session.getEventDispatcher().dispatchError( event, goalExecId, e );
425
426             throw e;
427         }
428         finally
429         {
430
431             Thread.currentThread().setContextClassLoader( oldClassLoader );
432
433             try
434             {
435                 PlexusContainer pluginContainer = getPluginContainer( mojoDescriptor.getPluginDescriptor() );
436
437                 pluginContainer.release( plugin );
438             }
439             catch ( ComponentLifecycleException e )
440             {
441                 if ( getLogger().isErrorEnabled() )
442                 {
443                     getLogger().error( "Error releasing plugin - ignoring.", e );
444                 }
445             }
446         }
447     }
448
449     public MavenReport getReport( MavenProject project, MojoExecution mojoExecution, MavenSession session )
450         throws ArtifactNotFoundException, PluginConfigurationException, PluginManagerException,
451         ArtifactResolutionException
452     {
453         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
454         PluginDescriptor descriptor = mojoDescriptor.getPluginDescriptor();
455         Xpp3Dom dom = project.getReportConfiguration( descriptor.getGroupId(), descriptor.getArtifactId(),
456                                                       mojoExecution.getExecutionId() );
457         if ( mojoExecution.getConfiguration() != null )
458         {
459             dom = Xpp3Dom.mergeXpp3Dom( dom, mojoExecution.getConfiguration() );
460         }
461
462         return (MavenReport) getConfiguredMojo( session, dom, project, true, mojoExecution );
463     }
464
465     public PluginDescriptor verifyReportPlugin( ReportPlugin reportPlugin, MavenProject project, MavenSession session )
466         throws PluginVersionResolutionException, ArtifactResolutionException, ArtifactNotFoundException,
467         InvalidVersionSpecificationException, InvalidPluginException, PluginManagerException, PluginNotFoundException,
468         PluginVersionNotFoundException
469     {
470         String JavaDoc version = reportPlugin.getVersion();
471
472         if ( version == null )
473         {
474             version = pluginVersionManager.resolveReportPluginVersion( reportPlugin.getGroupId(),
475                                                                        reportPlugin.getArtifactId(), project,
476                                                                        session.getSettings(),
477                                                                        session.getLocalRepository() );
478             reportPlugin.setVersion( version );
479         }
480
481         Plugin forLookup = new Plugin();
482
483         forLookup.setGroupId( reportPlugin.getGroupId() );
484         forLookup.setArtifactId( reportPlugin.getArtifactId() );
485         forLookup.setVersion( version );
486
487         return verifyVersionedPlugin( forLookup, project, session.getLocalRepository() );
488     }
489
490     private PlexusContainer getPluginContainer( PluginDescriptor pluginDescriptor )
491         throws PluginManagerException
492     {
493         String JavaDoc pluginKey = pluginDescriptor.getPluginLookupKey();
494
495         PlexusContainer pluginContainer = container.getChildContainer( pluginKey );
496
497         if ( pluginContainer == null )
498         {
499             throw new PluginManagerException( "Cannot find Plexus container for plugin: " + pluginKey );
500         }
501
502         return pluginContainer;
503     }
504
505     private Mojo getConfiguredMojo( MavenSession session, Xpp3Dom dom, MavenProject project, boolean report,
506                                     MojoExecution mojoExecution )
507         throws PluginConfigurationException, ArtifactNotFoundException, PluginManagerException,
508         ArtifactResolutionException
509     {
510         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
511
512         PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
513
514         PlexusContainer pluginContainer = getPluginContainer( pluginDescriptor );
515
516         // if this is the first time this plugin has been used, the plugin's container will only
517
// contain the plugin's artifact in isolation; we need to finish resolving the plugin's
518
// dependencies, and add them to the container.
519
ensurePluginContainerIsComplete( pluginDescriptor, pluginContainer, project, session );
520
521         Mojo plugin;
522         try
523         {
524             plugin = (Mojo) pluginContainer.lookup( Mojo.ROLE, mojoDescriptor.getRoleHint() );
525             if ( report && !( plugin instanceof MavenReport ) )
526             {
527                 // TODO: the mojoDescriptor should actually capture this information so we don't get this far
528
return null;
529             }
530         }
531         catch ( ComponentLookupException e )
532         {
533             throw new PluginManagerException( "Unable to find the mojo '" + mojoDescriptor.getRoleHint() +
534                 "' in the plugin '" + pluginDescriptor.getPluginLookupKey() + "'", e );
535         }
536
537         if ( plugin instanceof ContextEnabled )
538         {
539             Map JavaDoc pluginContext = session.getPluginContext( pluginDescriptor, project );
540
541             ( (ContextEnabled) plugin ).setPluginContext( pluginContext );
542         }
543
544         plugin.setLog( mojoLogger );
545
546         XmlPlexusConfiguration pomConfiguration;
547         if ( dom == null )
548         {
549             pomConfiguration = new XmlPlexusConfiguration( "configuration" );
550         }
551         else
552         {
553             pomConfiguration = new XmlPlexusConfiguration( dom );
554         }
555
556         // Validate against non-editable (@readonly) parameters, to make sure users aren't trying to
557
// override in the POM.
558
validatePomConfiguration( mojoDescriptor, pomConfiguration );
559
560         PlexusConfiguration mergedConfiguration = mergeMojoConfiguration( pomConfiguration, mojoDescriptor );
561
562         // TODO: plexus changes to make this more like the component descriptor so this can be used instead
563
// PlexusConfiguration mergedConfiguration = mergeConfiguration( pomConfiguration,
564
// mojoDescriptor.getConfiguration() );
565

566         ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution,
567                                                                                           pathTranslator, getLogger(),
568                                                                                           project,
569                                                                                           session.getExecutionProperties() );
570
571         PlexusConfiguration extractedMojoConfiguration =
572             extractMojoConfiguration( mergedConfiguration, mojoDescriptor );
573
574         checkRequiredParameters( mojoDescriptor, extractedMojoConfiguration, expressionEvaluator );
575
576         populatePluginFields( plugin, mojoDescriptor, extractedMojoConfiguration, pluginContainer,
577                               expressionEvaluator );
578         return plugin;
579     }
580
581     private void ensurePluginContainerIsComplete( PluginDescriptor pluginDescriptor, PlexusContainer pluginContainer,
582                                                   MavenProject project, MavenSession session )
583         throws ArtifactNotFoundException, PluginManagerException, ArtifactResolutionException
584     {
585         // if the plugin's already been used once, don't re-do this step...
586
// otherwise, we have to finish resolving the plugin's classpath and start the container.
587
if ( pluginDescriptor.getArtifacts() != null && pluginDescriptor.getArtifacts().size() == 1 )
588         {
589             Artifact pluginArtifact = (Artifact) pluginDescriptor.getArtifacts().get( 0 );
590
591             ArtifactRepository localRepository = session.getLocalRepository();
592
593             ResolutionGroup resolutionGroup;
594             try
595             {
596                 resolutionGroup = artifactMetadataSource.retrieve( pluginArtifact, localRepository,
597                                                                    project.getPluginArtifactRepositories() );
598             }
599             catch ( ArtifactMetadataRetrievalException e )
600             {
601                 throw new ArtifactResolutionException( "Unable to download metadata from repository for plugin '" +
602                     pluginArtifact.getId() + "': " + e.getMessage(), pluginArtifact, e );
603             }
604
605             Set JavaDoc dependencies = new HashSet JavaDoc( resolutionGroup.getArtifacts() );
606             dependencies.addAll( pluginDescriptor.getIntroducedDependencyArtifacts() );
607
608             ArtifactResolutionResult result = artifactResolver.resolveTransitively( dependencies, pluginArtifact,
609                                                                                     localRepository,
610                                                                                     resolutionGroup.getResolutionRepositories(),
611                                                                                     artifactMetadataSource,
612                                                                                     artifactFilter );
613
614             Set JavaDoc resolved = result.getArtifacts();
615
616             for ( Iterator JavaDoc it = resolved.iterator(); it.hasNext(); )
617             {
618                 Artifact artifact = (Artifact) it.next();
619
620                 if ( !artifact.equals( pluginArtifact ) )
621                 {
622                     artifact = project.replaceWithActiveArtifact( artifact );
623
624                     try
625                     {
626                         pluginContainer.addJarResource( artifact.getFile() );
627                     }
628                     catch ( PlexusContainerException e )
629                     {
630                         throw new PluginManagerException( "Error adding plugin dependency '" +
631                             artifact.getDependencyConflictId() + "' into plugin manager: " + e.getMessage(), e );
632                     }
633                 }
634             }
635
636             pluginDescriptor.setClassRealm( pluginContainer.getContainerRealm() );
637
638             List JavaDoc unresolved = new ArrayList JavaDoc( dependencies );
639
640             unresolved.removeAll( resolved );
641
642             resolveCoreArtifacts( unresolved, localRepository, resolutionGroup.getResolutionRepositories() );
643
644             List JavaDoc allResolved = new ArrayList JavaDoc( resolved.size() + unresolved.size() );
645
646             allResolved.addAll( resolved );
647             allResolved.addAll( unresolved );
648
649             pluginDescriptor.setArtifacts( allResolved );
650         }
651     }
652
653     private void resolveCoreArtifacts( List JavaDoc unresolved, ArtifactRepository localRepository,
654                                        List JavaDoc resolutionRepositories )
655         throws ArtifactResolutionException, ArtifactNotFoundException
656     {
657         for ( Iterator JavaDoc it = unresolved.iterator(); it.hasNext(); )
658         {
659             Artifact artifact = (Artifact) it.next();
660
661             File JavaDoc artifactFile = (File JavaDoc) resolvedCoreArtifactFiles.get( artifact.getId() );
662
663             if ( artifactFile == null )
664             {
665                 String JavaDoc resource =
666                     "/META-INF/maven/" + artifact.getGroupId() + "/" + artifact.getArtifactId() + "/pom.xml";
667
668                 URL JavaDoc resourceUrl = container.getContainerRealm().getResource( resource );
669
670                 if ( resourceUrl == null )
671                 {
672                     artifactResolver.resolve( artifact, resolutionRepositories, localRepository );
673
674                     artifactFile = artifact.getFile();
675                 }
676                 else
677                 {
678                     String JavaDoc artifactPath = resourceUrl.getPath();
679
680                     if ( artifactPath.startsWith( "file:" ) )
681                     {
682                         artifactPath = artifactPath.substring( "file:".length() );
683                     }
684
685                     artifactPath = artifactPath.substring( 0, artifactPath.length() - resource.length() );
686
687                     if ( artifactPath.endsWith( "/" ) )
688                     {
689                         artifactPath = artifactPath.substring( 0, artifactPath.length() - 1 );
690                     }
691
692                     if ( artifactPath.endsWith( "!" ) )
693                     {
694                         artifactPath = artifactPath.substring( 0, artifactPath.length() - 1 );
695                     }
696
697                     artifactFile = new File JavaDoc( artifactPath ).getAbsoluteFile();
698                 }
699
700                 resolvedCoreArtifactFiles.put( artifact.getId(), artifactFile );
701             }
702
703             artifact.setFile( artifactFile );
704         }
705     }
706
707     private PlexusConfiguration extractMojoConfiguration( PlexusConfiguration mergedConfiguration,
708                                                           MojoDescriptor mojoDescriptor )
709     {
710         Map JavaDoc parameterMap = mojoDescriptor.getParameterMap();
711
712         PlexusConfiguration[] mergedChildren = mergedConfiguration.getChildren();
713
714         XmlPlexusConfiguration extractedConfiguration = new XmlPlexusConfiguration( "configuration" );
715
716         for ( int i = 0; i < mergedChildren.length; i++ )
717         {
718             PlexusConfiguration child = mergedChildren[i];
719
720             if ( parameterMap.containsKey( child.getName() ) )
721             {
722                 extractedConfiguration.addChild( copyConfiguration( child ) );
723             }
724             else
725             {
726                 // TODO: I defy anyone to find these messages in the '-X' output! Do we need a new log level?
727
// ideally, this would be elevated above the true debug output, but below the default INFO level...
728
// [BP] (2004-07-18): need to understand the context more but would prefer this could be either WARN or
729
// removed - shouldn't need DEBUG to diagnose a problem most of the time.
730
getLogger().debug( "*** WARNING: Configuration \'" + child.getName() + "\' is not used in goal \'" +
731                     mojoDescriptor.getFullGoalName() + "; this may indicate a typo... ***" );
732             }
733         }
734
735         return extractedConfiguration;
736     }
737
738     private void checkRequiredParameters( MojoDescriptor goal, PlexusConfiguration configuration,
739                                           ExpressionEvaluator expressionEvaluator )
740         throws PluginConfigurationException
741     {
742         // TODO: this should be built in to the configurator, as we presently double process the expressions
743

744         List JavaDoc parameters = goal.getParameters();
745
746         if ( parameters == null )
747         {
748             return;
749         }
750
751         List JavaDoc invalidParameters = new ArrayList JavaDoc();
752
753         for ( int i = 0; i < parameters.size(); i++ )
754         {
755             Parameter parameter = (Parameter) parameters.get( i );
756
757             if ( parameter.isRequired() )
758             {
759                 // the key for the configuration map we're building.
760
String JavaDoc key = parameter.getName();
761
762                 Object JavaDoc fieldValue = null;
763                 String JavaDoc expression = null;
764                 PlexusConfiguration value = configuration.getChild( key, false );
765                 try
766                 {
767                     if ( value != null )
768                     {
769                         expression = value.getValue( null );
770
771                         fieldValue = expressionEvaluator.evaluate( expression );
772
773                         if ( fieldValue == null )
774                         {
775                             fieldValue = value.getAttribute( "default-value", null );
776                         }
777                     }
778
779                     if ( fieldValue == null && StringUtils.isNotEmpty( parameter.getAlias() ) )
780                     {
781                         value = configuration.getChild( parameter.getAlias(), false );
782                         if ( value != null )
783                         {
784                             expression = value.getValue( null );
785                             fieldValue = expressionEvaluator.evaluate( expression );
786                             if ( fieldValue == null )
787                             {
788                                 fieldValue = value.getAttribute( "default-value", null );
789                             }
790                         }
791                     }
792                 }
793                 catch ( ExpressionEvaluationException e )
794                 {
795                     throw new PluginConfigurationException( goal.getPluginDescriptor(), e.getMessage(), e );
796                 }
797
798                 // only mark as invalid if there are no child nodes
799
if ( fieldValue == null && ( value == null || value.getChildCount() == 0 ) )
800                 {
801                     parameter.setExpression( expression );
802                     invalidParameters.add( parameter );
803                 }
804             }
805         }
806
807         if ( !invalidParameters.isEmpty() )
808         {
809             throw new PluginParameterException( goal, invalidParameters );
810         }
811     }
812
813     private void validatePomConfiguration( MojoDescriptor goal, PlexusConfiguration pomConfiguration )
814         throws PluginConfigurationException
815     {
816         List JavaDoc parameters = goal.getParameters();
817
818         if ( parameters == null )
819         {
820             return;
821         }
822
823         for ( int i = 0; i < parameters.size(); i++ )
824         {
825             Parameter parameter = (Parameter) parameters.get( i );
826
827             // the key for the configuration map we're building.
828
String JavaDoc key = parameter.getName();
829
830             PlexusConfiguration value = pomConfiguration.getChild( key, false );
831
832             if ( value == null && StringUtils.isNotEmpty( parameter.getAlias() ) )
833             {
834                 key = parameter.getAlias();
835                 value = pomConfiguration.getChild( key, false );
836             }
837
838             if ( value != null )
839             {
840                 // Make sure the parameter is either editable/configurable, or else is NOT specified in the POM
841
if ( !parameter.isEditable() )
842                 {
843                     StringBuffer JavaDoc errorMessage = new StringBuffer JavaDoc()
844                         .append( "ERROR: Cannot override read-only parameter: " );
845                     errorMessage.append( key );
846                     errorMessage.append( " in goal: " ).append( goal.getFullGoalName() );
847
848                     throw new PluginConfigurationException( goal.getPluginDescriptor(), errorMessage.toString() );
849                 }
850
851                 String JavaDoc deprecated = parameter.getDeprecated();
852                 if ( StringUtils.isNotEmpty( deprecated ) )
853                 {
854                     getLogger().warn( "DEPRECATED [" + parameter.getName() + "]: " + deprecated );
855                 }
856             }
857         }
858     }
859
860     private PlexusConfiguration mergeMojoConfiguration( XmlPlexusConfiguration fromPom, MojoDescriptor mojoDescriptor )
861     {
862         XmlPlexusConfiguration result = new XmlPlexusConfiguration( fromPom.getName() );
863         result.setValue( fromPom.getValue( null ) );
864
865         if ( mojoDescriptor.getParameters() != null )
866         {
867             PlexusConfiguration fromMojo = mojoDescriptor.getMojoConfiguration();
868
869             for ( Iterator JavaDoc it = mojoDescriptor.getParameters().iterator(); it.hasNext(); )
870             {
871                 Parameter parameter = (Parameter) it.next();
872
873                 String JavaDoc paramName = parameter.getName();
874                 String JavaDoc alias = parameter.getAlias();
875
876                 PlexusConfiguration pomConfig = fromPom.getChild( paramName );
877                 PlexusConfiguration aliased = null;
878
879                 if ( alias != null )
880                 {
881                     aliased = fromPom.getChild( alias );
882                 }
883
884                 PlexusConfiguration mojoConfig = fromMojo.getChild( paramName, false );
885
886                 // first we'll merge configurations from the aliased and real params.
887
// TODO: Is this the right thing to do?
888
if ( aliased != null )
889                 {
890                     if ( pomConfig == null )
891                     {
892                         pomConfig = new XmlPlexusConfiguration( paramName );
893                     }
894
895                     pomConfig = buildTopDownMergedConfiguration( pomConfig, aliased );
896                 }
897
898                 boolean addedPomConfig = false;
899
900                 if ( pomConfig != null )
901                 {
902                     pomConfig = buildTopDownMergedConfiguration( pomConfig, mojoConfig );
903
904                     if ( StringUtils.isNotEmpty( pomConfig.getValue( null ) ) || pomConfig.getChildCount() > 0 )
905                     {
906                         result.addChild( pomConfig );
907
908                         addedPomConfig = true;
909                     }
910                 }
911
912                 if ( !addedPomConfig && mojoConfig != null )
913                 {
914                     result.addChild( copyConfiguration( mojoConfig ) );
915                 }
916             }
917         }
918         return result;
919     }
920
921     private XmlPlexusConfiguration buildTopDownMergedConfiguration( PlexusConfiguration dominant,
922                                                                     PlexusConfiguration recessive )
923     {
924         XmlPlexusConfiguration result = new XmlPlexusConfiguration( dominant.getName() );
925
926         String JavaDoc value = dominant.getValue( null );
927
928         if ( StringUtils.isEmpty( value ) && recessive != null )
929         {
930             value = recessive.getValue( null );
931         }
932
933         if ( StringUtils.isNotEmpty( value ) )
934         {
935             result.setValue( value );
936         }
937
938         String JavaDoc[] attributeNames = dominant.getAttributeNames();
939
940         for ( int i = 0; i < attributeNames.length; i++ )
941         {
942             String JavaDoc attributeValue = dominant.getAttribute( attributeNames[i], null );
943
944             result.setAttribute( attributeNames[i], attributeValue );
945         }
946
947         if ( recessive != null )
948         {
949             attributeNames = recessive.getAttributeNames();
950
951             for ( int i = 0; i < attributeNames.length; i++ )
952             {
953                 String JavaDoc attributeValue = recessive.getAttribute( attributeNames[i], null );
954                 // TODO: recessive seems to be dominant here?
955
result.setAttribute( attributeNames[i], attributeValue );
956             }
957         }
958
959         PlexusConfiguration[] children = dominant.getChildren();
960
961         for ( int i = 0; i < children.length; i++ )
962         {
963             PlexusConfiguration childDom = children[i];
964             PlexusConfiguration childRec = recessive == null ? null : recessive.getChild( childDom.getName(), false );
965
966             if ( childRec != null )
967             {
968                 result.addChild( buildTopDownMergedConfiguration( childDom, childRec ) );
969             }
970             else
971             { // FIXME: copy, or use reference?
972
result.addChild( copyConfiguration( childDom ) );
973             }
974         }
975
976         return result;
977     }
978
979     public static PlexusConfiguration copyConfiguration( PlexusConfiguration src )
980     {
981         // TODO: shouldn't be necessary
982
XmlPlexusConfiguration dom = new XmlPlexusConfiguration( src.getName() );
983         dom.setValue( src.getValue( null ) );
984
985         String JavaDoc[] attributeNames = src.getAttributeNames();
986         for ( int i = 0; i < attributeNames.length; i++ )
987         {
988             String JavaDoc attributeName = attributeNames[i];
989             dom.setAttribute( attributeName, src.getAttribute( attributeName, null ) );
990         }
991
992         PlexusConfiguration[] children = src.getChildren();
993         for ( int i = 0; i < children.length; i++ )
994         {
995             dom.addChild( copyConfiguration( children[i] ) );
996         }
997
998         return dom;
999     }
1000
1001    // ----------------------------------------------------------------------
1002
// Mojo Parameter Handling
1003
// ----------------------------------------------------------------------
1004

1005    private void populatePluginFields( Mojo plugin, MojoDescriptor mojoDescriptor, PlexusConfiguration configuration,
1006                                       PlexusContainer pluginContainer, ExpressionEvaluator expressionEvaluator )
1007        throws PluginConfigurationException
1008    {
1009        ComponentConfigurator configurator = null;
1010
1011        try
1012        {
1013            String JavaDoc configuratorId = mojoDescriptor.getComponentConfigurator();
1014
1015            // TODO: could the configuration be passed to lookup and the configurator known to plexus via the descriptor
1016
// so that this meethod could entirely be handled by a plexus lookup?
1017
if ( StringUtils.isNotEmpty( configuratorId ) )
1018            {
1019                configurator =
1020                    (ComponentConfigurator) pluginContainer.lookup( ComponentConfigurator.ROLE, configuratorId );
1021            }
1022            else
1023            {
1024                configurator = (ComponentConfigurator) pluginContainer.lookup( ComponentConfigurator.ROLE );
1025            }
1026
1027            ConfigurationListener listener = new DebugConfigurationListener( getLogger() );
1028
1029            getLogger().debug( "Configuring mojo '" + mojoDescriptor.getId() + "' -->" );
1030            configurator.configureComponent( plugin, configuration, expressionEvaluator,
1031                                             pluginContainer.getContainerRealm(), listener );
1032            getLogger().debug( "-- end configuration --" );
1033        }
1034        catch ( ComponentConfigurationException e )
1035        {
1036            throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(),
1037                                                    "Unable to parse the created DOM for plugin configuration", e );
1038        }
1039        catch ( ComponentLookupException e )
1040        {
1041            throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(),
1042                                                    "Unable to retrieve component configurator for plugin configuration",
1043                                                    e );
1044        }
1045        finally
1046        {
1047            if ( configurator != null )
1048            {
1049                try
1050                {
1051                    pluginContainer.release( configurator );
1052                }
1053                catch ( ComponentLifecycleException e )
1054                {
1055                    getLogger().debug( "Failed to release plugin container - ignoring." );
1056                }
1057            }
1058        }
1059    }
1060
1061    public static String JavaDoc createPluginParameterRequiredMessage( MojoDescriptor mojo, Parameter parameter,
1062                                                               String JavaDoc expression )
1063    {
1064        StringBuffer JavaDoc message = new StringBuffer JavaDoc();
1065
1066        message.append( "The '" );
1067        message.append( parameter.getName() );
1068        message.append( "' parameter is required for the execution of the " );
1069        message.append( mojo.getFullGoalName() );
1070        message.append( " mojo and cannot be null." );
1071        if ( expression != null )
1072        {
1073            message.append( " The retrieval expression was: " ).append( expression );
1074        }
1075
1076        return message.toString();
1077    }
1078
1079    // ----------------------------------------------------------------------
1080
// Lifecycle
1081
// ----------------------------------------------------------------------
1082

1083    public void contextualize( Context context )
1084        throws ContextException
1085    {
1086        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
1087
1088        mojoLogger = new DefaultLog( container.getLoggerManager().getLoggerForComponent( Mojo.ROLE ) );
1089    }
1090
1091    public void initialize()
1092    {
1093        artifactFilter = MavenArtifactFilterManager.createStandardFilter();
1094    }
1095
1096    // ----------------------------------------------------------------------
1097
// Artifact resolution
1098
// ----------------------------------------------------------------------
1099

1100    private void resolveTransitiveDependencies( MavenSession context, ArtifactResolver artifactResolver, String JavaDoc scope,
1101                                                ArtifactFactory artifactFactory, MavenProject project )
1102        throws ArtifactResolutionException, ArtifactNotFoundException, InvalidDependencyVersionException
1103    {
1104        ArtifactFilter filter = new ScopeArtifactFilter( scope );
1105
1106        // TODO: such a call in MavenMetadataSource too - packaging not really the intention of type
1107
Artifact artifact = artifactFactory.createBuildArtifact( project.getGroupId(), project.getArtifactId(),
1108                                                                 project.getVersion(), project.getPackaging() );
1109
1110        // TODO: we don't need to resolve over and over again, as long as we are sure that the parameters are the same
1111
// check this with yourkit as a hot spot.
1112
// Don't recreate if already created - for effeciency, and because clover plugin adds to it
1113
if ( project.getDependencyArtifacts() == null )
1114        {
1115            project.setDependencyArtifacts( project.createArtifacts( artifactFactory, null, null ) );
1116        }
1117        ArtifactResolutionResult result = artifactResolver.resolveTransitively( project.getDependencyArtifacts(),
1118                                                                                artifact, context.getLocalRepository(),
1119                                                                                project.getRemoteArtifactRepositories(),
1120                                                                                artifactMetadataSource, filter );
1121
1122        project.setArtifacts( result.getArtifacts() );
1123    }
1124
1125    // ----------------------------------------------------------------------
1126
// Artifact downloading
1127
// ----------------------------------------------------------------------
1128

1129    private void downloadDependencies( MavenProject project, MavenSession context, ArtifactResolver artifactResolver )
1130        throws ArtifactResolutionException, ArtifactNotFoundException
1131    {
1132        ArtifactRepository localRepository = context.getLocalRepository();
1133        List JavaDoc remoteArtifactRepositories = project.getRemoteArtifactRepositories();
1134
1135        for ( Iterator JavaDoc it = project.getArtifacts().iterator(); it.hasNext(); )
1136        {
1137            Artifact artifact = (Artifact) it.next();
1138
1139            artifactResolver.resolve( artifact, remoteArtifactRepositories, localRepository );
1140        }
1141    }
1142
1143    public Object JavaDoc getPluginComponent( Plugin plugin, String JavaDoc role, String JavaDoc roleHint )
1144        throws PluginManagerException, ComponentLookupException
1145    {
1146        PluginDescriptor pluginDescriptor = pluginCollector.getPluginDescriptor( plugin );
1147
1148        PlexusContainer pluginContainer = getPluginContainer( pluginDescriptor );
1149
1150        return pluginContainer.lookup( role, roleHint );
1151    }
1152
1153    public Map JavaDoc getPluginComponents( Plugin plugin, String JavaDoc role )
1154        throws ComponentLookupException, PluginManagerException
1155    {
1156        PluginDescriptor pluginDescriptor = pluginCollector.getPluginDescriptor( plugin );
1157
1158        PlexusContainer pluginContainer = getPluginContainer( pluginDescriptor );
1159
1160        return pluginContainer.lookupMap( role );
1161    }
1162
1163}
1164
Popular Tags