View Javadoc

1   package org.apache.maven.plugin.internal;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.LinkedHashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.apache.maven.ArtifactFilterManager;
27  import org.apache.maven.RepositoryUtils;
28  import org.apache.maven.model.Dependency;
29  import org.apache.maven.model.Plugin;
30  import org.apache.maven.plugin.PluginResolutionException;
31  import org.codehaus.plexus.component.annotations.Component;
32  import org.codehaus.plexus.component.annotations.Requirement;
33  import org.codehaus.plexus.logging.Logger;
34  import org.sonatype.aether.RepositorySystem;
35  import org.sonatype.aether.RepositorySystemSession;
36  import org.sonatype.aether.artifact.Artifact;
37  import org.sonatype.aether.collection.CollectRequest;
38  import org.sonatype.aether.collection.DependencyCollectionException;
39  import org.sonatype.aether.collection.DependencyGraphTransformer;
40  import org.sonatype.aether.collection.DependencySelector;
41  import org.sonatype.aether.graph.DependencyFilter;
42  import org.sonatype.aether.graph.DependencyNode;
43  import org.sonatype.aether.graph.DependencyVisitor;
44  import org.sonatype.aether.repository.RemoteRepository;
45  import org.sonatype.aether.resolution.ArtifactDescriptorException;
46  import org.sonatype.aether.resolution.ArtifactDescriptorRequest;
47  import org.sonatype.aether.resolution.ArtifactDescriptorResult;
48  import org.sonatype.aether.resolution.ArtifactRequest;
49  import org.sonatype.aether.resolution.ArtifactResolutionException;
50  import org.sonatype.aether.util.DefaultRepositorySystemSession;
51  import org.sonatype.aether.util.FilterRepositorySystemSession;
52  import org.sonatype.aether.util.artifact.DefaultArtifact;
53  import org.sonatype.aether.util.artifact.JavaScopes;
54  import org.sonatype.aether.util.filter.AndDependencyFilter;
55  import org.sonatype.aether.util.filter.ExclusionsDependencyFilter;
56  import org.sonatype.aether.util.filter.ScopeDependencyFilter;
57  import org.sonatype.aether.util.graph.selector.AndDependencySelector;
58  import org.sonatype.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
59  
60  /**
61   * Assists in resolving the dependencies of a plugin. <strong>Warning:</strong> This is an internal utility class that
62   * is only public for technical reasons, it is not part of the public API. In particular, this class can be changed or
63   * deleted without prior notice.
64   * 
65   * @since 3.0
66   * @author Benjamin Bentmann
67   */
68  @Component( role = PluginDependenciesResolver.class )
69  public class DefaultPluginDependenciesResolver
70      implements PluginDependenciesResolver
71  {
72  
73      private static final String REPOSITORY_CONTEXT = "plugin";
74  
75      @Requirement
76      private Logger logger;
77  
78      @Requirement
79      private ArtifactFilterManager artifactFilterManager;
80  
81      @Requirement
82      private RepositorySystem repoSystem;
83  
84      private Artifact toArtifact( Plugin plugin, RepositorySystemSession session )
85      {
86          return new DefaultArtifact( plugin.getGroupId(), plugin.getArtifactId(), null, "jar", plugin.getVersion(),
87                                      session.getArtifactTypeRegistry().get( "maven-plugin" ) );
88      }
89  
90      public Artifact resolve( Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session )
91          throws PluginResolutionException
92      {
93          Artifact pluginArtifact = toArtifact( plugin, session );
94  
95          try
96          {
97              RepositorySystemSession pluginSession = new FilterRepositorySystemSession( session )
98              {
99                  @Override
100                 public boolean isIgnoreMissingArtifactDescriptor()
101                 {
102                     return false;
103                 }
104             };
105 
106             ArtifactDescriptorRequest request =
107                 new ArtifactDescriptorRequest( pluginArtifact, repositories, REPOSITORY_CONTEXT );
108             ArtifactDescriptorResult result = repoSystem.readArtifactDescriptor( pluginSession, request );
109 
110             pluginArtifact = result.getArtifact();
111 
112             String requiredMavenVersion = (String) result.getProperties().get( "prerequisites.maven" );
113             if ( requiredMavenVersion != null )
114             {
115                 Map<String, String> props = new LinkedHashMap<String, String>( pluginArtifact.getProperties() );
116                 props.put( "requiredMavenVersion", requiredMavenVersion );
117                 pluginArtifact = pluginArtifact.setProperties( props );
118             }
119         }
120         catch ( ArtifactDescriptorException e )
121         {
122             throw new PluginResolutionException( plugin, e );
123         }
124 
125         try
126         {
127             ArtifactRequest request = new ArtifactRequest( pluginArtifact, repositories, REPOSITORY_CONTEXT );
128             pluginArtifact = repoSystem.resolveArtifact( session, request ).getArtifact();
129         }
130         catch ( ArtifactResolutionException e )
131         {
132             throw new PluginResolutionException( plugin, e );
133         }
134 
135         return pluginArtifact;
136     }
137 
138     public DependencyNode resolve( Plugin plugin, Artifact pluginArtifact, DependencyFilter dependencyFilter,
139                                    List<RemoteRepository> repositories, RepositorySystemSession session )
140         throws PluginResolutionException
141     {
142         if ( pluginArtifact == null )
143         {
144             pluginArtifact = toArtifact( plugin, session );
145         }
146 
147         DependencyFilter collectionFilter = new ScopeDependencyFilter( "provided", "test" );
148 
149         DependencyFilter resolutionFilter =
150             new ExclusionsDependencyFilter( artifactFilterManager.getCoreArtifactExcludes() );
151         resolutionFilter = AndDependencyFilter.newInstance( resolutionFilter, dependencyFilter );
152         resolutionFilter = new AndDependencyFilter( collectionFilter, resolutionFilter );
153 
154         DependencyNode node;
155 
156         try
157         {
158             DependencySelector selector =
159                 AndDependencySelector.newInstance( session.getDependencySelector(), new WagonExcluder() );
160 
161             DependencyGraphTransformer transformer =
162                 ChainedDependencyGraphTransformer.newInstance( session.getDependencyGraphTransformer(),
163                                                                new PlexusUtilsInjector() );
164 
165             DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession( session );
166             pluginSession.setDependencySelector( selector );
167             pluginSession.setDependencyGraphTransformer( transformer );
168 
169             CollectRequest request = new CollectRequest();
170             request.setRequestContext( REPOSITORY_CONTEXT );
171             request.setRepositories( repositories );
172             request.setRoot( new org.sonatype.aether.graph.Dependency( pluginArtifact, null ) );
173             for ( Dependency dependency : plugin.getDependencies() )
174             {
175                 org.sonatype.aether.graph.Dependency pluginDep =
176                     RepositoryUtils.toDependency( dependency, session.getArtifactTypeRegistry() );
177                 if ( !JavaScopes.SYSTEM.equals( pluginDep.getScope() ) )
178                 {
179                     pluginDep = pluginDep.setScope( JavaScopes.RUNTIME );
180                 }
181                 request.addDependency( pluginDep );
182             }
183 
184             node = repoSystem.collectDependencies( pluginSession, request ).getRoot();
185 
186             if ( logger.isDebugEnabled() )
187             {
188                 node.accept( new GraphLogger() );
189             }
190 
191             repoSystem.resolveDependencies( session, node, resolutionFilter );
192         }
193         catch ( DependencyCollectionException e )
194         {
195             throw new PluginResolutionException( plugin, e );
196         }
197         catch ( ArtifactResolutionException e )
198         {
199             throw new PluginResolutionException( plugin, e );
200         }
201 
202         return node;
203     }
204 
205     class GraphLogger
206         implements DependencyVisitor
207     {
208 
209         private String indent = "";
210 
211         public boolean visitEnter( DependencyNode node )
212         {
213             StringBuilder buffer = new StringBuilder( 128 );
214             buffer.append( indent );
215             org.sonatype.aether.graph.Dependency dep = node.getDependency();
216             if ( dep != null )
217             {
218                 org.sonatype.aether.artifact.Artifact art = dep.getArtifact();
219 
220                 buffer.append( art );
221                 buffer.append( ':' ).append( dep.getScope() );
222 
223                 if ( node.getPremanagedScope() != null && !node.getPremanagedScope().equals( dep.getScope() ) )
224                 {
225                     buffer.append( " (scope managed from " ).append( node.getPremanagedScope() ).append( ")" );
226                 }
227 
228                 if ( node.getPremanagedVersion() != null && !node.getPremanagedVersion().equals( art.getVersion() ) )
229                 {
230                     buffer.append( " (version managed from " ).append( node.getPremanagedVersion() ).append( ")" );
231                 }
232             }
233 
234             logger.debug( buffer.toString() );
235             indent += "   ";
236             return true;
237         }
238 
239         public boolean visitLeave( DependencyNode node )
240         {
241             indent = indent.substring( 0, indent.length() - 3 );
242             return true;
243         }
244 
245     }
246 
247 }