1 package org.apache.maven.plugin.version.internal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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.Versioning;
30 import org.apache.maven.artifact.repository.metadata.io.MetadataReader;
31 import org.apache.maven.model.Build;
32 import org.apache.maven.model.Plugin;
33 import org.apache.maven.plugin.version.PluginVersionRequest;
34 import org.apache.maven.plugin.version.PluginVersionResolutionException;
35 import org.apache.maven.plugin.version.PluginVersionResolver;
36 import org.apache.maven.plugin.version.PluginVersionResult;
37 import org.codehaus.plexus.component.annotations.Component;
38 import org.codehaus.plexus.component.annotations.Requirement;
39 import org.codehaus.plexus.logging.Logger;
40 import org.codehaus.plexus.util.StringUtils;
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.LocalRepository;
47 import org.sonatype.aether.repository.RemoteRepository;
48 import org.sonatype.aether.resolution.MetadataRequest;
49 import org.sonatype.aether.resolution.MetadataResult;
50 import org.sonatype.aether.util.listener.DefaultRepositoryEvent;
51 import org.sonatype.aether.util.metadata.DefaultMetadata;
52
53
54
55
56
57
58
59 @Component( role = PluginVersionResolver.class )
60 public class DefaultPluginVersionResolver
61 implements PluginVersionResolver
62 {
63
64 private static final String REPOSITORY_CONTEXT = "plugin";
65
66 @Requirement
67 private Logger logger;
68
69 @Requirement
70 private RepositorySystem repositorySystem;
71
72 @Requirement
73 private MetadataReader metadataReader;
74
75 public PluginVersionResult resolve( PluginVersionRequest request )
76 throws PluginVersionResolutionException
77 {
78 logger.debug( "Resolving plugin version for " + request.getGroupId() + ":" + request.getArtifactId() );
79
80 PluginVersionResult result = resolveFromProject( request );
81
82 if ( result == null )
83 {
84 result = resolveFromRepository( request );
85
86 if ( logger.isDebugEnabled() )
87 {
88 logger.debug( "Resolved plugin version for " + request.getGroupId() + ":" + request.getArtifactId()
89 + " to " + result.getVersion() + " from repository " + result.getRepository() );
90 }
91 }
92 else if ( logger.isDebugEnabled() )
93 {
94 logger.debug( "Resolved plugin version for " + request.getGroupId() + ":" + request.getArtifactId()
95 + " to " + result.getVersion() + " from POM " + request.getPom() );
96 }
97
98 return result;
99 }
100
101 private PluginVersionResult resolveFromRepository( PluginVersionRequest request )
102 throws PluginVersionResolutionException
103 {
104 DefaultPluginVersionResult result = new DefaultPluginVersionResult();
105
106 org.sonatype.aether.metadata.Metadata metadata =
107 new DefaultMetadata( request.getGroupId(), request.getArtifactId(), "maven-metadata.xml",
108 DefaultMetadata.Nature.RELEASE_OR_SNAPSHOT );
109
110 List<MetadataRequest> requests = new ArrayList<MetadataRequest>();
111
112 requests.add( new MetadataRequest( metadata, null, REPOSITORY_CONTEXT ) );
113
114 for ( RemoteRepository repository : request.getRepositories() )
115 {
116 requests.add( new MetadataRequest( metadata, repository, REPOSITORY_CONTEXT ) );
117 }
118
119 List<MetadataResult> results = repositorySystem.resolveMetadata( request.getRepositorySession(), requests );
120
121 LocalRepository localRepo = request.getRepositorySession().getLocalRepository();
122
123 Versions versions = new Versions();
124
125 for ( MetadataResult res : results )
126 {
127 ArtifactRepository repository = res.getRequest().getRepository();
128 if ( repository == null )
129 {
130 repository = request.getRepositorySession().getLocalRepository();
131 }
132
133 mergeMetadata( request.getRepositorySession(), versions, res.getMetadata(), repository );
134 }
135
136 if ( StringUtils.isNotEmpty( versions.releaseVersion ) )
137 {
138 result.setVersion( versions.releaseVersion );
139 result.setRepository( ( versions.releaseRepository == null ) ? localRepo : versions.releaseRepository );
140 }
141 else if ( StringUtils.isNotEmpty( versions.latestVersion ) )
142 {
143 result.setVersion( versions.latestVersion );
144 result.setRepository( ( versions.latestRepository == null ) ? localRepo : versions.latestRepository );
145 }
146 else
147 {
148 throw new PluginVersionResolutionException( request.getGroupId(), request.getArtifactId(), localRepo,
149 request.getRepositories(),
150 "Plugin not found in any plugin repository" );
151 }
152
153 return result;
154 }
155
156 private void mergeMetadata( RepositorySystemSession session, Versions versions,
157 org.sonatype.aether.metadata.Metadata metadata, ArtifactRepository repository )
158 {
159 if ( metadata != null && metadata.getFile() != null && metadata.getFile().isFile() )
160 {
161 try
162 {
163 Map<String, ?> options = Collections.singletonMap( MetadataReader.IS_STRICT, Boolean.FALSE );
164
165 Metadata repoMetadata = metadataReader.read( metadata.getFile(), options );
166
167 mergeMetadata( versions, repoMetadata, repository );
168 }
169 catch ( IOException e )
170 {
171 invalidMetadata( session, metadata, repository, e );
172 }
173 }
174 }
175
176 private void invalidMetadata( RepositorySystemSession session, org.sonatype.aether.metadata.Metadata metadata,
177 ArtifactRepository repository, Exception exception )
178 {
179 RepositoryListener listener = session.getRepositoryListener();
180 if ( listener != null )
181 {
182 DefaultRepositoryEvent event = new DefaultRepositoryEvent( EventType.METADATA_INVALID, session );
183 event.setMetadata( metadata );
184 event.setException( exception );
185 event.setRepository( repository );
186 listener.metadataInvalid( event );
187 }
188 }
189
190 private void mergeMetadata( Versions versions, Metadata source, ArtifactRepository repository )
191 {
192 Versioning versioning = source.getVersioning();
193 if ( versioning != null )
194 {
195 String timestamp = StringUtils.clean( versioning.getLastUpdated() );
196
197 if ( StringUtils.isNotEmpty( versioning.getRelease() )
198 && timestamp.compareTo( versions.releaseTimestamp ) > 0 )
199 {
200 versions.releaseVersion = versioning.getRelease();
201 versions.releaseTimestamp = timestamp;
202 versions.releaseRepository = repository;
203 }
204
205 if ( StringUtils.isNotEmpty( versioning.getLatest() )
206 && timestamp.compareTo( versions.latestTimestamp ) > 0 )
207 {
208 versions.latestVersion = versioning.getLatest();
209 versions.latestTimestamp = timestamp;
210 versions.latestRepository = repository;
211 }
212 }
213 }
214
215 private PluginVersionResult resolveFromProject( PluginVersionRequest request )
216 {
217 PluginVersionResult result = null;
218
219 if ( request.getPom() != null && request.getPom().getBuild() != null )
220 {
221 Build build = request.getPom().getBuild();
222
223 result = resolveFromProject( request, build.getPlugins() );
224
225 if ( result == null && build.getPluginManagement() != null )
226 {
227 result = resolveFromProject( request, build.getPluginManagement().getPlugins() );
228 }
229 }
230
231 return result;
232 }
233
234 private PluginVersionResult resolveFromProject( PluginVersionRequest request, List<Plugin> plugins )
235 {
236 for ( Plugin plugin : plugins )
237 {
238 if ( request.getGroupId().equals( plugin.getGroupId() )
239 && request.getArtifactId().equals( plugin.getArtifactId() ) )
240 {
241 if ( plugin.getVersion() != null )
242 {
243 return new DefaultPluginVersionResult( plugin.getVersion() );
244 }
245 else
246 {
247 return null;
248 }
249 }
250 }
251 return null;
252 }
253
254 static class Versions
255 {
256
257 String releaseVersion = "";
258
259 String releaseTimestamp = "";
260
261 ArtifactRepository releaseRepository;
262
263 String latestVersion = "";
264
265 String latestTimestamp = "";
266
267 ArtifactRepository latestRepository;
268
269 }
270
271 }