View Javadoc
1   package org.apache.maven.repository.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.File;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.Set;
28  
29  import org.apache.maven.model.Parent;
30  import org.apache.maven.model.Repository;
31  import org.apache.maven.model.building.FileModelSource;
32  import org.apache.maven.model.building.ModelSource;
33  import org.apache.maven.model.resolution.InvalidRepositoryException;
34  import org.apache.maven.model.resolution.ModelResolver;
35  import org.apache.maven.model.resolution.UnresolvableModelException;
36  import org.eclipse.aether.RepositorySystemSession;
37  import org.eclipse.aether.RequestTrace;
38  import org.eclipse.aether.artifact.Artifact;
39  import org.eclipse.aether.artifact.DefaultArtifact;
40  import org.eclipse.aether.impl.ArtifactResolver;
41  import org.eclipse.aether.impl.RemoteRepositoryManager;
42  import org.eclipse.aether.impl.VersionRangeResolver;
43  import org.eclipse.aether.repository.RemoteRepository;
44  import org.eclipse.aether.resolution.ArtifactRequest;
45  import org.eclipse.aether.resolution.ArtifactResolutionException;
46  import org.eclipse.aether.resolution.VersionRangeRequest;
47  import org.eclipse.aether.resolution.VersionRangeResolutionException;
48  import org.eclipse.aether.resolution.VersionRangeResult;
49  
50  /**
51   * A model resolver to assist building of dependency POMs. This resolver gives priority to those repositories that have
52   * been initially specified and repositories discovered in dependency POMs are recessively merged into the search chain.
53   * 
54   * @author Benjamin Bentmann
55   * @see DefaultArtifactDescriptorReader
56   */
57  class DefaultModelResolver
58      implements ModelResolver
59  {
60  
61      private final RepositorySystemSession session;
62  
63      private final RequestTrace trace;
64  
65      private final String context;
66  
67      private List<RemoteRepository> repositories;
68  
69      private final List<RemoteRepository> externalRepositories;
70  
71      private final ArtifactResolver resolver;
72  
73      private final VersionRangeResolver versionRangeResolver;
74  
75      private final RemoteRepositoryManager remoteRepositoryManager;
76  
77      private final Set<String> repositoryIds;
78  
79      public DefaultModelResolver( RepositorySystemSession session, RequestTrace trace, String context,
80                                   ArtifactResolver resolver, VersionRangeResolver versionRangeResolver,
81                                   RemoteRepositoryManager remoteRepositoryManager, List<RemoteRepository> repositories )
82      {
83          this.session = session;
84          this.trace = trace;
85          this.context = context;
86          this.resolver = resolver;
87          this.versionRangeResolver = versionRangeResolver;
88          this.remoteRepositoryManager = remoteRepositoryManager;
89          this.repositories = repositories;
90          List<RemoteRepository> externalRepositories = new ArrayList<RemoteRepository>();
91          externalRepositories.addAll( repositories );
92          this.externalRepositories = Collections.unmodifiableList( externalRepositories );
93  
94          this.repositoryIds = new HashSet<String>();
95      }
96  
97      private DefaultModelResolver( DefaultModelResolver original )
98      {
99          this.session = original.session;
100         this.trace = original.trace;
101         this.context = original.context;
102         this.resolver = original.resolver;
103         this.versionRangeResolver = original.versionRangeResolver;
104         this.remoteRepositoryManager = original.remoteRepositoryManager;
105         this.repositories = original.repositories;
106         this.externalRepositories = original.externalRepositories;
107         this.repositoryIds = new HashSet<String>( original.repositoryIds );
108     }
109 
110     @Override
111     public void addRepository( Repository repository )
112         throws InvalidRepositoryException
113     {
114         if ( session.isIgnoreArtifactDescriptorRepositories() || !repositoryIds.add( repository.getId() ) )
115         {
116             return;
117         }
118 
119         List<RemoteRepository> newRepositories =
120             Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( repository ) );
121 
122         this.repositories =
123             remoteRepositoryManager.aggregateRepositories( session, repositories, newRepositories, true );
124     }
125 
126     @Override
127     public void resetRepositories()
128     {
129         this.repositoryIds.clear();
130         this.repositories.clear();
131         this.repositories.addAll( externalRepositories );
132     }
133 
134     @Override
135     public ModelResolver newCopy()
136     {
137         return new DefaultModelResolver( this );
138     }
139 
140     @Override
141     public ModelSource resolveModel( String groupId, String artifactId, String version )
142         throws UnresolvableModelException
143     {
144         Artifact pomArtifact = new DefaultArtifact( groupId, artifactId, "", "pom", version );
145 
146         try
147         {
148             ArtifactRequest request = new ArtifactRequest( pomArtifact, repositories, context );
149             request.setTrace( trace );
150             pomArtifact = resolver.resolveArtifact( session, request ).getArtifact();
151         }
152         catch ( ArtifactResolutionException e )
153         {
154             throw new UnresolvableModelException( e.getMessage(), groupId, artifactId, version, e );
155         }
156 
157         File pomFile = pomArtifact.getFile();
158 
159         return new FileModelSource( pomFile );
160     }
161 
162     public ModelSource resolveModel( Parent parent )
163         throws UnresolvableModelException
164     {
165         Artifact artifact = new DefaultArtifact( parent.getGroupId(), parent.getArtifactId(), "", "pom",
166                                                  parent.getVersion() );
167 
168         VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context );
169         versionRangeRequest.setTrace( trace );
170 
171         try
172         {
173             VersionRangeResult versionRangeResult =
174                 versionRangeResolver.resolveVersionRange( session, versionRangeRequest );
175 
176             if ( versionRangeResult.getHighestVersion() == null )
177             {
178                 throw new UnresolvableModelException( "No versions matched the requested range '" + parent.getVersion()
179                                                           + "'", parent.getGroupId(), parent.getArtifactId(),
180                                                       parent.getVersion() );
181 
182             }
183 
184             if ( versionRangeResult.getVersionConstraint() != null
185                      && versionRangeResult.getVersionConstraint().getRange() != null
186                      && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null )
187             {
188                 throw new UnresolvableModelException( "The requested version range '" + parent.getVersion()
189                                                           + "' does not specify an upper bound", parent.getGroupId(),
190                                                       parent.getArtifactId(), parent.getVersion() );
191 
192             }
193 
194             parent.setVersion( versionRangeResult.getHighestVersion().toString() );
195         }
196         catch ( VersionRangeResolutionException e )
197         {
198             throw new UnresolvableModelException( e.getMessage(), parent.getGroupId(), parent.getArtifactId(),
199                                                   parent.getVersion(), e );
200 
201         }
202 
203         return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
204     }
205 
206 }