View Javadoc

1   package org.apache.maven.artifact.resolver;
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 org.apache.maven.artifact.Artifact;
23  import org.apache.maven.artifact.factory.ArtifactFactory;
24  import org.apache.maven.artifact.manager.WagonManager;
25  import org.apache.maven.artifact.metadata.ArtifactMetadata;
26  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
27  import org.apache.maven.artifact.repository.ArtifactRepository;
28  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
29  import org.apache.maven.artifact.repository.metadata.Metadata;
30  import org.apache.maven.artifact.repository.metadata.Snapshot;
31  import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;
32  import org.apache.maven.artifact.repository.metadata.Versioning;
33  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
34  import org.apache.maven.artifact.transform.ArtifactTransformationManager;
35  import org.apache.maven.wagon.ResourceDoesNotExistException;
36  import org.apache.maven.wagon.TransferFailedException;
37  import org.codehaus.plexus.logging.AbstractLogEnabled;
38  import org.codehaus.plexus.util.FileUtils;
39  
40  import java.io.File;
41  import java.io.IOException;
42  import java.util.ArrayList;
43  import java.util.Collections;
44  import java.util.Date;
45  import java.util.Iterator;
46  import java.util.List;
47  import java.util.Map;
48  import java.util.Set;
49  import java.util.HashMap;
50  
51  public class DefaultArtifactResolver
52      extends AbstractLogEnabled
53      implements ArtifactResolver
54  {
55      // ----------------------------------------------------------------------
56      // Components
57      // ----------------------------------------------------------------------
58  
59      private WagonManager wagonManager;
60  
61      private ArtifactTransformationManager transformationManager;
62  
63      protected ArtifactFactory artifactFactory;
64  
65      private ArtifactCollector artifactCollector;
66  
67      // ----------------------------------------------------------------------
68      // Implementation
69      // ----------------------------------------------------------------------
70  
71      public void resolve( Artifact artifact, List remoteRepositories, ArtifactRepository localRepository )
72          throws ArtifactResolutionException, ArtifactNotFoundException
73      {
74          resolve( artifact, remoteRepositories, localRepository, false );
75      }
76  
77      public void resolveAlways( Artifact artifact, List remoteRepositories, ArtifactRepository localRepository )
78          throws ArtifactResolutionException, ArtifactNotFoundException
79      {
80          resolve( artifact, remoteRepositories, localRepository, true );
81      }
82  
83      private void resolve( Artifact artifact, List remoteRepositories, ArtifactRepository localRepository,
84                            boolean force )
85          throws ArtifactResolutionException, ArtifactNotFoundException
86      {
87          if ( artifact == null )
88          {
89              return;
90          }
91  
92          if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
93          {
94              File systemFile = artifact.getFile();
95  
96              if ( systemFile == null )
97              {
98                  throw new ArtifactNotFoundException(
99                      "System artifact: " + artifact + " has no file attached", artifact );
100             }
101 
102             if ( !systemFile.isFile() )
103             {
104                 throw new ArtifactNotFoundException( "System artifact: " + artifact
105                     + " is not a file: " + systemFile, artifact );
106             }
107 
108             if ( !systemFile.exists() )
109             {
110                 throw new ArtifactNotFoundException(
111                     "System artifact: " + artifact + " not found in path: " + systemFile,
112                     artifact );
113             }
114 
115             artifact.setResolved( true );
116         }
117         else if ( !artifact.isResolved() )
118         {
119             // ----------------------------------------------------------------------
120             // Check for the existence of the artifact in the specified local
121             // ArtifactRepository. If it is present then simply return as the
122             // request for resolution has been satisfied.
123             // ----------------------------------------------------------------------
124 
125             String localPath = localRepository.pathOf( artifact );
126 
127             artifact.setFile( new File( localRepository.getBasedir(), localPath ) );
128 
129             transformationManager.transformForResolve( artifact, remoteRepositories, localRepository );
130 
131             boolean localCopy = false;
132             for ( Iterator i = artifact.getMetadataList().iterator(); i.hasNext(); )
133             {
134                 ArtifactMetadata m = (ArtifactMetadata) i.next();
135                 if ( m instanceof SnapshotArtifactRepositoryMetadata )
136                 {
137                     SnapshotArtifactRepositoryMetadata snapshotMetadata = (SnapshotArtifactRepositoryMetadata) m;
138 
139                     Metadata metadata = snapshotMetadata.getMetadata();
140                     if ( metadata != null )
141                     {
142                         Versioning versioning = metadata.getVersioning();
143                         if ( versioning != null )
144                         {
145                             Snapshot snapshot = versioning.getSnapshot();
146                             if ( snapshot != null )
147                             {
148                                 localCopy = snapshot.isLocalCopy();
149                             }
150                         }
151                     }
152                 }
153             }
154 
155             File destination = artifact.getFile();
156             List repositories = remoteRepositories;
157 
158             // TODO: would prefer the snapshot transformation took care of this. Maybe we need a "shouldresolve" flag.
159             if ( artifact.isSnapshot() && artifact.getBaseVersion().equals( artifact.getVersion() ) &&
160                 destination.exists() && !localCopy && wagonManager.isOnline() )
161             {
162                 Date comparisonDate = new Date( destination.lastModified() );
163 
164                 // cull to list of repositories that would like an update
165                 repositories = new ArrayList( remoteRepositories );
166                 for ( Iterator i = repositories.iterator(); i.hasNext(); )
167                 {
168                     ArtifactRepository repository = (ArtifactRepository) i.next();
169                     ArtifactRepositoryPolicy policy = repository.getSnapshots();
170                     if ( !policy.isEnabled() || !policy.checkOutOfDate( comparisonDate ) )
171                     {
172                         i.remove();
173                     }
174                 }
175 
176                 if ( !repositories.isEmpty() )
177                 {
178                     // someone wants to check for updates
179                     force = true;
180                 }
181             }
182             boolean resolved = false;
183             if ( !destination.exists() || force )
184             {
185                 if ( !wagonManager.isOnline() )
186                 {
187                     throw new ArtifactNotFoundException( "System is offline.", artifact );
188                 }
189 
190                 try
191                 {
192                     // TODO: force should be passed to the wagon manager
193                     if ( artifact.getRepository() != null )
194                     {
195                         // the transformations discovered the artifact - so use it exclusively
196                         wagonManager.getArtifact( artifact, artifact.getRepository() );
197                     }
198                     else
199                     {
200                         wagonManager.getArtifact( artifact, repositories );
201                     }
202 
203                     if ( !artifact.isResolved() && !destination.exists() )
204                     {
205                         throw new ArtifactResolutionException(
206                             "Failed to resolve artifact, possibly due to a repository list that is not appropriately equipped for this artifact's metadata.",
207                             artifact, getMirroredRepositories( remoteRepositories ) );
208                     }
209                 }
210                 catch ( ResourceDoesNotExistException e )
211                 {
212                     throw new ArtifactNotFoundException( e.getMessage(), artifact,
213                                                          getMirroredRepositories( remoteRepositories ), e );
214                 }
215                 catch ( TransferFailedException e )
216                 {
217                     throw new ArtifactResolutionException( e.getMessage(), artifact,
218                                                            getMirroredRepositories( remoteRepositories ), e );
219                 }
220 
221                 resolved = true;
222             }
223             else if ( destination.exists() )
224             {
225                 // locally resolved...no need to hit the remote repo.
226                 artifact.setResolved( true );
227             }
228 
229             if ( artifact.isSnapshot() && !artifact.getBaseVersion().equals( artifact.getVersion() ) )
230             {
231                 String version = artifact.getVersion();
232                 artifact.selectVersion( artifact.getBaseVersion() );
233                 File copy = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );
234                 if ( resolved || !copy.exists() )
235                 {
236                     // recopy file if it was reresolved, or doesn't exist.
237                     try
238                     {
239                         FileUtils.copyFile( destination, copy );
240                     }
241                     catch ( IOException e )
242                     {
243                         throw new ArtifactResolutionException(
244                             "Unable to copy resolved artifact for local use: " + e.getMessage(), artifact,
245                             getMirroredRepositories( remoteRepositories ), e );
246                     }
247                 }
248                 artifact.setFile( copy );
249                 artifact.selectVersion( version );
250             }
251         }
252     }
253 
254     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
255                                                          ArtifactRepository localRepository, List remoteRepositories,
256                                                          ArtifactMetadataSource source, ArtifactFilter filter )
257         throws ArtifactResolutionException, ArtifactNotFoundException
258     {
259         return resolveTransitively( artifacts, originatingArtifact, Collections.EMPTY_MAP, localRepository,
260                                     remoteRepositories, source, filter );
261 
262     }
263 
264     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
265                                                          Map managedVersions, ArtifactRepository localRepository,
266                                                          List remoteRepositories, ArtifactMetadataSource source )
267         throws ArtifactResolutionException, ArtifactNotFoundException
268     {
269         return resolveTransitively( artifacts, originatingArtifact, managedVersions, localRepository,
270                                     remoteRepositories, source, null );
271     }
272 
273     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
274                                                          Map managedVersions, ArtifactRepository localRepository,
275                                                          List remoteRepositories, ArtifactMetadataSource source,
276                                                          ArtifactFilter filter )
277         throws ArtifactResolutionException, ArtifactNotFoundException
278     {
279         // TODO: this is simplistic
280         List listeners = new ArrayList();
281         if ( getLogger().isDebugEnabled() )
282         {
283             listeners.add( new DebugResolutionListener( getLogger() ) );
284         }
285 
286         listeners.add( new WarningResolutionListener( getLogger() ) );
287 
288         return resolveTransitively( artifacts, originatingArtifact, managedVersions, localRepository,
289                                     remoteRepositories, source, filter, listeners );
290 
291     }
292 
293     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
294                                                          Map managedVersions, ArtifactRepository localRepository,
295                                                          List remoteRepositories, ArtifactMetadataSource source,
296                                                          ArtifactFilter filter, List listeners )
297         throws ArtifactResolutionException, ArtifactNotFoundException
298     {
299         ArtifactResolutionResult artifactResolutionResult;
300         artifactResolutionResult = artifactCollector.collect( artifacts, originatingArtifact, managedVersions,
301                                                               localRepository, remoteRepositories, source, filter,
302                                                               listeners );
303 
304         List resolvedArtifacts = new ArrayList();
305         List missingArtifacts = new ArrayList();
306         for ( Iterator i = artifactResolutionResult.getArtifactResolutionNodes().iterator(); i.hasNext(); )
307         {
308             ResolutionNode node = (ResolutionNode) i.next();
309             try
310             {
311                 resolve( node.getArtifact(), node.getRemoteRepositories(), localRepository );
312                 resolvedArtifacts.add( node.getArtifact() );
313             }
314             catch ( ArtifactNotFoundException anfe )
315             {
316                 getLogger().debug( anfe.getMessage(), anfe );
317 
318                 missingArtifacts.add( node.getArtifact() );
319             }
320         }
321 
322         if ( missingArtifacts.size() > 0 )
323         {
324             throw new MultipleArtifactsNotFoundException( originatingArtifact, resolvedArtifacts, missingArtifacts,
325                                                           getMirroredRepositories( remoteRepositories ) );
326         }
327 
328         return artifactResolutionResult;
329     }
330 
331     private List getMirroredRepositories( List remoteRepositories )
332     {
333         Map repos = new HashMap();
334         for ( Iterator i = remoteRepositories.iterator(); i.hasNext(); )
335         {
336             ArtifactRepository repository = (ArtifactRepository) i.next();
337             ArtifactRepository repo = wagonManager.getMirrorRepository( repository );
338             repos.put( repo.getId(), repo );
339         }
340         return new ArrayList( repos.values() );
341     }
342 
343     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
344                                                          List remoteRepositories, ArtifactRepository localRepository,
345                                                          ArtifactMetadataSource source )
346         throws ArtifactResolutionException, ArtifactNotFoundException
347     {
348         return resolveTransitively( artifacts, originatingArtifact, localRepository, remoteRepositories, source, null );
349     }
350 
351     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
352                                                          List remoteRepositories, ArtifactRepository localRepository,
353                                                          ArtifactMetadataSource source, List listeners )
354         throws ArtifactResolutionException, ArtifactNotFoundException
355     {
356         return resolveTransitively( artifacts, originatingArtifact, Collections.EMPTY_MAP, localRepository,
357                                     remoteRepositories, source, null, listeners );
358     }
359 
360 }