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