1 package org.apache.maven.project;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.concurrent.atomic.AtomicReference;
29
30 import org.apache.maven.api.model.Dependency;
31 import org.apache.maven.api.model.Parent;
32 import org.apache.maven.api.model.Repository;
33 import org.apache.maven.model.Model;
34 import org.apache.maven.model.building.ArtifactModelSource;
35 import org.apache.maven.model.building.FileModelSource;
36 import org.apache.maven.model.building.ModelSource;
37 import org.apache.maven.model.resolution.InvalidRepositoryException;
38 import org.apache.maven.model.resolution.ModelResolver;
39 import org.apache.maven.model.resolution.UnresolvableModelException;
40 import org.apache.maven.repository.internal.ArtifactDescriptorUtils;
41 import org.eclipse.aether.RepositorySystem;
42 import org.eclipse.aether.RepositorySystemSession;
43 import org.eclipse.aether.RequestTrace;
44 import org.eclipse.aether.artifact.Artifact;
45 import org.eclipse.aether.artifact.DefaultArtifact;
46 import org.eclipse.aether.impl.RemoteRepositoryManager;
47 import org.eclipse.aether.repository.RemoteRepository;
48 import org.eclipse.aether.resolution.ArtifactRequest;
49 import org.eclipse.aether.resolution.ArtifactResolutionException;
50 import org.eclipse.aether.resolution.VersionRangeRequest;
51 import org.eclipse.aether.resolution.VersionRangeResolutionException;
52 import org.eclipse.aether.resolution.VersionRangeResult;
53
54
55
56
57
58
59
60
61 public class ProjectModelResolver
62 implements ModelResolver
63 {
64
65 private final RepositorySystemSession session;
66
67 private final RequestTrace trace;
68
69 private final String context = "project";
70
71 private List<RemoteRepository> repositories;
72
73 private List<RemoteRepository> pomRepositories;
74
75 private final List<RemoteRepository> externalRepositories;
76
77 private final RepositorySystem resolver;
78
79 private final RemoteRepositoryManager remoteRepositoryManager;
80
81 private final Set<String> repositoryIds;
82
83 private final ReactorModelPool modelPool;
84
85 private final ProjectBuildingRequest.RepositoryMerging repositoryMerging;
86
87 public ProjectModelResolver( RepositorySystemSession session, RequestTrace trace, RepositorySystem resolver,
88 RemoteRepositoryManager remoteRepositoryManager, List<RemoteRepository> repositories,
89 ProjectBuildingRequest.RepositoryMerging repositoryMerging,
90 ReactorModelPool modelPool )
91 {
92 this.session = session;
93 this.trace = trace;
94 this.resolver = resolver;
95 this.remoteRepositoryManager = remoteRepositoryManager;
96 this.pomRepositories = new ArrayList<>();
97 this.externalRepositories = Collections.unmodifiableList( new ArrayList<>( repositories ) );
98 this.repositories = new ArrayList<>();
99 this.repositories.addAll( externalRepositories );
100 this.repositoryMerging = repositoryMerging;
101 this.repositoryIds = new HashSet<>();
102 this.modelPool = modelPool;
103 }
104
105 private ProjectModelResolver( ProjectModelResolver original )
106 {
107 this.session = original.session;
108 this.trace = original.trace;
109 this.resolver = original.resolver;
110 this.remoteRepositoryManager = original.remoteRepositoryManager;
111 this.pomRepositories = new ArrayList<>( original.pomRepositories );
112 this.externalRepositories = original.externalRepositories;
113 this.repositories = new ArrayList<>( original.repositories );
114 this.repositoryMerging = original.repositoryMerging;
115 this.repositoryIds = new HashSet<>( original.repositoryIds );
116 this.modelPool = original.modelPool;
117 }
118
119 public void addRepository( Repository repository )
120 throws InvalidRepositoryException
121 {
122 addRepository( repository, false );
123 }
124
125 @Override
126 public void addRepository( final Repository repository, boolean replace )
127 throws InvalidRepositoryException
128 {
129 if ( !repositoryIds.add( repository.getId() ) )
130 {
131 if ( !replace )
132 {
133 return;
134 }
135
136
137 removeMatchingRepository( repositories, repository.getId() );
138 removeMatchingRepository( pomRepositories, repository.getId() );
139 }
140
141 List<RemoteRepository> newRepositories =
142 Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository(
143 new org.apache.maven.model.Repository( repository ) ) );
144
145 if ( ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT.equals( repositoryMerging ) )
146 {
147 repositories = remoteRepositoryManager.aggregateRepositories( session, repositories, newRepositories,
148 true );
149 }
150 else
151 {
152 pomRepositories =
153 remoteRepositoryManager.aggregateRepositories( session, pomRepositories, newRepositories, true );
154 repositories =
155 remoteRepositoryManager.aggregateRepositories( session, pomRepositories, externalRepositories, false );
156 }
157 }
158
159 private static void removeMatchingRepository( Iterable<RemoteRepository> repositories, final String id )
160 {
161 Iterator<RemoteRepository> iterator = repositories.iterator( );
162 while ( iterator.hasNext() )
163 {
164 RemoteRepository next = iterator.next();
165 if ( next.getId().equals( id ) )
166 {
167 iterator.remove();
168 }
169 }
170 }
171
172 public ModelResolver newCopy()
173 {
174 return new ProjectModelResolver( this );
175 }
176
177 public ModelSource resolveModel( String groupId, String artifactId, String version )
178 throws UnresolvableModelException
179 {
180 Artifact pomArtifact = new DefaultArtifact( groupId, artifactId, "", "pom", version );
181
182 try
183 {
184 ArtifactRequest request = new ArtifactRequest( pomArtifact, repositories, context );
185 request.setTrace( trace );
186 pomArtifact = resolver.resolveArtifact( session, request ).getArtifact();
187 }
188 catch ( ArtifactResolutionException e )
189 {
190 throw new UnresolvableModelException( e.getMessage(), groupId, artifactId, version, e );
191 }
192
193 return new ArtifactModelSource( pomArtifact.getFile(), groupId, artifactId, version );
194 }
195
196 @Override
197 public ModelSource resolveModel( final Parent parent, AtomicReference<Parent> modified )
198 throws UnresolvableModelException
199 {
200 try
201 {
202 final Artifact artifact = new DefaultArtifact( parent.getGroupId(), parent.getArtifactId(), "", "pom",
203 parent.getVersion() );
204
205 final VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context );
206 versionRangeRequest.setTrace( trace );
207
208 final VersionRangeResult versionRangeResult = resolver.resolveVersionRange( session, versionRangeRequest );
209
210 if ( versionRangeResult.getHighestVersion() == null )
211 {
212 throw new UnresolvableModelException(
213 String.format( "No versions matched the requested parent version range '%s'",
214 parent.getVersion() ),
215 parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
216
217 }
218
219 if ( versionRangeResult.getVersionConstraint() != null
220 && versionRangeResult.getVersionConstraint().getRange() != null
221 && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null )
222 {
223
224 throw new UnresolvableModelException(
225 String.format( "The requested parent version range '%s' does not specify an upper bound",
226 parent.getVersion() ),
227 parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
228
229 }
230
231 String newVersion = versionRangeResult.getHighestVersion().toString();
232 if ( !parent.getVersion().equals( newVersion ) )
233 {
234 modified.set( parent.withVersion( newVersion ) );
235 }
236
237 return resolveModel( parent.getGroupId(), parent.getArtifactId(), newVersion );
238 }
239 catch ( final VersionRangeResolutionException e )
240 {
241 throw new UnresolvableModelException( e.getMessage(), parent.getGroupId(), parent.getArtifactId(),
242 parent.getVersion(), e );
243
244 }
245 }
246
247 @Override
248 public ModelSource resolveModel( final Dependency dependency, AtomicReference<Dependency> modified )
249 throws UnresolvableModelException
250 {
251 try
252 {
253 final Artifact artifact = new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), "",
254 "pom", dependency.getVersion() );
255
256 final VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context );
257 versionRangeRequest.setTrace( trace );
258
259 final VersionRangeResult versionRangeResult = resolver.resolveVersionRange( session, versionRangeRequest );
260
261 if ( versionRangeResult.getHighestVersion() == null )
262 {
263 throw new UnresolvableModelException(
264 String.format( "No versions matched the requested dependency version range '%s'",
265 dependency.getVersion() ),
266 dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() );
267
268 }
269
270 if ( versionRangeResult.getVersionConstraint() != null
271 && versionRangeResult.getVersionConstraint().getRange() != null
272 && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null )
273 {
274
275 throw new UnresolvableModelException(
276 String.format( "The requested dependency version range '%s' does not specify an upper bound",
277 dependency.getVersion() ),
278 dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() );
279
280 }
281
282 String newVersion = versionRangeResult.getHighestVersion().toString();
283 if ( !dependency.getVersion().equals( newVersion ) )
284 {
285 modified.set( dependency.withVersion( newVersion ) );
286 }
287
288 if ( modelPool != null )
289 {
290 Model model =
291 modelPool.get( dependency.getGroupId(), dependency.getArtifactId(), newVersion );
292
293 if ( model != null )
294 {
295 return new FileModelSource( model.getPomFile() );
296 }
297 }
298
299 return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), newVersion );
300 }
301 catch ( VersionRangeResolutionException e )
302 {
303 throw new UnresolvableModelException( e.getMessage(), dependency.getGroupId(), dependency.getArtifactId(),
304 dependency.getVersion(), e );
305
306 }
307 }
308
309 @Override
310 public ModelSource resolveModel( org.apache.maven.model.Parent parent ) throws UnresolvableModelException
311 {
312 AtomicReference<org.apache.maven.api.model.Parent> resolvedParent = new AtomicReference<>();
313 ModelSource result = resolveModel( parent.getDelegate(), resolvedParent );
314 if ( resolvedParent.get() != null )
315 {
316 parent.setVersion( resolvedParent.get().getVersion() );
317 }
318 return result;
319 }
320
321 @Override
322 public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException
323 {
324 AtomicReference<org.apache.maven.api.model.Dependency> resolvedDependency = new AtomicReference<>();
325 ModelSource result = resolveModel( dependency.getDelegate(), resolvedDependency );
326 if ( resolvedDependency.get() != null )
327 {
328 dependency.setVersion( resolvedDependency.get().getVersion() );
329 }
330 return result;
331 }
332
333 @Override
334 public void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException
335 {
336 addRepository( repository.getDelegate() );
337 }
338
339 @Override
340 public void addRepository( org.apache.maven.model.Repository repository, boolean replace )
341 throws InvalidRepositoryException
342 {
343 addRepository( repository.getDelegate(), replace );
344 }
345 }