001 package org.apache.maven.plugin.prefix.internal;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.io.IOException;
023 import java.util.ArrayList;
024 import java.util.Collections;
025 import java.util.List;
026 import java.util.Map;
027
028 import org.apache.maven.artifact.repository.metadata.Metadata;
029 import org.apache.maven.artifact.repository.metadata.io.MetadataReader;
030 import org.apache.maven.model.Build;
031 import org.apache.maven.model.Plugin;
032 import org.apache.maven.plugin.BuildPluginManager;
033 import org.apache.maven.plugin.descriptor.PluginDescriptor;
034 import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
035 import org.apache.maven.plugin.prefix.PluginPrefixRequest;
036 import org.apache.maven.plugin.prefix.PluginPrefixResolver;
037 import org.apache.maven.plugin.prefix.PluginPrefixResult;
038 import org.codehaus.plexus.component.annotations.Component;
039 import org.codehaus.plexus.component.annotations.Requirement;
040 import org.codehaus.plexus.logging.Logger;
041 import org.eclipse.aether.RepositoryEvent.EventType;
042 import org.eclipse.aether.DefaultRepositorySystemSession;
043 import org.eclipse.aether.RepositoryEvent;
044 import org.eclipse.aether.RepositoryListener;
045 import org.eclipse.aether.RepositorySystem;
046 import org.eclipse.aether.RepositorySystemSession;
047 import org.eclipse.aether.RequestTrace;
048 import org.eclipse.aether.metadata.DefaultMetadata;
049 import org.eclipse.aether.repository.ArtifactRepository;
050 import org.eclipse.aether.repository.RemoteRepository;
051 import org.eclipse.aether.repository.RepositoryPolicy;
052 import org.eclipse.aether.resolution.MetadataRequest;
053 import org.eclipse.aether.resolution.MetadataResult;
054
055 /**
056 * Resolves a plugin prefix.
057 *
058 * @since 3.0
059 * @author Benjamin Bentmann
060 */
061 @Component( role = PluginPrefixResolver.class )
062 public class DefaultPluginPrefixResolver
063 implements PluginPrefixResolver
064 {
065
066 private static final String REPOSITORY_CONTEXT = "plugin";
067
068 @Requirement
069 private Logger logger;
070
071 @Requirement
072 private BuildPluginManager pluginManager;
073
074 @Requirement
075 private RepositorySystem repositorySystem;
076
077 @Requirement
078 private MetadataReader metadataReader;
079
080 public PluginPrefixResult resolve( PluginPrefixRequest request )
081 throws NoPluginFoundForPrefixException
082 {
083 logger.debug( "Resolving plugin prefix " + request.getPrefix() + " from " + request.getPluginGroups() );
084
085 PluginPrefixResult result = resolveFromProject( request );
086
087 if ( result == null )
088 {
089 result = resolveFromRepository( request );
090
091 if ( result == null )
092 {
093 throw new NoPluginFoundForPrefixException( request.getPrefix(), request.getPluginGroups(),
094 request.getRepositorySession().getLocalRepository(),
095 request.getRepositories() );
096 }
097 else if ( logger.isDebugEnabled() )
098 {
099 logger.debug( "Resolved plugin prefix " + request.getPrefix() + " to " + result.getGroupId() + ":"
100 + result.getArtifactId() + " from repository "
101 + ( result.getRepository() != null ? result.getRepository().getId() : "null" ) );
102 }
103 }
104 else if ( logger.isDebugEnabled() )
105 {
106 logger.debug( "Resolved plugin prefix " + request.getPrefix() + " to " + result.getGroupId() + ":"
107 + result.getArtifactId() + " from POM " + request.getPom() );
108 }
109
110 return result;
111 }
112
113 private PluginPrefixResult resolveFromProject( PluginPrefixRequest request )
114 {
115 PluginPrefixResult result = null;
116
117 if ( request.getPom() != null && request.getPom().getBuild() != null )
118 {
119 Build build = request.getPom().getBuild();
120
121 result = resolveFromProject( request, build.getPlugins() );
122
123 if ( result == null && build.getPluginManagement() != null )
124 {
125 result = resolveFromProject( request, build.getPluginManagement().getPlugins() );
126 }
127 }
128
129 return result;
130 }
131
132 private PluginPrefixResult resolveFromProject( PluginPrefixRequest request, List<Plugin> plugins )
133 {
134 for ( Plugin plugin : plugins )
135 {
136 try
137 {
138 PluginDescriptor pluginDescriptor =
139 pluginManager.loadPlugin( plugin, request.getRepositories(), request.getRepositorySession() );
140
141 if ( request.getPrefix().equals( pluginDescriptor.getGoalPrefix() ) )
142 {
143 return new DefaultPluginPrefixResult( plugin );
144 }
145 }
146 catch ( Exception e )
147 {
148 if ( logger.isDebugEnabled() )
149 {
150 logger.warn( "Failed to retrieve plugin descriptor for " + plugin.getId() + ": " + e.getMessage(),
151 e );
152 }
153 else
154 {
155 logger.warn( "Failed to retrieve plugin descriptor for " + plugin.getId() + ": " + e.getMessage() );
156 }
157 }
158 }
159
160 return null;
161 }
162
163 private PluginPrefixResult resolveFromRepository( PluginPrefixRequest request )
164 {
165 RequestTrace trace = RequestTrace.newChild( null, request );
166
167 List<MetadataRequest> requests = new ArrayList<MetadataRequest>();
168
169 for ( String pluginGroup : request.getPluginGroups() )
170 {
171 org.eclipse.aether.metadata.Metadata metadata =
172 new DefaultMetadata( pluginGroup, "maven-metadata.xml", DefaultMetadata.Nature.RELEASE_OR_SNAPSHOT );
173
174 requests.add( new MetadataRequest( metadata, null, REPOSITORY_CONTEXT ).setTrace( trace ) );
175
176 for ( RemoteRepository repository : request.getRepositories() )
177 {
178 requests.add( new MetadataRequest( metadata, repository, REPOSITORY_CONTEXT ).setTrace( trace ) );
179 }
180 }
181
182 // initial try, use locally cached metadata
183
184 List<MetadataResult> results = repositorySystem.resolveMetadata( request.getRepositorySession(), requests );
185 requests.clear();
186
187 PluginPrefixResult result = processResults( request, trace, results, requests );
188
189 if ( result != null )
190 {
191 return result;
192 }
193
194 // second try, refetch all (possibly outdated) metadata that wasn't updated in the first attempt
195
196 if ( !request.getRepositorySession().isOffline() && !requests.isEmpty() )
197 {
198 DefaultRepositorySystemSession session =
199 new DefaultRepositorySystemSession( request.getRepositorySession() );
200 session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_ALWAYS );
201
202 results = repositorySystem.resolveMetadata( session, requests );
203
204 return processResults( request, trace, results, null );
205 }
206
207 return null;
208 }
209
210 private PluginPrefixResult processResults( PluginPrefixRequest request, RequestTrace trace,
211 List<MetadataResult> results, List<MetadataRequest> requests )
212 {
213 for ( MetadataResult res : results )
214 {
215 org.eclipse.aether.metadata.Metadata metadata = res.getMetadata();
216
217 if ( metadata != null )
218 {
219 ArtifactRepository repository = res.getRequest().getRepository();
220 if ( repository == null )
221 {
222 repository = request.getRepositorySession().getLocalRepository();
223 }
224
225 PluginPrefixResult result =
226 resolveFromRepository( request, trace, metadata.getGroupId(), metadata, repository );
227
228 if ( result != null )
229 {
230 return result;
231 }
232 }
233
234 if ( requests != null && !res.isUpdated() )
235 {
236 requests.add( res.getRequest() );
237 }
238 }
239
240 return null;
241 }
242
243 private PluginPrefixResult resolveFromRepository( PluginPrefixRequest request, RequestTrace trace,
244 String pluginGroup,
245 org.eclipse.aether.metadata.Metadata metadata,
246 ArtifactRepository repository )
247 {
248 if ( metadata != null && metadata.getFile() != null && metadata.getFile().isFile() )
249 {
250 try
251 {
252 Map<String, ?> options = Collections.singletonMap( MetadataReader.IS_STRICT, Boolean.FALSE );
253
254 Metadata pluginGroupMetadata = metadataReader.read( metadata.getFile(), options );
255
256 List<org.apache.maven.artifact.repository.metadata.Plugin> plugins = pluginGroupMetadata.getPlugins();
257
258 if ( plugins != null )
259 {
260 for ( org.apache.maven.artifact.repository.metadata.Plugin plugin : plugins )
261 {
262 if ( request.getPrefix().equals( plugin.getPrefix() ) )
263 {
264 return new DefaultPluginPrefixResult( pluginGroup, plugin.getArtifactId(), repository );
265 }
266 }
267 }
268 }
269 catch ( IOException e )
270 {
271 invalidMetadata( request.getRepositorySession(), trace, metadata, repository, e );
272 }
273 }
274
275 return null;
276 }
277
278 private void invalidMetadata( RepositorySystemSession session, RequestTrace trace,
279 org.eclipse.aether.metadata.Metadata metadata, ArtifactRepository repository,
280 Exception exception )
281 {
282 RepositoryListener listener = session.getRepositoryListener();
283 if ( listener != null )
284 {
285 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INVALID );
286 event.setTrace( trace );
287 event.setMetadata( metadata );
288 event.setException( exception );
289 event.setRepository( repository );
290 listener.metadataInvalid( event.build() );
291 }
292 }
293
294 }