Author: brett
Date: Wed Mar  4 12:46:53 2009
New Revision: 749987

URL: http://svn.apache.org/viewvc?rev=749987&view=rev
Log:
[MNG-3379] avoid deadlocking on remote errors, check test coverage for the new 
code including exceptional cases

Modified:
    
maven/components/branches/maven-2.1.x/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
    
maven/components/branches/maven-2.1.x/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java

Modified: 
maven/components/branches/maven-2.1.x/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
URL: 
http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java?rev=749987&r1=749986&r2=749987&view=diff
==============================================================================
--- 
maven/components/branches/maven-2.1.x/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
 (original)
+++ 
maven/components/branches/maven-2.1.x/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
 Wed Mar  4 12:46:53 2009
@@ -333,6 +333,7 @@
             nodes.add( node );
         }
 
+        List resolutionExceptions = new ArrayList();
         try
         {
             for ( Iterator i = nodesByGroupId.values().iterator(); 
i.hasNext(); )
@@ -340,7 +341,7 @@
                 List nodes = (List) i.next();
                 resolveArtifactPool.execute( new ResolveArtifactTask( 
resolveArtifactPool, latch, nodes,
                                                                       
localRepository, resolvedArtifacts,
-                                                                      
missingArtifacts ) );
+                                                                      
missingArtifacts, resolutionExceptions ) );
             }
             latch.await();
         }
@@ -348,18 +349,12 @@
         {
             throw new ArtifactResolutionException( "Resolution interrupted", 
null, e );
         }
-        catch ( RuntimeException ex )
-        {
-            if ( ex.getCause() instanceof ArtifactResolutionException )
-            {
-                throw (ArtifactResolutionException) ex.getCause();
-            }
-            else
-            {
-                throw ex;
-            }
-        } 
 
+        if ( !resolutionExceptions.isEmpty() )
+        {
+            throw (ArtifactResolutionException) resolutionExceptions.get( 0 );
+        }
+        
         if ( missingArtifacts.size() > 0 )
         {
             throw new MultipleArtifactsNotFoundException( originatingArtifact, 
resolvedArtifacts, missingArtifacts,
@@ -413,8 +408,11 @@
 
         private ThreadPoolExecutor pool;
 
+        private List resolutionExceptions;
+
         public ResolveArtifactTask( ThreadPoolExecutor pool, CountDownLatch 
latch, List nodes,
-                                    ArtifactRepository localRepository, List 
resolvedArtifacts, List missingArtifacts )
+                                    ArtifactRepository localRepository, List 
resolvedArtifacts, List missingArtifacts,
+                                    List resolutionExceptions )
         {
             this.nodes = nodes;
             this.localRepository = localRepository;
@@ -422,6 +420,7 @@
             this.missingArtifacts = missingArtifacts;
             this.latch = latch;
             this.pool = pool;
+            this.resolutionExceptions = resolutionExceptions;
         }
 
         public void run()
@@ -435,14 +434,17 @@
                 if ( i.hasNext() )
                 {
                     pool.execute( new ResolveArtifactTask( pool, latch, nodes, 
localRepository, resolvedArtifacts,
-                                                           missingArtifacts ) 
);
+                                                           missingArtifacts, 
resolutionExceptions ) );
                 }
             }
             catch ( ArtifactResolutionException e )
             {
-                throw new RuntimeException( e );
+                resolutionExceptions.add( e );
+            }
+            finally 
+            {
+                latch.countDown();
             }
-            latch.countDown();
         }
 
         private void resolveArtifact( ResolutionNode node )
@@ -467,4 +469,9 @@
         resolveArtifactPool.setCorePoolSize( threads );
         resolveArtifactPool.setMaximumPoolSize( threads );
     }
+
+    void setWagonManager( WagonManager wagonManager )
+    {
+        this.wagonManager = wagonManager;
+    }
 }

Modified: 
maven/components/branches/maven-2.1.x/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java
URL: 
http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java?rev=749987&r1=749986&r2=749987&view=diff
==============================================================================
--- 
maven/components/branches/maven-2.1.x/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java
 (original)
+++ 
maven/components/branches/maven-2.1.x/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java
 Wed Mar  4 12:46:53 2009
@@ -19,6 +19,14 @@
  * under the License.
  */
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
 import org.apache.maven.artifact.AbstractArtifactComponentTestCase;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.manager.WagonManager;
@@ -26,12 +34,8 @@
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 import org.apache.maven.artifact.metadata.ResolutionGroup;
 import org.apache.maven.artifact.repository.ArtifactRepository;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
+import org.apache.maven.wagon.TransferFailedException;
+import org.easymock.MockControl;
 
 // It would be cool if there was a hook that i could use to setup a test 
environment.
 // I want to setup a local/remote repositories for testing but i don't want to 
