Save This Page
Home » maven-2.0.9-src » org.apache » maven » plugin » [javadoc | source]
    1   
    2   package org.apache.maven.plugin;
    3   
    4   /*
    5    * Licensed to the Apache Software Foundation (ASF) under one
    6    * or more contributor license agreements.  See the NOTICE file
    7    * distributed with this work for additional information
    8    * regarding copyright ownership.  The ASF licenses this file
    9    * to you under the Apache License, Version 2.0 (the
   10    * "License"); you may not use this file except in compliance
   11    * with the License.  You may obtain a copy of the License at
   12    *
   13    *  http://www.apache.org/licenses/LICENSE-2.0
   14    *
   15    * Unless required by applicable law or agreed to in writing,
   16    * software distributed under the License is distributed on an
   17    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   18    * KIND, either express or implied.  See the License for the
   19    * specific language governing permissions and limitations
   20    * under the License.
   21    */
   22   
   23   import java.io.File;
   24   import java.net.URL;
   25   import java.util.ArrayList;
   26   import java.util.Collection;
   27   import java.util.Collections;
   28   import java.util.HashMap;
   29   import java.util.HashSet;
   30   import java.util.Iterator;
   31   import java.util.LinkedHashMap;
   32   import java.util.LinkedHashSet;
   33   import java.util.List;
   34   import java.util.Map;
   35   import java.util.Set;
   36   
   37   import org.apache.maven.MavenArtifactFilterManager;
   38   import org.apache.maven.artifact.Artifact;
   39   import org.apache.maven.artifact.factory.ArtifactFactory;
   40   import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
   41   import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
   42   import org.apache.maven.artifact.metadata.ResolutionGroup;
   43   import org.apache.maven.artifact.repository.ArtifactRepository;
   44   import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
   45   import org.apache.maven.artifact.resolver.ArtifactResolutionException;
   46   import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
   47   import org.apache.maven.artifact.resolver.ArtifactResolver;
   48   import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException;
   49   import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
   50   import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
   51   import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
   52   import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
   53   import org.apache.maven.artifact.versioning.VersionRange;
   54   import org.apache.maven.execution.MavenSession;
   55   import org.apache.maven.execution.RuntimeInformation;
   56   import org.apache.maven.model.Plugin;
   57   import org.apache.maven.model.ReportPlugin;
   58   import org.apache.maven.monitor.event.EventDispatcher;
   59   import org.apache.maven.monitor.event.MavenEvents;
   60   import org.apache.maven.monitor.logging.DefaultLog;
   61   import org.apache.maven.plugin.descriptor.MojoDescriptor;
   62   import org.apache.maven.plugin.descriptor.Parameter;
   63   import org.apache.maven.plugin.descriptor.PluginDescriptor;
   64   import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
   65   import org.apache.maven.plugin.logging.Log;
   66   import org.apache.maven.plugin.version.PluginVersionManager;
   67   import org.apache.maven.plugin.version.PluginVersionNotFoundException;
   68   import org.apache.maven.plugin.version.PluginVersionResolutionException;
   69   import org.apache.maven.project.MavenProject;
   70   import org.apache.maven.project.MavenProjectBuilder;
   71   import org.apache.maven.project.ProjectBuildingException;
   72   import org.apache.maven.project.artifact.InvalidDependencyVersionException;
   73   import org.apache.maven.project.artifact.MavenMetadataSource;
   74   import org.apache.maven.project.path.PathTranslator;
   75   import org.apache.maven.reporting.MavenReport;
   76   import org.apache.maven.settings.Settings;
   77   import org.codehaus.classworlds.ClassRealm;
   78   import org.codehaus.classworlds.NoSuchRealmException;
   79   import org.codehaus.plexus.PlexusConstants;
   80   import org.codehaus.plexus.PlexusContainer;
   81   import org.codehaus.plexus.PlexusContainerException;
   82   import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
   83   import org.codehaus.plexus.component.configurator.ComponentConfigurator;
   84   import org.codehaus.plexus.component.configurator.ConfigurationListener;
   85   import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
   86   import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
   87   import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
   88   import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
   89   import org.codehaus.plexus.configuration.PlexusConfiguration;
   90   import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
   91   import org.codehaus.plexus.context.Context;
   92   import org.codehaus.plexus.context.ContextException;
   93   import org.codehaus.plexus.logging.AbstractLogEnabled;
   94   import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
   95   import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
   96   import org.codehaus.plexus.util.StringUtils;
   97   import org.codehaus.plexus.util.xml.Xpp3Dom;
   98   
   99   public class DefaultPluginManager
  100       extends AbstractLogEnabled
  101       implements PluginManager, Initializable, Contextualizable
  102   {
  103       protected PlexusContainer container;
  104   
  105       protected PluginDescriptorBuilder pluginDescriptorBuilder;
  106   
  107       protected ArtifactFilter artifactFilter;
  108   
  109       private Log mojoLogger;
  110   
  111       private Map resolvedCoreArtifactFiles = new HashMap();
  112   
  113       // component requirements
  114       protected PathTranslator pathTranslator;
  115   
  116       protected MavenPluginCollector pluginCollector;
  117   
  118       protected PluginVersionManager pluginVersionManager;
  119   
  120       protected ArtifactFactory artifactFactory;
  121   
  122       protected ArtifactResolver artifactResolver;
  123   
  124       protected ArtifactMetadataSource artifactMetadataSource;
  125   
  126       protected RuntimeInformation runtimeInformation;
  127   
  128       protected MavenProjectBuilder mavenProjectBuilder;
  129   
  130       protected PluginMappingManager pluginMappingManager;
  131   
  132       // END component requirements
  133   
  134       public DefaultPluginManager()
  135       {
  136           pluginDescriptorBuilder = new PluginDescriptorBuilder();
  137       }
  138   
  139       // ----------------------------------------------------------------------
  140       //
  141       // ----------------------------------------------------------------------
  142   
  143       public PluginDescriptor getPluginDescriptorForPrefix( String prefix )
  144       {
  145           return pluginCollector.getPluginDescriptorForPrefix( prefix );
  146       }
  147   
  148       public Plugin getPluginDefinitionForPrefix( String prefix,
  149                                                   MavenSession session,
  150                                                   MavenProject project )
  151       {
  152           // TODO: since this is only used in the lifecycle executor, maybe it should be moved there? There is no other
  153           // use for the mapping manager in here
  154           return pluginMappingManager.getByPrefix( prefix, session.getSettings().getPluginGroups(),
  155                                                    project.getPluginArtifactRepositories(),
  156                                                    session.getLocalRepository() );
  157       }
  158   
  159       public PluginDescriptor verifyPlugin( Plugin plugin,
  160                                             MavenProject project,
  161                                             Settings settings,
  162                                             ArtifactRepository localRepository )
  163           throws ArtifactResolutionException, PluginVersionResolutionException, ArtifactNotFoundException,
  164           InvalidVersionSpecificationException, InvalidPluginException, PluginManagerException, PluginNotFoundException,
  165           PluginVersionNotFoundException
  166       {
  167           // TODO: this should be possibly outside
  168           // All version-resolution logic has been moved to DefaultPluginVersionManager.
  169           if ( plugin.getVersion() == null )
  170           {
  171               String version = pluginVersionManager.resolvePluginVersion( plugin.getGroupId(), plugin.getArtifactId(),
  172                                                                           project, settings, localRepository );
  173               plugin.setVersion( version );
  174           }
  175   
  176           return verifyVersionedPlugin( plugin, project, localRepository );
  177       }
  178   
  179       private PluginDescriptor verifyVersionedPlugin( Plugin plugin,
  180                                                       MavenProject project,
  181                                                       ArtifactRepository localRepository )
  182           throws PluginVersionResolutionException, ArtifactNotFoundException, ArtifactResolutionException,
  183           InvalidVersionSpecificationException, InvalidPluginException, PluginManagerException, PluginNotFoundException
  184       {
  185           // TODO: this might result in an artifact "RELEASE" being resolved continuously
  186           // FIXME: need to find out how a plugin gets marked as 'installed'
  187           // and no ChildContainer exists. The check for that below fixes
  188           // the 'Can't find plexus container for plugin: xxx' error.
  189           try
  190           {
  191               VersionRange versionRange = VersionRange.createFromVersionSpec( plugin.getVersion() );
  192   
  193               List remoteRepositories = new ArrayList();
  194               remoteRepositories.addAll( project.getPluginArtifactRepositories() );
  195               remoteRepositories.addAll( project.getRemoteArtifactRepositories() );
  196   
  197               checkRequiredMavenVersion( plugin, localRepository, remoteRepositories );
  198   
  199               Artifact pluginArtifact =
  200                   artifactFactory.createPluginArtifact( plugin.getGroupId(), plugin.getArtifactId(), versionRange );
  201   
  202               pluginArtifact = project.replaceWithActiveArtifact( pluginArtifact );
  203   
  204               artifactResolver.resolve( pluginArtifact, project.getPluginArtifactRepositories(), localRepository );
  205   
  206               PlexusContainer pluginContainer = container.getChildContainer( plugin.getKey() );
  207   
  208               File pluginFile = pluginArtifact.getFile();
  209   
  210               if ( !pluginCollector.isPluginInstalled( plugin ) || ( pluginContainer == null ) )
  211               {
  212                   addPlugin( plugin, pluginArtifact, project, localRepository );
  213               }
  214               else if ( pluginFile.lastModified() > pluginContainer.getCreationDate().getTime() )
  215               {
  216                   getLogger().info(
  217                       "Reloading plugin container for: " + plugin.getKey() + ". The plugin artifact has changed." );
  218   
  219                   pluginContainer.dispose();
  220   
  221                   pluginCollector.flushPluginDescriptor( plugin );
  222   
  223                   addPlugin( plugin, pluginArtifact, project, localRepository );
  224               }
  225   
  226               project.addPlugin( plugin );
  227           }
  228           catch ( ArtifactNotFoundException e )
  229           {
  230               String groupId = plugin.getGroupId();
  231               String artifactId = plugin.getArtifactId();
  232               String version = plugin.getVersion();
  233   
  234               if ( ( groupId == null ) || ( artifactId == null ) || ( version == null ) )
  235               {
  236                   throw new PluginNotFoundException( e );
  237               }
  238               else if ( groupId.equals( e.getGroupId() ) && artifactId.equals( e.getArtifactId() ) &&
  239                   version.equals( e.getVersion() ) && "maven-plugin".equals( e.getType() ) )
  240               {
  241                   throw new PluginNotFoundException( e );
  242               }
  243               else
  244               {
  245                   throw e;
  246               }
  247           }
  248   
  249           return pluginCollector.getPluginDescriptor( plugin );
  250       }
  251   
  252       /**
  253        * @todo would be better to store this in the plugin descriptor, but then it won't be available to the version
  254        * manager which executes before the plugin is instantiated
  255        */
  256       private void checkRequiredMavenVersion( Plugin plugin,
  257                                               ArtifactRepository localRepository,
  258                                               List remoteRepositories )
  259           throws PluginVersionResolutionException, InvalidPluginException
  260       {
  261           try
  262           {
  263               Artifact artifact = artifactFactory.createProjectArtifact( plugin.getGroupId(), plugin.getArtifactId(),
  264                                                                          plugin.getVersion() );
  265               MavenProject project =
  266                   mavenProjectBuilder.buildFromRepository( artifact, remoteRepositories, localRepository, false );
  267               // if we don't have the required Maven version, then ignore an update
  268               if ( ( project.getPrerequisites() != null ) && ( project.getPrerequisites().getMaven() != null ) )
  269               {
  270                   DefaultArtifactVersion requiredVersion =
  271                       new DefaultArtifactVersion( project.getPrerequisites().getMaven() );
  272                   if ( runtimeInformation.getApplicationVersion().compareTo( requiredVersion ) < 0 )
  273                   {
  274                       throw new PluginVersionResolutionException( plugin.getGroupId(), plugin.getArtifactId(),
  275                                                                   "Plugin requires Maven version " + requiredVersion );
  276                   }
  277               }
  278           }
  279           catch ( ProjectBuildingException e )
  280           {
  281               throw new InvalidPluginException(
  282                   "Unable to build project for plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
  283           }
  284       }
  285   
  286       protected void addPlugin( Plugin plugin,
  287                                 Artifact pluginArtifact,
  288                                 MavenProject project,
  289                                 ArtifactRepository localRepository )
  290           throws PluginManagerException, InvalidPluginException
  291       {
  292           PlexusContainer child;
  293   
  294           try
  295           {
  296               child = container.createChildContainer( plugin.getKey(),
  297                                                       Collections.singletonList( pluginArtifact.getFile() ),
  298                                                       Collections.EMPTY_MAP,
  299                                                       Collections.singletonList( pluginCollector ) );
  300               try
  301               {
  302                   child.getContainerRealm().importFrom( "plexus.core", "org.codehaus.plexus.util.xml.Xpp3Dom" );
  303                   child.getContainerRealm().importFrom( "plexus.core", "org.codehaus.plexus.util.xml.pull" );
  304   
  305                   // MNG-2878
  306                   child.getContainerRealm().importFrom( "plexus.core", "/default-report.xml" );
  307               }
  308               catch ( NoSuchRealmException e )
  309               {
  310                   // won't happen
  311               }
  312           }
  313           catch ( PlexusContainerException e )
  314           {
  315               throw new PluginManagerException(
  316                   "Failed to create plugin container for plugin '" + plugin + "': " + e.getMessage(), e );
  317           }
  318   
  319           // this plugin's descriptor should have been discovered in the child creation, so we should be able to
  320           // circle around and set the artifacts and class realm
  321           PluginDescriptor addedPlugin = pluginCollector.getPluginDescriptor( plugin );
  322   
  323           if ( addedPlugin == null )
  324           {
  325               throw new IllegalStateException( "The PluginDescriptor for the plugin " + plugin + " was not found." );
  326           }
  327   
  328           addedPlugin.setClassRealm( child.getContainerRealm() );
  329   
  330           // we're only setting the plugin's artifact itself as the artifact list, to allow it to be retrieved
  331           // later when the plugin is first invoked. Retrieving this artifact will in turn allow us to
  332           // transitively resolve its dependencies, and add them to the plugin container...
  333           addedPlugin.setArtifacts( Collections.singletonList( pluginArtifact ) );
  334   
  335           try
  336           {
  337               // the only Plugin instance which will have dependencies is the one specified in the project.
  338               // We need to look for a Plugin instance there, in case the instance we're using didn't come from
  339               // the project.
  340               Plugin projectPlugin = (Plugin) project.getBuild().getPluginsAsMap().get( plugin.getKey() );
  341   
  342               if ( projectPlugin == null )
  343               {
  344                   projectPlugin = plugin;
  345               }
  346   
  347               Set artifacts = MavenMetadataSource.createArtifacts( artifactFactory, projectPlugin.getDependencies(), null,
  348                                                                    null, project );
  349   
  350   //            Set artifacts =
  351   //                MavenMetadataSource.createArtifacts( artifactFactory, plugin.getDependencies(), null, null, project );
  352   
  353               addedPlugin.setIntroducedDependencyArtifacts( artifacts );
  354           }
  355           catch ( InvalidDependencyVersionException e )
  356           {
  357               throw new InvalidPluginException( "Plugin '" + plugin + "' is invalid: " + e.getMessage(), e );
  358           }
  359       }
  360   
  361       // ----------------------------------------------------------------------
  362       // Mojo execution
  363       // ----------------------------------------------------------------------
  364   
  365       public void executeMojo( MavenProject project,
  366                                MojoExecution mojoExecution,
  367                                MavenSession session )
  368           throws ArtifactResolutionException, MojoExecutionException, MojoFailureException, ArtifactNotFoundException,
  369           InvalidDependencyVersionException, PluginManagerException, PluginConfigurationException
  370       {
  371           MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
  372   
  373           // NOTE: I'm putting these checks in here, since this is the central point of access for
  374           // anything that wants to execute a mojo.
  375           if ( mojoDescriptor.isProjectRequired() && !session.isUsingPOMsFromFilesystem() )
  376           {
  377               throw new MojoExecutionException( "Cannot execute mojo: " + mojoDescriptor.getGoal() +
  378                   ". It requires a project with an existing pom.xml, but the build is not using one." );
  379           }
  380   
  381           if ( mojoDescriptor.isOnlineRequired() && session.getSettings().isOffline() )
  382           {
  383               // TODO: Should we error out, or simply warn and skip??
  384               throw new MojoExecutionException( "Mojo: " + mojoDescriptor.getGoal() +
  385                   " requires online mode for execution. Maven is currently offline." );
  386           }
  387   
  388           if ( mojoDescriptor.isDependencyResolutionRequired() != null )
  389           {
  390               Collection projects;
  391   
  392               if ( mojoDescriptor.isAggregator() )
  393               {
  394                   projects = session.getSortedProjects();
  395               }
  396               else
  397               {
  398                   projects = Collections.singleton( project );
  399               }
  400   
  401               for ( Iterator i = projects.iterator(); i.hasNext(); )
  402               {
  403                   MavenProject p = (MavenProject) i.next();
  404   
  405                   resolveTransitiveDependencies( session, artifactResolver,
  406                                                  mojoDescriptor.isDependencyResolutionRequired(), artifactFactory, p, mojoDescriptor.isAggregator() );
  407               }
  408   
  409               downloadDependencies( project, session, artifactResolver );
  410           }
  411   
  412           String goalName = mojoDescriptor.getFullGoalName();
  413   
  414           Mojo plugin;
  415   
  416           PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
  417           String goalId = mojoDescriptor.getGoal();
  418           String groupId = pluginDescriptor.getGroupId();
  419           String artifactId = pluginDescriptor.getArtifactId();
  420           String executionId = mojoExecution.getExecutionId();
  421           Xpp3Dom dom = project.getGoalConfiguration( groupId, artifactId, executionId, goalId );
  422           Xpp3Dom reportDom = project.getReportConfiguration( groupId, artifactId, executionId );
  423           dom = Xpp3Dom.mergeXpp3Dom( dom, reportDom );
  424           if ( mojoExecution.getConfiguration() != null )
  425           {
  426               dom = Xpp3Dom.mergeXpp3Dom( dom, mojoExecution.getConfiguration() );
  427           }
  428   
  429           plugin = getConfiguredMojo( session, dom, project, false, mojoExecution );
  430   
  431           // Event monitoring.
  432           String event = MavenEvents.MOJO_EXECUTION;
  433           EventDispatcher dispatcher = session.getEventDispatcher();
  434   
  435           String goalExecId = goalName;
  436   
  437           if ( mojoExecution.getExecutionId() != null )
  438           {
  439               goalExecId += " {execution: " + mojoExecution.getExecutionId() + "}";
  440           }
  441   
  442           dispatcher.dispatchStart( event, goalExecId );
  443   
  444           ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
  445   
  446           try
  447           {
  448               Thread.currentThread().setContextClassLoader(
  449                   mojoDescriptor.getPluginDescriptor().getClassRealm().getClassLoader() );
  450   
  451               plugin.execute();
  452   
  453               dispatcher.dispatchEnd( event, goalExecId );
  454           }
  455           catch ( MojoExecutionException e )
  456           {
  457               session.getEventDispatcher().dispatchError( event, goalExecId, e );
  458   
  459               throw e;
  460           }
  461           catch ( MojoFailureException e )
  462           {
  463               session.getEventDispatcher().dispatchError( event, goalExecId, e );
  464   
  465               throw e;
  466           }
  467           catch ( LinkageError e )
  468           {
  469               if ( getLogger().isFatalErrorEnabled() )
  470               {
  471                   getLogger().fatalError(
  472                                           plugin.getClass().getName() + "#execute() caused a linkage error ("
  473                                               + e.getClass().getName() + ") and may be out-of-date. Check the realms:" );
  474   
  475                   ClassRealm pluginRealm = mojoDescriptor.getPluginDescriptor().getClassRealm();
  476                   StringBuffer sb = new StringBuffer();
  477                   sb.append( "Plugin realm = " + pluginRealm.getId() ).append( '\n' );
  478                   for ( int i = 0; i < pluginRealm.getConstituents().length; i++ )
  479                   {
  480                       sb.append( "urls[" + i + "] = " + pluginRealm.getConstituents()[i] );
  481                       if ( i != ( pluginRealm.getConstituents().length - 1 ) )
  482                       {
  483                           sb.append( '\n' );
  484                       }
  485                   }
  486                   getLogger().fatalError( sb.toString() );
  487   
  488                   ClassRealm containerRealm = container.getContainerRealm();
  489                   sb = new StringBuffer();
  490                   sb.append( "Container realm = " + containerRealm.getId() ).append( '\n' );
  491                   for ( int i = 0; i < containerRealm.getConstituents().length; i++ )
  492                   {
  493                       sb.append( "urls[" + i + "] = " + containerRealm.getConstituents()[i] );
  494                       if ( i != ( containerRealm.getConstituents().length - 1 ) )
  495                       {
  496                           sb.append( '\n' );
  497                       }
  498                   }
  499                   getLogger().fatalError( sb.toString() );
  500               }
  501   
  502               session.getEventDispatcher().dispatchError( event, goalExecId, e );
  503   
  504               throw e;
  505           }
  506           finally
  507           {
  508   
  509               Thread.currentThread().setContextClassLoader( oldClassLoader );
  510   
  511               try
  512               {
  513                   PlexusContainer pluginContainer = getPluginContainer( mojoDescriptor.getPluginDescriptor() );
  514   
  515                   pluginContainer.release( plugin );
  516               }
  517               catch ( ComponentLifecycleException e )
  518               {
  519                   if ( getLogger().isErrorEnabled() )
  520                   {
  521                       getLogger().error( "Error releasing plugin - ignoring.", e );
  522                   }
  523               }
  524           }
  525       }
  526   
  527       public MavenReport getReport( MavenProject project,
  528                                     MojoExecution mojoExecution,
  529                                     MavenSession session )
  530           throws ArtifactNotFoundException, PluginConfigurationException, PluginManagerException,
  531           ArtifactResolutionException
  532       {
  533           MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
  534           PluginDescriptor descriptor = mojoDescriptor.getPluginDescriptor();
  535           Xpp3Dom dom = project.getReportConfiguration( descriptor.getGroupId(), descriptor.getArtifactId(),
  536                                                         mojoExecution.getExecutionId() );
  537           if ( mojoExecution.getConfiguration() != null )
  538           {
  539               dom = Xpp3Dom.mergeXpp3Dom( dom, mojoExecution.getConfiguration() );
  540           }
  541   
  542           return (MavenReport) getConfiguredMojo( session, dom, project, true, mojoExecution );
  543       }
  544   
  545       public PluginDescriptor verifyReportPlugin( ReportPlugin reportPlugin,
  546                                                   MavenProject project,
  547                                                   MavenSession session )
  548           throws PluginVersionResolutionException, ArtifactResolutionException, ArtifactNotFoundException,
  549           InvalidVersionSpecificationException, InvalidPluginException, PluginManagerException, PluginNotFoundException,
  550           PluginVersionNotFoundException
  551       {
  552           String version = reportPlugin.getVersion();
  553   
  554           if ( version == null )
  555           {
  556               version = pluginVersionManager.resolveReportPluginVersion( reportPlugin.getGroupId(),
  557                                                                          reportPlugin.getArtifactId(), project,
  558                                                                          session.getSettings(),
  559                                                                          session.getLocalRepository() );
  560               reportPlugin.setVersion( version );
  561           }
  562   
  563           Plugin forLookup = new Plugin();
  564   
  565           forLookup.setGroupId( reportPlugin.getGroupId() );
  566           forLookup.setArtifactId( reportPlugin.getArtifactId() );
  567           forLookup.setVersion( version );
  568   
  569           return verifyVersionedPlugin( forLookup, project, session.getLocalRepository() );
  570       }
  571   
  572       private PlexusContainer getPluginContainer( PluginDescriptor pluginDescriptor )
  573           throws PluginManagerException
  574       {
  575           String pluginKey = pluginDescriptor.getPluginLookupKey();
  576   
  577           PlexusContainer pluginContainer = container.getChildContainer( pluginKey );
  578   
  579           if ( pluginContainer == null )
  580           {
  581               throw new PluginManagerException( "Cannot find Plexus container for plugin: " + pluginKey );
  582           }
  583   
  584           return pluginContainer;
  585       }
  586   
  587       private Mojo getConfiguredMojo( MavenSession session,
  588                                       Xpp3Dom dom,
  589                                       MavenProject project,
  590                                       boolean report,
  591                                       MojoExecution mojoExecution )
  592           throws PluginConfigurationException, ArtifactNotFoundException, PluginManagerException,
  593           ArtifactResolutionException
  594       {
  595           MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
  596   
  597           PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
  598   
  599           PlexusContainer pluginContainer = getPluginContainer( pluginDescriptor );
  600   
  601           // if this is the first time this plugin has been used, the plugin's container will only
  602           // contain the plugin's artifact in isolation; we need to finish resolving the plugin's
  603           // dependencies, and add them to the container.
  604           ensurePluginContainerIsComplete( pluginDescriptor, pluginContainer, project, session );
  605   
  606           Mojo plugin;
  607           try
  608           {
  609               plugin = (Mojo) pluginContainer.lookup( Mojo.ROLE, mojoDescriptor.getRoleHint() );
  610               if ( report && !( plugin instanceof MavenReport ) )
  611               {
  612                   // TODO: the mojoDescriptor should actually capture this information so we don't get this far
  613                   return null;
  614               }
  615           }
  616           catch ( ComponentLookupException e )
  617           {
  618               throw new PluginManagerException( "Unable to find the mojo '" + mojoDescriptor.getRoleHint() +
  619                   "' in the plugin '" + pluginDescriptor.getPluginLookupKey() + "'", e );
  620           }
  621   
  622           if ( plugin instanceof ContextEnabled )
  623           {
  624               Map pluginContext = session.getPluginContext( pluginDescriptor, project );
  625   
  626               ( (ContextEnabled) plugin ).setPluginContext( pluginContext );
  627           }
  628   
  629           plugin.setLog( mojoLogger );
  630   
  631           XmlPlexusConfiguration pomConfiguration;
  632           if ( dom == null )
  633           {
  634               pomConfiguration = new XmlPlexusConfiguration( "configuration" );
  635           }
  636           else
  637           {
  638               pomConfiguration = new XmlPlexusConfiguration( dom );
  639           }
  640   
  641           // Validate against non-editable (@readonly) parameters, to make sure users aren't trying to
  642           // override in the POM.
  643           validatePomConfiguration( mojoDescriptor, pomConfiguration );
  644   
  645           PlexusConfiguration mergedConfiguration = mergeMojoConfiguration( pomConfiguration, mojoDescriptor );
  646   
  647           // TODO: plexus changes to make this more like the component descriptor so this can be used instead
  648           //            PlexusConfiguration mergedConfiguration = mergeConfiguration( pomConfiguration,
  649           //                                                                          mojoDescriptor.getConfiguration() );
  650   
  651           ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution,
  652                                                                                             pathTranslator, getLogger(),
  653                                                                                             project,
  654                                                                                             session.getExecutionProperties() );
  655   
  656           PlexusConfiguration extractedMojoConfiguration =
  657               extractMojoConfiguration( mergedConfiguration, mojoDescriptor );
  658   
  659           checkRequiredParameters( mojoDescriptor, extractedMojoConfiguration, expressionEvaluator );
  660   
  661           populatePluginFields( plugin, mojoDescriptor, extractedMojoConfiguration, pluginContainer,
  662                                 expressionEvaluator );
  663           return plugin;
  664       }
  665   
  666       private void ensurePluginContainerIsComplete( PluginDescriptor pluginDescriptor,
  667                                                     PlexusContainer pluginContainer,
  668                                                     MavenProject project,
  669                                                     MavenSession session )
  670           throws ArtifactNotFoundException, PluginManagerException, ArtifactResolutionException
  671       {
  672           // if the plugin's already been used once, don't re-do this step...
  673           // otherwise, we have to finish resolving the plugin's classpath and start the container.
  674           if ( ( pluginDescriptor.getArtifacts() != null ) && ( pluginDescriptor.getArtifacts().size() == 1 ) )
  675           {
  676               Artifact pluginArtifact = (Artifact) pluginDescriptor.getArtifacts().get( 0 );
  677   
  678               ArtifactRepository localRepository = session.getLocalRepository();
  679   
  680               ResolutionGroup resolutionGroup;
  681               try
  682               {
  683                   resolutionGroup = artifactMetadataSource.retrieve( pluginArtifact, localRepository,
  684                                                                      project.getPluginArtifactRepositories() );
  685               }
  686               catch ( ArtifactMetadataRetrievalException e )
  687               {
  688                   throw new ArtifactResolutionException( "Unable to download metadata from repository for plugin '" +
  689                       pluginArtifact.getId() + "': " + e.getMessage(), pluginArtifact, e );
  690               }
  691   
  692               checkPlexusUtils( resolutionGroup, artifactFactory );
  693   
  694               // [jdcasey; 20-March-2008]:
  695               // This is meant to eliminate the introduction of duplicated artifacts.
  696               // Since much of the reasoning for reversing the order of introduction of
  697               // plugin dependencies rests on the notion that we need to be able to
  698               // introduce upgraded versions of plugin dependencies on a case-by-case
  699               // basis, we need to remove the original version prior to artifact
  700               // resolution. This is consistent with recent thinking on duplicated
  701               // dependency specifications within a POM, where that case should
  702               // throw a model validation exception.
  703               //
  704               // Here, we just want to remove any chance that the ArtifactCollector
  705               // could make a bad choice, and use the old version in spite of our
  706               // explicit preference otherwise.
  707   
  708               // First, we're going to accumulate plugin dependencies in an ordered map,
  709               // keyed by dependencyConflictId (the ordered map is meant to preserve relative
  710               // ordering of the dependencies that do make the cut).
  711               Map dependencyMap = new LinkedHashMap();
  712   
  713               // Next, we need to accumulate all dependencies in a List, to make it
  714               // simpler to iterate through them all and add them to the map.
  715               List all = new ArrayList();
  716   
  717               // plugin-level dependencies from the consuming POM override dependencies
  718               // from the plugin's own POM.
  719               all.addAll( pluginDescriptor.getIntroducedDependencyArtifacts() );
  720   
  721               // add in the deps from the plugin POM now.
  722               all.addAll( resolutionGroup.getArtifacts() );
  723   
  724               for ( Iterator it = all.iterator(); it.hasNext(); )
  725               {
  726                   Artifact artifact = (Artifact) it.next();
  727                   String conflictId = artifact.getDependencyConflictId();
  728   
  729                   // if the map already contains this dependencyConflictId, it constitutes an
  730                   // overridden dependency. Don't use the old one (we know it's old from the
  731                   // order in which dependencies were added to this list).
  732                   if ( !dependencyMap.containsKey( conflictId ) )
  733                   {
  734                       dependencyMap.put( conflictId, artifact );
  735                   }
  736               }
  737   
  738               // Create an ordered set of dependencies from the ordered map we used above, to feed into the resolver.
  739               Set dependencies = new LinkedHashSet( dependencyMap.values() );
  740   
  741               if ( getLogger().isDebugEnabled() )
  742               {
  743                   // list all dependencies to be used by this plugin (first-level deps, not transitive ones).
  744                   getLogger().debug( "Plugin dependencies for:\n\n" + pluginDescriptor.getId()
  745                                      + "\n\nare:\n\n"
  746                                      + StringUtils.join( dependencies.iterator(), "\n" ) + "\n\n" );
  747               }
  748   
  749               List repositories = new ArrayList();
  750               repositories.addAll( resolutionGroup.getResolutionRepositories() );
  751               repositories.addAll( project.getRemoteArtifactRepositories() );
  752   
  753               /* get plugin managed versions */
  754               Map pluginManagedDependencies = new HashMap();
  755               try
  756               {
  757                   MavenProject pluginProject =
  758                       mavenProjectBuilder.buildFromRepository( pluginArtifact, project.getRemoteArtifactRepositories(),
  759                                                                localRepository );
  760                   if ( pluginProject != null )
  761                   {
  762                       pluginManagedDependencies = pluginProject.getManagedVersionMap();
  763                   }
  764               }
  765               catch ( ProjectBuildingException e )
  766               {
  767                   // this can't happen, it would have blowed up at artifactMetadataSource.retrieve()
  768               }
  769   
  770               ArtifactResolutionResult result = artifactResolver.resolveTransitively( dependencies, pluginArtifact,
  771                                                                                       pluginManagedDependencies,
  772                                                                                       localRepository, repositories,
  773                                                                                       artifactMetadataSource,
  774                                                                                       artifactFilter );
  775   
  776               Set resolved = result.getArtifacts();
  777   
  778               for ( Iterator it = resolved.iterator(); it.hasNext(); )
  779               {
  780                   Artifact artifact = (Artifact) it.next();
  781   
  782                   if ( !artifact.equals( pluginArtifact ) )
  783                   {
  784                       artifact = project.replaceWithActiveArtifact( artifact );
  785   
  786                       try
  787                       {
  788                           pluginContainer.addJarResource( artifact.getFile() );
  789                       }
  790                       catch ( PlexusContainerException e )
  791                       {
  792                           throw new PluginManagerException( "Error adding plugin dependency '" +
  793                               artifact.getDependencyConflictId() + "' into plugin manager: " + e.getMessage(), e );
  794                       }
  795                   }
  796               }
  797   
  798               pluginDescriptor.setClassRealm( pluginContainer.getContainerRealm() );
  799   
  800               List unresolved = new ArrayList( dependencies );
  801   
  802               unresolved.removeAll( resolved );
  803   
  804               if ( getLogger().isDebugEnabled() )
  805               {
  806                   // list all artifacts that were filtered out during the resolution process.
  807                   // these are already present in the core container.
  808                   getLogger().debug( " The following artifacts were filtered out for plugin: "
  809                                      + pluginDescriptor.getId()
  810                                      + " because they're already in the core of Maven:\n\n"
  811                                      + StringUtils.join( unresolved.iterator(), "\n" )
  812                                      + "\n\nThese will use the artifact files already in the core ClassRealm instead, to allow them to be included in PluginDescriptor.getArtifacts().\n\n" );
  813               }
  814   
  815               // Grab a file for all filtered artifacts, even if it means resolving them. This
  816               // is necessary in order to present a full complement of a plugin's transitive
  817               // dependencies to anyone who calls PluginDescriptor.getArtifacts().
  818               resolveCoreArtifacts( unresolved, localRepository, resolutionGroup.getResolutionRepositories() );
  819   
  820               // Re-join resolved and filtered-but-now-resolved artifacts.
  821               // NOTE: The process of filtering then re-adding some artifacts will
  822               // result in different ordering within the PluginDescriptor.getArtifacts()
  823               // List than should have happened if none had been filtered. All filtered
  824               // artifacts will be listed last...
  825               List allResolved = new ArrayList( resolved.size() + unresolved.size() );
  826   
  827               allResolved.addAll( resolved );
  828               allResolved.addAll( unresolved );
  829   
  830               pluginDescriptor.setArtifacts( allResolved );
  831           }
  832       }
  833   
  834       public static void checkPlexusUtils( ResolutionGroup resolutionGroup, ArtifactFactory artifactFactory )
  835       {
  836           // ----------------------------------------------------------------------------
  837           // If the plugin already declares a dependency on plexus-utils then we're all
  838           // set as the plugin author is aware of its use. If we don't have a dependency
  839           // on plexus-utils then we must protect users from stupid plugin authors who
  840           // did not declare a direct dependency on plexus-utils because the version
  841           // Maven uses is hidden from downstream use. We will also bump up any
  842           // anything below 1.1 to 1.1 as this mimics the behaviour in 2.0.5 where
  843           // plexus-utils 1.1 was being forced into use.
  844           // ----------------------------------------------------------------------------
  845   
  846           VersionRange vr = null;
  847   
  848           try
  849           {
  850               vr = VersionRange.createFromVersionSpec( "[1.1,)" );
  851           }
  852           catch ( InvalidVersionSpecificationException e )
  853           {
  854               // Won't happen
  855           }
  856   
  857           boolean plexusUtilsPresent = false;
  858   
  859           for ( Iterator i = resolutionGroup.getArtifacts().iterator(); i.hasNext(); )
  860           {
  861               Artifact a = (Artifact) i.next();
  862   
  863               if ( a.getArtifactId().equals( "plexus-utils" ) &&
  864                   vr.containsVersion( new DefaultArtifactVersion( a.getVersion() ) ) )
  865               {
  866                   plexusUtilsPresent = true;
  867   
  868                   break;
  869               }
  870           }
  871   
  872           if ( !plexusUtilsPresent )
  873           {
  874               // We will add plexus-utils as every plugin was getting this anyway from Maven itself. We will set the
  875               // version to the latest version we know that works as of the 2.0.6 release. We set the scope to runtime
  876               // as this is what's implicitly happening in 2.0.6.
  877   
  878               resolutionGroup.getArtifacts().add( artifactFactory.createArtifact( "org.codehaus.plexus",
  879                                                                                   "plexus-utils", "1.1",
  880                                                                                   Artifact.SCOPE_RUNTIME, "jar" ) );
  881           }
  882       }
  883   
  884       private void resolveCoreArtifacts( List unresolved,
  885                                          ArtifactRepository localRepository,
  886                                          List resolutionRepositories )
  887           throws ArtifactResolutionException, ArtifactNotFoundException
  888       {
  889           for ( Iterator it = unresolved.iterator(); it.hasNext(); )
  890           {
  891               Artifact artifact = (Artifact) it.next();
  892   
  893               File artifactFile = (File) resolvedCoreArtifactFiles.get( artifact.getId() );
  894   
  895               if ( artifactFile == null )
  896               {
  897                   String resource =
  898                       "/META-INF/maven/" + artifact.getGroupId() + "/" + artifact.getArtifactId() + "/pom.xml";
  899   
  900                   URL resourceUrl = container.getContainerRealm().getResource( resource );
  901   
  902                   if ( resourceUrl == null )
  903                   {
  904                       artifactResolver.resolve( artifact, resolutionRepositories, localRepository );
  905   
  906                       artifactFile = artifact.getFile();
  907                   }
  908                   else
  909                   {
  910                       String artifactPath = resourceUrl.getPath();
  911   
  912                       if ( artifactPath.startsWith( "file:" ) )
  913                       {
  914                           artifactPath = artifactPath.substring( "file:".length() );
  915                       }
  916   
  917                       artifactPath = artifactPath.substring( 0, artifactPath.length() - resource.length() );
  918   
  919                       if ( artifactPath.endsWith( "/" ) )
  920                       {
  921                           artifactPath = artifactPath.substring( 0, artifactPath.length() - 1 );
  922                       }
  923   
  924                       if ( artifactPath.endsWith( "!" ) )
  925                       {
  926                           artifactPath = artifactPath.substring( 0, artifactPath.length() - 1 );
  927                       }
  928   
  929                       artifactFile = new File( artifactPath ).getAbsoluteFile();
  930                   }
  931   
  932                   resolvedCoreArtifactFiles.put( artifact.getId(), artifactFile );
  933               }
  934   
  935               artifact.setFile( artifactFile );
  936           }
  937       }
  938   
  939       private PlexusConfiguration extractMojoConfiguration( PlexusConfiguration mergedConfiguration,
  940                                                             MojoDescriptor mojoDescriptor )
  941       {
  942           Map parameterMap = mojoDescriptor.getParameterMap();
  943   
  944           PlexusConfiguration[] mergedChildren = mergedConfiguration.getChildren();
  945   
  946           XmlPlexusConfiguration extractedConfiguration = new XmlPlexusConfiguration( "configuration" );
  947   
  948           for ( int i = 0; i < mergedChildren.length; i++ )
  949           {
  950               PlexusConfiguration child = mergedChildren[i];
  951   
  952               if ( parameterMap.containsKey( child.getName() ) )
  953               {
  954                   extractedConfiguration.addChild( copyConfiguration( child ) );
  955               }
  956               else
  957               {
  958                   // TODO: I defy anyone to find these messages in the '-X' output! Do we need a new log level?
  959                   // ideally, this would be elevated above the true debug output, but below the default INFO level...
  960                   // [BP] (2004-07-18): need to understand the context more but would prefer this could be either WARN or
  961                   // removed - shouldn't need DEBUG to diagnose a problem most of the time.
  962                   getLogger().debug( "*** WARNING: Configuration \'" + child.getName() + "\' is not used in goal \'" +
  963                       mojoDescriptor.getFullGoalName() + "; this may indicate a typo... ***" );
  964               }
  965           }
  966   
  967           return extractedConfiguration;
  968       }
  969   
  970       private void checkRequiredParameters( MojoDescriptor goal,
  971                                             PlexusConfiguration configuration,
  972                                             ExpressionEvaluator expressionEvaluator )
  973           throws PluginConfigurationException
  974       {
  975           // TODO: this should be built in to the configurator, as we presently double process the expressions
  976   
  977           List parameters = goal.getParameters();
  978   
  979           if ( parameters == null )
  980           {
  981               return;
  982           }
  983   
  984           List invalidParameters = new ArrayList();
  985   
  986           for ( int i = 0; i < parameters.size(); i++ )
  987           {
  988               Parameter parameter = (Parameter) parameters.get( i );
  989   
  990               if ( parameter.isRequired() )
  991               {
  992                   // the key for the configuration map we're building.
  993                   String key = parameter.getName();
  994   
  995                   Object fieldValue = null;
  996                   String expression = null;
  997                   PlexusConfiguration value = configuration.getChild( key, false );
  998                   try
  999                   {
 1000                       if ( value != null )
 1001                       {
 1002                           expression = value.getValue( null );
 1003   
 1004                           fieldValue = expressionEvaluator.evaluate( expression );
 1005   
 1006                           if ( fieldValue == null )
 1007                           {
 1008                               fieldValue = value.getAttribute( "default-value", null );
 1009                           }
 1010                       }
 1011   
 1012                       if ( ( fieldValue == null ) && StringUtils.isNotEmpty( parameter.getAlias() ) )
 1013                       {
 1014                           value = configuration.getChild( parameter.getAlias(), false );
 1015                           if ( value != null )
 1016                           {
 1017                               expression = value.getValue( null );
 1018                               fieldValue = expressionEvaluator.evaluate( expression );
 1019                               if ( fieldValue == null )
 1020                               {
 1021                                   fieldValue = value.getAttribute( "default-value", null );
 1022                               }
 1023                           }
 1024                       }
 1025                   }
 1026                   catch ( ExpressionEvaluationException e )
 1027                   {
 1028                       throw new PluginConfigurationException( goal.getPluginDescriptor(), e.getMessage(), e );
 1029                   }
 1030   
 1031                   // only mark as invalid if there are no child nodes
 1032                   if ( ( fieldValue == null ) && ( ( value == null ) || ( value.getChildCount() == 0 ) ) )
 1033                   {
 1034                       parameter.setExpression( expression );
 1035                       invalidParameters.add( parameter );
 1036                   }
 1037               }
 1038           }
 1039   
 1040           if ( !invalidParameters.isEmpty() )
 1041           {
 1042               throw new PluginParameterException( goal, invalidParameters );
 1043           }
 1044       }
 1045   
 1046       private void validatePomConfiguration( MojoDescriptor goal,
 1047                                              PlexusConfiguration pomConfiguration )
 1048           throws PluginConfigurationException
 1049       {
 1050           List parameters = goal.getParameters();
 1051   
 1052           if ( parameters == null )
 1053           {
 1054               return;
 1055           }
 1056   
 1057           for ( int i = 0; i < parameters.size(); i++ )
 1058           {
 1059               Parameter parameter = (Parameter) parameters.get( i );
 1060   
 1061               // the key for the configuration map we're building.
 1062               String key = parameter.getName();
 1063   
 1064               PlexusConfiguration value = pomConfiguration.getChild( key, false );
 1065   
 1066               if ( ( value == null ) && StringUtils.isNotEmpty( parameter.getAlias() ) )
 1067               {
 1068                   key = parameter.getAlias();
 1069                   value = pomConfiguration.getChild( key, false );
 1070               }
 1071   
 1072               if ( value != null )
 1073               {
 1074                   // Make sure the parameter is either editable/configurable, or else is NOT specified in the POM
 1075                   if ( !parameter.isEditable() )
 1076                   {
 1077                       StringBuffer errorMessage = new StringBuffer()
 1078                           .append( "ERROR: Cannot override read-only parameter: " );
 1079                       errorMessage.append( key );
 1080                       errorMessage.append( " in goal: " ).append( goal.getFullGoalName() );
 1081   
 1082                       throw new PluginConfigurationException( goal.getPluginDescriptor(), errorMessage.toString() );
 1083                   }
 1084   
 1085                   String deprecated = parameter.getDeprecated();
 1086                   if ( StringUtils.isNotEmpty( deprecated ) )
 1087                   {
 1088                       getLogger().warn( "DEPRECATED [" + parameter.getName() + "]: " + deprecated );
 1089                   }
 1090               }
 1091           }
 1092       }
 1093   
 1094       private PlexusConfiguration mergeMojoConfiguration( XmlPlexusConfiguration fromPom,
 1095                                                           MojoDescriptor mojoDescriptor )
 1096       {
 1097           XmlPlexusConfiguration result = new XmlPlexusConfiguration( fromPom.getName() );
 1098           result.setValue( fromPom.getValue( null ) );
 1099   
 1100           if ( mojoDescriptor.getParameters() != null )
 1101           {
 1102               PlexusConfiguration fromMojo = mojoDescriptor.getMojoConfiguration();
 1103   
 1104               for ( Iterator it = mojoDescriptor.getParameters().iterator(); it.hasNext(); )
 1105               {
 1106                   Parameter parameter = (Parameter) it.next();
 1107   
 1108                   String paramName = parameter.getName();
 1109                   String alias = parameter.getAlias();
 1110                   String implementation = parameter.getImplementation();
 1111   
 1112                   PlexusConfiguration pomConfig = fromPom.getChild( paramName );
 1113                   PlexusConfiguration aliased = null;
 1114   
 1115                   if ( alias != null )
 1116                   {
 1117                       aliased = fromPom.getChild( alias );
 1118                   }
 1119   
 1120                   PlexusConfiguration mojoConfig = fromMojo.getChild( paramName, false );
 1121   
 1122                   // first we'll merge configurations from the aliased and real params.
 1123                   // TODO: Is this the right thing to do?
 1124                   if ( aliased != null )
 1125                   {
 1126                       if ( pomConfig == null )
 1127                       {
 1128                           pomConfig = new XmlPlexusConfiguration( paramName );
 1129                       }
 1130   
 1131                       pomConfig = buildTopDownMergedConfiguration( pomConfig, aliased );
 1132                   }
 1133   
 1134                   PlexusConfiguration toAdd = null;
 1135   
 1136                   if ( pomConfig != null )
 1137                   {
 1138                       pomConfig = buildTopDownMergedConfiguration( pomConfig, mojoConfig );
 1139   
 1140                       if ( StringUtils.isNotEmpty( pomConfig.getValue( null ) ) || ( pomConfig.getChildCount() > 0 ) )
 1141                       {
 1142                           toAdd = pomConfig;
 1143                       }
 1144                   }
 1145   
 1146                   if ( ( toAdd == null ) && ( mojoConfig != null ) )
 1147                   {
 1148                       toAdd = copyConfiguration( mojoConfig );
 1149                   }
 1150   
 1151                   if ( toAdd != null )
 1152                   {
 1153                       if ( ( implementation != null ) && ( toAdd.getAttribute( "implementation", null ) == null ) )
 1154                       {
 1155   
 1156                           XmlPlexusConfiguration implementationConf = new XmlPlexusConfiguration( paramName );
 1157   
 1158                           implementationConf.setAttribute( "implementation", parameter.getImplementation() );
 1159   
 1160                           toAdd = buildTopDownMergedConfiguration( toAdd, implementationConf );
 1161                       }
 1162   
 1163                       result.addChild( toAdd );
 1164                   }
 1165               }
 1166           }
 1167           return result;
 1168       }
 1169   
 1170       private XmlPlexusConfiguration buildTopDownMergedConfiguration( PlexusConfiguration dominant,
 1171                                                                       PlexusConfiguration recessive )
 1172       {
 1173           XmlPlexusConfiguration result = new XmlPlexusConfiguration( dominant.getName() );
 1174   
 1175           String value = dominant.getValue( null );
 1176   
 1177           if ( StringUtils.isEmpty( value ) && ( recessive != null ) )
 1178           {
 1179               value = recessive.getValue( null );
 1180           }
 1181   
 1182           if ( StringUtils.isNotEmpty( value ) )
 1183           {
 1184               result.setValue( value );
 1185           }
 1186   
 1187           String[] attributeNames = dominant.getAttributeNames();
 1188   
 1189           for ( int i = 0; i < attributeNames.length; i++ )
 1190           {
 1191               String attributeValue = dominant.getAttribute( attributeNames[i], null );
 1192   
 1193               result.setAttribute( attributeNames[i], attributeValue );
 1194           }
 1195   
 1196           if ( recessive != null )
 1197           {
 1198               attributeNames = recessive.getAttributeNames();
 1199   
 1200               for ( int i = 0; i < attributeNames.length; i++ )
 1201               {
 1202                   String attributeValue = recessive.getAttribute( attributeNames[i], null );
 1203                   // TODO: recessive seems to be dominant here?
 1204                   result.setAttribute( attributeNames[i], attributeValue );
 1205               }
 1206           }
 1207   
 1208           PlexusConfiguration[] children = dominant.getChildren();
 1209   
 1210           for ( int i = 0; i < children.length; i++ )
 1211           {
 1212               PlexusConfiguration childDom = children[i];
 1213               PlexusConfiguration childRec = recessive == null ? null : recessive.getChild( childDom.getName(), false );
 1214   
 1215               if ( childRec != null )
 1216               {
 1217                   result.addChild( buildTopDownMergedConfiguration( childDom, childRec ) );
 1218               }
 1219               else
 1220               {   // FIXME: copy, or use reference?
 1221                   result.addChild( copyConfiguration( childDom ) );
 1222               }
 1223           }
 1224   
 1225           return result;
 1226       }
 1227   
 1228       public static PlexusConfiguration copyConfiguration( PlexusConfiguration src )
 1229       {
 1230           // TODO: shouldn't be necessary
 1231           XmlPlexusConfiguration dom = new XmlPlexusConfiguration( src.getName() );
 1232           dom.setValue( src.getValue( null ) );
 1233   
 1234           String[] attributeNames = src.getAttributeNames();
 1235           for ( int i = 0; i < attributeNames.length; i++ )
 1236           {
 1237               String attributeName = attributeNames[i];
 1238               dom.setAttribute( attributeName, src.getAttribute( attributeName, null ) );
 1239           }
 1240   
 1241           PlexusConfiguration[] children = src.getChildren();
 1242           for ( int i = 0; i < children.length; i++ )
 1243           {
 1244               dom.addChild( copyConfiguration( children[i] ) );
 1245           }
 1246   
 1247           return dom;
 1248       }
 1249   
 1250       // ----------------------------------------------------------------------
 1251       // Mojo Parameter Handling
 1252       // ----------------------------------------------------------------------
 1253   
 1254       private void populatePluginFields( Mojo plugin,
 1255                                          MojoDescriptor mojoDescriptor,
 1256                                          PlexusConfiguration configuration,
 1257                                          PlexusContainer pluginContainer,
 1258                                          ExpressionEvaluator expressionEvaluator )
 1259           throws PluginConfigurationException
 1260       {
 1261           ComponentConfigurator configurator = null;
 1262   
 1263           try
 1264           {
 1265               String configuratorId = mojoDescriptor.getComponentConfigurator();
 1266   
 1267               // TODO: could the configuration be passed to lookup and the configurator known to plexus via the descriptor
 1268               // so that this meethod could entirely be handled by a plexus lookup?
 1269               if ( StringUtils.isNotEmpty( configuratorId ) )
 1270               {
 1271                   configurator =
 1272                       (ComponentConfigurator) pluginContainer.lookup( ComponentConfigurator.ROLE, configuratorId );
 1273               }
 1274               else
 1275               {
 1276                   configurator = (ComponentConfigurator) pluginContainer.lookup( ComponentConfigurator.ROLE );
 1277               }
 1278   
 1279               ConfigurationListener listener = new DebugConfigurationListener( getLogger() );
 1280   
 1281               getLogger().debug( "Configuring mojo '" + mojoDescriptor.getId() + "' -->" );
 1282               configurator.configureComponent( plugin, configuration, expressionEvaluator,
 1283                                                pluginContainer.getContainerRealm(), listener );
 1284               getLogger().debug( "-- end configuration --" );
 1285           }
 1286           catch ( ComponentConfigurationException e )
 1287           {
 1288               throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(),
 1289                                                       "Unable to parse the created DOM for plugin configuration", e );
 1290           }
 1291           catch ( ComponentLookupException e )
 1292           {
 1293               throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(),
 1294                                                       "Unable to retrieve component configurator for plugin configuration",
 1295                                                       e );
 1296           }
 1297           catch ( LinkageError e )
 1298           {
 1299               if ( getLogger().isFatalErrorEnabled() )
 1300               {
 1301                   getLogger().fatalError(
 1302                                           configurator.getClass().getName() + "#configureComponent(...) caused a linkage error ("
 1303                                               + e.getClass().getName() + ") and may be out-of-date. Check the realms:" );
 1304   
 1305                   ClassRealm pluginRealm = mojoDescriptor.getPluginDescriptor().getClassRealm();
 1306                   StringBuffer sb = new StringBuffer();
 1307                   sb.append( "Plugin realm = " + pluginRealm.getId() ).append( '\n' );
 1308                   for ( int i = 0; i < pluginRealm.getConstituents().length; i++ )
 1309                   {
 1310                       sb.append( "urls[" + i + "] = " + pluginRealm.getConstituents()[i] );
 1311                       if ( i != ( pluginRealm.getConstituents().length - 1 ) )
 1312                       {
 1313                           sb.append( '\n' );
 1314                       }
 1315                   }
 1316                   getLogger().fatalError( sb.toString() );
 1317   
 1318                   ClassRealm containerRealm = container.getContainerRealm();
 1319                   sb = new StringBuffer();
 1320                   sb.append( "Container realm = " + containerRealm.getId() ).append( '\n' );
 1321                   for ( int i = 0; i < containerRealm.getConstituents().length; i++ )
 1322                   {
 1323                       sb.append( "urls[" + i + "] = " + containerRealm.getConstituents()[i] );
 1324                       if ( i != ( containerRealm.getConstituents().length - 1 ) )
 1325                       {
 1326                           sb.append( '\n' );
 1327                       }
 1328                   }
 1329                   getLogger().fatalError( sb.toString() );
 1330               }
 1331   
 1332               throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(),
 1333                                                       e.getClass().getName() + ": " + e.getMessage(), e );
 1334           }
 1335           finally
 1336           {
 1337               if ( configurator != null )
 1338               {
 1339                   try
 1340                   {
 1341                       pluginContainer.release( configurator );
 1342                   }
 1343                   catch ( ComponentLifecycleException e )
 1344                   {
 1345                       getLogger().debug( "Failed to release plugin container - ignoring." );
 1346                   }
 1347               }
 1348           }
 1349       }
 1350   
 1351       public static String createPluginParameterRequiredMessage( MojoDescriptor mojo,
 1352                                                                  Parameter parameter,
 1353                                                                  String expression )
 1354       {
 1355           StringBuffer message = new StringBuffer();
 1356   
 1357           message.append( "The '" );
 1358           message.append( parameter.getName() );
 1359           message.append( "' parameter is required for the execution of the " );
 1360           message.append( mojo.getFullGoalName() );
 1361           message.append( " mojo and cannot be null." );
 1362           if ( expression != null )
 1363           {
 1364               message.append( " The retrieval expression was: " ).append( expression );
 1365           }
 1366   
 1367           return message.toString();
 1368       }
 1369   
 1370       // ----------------------------------------------------------------------
 1371       // Lifecycle
 1372       // ----------------------------------------------------------------------
 1373   
 1374       public void contextualize( Context context )
 1375           throws ContextException
 1376       {
 1377           container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
 1378   
 1379           mojoLogger = new DefaultLog( container.getLoggerManager().getLoggerForComponent( Mojo.ROLE ) );
 1380       }
 1381   
 1382       public void initialize()
 1383       {
 1384           artifactFilter = MavenArtifactFilterManager.createStandardFilter();
 1385       }
 1386   
 1387       // ----------------------------------------------------------------------
 1388       // Artifact resolution
 1389       // ----------------------------------------------------------------------
 1390   
 1391       private void resolveTransitiveDependencies( MavenSession context,
 1392                                                   ArtifactResolver artifactResolver,
 1393                                                   String scope,
 1394                                                   ArtifactFactory artifactFactory,
 1395                                                   MavenProject project, boolean isAggregator )
 1396           throws ArtifactResolutionException, ArtifactNotFoundException, InvalidDependencyVersionException
 1397       {
 1398           ArtifactFilter filter = new ScopeArtifactFilter( scope );
 1399   
 1400           // TODO: such a call in MavenMetadataSource too - packaging not really the intention of type
 1401           Artifact artifact = artifactFactory.createBuildArtifact( project.getGroupId(), project.getArtifactId(),
 1402                                                                    project.getVersion(), project.getPackaging() );
 1403   
 1404           // TODO: we don't need to resolve over and over again, as long as we are sure that the parameters are the same
 1405           // check this with yourkit as a hot spot.
 1406           // Don't recreate if already created - for effeciency, and because clover plugin adds to it
 1407           if ( project.getDependencyArtifacts() == null )
 1408           {
 1409               project.setDependencyArtifacts( project.createArtifacts( artifactFactory, null, null ) );
 1410           }
 1411           
 1412           Set resolvedArtifacts;
 1413           try
 1414           {
 1415               ArtifactResolutionResult result = artifactResolver.resolveTransitively( project.getDependencyArtifacts(),
 1416                                                                                   artifact,
 1417                                                                                   project.getManagedVersionMap(),
 1418                                                                                   context.getLocalRepository(),
 1419                                                                                   project.getRemoteArtifactRepositories(),
 1420                                                                                   artifactMetadataSource, filter );
 1421               resolvedArtifacts = result.getArtifacts();
 1422           }
 1423           catch (MultipleArtifactsNotFoundException me)
 1424           {
 1425               /*only do this if we are an aggregating plugin: MNG-2277
 1426               if the dependency doesn't yet exist but is in the reactor, then 
 1427               all we can do is warn and skip it. A better fix can be inserted into 2.1*/
 1428               if (isAggregator && checkMissingArtifactsInReactor( context.getSortedProjects(), me.getMissingArtifacts() ))
 1429               {
 1430                   resolvedArtifacts = new HashSet(me.getResolvedArtifacts());
 1431               }
 1432               else
 1433               {
 1434                   //we can't find all the artifacts in the reactor so bubble the exception up.
 1435                   throw me;
 1436               }
 1437           }
 1438           project.setArtifacts( resolvedArtifacts );
 1439       }
 1440   
 1441       /**
 1442        * This method is checking to see if the artifacts that can't be resolved are all
 1443        * part of this reactor. This is done to prevent a chicken or egg scenario with
 1444        * fresh projects that have a plugin that is an aggregator and requires dependencies. See
 1445        * MNG-2277 for more info.
 1446        * @param projects the sibling projects in the reactor
 1447        * @param missing the artifacts that can't be found
 1448        * @return true if ALL missing artifacts are found in the reactor.
 1449        */
 1450       private boolean checkMissingArtifactsInReactor(Collection projects, Collection missing)
 1451       {
 1452           Collection foundInReactor = new HashSet();
 1453           Iterator iter = missing.iterator();
 1454           while (iter.hasNext())
 1455           {
 1456               Artifact mArtifact = (Artifact) iter.next();
 1457               Iterator pIter = projects.iterator();
 1458               while (pIter.hasNext())
 1459               {
 1460                   MavenProject p = (MavenProject) pIter.next();
 1461                   if (p.getArtifactId().equals( mArtifact.getArtifactId()) &&
 1462                       p.getGroupId().equals( mArtifact.getGroupId()) &&
 1463                       p.getVersion().equals( mArtifact.getVersion()))
 1464                   {
 1465                       //TODO: the packaging could be different, but the exception doesn't contain that info
 1466                       //most likely it would be produced by the project we just found in the reactor since all
 1467                       //the other info matches. Assume it's ok.
 1468                       getLogger().warn( "The dependency: "+ p.getId()+" can't be resolved but has been found in the reactor.\nThis dependency has been excluded from the plugin execution. You should rerun this mojo after executing mvn install.\n" );
 1469                       
 1470                       //found it, move on.
 1471                       foundInReactor.add( p );
 1472                       break;
 1473                   }   
 1474               }
 1475           }
 1476           
 1477           //if all of them have been found, we can continue.
 1478           return foundInReactor.size() == missing.size();
 1479       }
 1480       
 1481       
 1482       // ----------------------------------------------------------------------
 1483       // Artifact downloading
 1484       // ----------------------------------------------------------------------
 1485   
 1486       private void downloadDependencies( MavenProject project,
 1487                                          MavenSession context,
 1488                                          ArtifactResolver artifactResolver )
 1489           throws ArtifactResolutionException, ArtifactNotFoundException
 1490       {
 1491           ArtifactRepository localRepository = context.getLocalRepository();
 1492           List remoteArtifactRepositories = project.getRemoteArtifactRepositories();
 1493   
 1494           for ( Iterator it = project.getArtifacts().iterator(); it.hasNext(); )
 1495           {
 1496               Artifact artifact = (Artifact) it.next();
 1497   
 1498               artifactResolver.resolve( artifact, remoteArtifactRepositories, localRepository );
 1499           }
 1500       }
 1501   
 1502       public Object getPluginComponent( Plugin plugin,
 1503                                         String role,
 1504                                         String roleHint )
 1505           throws PluginManagerException, ComponentLookupException
 1506       {
 1507           PluginDescriptor pluginDescriptor = pluginCollector.getPluginDescriptor( plugin );
 1508   
 1509           PlexusContainer pluginContainer = getPluginContainer( pluginDescriptor );
 1510   
 1511           return pluginContainer.lookup( role, roleHint );
 1512       }
 1513   
 1514       public Map getPluginComponents( Plugin plugin,
 1515                                       String role )
 1516           throws ComponentLookupException, PluginManagerException
 1517       {
 1518           PluginDescriptor pluginDescriptor = pluginCollector.getPluginDescriptor( plugin );
 1519   
 1520           PlexusContainer pluginContainer = getPluginContainer( pluginDescriptor );
 1521   
 1522           return pluginContainer.lookupMap( role );
 1523       }
 1524   }

Save This Page
Home » maven-2.0.9-src » org.apache » maven » plugin » [javadoc | source]