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