have
@@ -46,6 +50,31 @@
 public class ArtifactResolverTest
     extends AbstractArtifactComponentTestCase
 {
+    private static class ArtifactMetadataSourceImplementation
+        implements ArtifactMetadataSource
+    {
+        public ResolutionGroup retrieve( Artifact artifact, ArtifactRepository 
localRepository,
+                                         List remoteRepositories )
+            throws ArtifactMetadataRetrievalException
+        {
+            return new ResolutionGroup( artifact, Collections.EMPTY_SET, 
remoteRepositories );
+        }
+
+        public List retrieveAvailableVersions( Artifact artifact, 
ArtifactRepository localRepository,
+                                               List remoteRepositories )
+        {
+            throw new UnsupportedOperationException( "Cannot get available 
versions in this test case" );
+        }
+
+        public Artifact retrieveRelocatedArtifact( Artifact artifact,
+                                                   ArtifactRepository 
localRepository,
+                                                   List remoteRepositories )
+            throws ArtifactMetadataRetrievalException
+        {
+            return artifact;
+        }
+    }
+
     private ArtifactResolver artifactResolver;
 
     private Artifact projectArtifact;
@@ -100,7 +129,7 @@
 
         Artifact h = createLocalArtifact( "h", "1.0" );
 
-        ArtifactMetadataSource mds = new ArtifactMetadataSource()
+        ArtifactMetadataSource mds = new ArtifactMetadataSourceImplementation()
         {
             public ResolutionGroup retrieve( Artifact artifact, 
ArtifactRepository localRepository,
                                              List remoteRepositories )
@@ -124,20 +153,6 @@
 
                 return new ResolutionGroup( artifact, dependencies, 
remoteRepositories );
             }
-
-            public List retrieveAvailableVersions( Artifact artifact, 
ArtifactRepository localRepository,
-                                                   List remoteRepositories )
-            {
-                throw new UnsupportedOperationException( "Cannot get available 
versions in this test case" );
-            }
-
-            public Artifact retrieveRelocatedArtifact( Artifact artifact,
-                                                       ArtifactRepository 
localRepository,
-                                                       List remoteRepositories 
)
-                throws ArtifactMetadataRetrievalException
-            {
-                return artifact;
-            }
         };
 
         ArtifactResolutionResult result = 
artifactResolver.resolveTransitively( Collections.singleton( g ),
@@ -164,7 +179,7 @@
         Artifact j = createRemoteArtifact( "j", "1.0" );
         deleteLocalArtifact( j );
 
-        ArtifactMetadataSource mds = new ArtifactMetadataSource()
+        ArtifactMetadataSource mds = new ArtifactMetadataSourceImplementation()
         {
             public ResolutionGroup retrieve( Artifact artifact, 
ArtifactRepository localRepository,
                                              List remoteRepositories )
@@ -188,20 +203,6 @@
 
                 return new ResolutionGroup( artifact, dependencies, 
remoteRepositories );
             }
-
-            public List retrieveAvailableVersions( Artifact artifact, 
ArtifactRepository localRepository,
-                                                   List remoteRepositories )
-            {
-                throw new UnsupportedOperationException( "Cannot get available 
versions in this test case" );
-            }
-
-            public Artifact retrieveRelocatedArtifact( Artifact artifact,
-                                                       ArtifactRepository 
localRepository,
-                                                       List remoteRepositories 
)
-                throws ArtifactMetadataRetrievalException
-            {
-                return artifact;
-            }
         };
 
         ArtifactResolutionResult result = 
artifactResolver.resolveTransitively( Collections.singleton( i ),
@@ -287,5 +288,78 @@
      }
      */
 
+    public void 
testResolutionFailureWhenMultipleArtifactsNotPresentInRemoteRepository()
+        throws Exception
+    {
+        Artifact i = createArtifact( "i", "1.0" );
+        Artifact n = createArtifact( "n", "1.0" );
+        Artifact o = createArtifact( "o", "1.0" );
+    
+        try
+        {
+            ArtifactMetadataSource mds = new 
ArtifactMetadataSourceImplementation();
+            artifactResolver.resolveTransitively( new HashSet( Arrays.asList( 
new Artifact[] { i, n, o } ) ),
+                                                  projectArtifact, 
remoteRepositories(), localRepository(), mds );
+            fail( "Resolution succeeded when it should have failed" );
+        }
+        catch ( MultipleArtifactsNotFoundException expected )
+        {
+            List repos = expected.getRemoteRepositories();
+            assertEquals( 1, repos.size() );
+            assertEquals( "test", ( (ArtifactRepository) repos.get( 0 ) 
).getId() );
+            
+            List missingArtifacts = expected.getMissingArtifacts();
+            assertEquals( 2, missingArtifacts.size() );
+            assertTrue( missingArtifacts.contains( n ) );
+            assertTrue( missingArtifacts.contains( o ) );
+            assertFalse( missingArtifacts.contains( i ) );
+        }
+    }
+
+    /**
+     * Test deadlocking (which occurs even with a single artifact in error).
+     */
+    public void testResolveWithException()
+        throws Exception
+    {
+        ArtifactRepository repository = remoteRepository();
+        List remoteRepositories = Collections.singletonList( repository );
+
+        Artifact a1 = createArtifact( "testGroup", "artifactId", "1.0", "jar" 
);
+
+        ArtifactMetadataSource mds = new 
ArtifactMetadataSourceImplementation();
+
+        DefaultArtifactResolver artifactResolver = (DefaultArtifactResolver) 
this.artifactResolver;
+
+        MockControl control = MockControl.createControl( WagonManager.class );
+        WagonManager wagonManager = (WagonManager) control.getMock();
+        artifactResolver.setWagonManager( wagonManager );
+
+        wagonManager.isOnline();
+        control.setReturnValue( true );
+        wagonManager.getArtifact( a1, remoteRepositories );
+        control.setThrowable( new TransferFailedException( "message" ) );
+        wagonManager.getMirrorRepository( repository );
+        control.setReturnValue( repository );
+
+        control.replay();
+
+        try
+        {
+            artifactResolver.resolveTransitively( new LinkedHashSet( 
Arrays.asList( new Artifact[] { a1 } ) ),
+                                                  projectArtifact, 
remoteRepositories, localRepository(), mds );
+            fail( "Resolution succeeded when it should have failed" );
+        }
+        catch ( ArtifactResolutionException expected )
+        {
+            List repos = expected.getRemoteRepositories();
+            assertEquals( 1, repos.size() );
+            assertEquals( "test", ( (ArtifactRepository) repos.get( 0 ) 
).getId() );
+
+            assertEquals( "testGroup", expected.getGroupId() );
+        }
+
+        control.verify();
+    }
 }
 


Reply via email to