View Javadoc

1   package org.apache.maven.plugin.prefix.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.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.maven.artifact.repository.metadata.Metadata;
29  import org.apache.maven.artifact.repository.metadata.io.MetadataReader;
30  import org.apache.maven.model.Build;
31  import org.apache.maven.model.Plugin;
32  import org.apache.maven.plugin.BuildPluginManager;
33  import org.apache.maven.plugin.descriptor.PluginDescriptor;
34  import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
35  import org.apache.maven.plugin.prefix.PluginPrefixRequest;
36  import org.apache.maven.plugin.prefix.PluginPrefixResolver;
37  import org.apache.maven.plugin.prefix.PluginPrefixResult;
38  import org.codehaus.plexus.component.annotations.Component;
39  import org.codehaus.plexus.component.annotations.Requirement;
40  import org.codehaus.plexus.logging.Logger;
41  import org.sonatype.aether.RepositoryListener;
42  import org.sonatype.aether.RepositorySystem;
43  import org.sonatype.aether.RepositorySystemSession;
44  import org.sonatype.aether.repository.ArtifactRepository;
45  import org.sonatype.aether.repository.RemoteRepository;
46  import org.sonatype.aether.repository.RepositoryPolicy;
47  import org.sonatype.aether.resolution.MetadataRequest;
48  import org.sonatype.aether.resolution.MetadataResult;
49  import org.sonatype.aether.util.DefaultRepositorySystemSession;
50  import org.sonatype.aether.util.listener.DefaultRepositoryEvent;
51  import org.sonatype.aether.util.metadata.DefaultMetadata;
52  
53  /**
54   * Resolves a plugin prefix.
55   * 
56   * @since 3.0
57   * @author Benjamin Bentmann
58   */
59  @Component( role = PluginPrefixResolver.class )
60  public class DefaultPluginPrefixResolver
61      implements PluginPrefixResolver
62  {
63  
64      private static final String REPOSITORY_CONTEXT = "plugin";
65  
66      @Requirement
67      private Logger logger;
68  
69      @Requirement
70      private BuildPluginManager pluginManager;
71  
72      @Requirement
73      private RepositorySystem repositorySystem;
74  
75      @Requirement
76      private MetadataReader metadataReader;
77  
78      public PluginPrefixResult resolve( PluginPrefixRequest request )
79          throws NoPluginFoundForPrefixException
80      {
81          logger.debug( "Resolving plugin prefix " + request.getPrefix() + " from " + request.getPluginGroups() );
82  
83          PluginPrefixResult result = resolveFromProject( request );
84  
85          if ( result == null )
86          {
87              result = resolveFromRepository( request );
88  
89              if ( result == null )
90              {
91                  throw new NoPluginFoundForPrefixException( request.getPrefix(), request.getPluginGroups(),
92                                                             request.getRepositorySession().getLocalRepository(),
93                                                             request.getRepositories() );
94              }
95              else if ( logger.isDebugEnabled() )
96              {
97                  logger.debug( "Resolved plugin prefix " + request.getPrefix() + " to " + result.getGroupId() + ":"
98                      + result.getArtifactId() + " from repository "
99                      + ( result.getRepository() != null ? result.getRepository().getId() : "null" ) );
100             }
101         }
102         else if ( logger.isDebugEnabled() )
103         {
104             logger.debug( "Resolved plugin prefix " + request.getPrefix() + " to " + result.getGroupId() + ":"
105                 + result.getArtifactId() + " from POM " + request.getPom() );
106         }
107 
108         return result;
109     }
110 
111     private PluginPrefixResult resolveFromProject( PluginPrefixRequest request )
112     {
113         PluginPrefixResult result = null;
114 
115         if ( request.getPom() != null && request.getPom().getBuild() != null )
116         {
117             Build build = request.getPom().getBuild();
118 
119             result = resolveFromProject( request, build.getPlugins() );
120 
121             if ( result == null && build.getPluginManagement() != null )
122             {
123                 result = resolveFromProject( request, build.getPluginManagement().getPlugins() );
124             }
125         }
126 
127         return result;
128     }
129 
130     private PluginPrefixResult resolveFromProject( PluginPrefixRequest request, List<Plugin> plugins )
131     {
132         for ( Plugin plugin : plugins )
133         {
134             try
135             {
136                 PluginDescriptor pluginDescriptor =
137                     pluginManager.loadPlugin( plugin, request.getRepositories(), request.getRepositorySession() );
138 
139                 if ( request.getPrefix().equals( pluginDescriptor.getGoalPrefix() ) )
140                 {
141                     return new DefaultPluginPrefixResult( plugin );
142                 }
143             }
144             catch ( Exception e )
145             {
146                 if ( logger.isDebugEnabled() )
147                 {
148                     logger.warn( "Failed to retrieve plugin descriptor for " + plugin.getId() + ": " + e.getMessage(),
149                                  e );
150                 }
151                 else
152                 {
153                     logger.warn( "Failed to retrieve plugin descriptor for " + plugin.getId() + ": " + e.getMessage() );
154                 }
155             }
156         }
157 
158         return null;
159     }
160 
161     private PluginPrefixResult resolveFromRepository( PluginPrefixRequest request )
162     {
163         List<MetadataRequest> requests = new ArrayList<MetadataRequest>();
164 
165         for ( String pluginGroup : request.getPluginGroups() )
166         {
167             org.sonatype.aether.metadata.Metadata metadata =
168                 new DefaultMetadata( pluginGroup, "maven-metadata.xml", DefaultMetadata.Nature.RELEASE_OR_SNAPSHOT );
169 
170             requests.add( new MetadataRequest( metadata, null, REPOSITORY_CONTEXT ) );
171 
172             for ( RemoteRepository repository : request.getRepositories() )
173             {
174                 requests.add( new MetadataRequest( metadata, repository, REPOSITORY_CONTEXT ) );
175             }
176         }
177 
178         // initial try, use locally cached metadata
179 
180         List<MetadataResult> results = repositorySystem.resolveMetadata( request.getRepositorySession(), requests );
181         requests.clear();
182 
183         PluginPrefixResult result = processResults( request, results, requests );
184 
185         if ( result != null )
186         {
187             return result;
188         }
189 
190         // second try, refetch all (possibly outdated) metadata that wasn't updated in the first attempt
191 
192         if ( !request.getRepositorySession().isOffline() && !requests.isEmpty() )
193         {
194             DefaultRepositorySystemSession session =
195                 new DefaultRepositorySystemSession( request.getRepositorySession() );
196             session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_ALWAYS );
197 
198             results = repositorySystem.resolveMetadata( session, requests );
199 
200             return processResults( request, results, null );
201         }
202 
203         return null;
204     }
205 
206     private PluginPrefixResult processResults( PluginPrefixRequest request, List<MetadataResult> results,
207                                                List<MetadataRequest> requests )
208     {
209         for ( MetadataResult res : results )
210         {
211             org.sonatype.aether.metadata.Metadata metadata = res.getMetadata();
212 
213             if ( metadata != null )
214             {
215                 ArtifactRepository repository = res.getRequest().getRepository();
216                 if ( repository == null )
217                 {
218                     repository = request.getRepositorySession().getLocalRepository();
219                 }
220 
221                 PluginPrefixResult result =
222                     resolveFromRepository( request, metadata.getGroupId(), metadata, repository );
223 
224                 if ( result != null )
225                 {
226                     return result;
227                 }
228             }
229 
230             if ( requests != null && !res.isUpdated() )
231             {
232                 requests.add( res.getRequest() );
233             }
234         }
235 
236         return null;
237     }
238 
239     private PluginPrefixResult resolveFromRepository( PluginPrefixRequest request, String pluginGroup,
240                                                       org.sonatype.aether.metadata.Metadata metadata,
241                                                       ArtifactRepository repository )
242     {
243         if ( metadata != null && metadata.getFile() != null && metadata.getFile().isFile() )
244         {
245             try
246             {
247                 Map<String, ?> options = Collections.singletonMap( MetadataReader.IS_STRICT, Boolean.FALSE );
248 
249                 Metadata pluginGroupMetadata = metadataReader.read( metadata.getFile(), options );
250 
251                 List<org.apache.maven.artifact.repository.metadata.Plugin> plugins = pluginGroupMetadata.getPlugins();
252 
253                 if ( plugins != null )
254                 {
255                     for ( org.apache.maven.artifact.repository.metadata.Plugin plugin : plugins )
256                     {
257                         if ( request.getPrefix().equals( plugin.getPrefix() ) )
258                         {
259                             return new DefaultPluginPrefixResult( pluginGroup, plugin.getArtifactId(), repository );
260                         }
261                     }
262                 }
263             }
264             catch ( IOException e )
265             {
266                 invalidMetadata( request.getRepositorySession(), metadata, repository, e );
267             }
268         }
269 
270         return null;
271     }
272 
273     private void invalidMetadata( RepositorySystemSession session, org.sonatype.aether.metadata.Metadata metadata,
274                                   ArtifactRepository repository, Exception exception )
275     {
276         RepositoryListener listener = session.getRepositoryListener();
277         if ( listener != null )
278         {
279             DefaultRepositoryEvent event = new DefaultRepositoryEvent( session, metadata );
280             event.setException( exception );
281             event.setRepository( repository );
282             listener.metadataInvalid( event );
283         }
284     }
285 
286 }