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