Coverage Report - org.apache.maven.artifact.resolver.DefaultArtifactResolver
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultArtifactResolver
63 %
80/126
42 %
33/78
4
DefaultArtifactResolver$ResolveArtifactTask
100 %
26/26
100 %
2/2
4
 
 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 java.io.File;
 23  
 import java.io.IOException;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Collections;
 26  
 import java.util.Date;
 27  
 import java.util.HashMap;
 28  
 import java.util.Iterator;
 29  
 import java.util.List;
 30  
 import java.util.Map;
 31  
 import java.util.Set;
 32  
 
 33  
 import org.apache.maven.artifact.Artifact;
 34  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 35  
 import org.apache.maven.artifact.manager.WagonManager;
 36  
 import org.apache.maven.artifact.metadata.ArtifactMetadata;
 37  
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 38  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 39  
 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
 40  
 import org.apache.maven.artifact.repository.metadata.Metadata;
 41  
 import org.apache.maven.artifact.repository.metadata.Snapshot;
 42  
 import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;
 43  
 import org.apache.maven.artifact.repository.metadata.Versioning;
 44  
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 45  
 import org.apache.maven.artifact.transform.ArtifactTransformationManager;
 46  
 import org.apache.maven.wagon.ResourceDoesNotExistException;
 47  
 import org.apache.maven.wagon.TransferFailedException;
 48  
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 49  
 import org.codehaus.plexus.util.FileUtils;
 50  
 
 51  
 import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
 52  
 import edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue;
 53  
 import edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor;
 54  
 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
 55  
 
 56  2
 public class DefaultArtifactResolver
 57  
     extends AbstractLogEnabled
 58  
     implements ArtifactResolver
 59  
 {
 60  
     // ----------------------------------------------------------------------
 61  
     // Components
 62  
     // ----------------------------------------------------------------------
 63  
 
 64  
     private static final int DEFAULT_POOL_SIZE = 5;
 65  
 
 66  
     private WagonManager wagonManager;
 67  
 
 68  
     private ArtifactTransformationManager transformationManager;
 69  
 
 70  
     protected ArtifactFactory artifactFactory;
 71  
 
 72  
     private ArtifactCollector artifactCollector;
 73  
     private final ThreadPoolExecutor resolveArtifactPool;
 74  
 
 75  
     public DefaultArtifactResolver()
 76  
     {
 77  11
         super();
 78  11
         resolveArtifactPool = 
 79  
             new ThreadPoolExecutor( DEFAULT_POOL_SIZE, DEFAULT_POOL_SIZE, 3, TimeUnit.SECONDS,
 80  
                                     new LinkedBlockingQueue() );
 81  11
     }
 82  
 
 83  
     // ----------------------------------------------------------------------
 84  
     // Implementation
 85  
     // ----------------------------------------------------------------------
 86  
 
 87  
     public void resolve( Artifact artifact, List remoteRepositories, ArtifactRepository localRepository )
 88  
         throws ArtifactResolutionException, ArtifactNotFoundException
 89  
     {
 90  16
         resolve( artifact, remoteRepositories, localRepository, false );
 91  9
     }
 92  
 
 93  
     public void resolveAlways( Artifact artifact, List remoteRepositories, ArtifactRepository localRepository )
 94  
         throws ArtifactResolutionException, ArtifactNotFoundException
 95  
     {
 96  0
         resolve( artifact, remoteRepositories, localRepository, true );
 97  0
     }
 98  
 
 99  
     private void resolve( Artifact artifact, List remoteRepositories, ArtifactRepository localRepository,
 100  
                           boolean force )
 101  
         throws ArtifactResolutionException, ArtifactNotFoundException
 102  
     {
 103  16
         if ( artifact == null )
 104  
         {
 105  0
             return;
 106  
         }
 107  
 
 108  16
         if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
 109  
         {
 110  0
             File systemFile = artifact.getFile();
 111  
 
 112  0
             if ( systemFile == null )
 113  
             {
 114  0
                 throw new ArtifactNotFoundException(
 115  
                     "System artifact: " + artifact + " has no file attached", artifact );
 116  
             }
 117  
 
 118  0
             if ( !systemFile.isFile() )
 119  
             {
 120  0
                 throw new ArtifactNotFoundException( "System artifact: " + artifact
 121  
                     + " is not a file: " + systemFile, artifact );
 122  
             }
 123  
 
 124  0
             if ( !systemFile.exists() )
 125  
             {
 126  0
                 throw new ArtifactNotFoundException(
 127  
                     "System artifact: " + artifact + " not found in path: " + systemFile,
 128  
                     artifact );
 129  
             }
 130  
 
 131  0
             artifact.setResolved( true );
 132  0
         }
 133  16
         else if ( !artifact.isResolved() )
 134  
         {
 135  
             // ----------------------------------------------------------------------
 136  
             // Check for the existence of the artifact in the specified local
 137  
             // ArtifactRepository. If it is present then simply return as the
 138  
             // request for resolution has been satisfied.
 139  
             // ----------------------------------------------------------------------
 140  
 
 141  16
             String localPath = localRepository.pathOf( artifact );
 142  
 
 143  16
             artifact.setFile( new File( localRepository.getBasedir(), localPath ) );
 144  
 
 145  16
             transformationManager.transformForResolve( artifact, remoteRepositories, localRepository );
 146  
 
 147  16
             boolean localCopy = false;
 148  16
             for ( Iterator i = artifact.getMetadataList().iterator(); i.hasNext(); )
 149  
             {
 150  0
                 ArtifactMetadata m = (ArtifactMetadata) i.next();
 151  0
                 if ( m instanceof SnapshotArtifactRepositoryMetadata )
 152  
                 {
 153  0
                     SnapshotArtifactRepositoryMetadata snapshotMetadata = (SnapshotArtifactRepositoryMetadata) m;
 154  
 
 155  0
                     Metadata metadata = snapshotMetadata.getMetadata();
 156  0
                     if ( metadata != null )
 157  
                     {
 158  0
                         Versioning versioning = metadata.getVersioning();
 159  0
                         if ( versioning != null )
 160  
                         {
 161  0
                             Snapshot snapshot = versioning.getSnapshot();
 162  0
                             if ( snapshot != null )
 163  
                             {
 164  0
                                 localCopy = snapshot.isLocalCopy();
 165  
                             }
 166  
                         }
 167  
                     }
 168  
                 }
 169  0
             }
 170  
 
 171  16
             File destination = artifact.getFile();
 172  16
             List repositories = remoteRepositories;
 173  
 
 174  
             // TODO: would prefer the snapshot transformation took care of this. Maybe we need a "shouldresolve" flag.
 175  16
             if ( artifact.isSnapshot() && artifact.getBaseVersion().equals( artifact.getVersion() ) &&
 176  
                 destination.exists() && !localCopy && wagonManager.isOnline() )
 177  
             {
 178  0
                 Date comparisonDate = new Date( destination.lastModified() );
 179  
 
 180  
                 // cull to list of repositories that would like an update
 181  0
                 repositories = new ArrayList( remoteRepositories );
 182  0
                 for ( Iterator i = repositories.iterator(); i.hasNext(); )
 183  
                 {
 184  0
                     ArtifactRepository repository = (ArtifactRepository) i.next();
 185  0
                     ArtifactRepositoryPolicy policy = repository.getSnapshots();
 186  0
                     if ( !policy.isEnabled() || !policy.checkOutOfDate( comparisonDate ) )
 187  
                     {
 188  0
                         i.remove();
 189  
                     }
 190  0
                 }
 191  
 
 192  0
                 if ( !repositories.isEmpty() )
 193  
                 {
 194  
                     // someone wants to check for updates
 195  0
                     force = true;
 196  
                 }
 197  
             }
 198  
 
 199  16
             if ( !destination.exists() || force )
 200  
             {
 201  11
                 if ( !wagonManager.isOnline() )
 202  
                 {
 203  0
                     throw new ArtifactNotFoundException( "System is offline.", artifact );
 204  
                 }
 205  
 
 206  
                 try
 207  
                 {
 208  
                     // TODO: force should be passed to the wagon manager
 209  11
                     if ( artifact.getRepository() != null )
 210  
                     {
 211  
                         // the transformations discovered the artifact - so use it exclusively
 212  0
                         wagonManager.getArtifact( artifact, artifact.getRepository() );
 213  
                     }
 214  
                     else
 215  
                     {
 216  11
                         wagonManager.getArtifact( artifact, repositories );
 217  
                     }
 218  
 
 219  4
                     if ( !artifact.isResolved() && !destination.exists() )
 220  
                     {
 221  0
                         throw new ArtifactResolutionException(
 222  
                             "Failed to resolve artifact, possibly due to a repository list that is not appropriately equipped for this artifact's metadata.",
 223  
                             artifact, getMirroredRepositories( remoteRepositories ) );
 224  
                     }
 225  
                 }
 226  4
                 catch ( ResourceDoesNotExistException e )
 227  
                 {
 228  4
                     throw new ArtifactNotFoundException( e.getMessage(), artifact,
 229  
                                                          getMirroredRepositories( remoteRepositories ), e );
 230  
                 }
 231  3
                 catch ( TransferFailedException e )
 232  
                 {
 233  3
                     throw new ArtifactResolutionException( e.getMessage(), artifact,
 234  
                                                            getMirroredRepositories( remoteRepositories ), e );
 235  4
                 }
 236  
             }
 237  5
             else if ( destination.exists() )
 238  
             {
 239  
                 // locally resolved...no need to hit the remote repo.
 240  5
                 artifact.setResolved( true );
 241  
             }
 242  
 
 243  9
             if ( artifact.isSnapshot() && !artifact.getBaseVersion().equals( artifact.getVersion() ) )
 244  
             {
 245  1
                 String version = artifact.getVersion();
 246  1
                 artifact.selectVersion( artifact.getBaseVersion() );
 247  1
                 File copy = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );
 248  1
                 if ( !copy.exists() || copy.lastModified() != destination.lastModified()
 249  
                     || copy.length() != destination.length() )
 250  
                 {
 251  
                     // recopy file if it was reresolved, or doesn't exist.
 252  
                     try
 253  
                     {
 254  1
                         FileUtils.copyFile( destination, copy );
 255  1
                         copy.setLastModified( destination.lastModified() );
 256  
                     }
 257  0
                     catch ( IOException e )
 258  
                     {
 259  0
                         throw new ArtifactResolutionException(
 260  
                             "Unable to copy resolved artifact for local use: " + e.getMessage(), artifact,
 261  
                             getMirroredRepositories( remoteRepositories ), e );
 262  1
                     }
 263  
                 }
 264  1
                 artifact.setFile( copy );
 265  1
                 artifact.selectVersion( version );
 266  
             }
 267  
         }
 268  9
     }
 269  
 
 270  
     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
 271  
                                                          ArtifactRepository localRepository, List remoteRepositories,
 272  
                                                          ArtifactMetadataSource source, ArtifactFilter filter )
 273  
         throws ArtifactResolutionException, ArtifactNotFoundException
 274  
     {
 275  6
         return resolveTransitively( artifacts, originatingArtifact, Collections.EMPTY_MAP, localRepository,
 276  
                                     remoteRepositories, source, filter );
 277  
 
 278  
     }
 279  
 
 280  
     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
 281  
                                                          Map managedVersions, ArtifactRepository localRepository,
 282  
                                                          List remoteRepositories, ArtifactMetadataSource source )
 283  
         throws ArtifactResolutionException, ArtifactNotFoundException
 284  
     {
 285  0
         return resolveTransitively( artifacts, originatingArtifact, managedVersions, localRepository,
 286  
                                     remoteRepositories, source, null );
 287  
     }
 288  
 
 289  
     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
 290  
                                                          Map managedVersions, ArtifactRepository localRepository,
 291  
                                                          List remoteRepositories, ArtifactMetadataSource source,
 292  
                                                          ArtifactFilter filter )
 293  
         throws ArtifactResolutionException, ArtifactNotFoundException
 294  
     {
 295  
         // TODO: this is simplistic
 296  6
         List listeners = new ArrayList();
 297  6
         if ( getLogger().isDebugEnabled() )
 298  
         {
 299  0
             listeners.add( new DebugResolutionListener( getLogger() ) );
 300  
         }
 301  
 
 302  6
         listeners.add( new WarningResolutionListener( getLogger() ) );
 303  
 
 304  6
         return resolveTransitively( artifacts, originatingArtifact, managedVersions, localRepository,
 305  
                                     remoteRepositories, source, filter, listeners );
 306  
 
 307  
     }
 308  
 
 309  
     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
 310  
                                                          Map managedVersions, ArtifactRepository localRepository,
 311  
                                                          List remoteRepositories, ArtifactMetadataSource source,
 312  
                                                          ArtifactFilter filter, List listeners )
 313  
         throws ArtifactResolutionException, ArtifactNotFoundException
 314  
     {
 315  
         ArtifactResolutionResult artifactResolutionResult;
 316  6
         artifactResolutionResult =
 317  
             artifactCollector.collect( artifacts, originatingArtifact, managedVersions, localRepository,
 318  
                                        remoteRepositories, source, filter, listeners );
 319  
 
 320  6
         List resolvedArtifacts = Collections.synchronizedList( new ArrayList() );
 321  6
         List missingArtifacts = Collections.synchronizedList( new ArrayList() );
 322  6
         CountDownLatch latch = new CountDownLatch( artifactResolutionResult.getArtifactResolutionNodes().size() );
 323  6
         Map nodesByGroupId = new HashMap();
 324  6
         for ( Iterator i = artifactResolutionResult.getArtifactResolutionNodes().iterator(); i.hasNext(); )
 325  
         {
 326  11
             ResolutionNode node = (ResolutionNode) i.next();
 327  11
             List nodes = (List) nodesByGroupId.get( node.getArtifact().getGroupId() );
 328  11
             if ( nodes == null )
 329  
             {
 330  6
                 nodes = new ArrayList();
 331  6
                 nodesByGroupId.put( node.getArtifact().getGroupId(), nodes );
 332  
             }
 333  11
             nodes.add( node );
 334  11
         }
 335  
 
 336  6
         List resolutionExceptions = Collections.synchronizedList( new ArrayList() );
 337  
         try
 338  
         {
 339  6
             for ( Iterator i = nodesByGroupId.values().iterator(); i.hasNext(); )
 340  
             {
 341  6
                 List nodes = (List) i.next();
 342  6
                 resolveArtifactPool.execute( new ResolveArtifactTask( resolveArtifactPool, latch, nodes,
 343  
                                                                       localRepository, resolvedArtifacts,
 344  
                                                                       missingArtifacts, resolutionExceptions ) );
 345  6
             }
 346  6
             latch.await();
 347  
         }
 348  0
         catch ( InterruptedException e )
 349  
         {
 350  0
             throw new ArtifactResolutionException( "Resolution interrupted", originatingArtifact, e );
 351  6
         }
 352  
 
 353  6
         if ( !resolutionExceptions.isEmpty() )
 354  
         {
 355  2
             throw (ArtifactResolutionException) resolutionExceptions.get( 0 );
 356  
         }
 357  
         
 358  4
         if ( missingArtifacts.size() > 0 )
 359  
         {
 360  1
             throw new MultipleArtifactsNotFoundException( originatingArtifact, resolvedArtifacts, missingArtifacts,
 361  
                                                           getMirroredRepositories( remoteRepositories ) );
 362  
         }
 363  
 
 364  3
         return artifactResolutionResult;
 365  
     }
 366  
 
 367  
     private List getMirroredRepositories( List remoteRepositories )
 368  
     {
 369  8
         Map repos = new HashMap();
 370  8
         for ( Iterator i = remoteRepositories.iterator(); i.hasNext(); )
 371  
         {
 372  8
             ArtifactRepository repository = (ArtifactRepository) i.next();
 373  8
             ArtifactRepository repo = wagonManager.getMirrorRepository( repository );
 374  8
             repos.put( repo.getId(), repo );
 375  8
         }
 376  8
         return new ArrayList( repos.values() );
 377  
     }
 378  
 
 379  
     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
 380  
                                                          List remoteRepositories, ArtifactRepository localRepository,
 381  
                                                          ArtifactMetadataSource source )
 382  
         throws ArtifactResolutionException, ArtifactNotFoundException
 383  
     {
 384  6
         return resolveTransitively( artifacts, originatingArtifact, localRepository, remoteRepositories, source, null );
 385  
     }
 386  
 
 387  
     public ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact,
 388  
                                                          List remoteRepositories, ArtifactRepository localRepository,
 389  
                                                          ArtifactMetadataSource source, List listeners )
 390  
         throws ArtifactResolutionException, ArtifactNotFoundException
 391  
     {
 392  0
         return resolveTransitively( artifacts, originatingArtifact, Collections.EMPTY_MAP, localRepository,
 393  
                                     remoteRepositories, source, null, listeners );
 394  
     }
 395  
 
 396  
     private class ResolveArtifactTask
 397  
         implements Runnable
 398  
     {
 399  
         private List nodes;
 400  
 
 401  
         private ArtifactRepository localRepository;
 402  
 
 403  
         private List resolvedArtifacts;
 404  
 
 405  
         private List missingArtifacts;
 406  
 
 407  
         private CountDownLatch latch;
 408  
 
 409  
         private ThreadPoolExecutor pool;
 410  
 
 411  
         private List resolutionExceptions;
 412  
 
 413  
         public ResolveArtifactTask( ThreadPoolExecutor pool, CountDownLatch latch, List nodes,
 414  
                                     ArtifactRepository localRepository, List resolvedArtifacts, List missingArtifacts,
 415  
                                     List resolutionExceptions )
 416  11
         {
 417  11
             this.nodes = nodes;
 418  11
             this.localRepository = localRepository;
 419  11
             this.resolvedArtifacts = resolvedArtifacts;
 420  11
             this.missingArtifacts = missingArtifacts;
 421  11
             this.latch = latch;
 422  11
             this.pool = pool;
 423  11
             this.resolutionExceptions = resolutionExceptions;
 424  11
         }
 425  
 
 426  
         public void run()
 427  
         {
 428  11
             Iterator i = nodes.iterator();
 429  11
             ResolutionNode node = (ResolutionNode) i.next();
 430  11
             i.remove();
 431  
             try
 432  
             {
 433  11
                 resolveArtifact( node );
 434  
             }
 435  3
             catch ( ArtifactResolutionException e )
 436  
             {
 437  3
                 resolutionExceptions.add( e );
 438  
             }
 439  
             finally 
 440  
             {
 441  11
                 latch.countDown();
 442  
 
 443  11
                 if ( i.hasNext() )
 444  
                 {
 445  5
                     pool.execute( new ResolveArtifactTask( pool, latch, nodes, localRepository, resolvedArtifacts,
 446  
                                                            missingArtifacts, resolutionExceptions ) );
 447  
                 }
 448  
             }
 449  11
         }
 450  
 
 451  
         private void resolveArtifact( ResolutionNode node )
 452  
             throws ArtifactResolutionException
 453  
         {
 454  
             try
 455  
             {
 456  11
                 resolve( node.getArtifact(), node.getRemoteRepositories(), localRepository );
 457  6
                 resolvedArtifacts.add( node.getArtifact() );
 458  
             }
 459  2
             catch ( ArtifactNotFoundException anfe )
 460  
             {
 461  2
                 getLogger().debug( anfe.getMessage(), anfe );
 462  
 
 463  2
                 missingArtifacts.add( node.getArtifact() );
 464  6
             }
 465  8
         }
 466  
     }
 467  
 
 468  
     public synchronized void configureNumberOfThreads( int threads )
 469  
     {
 470  0
         resolveArtifactPool.setCorePoolSize( threads );
 471  0
         resolveArtifactPool.setMaximumPoolSize( threads );
 472  0
     }
 473  
 
 474  
     void setWagonManager( WagonManager wagonManager )
 475  
     {
 476  2
         this.wagonManager = wagonManager;
 477  2
     }
 478  
 }