You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sc...@apache.org on 2016/06/10 13:56:16 UTC

[1/2] maven-aether git commit: Bugfix: DefaultDependencyCollector does not correctly handle dependency management. Blocks MNG-5227. Bugfix: ScopeDependencySelector incorrectly excludes direct dependencies. See MPLUGIN-296 for an example. Bugfix: Exceptio

Repository: maven-aether
Updated Branches:
  refs/heads/master 11a061b66 -> 1ee92862c


http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java
new file mode 100644
index 0000000..aeac09f
--- /dev/null
+++ b/aether-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java
@@ -0,0 +1,321 @@
+package org.eclipse.aether.util.graph.manager;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.ArtifactProperties;
+import org.eclipse.aether.collection.DependencyCollectionContext;
+import org.eclipse.aether.collection.DependencyManagement;
+import org.eclipse.aether.collection.DependencyManager;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.graph.Exclusion;
+import org.eclipse.aether.util.artifact.JavaScopes;
+
+/**
+ * A dependency manager supporting transitive dependency management.
+ *
+ * @author Christian Schulte
+ * @since 1.2
+ */
+public final class TransitiveDependencyManager
+    implements DependencyManager
+{
+
+    private final int depth;
+
+    private final Map<Object, String> managedVersions;
+
+    private final Map<Object, String> managedScopes;
+
+    private final Map<Object, Boolean> managedOptionals;
+
+    private final Map<Object, String> managedLocalPaths;
+
+    private final Map<Object, Collection<Exclusion>> managedExclusions;
+
+    private int hashCode;
+
+    /**
+     * Creates a new dependency manager without any management information.
+     */
+    public TransitiveDependencyManager()
+    {
+        this( 0, Collections.<Object, String>emptyMap(), Collections.<Object, String>emptyMap(),
+              Collections.<Object, Boolean>emptyMap(), Collections.<Object, String>emptyMap(),
+              Collections.<Object, Collection<Exclusion>>emptyMap() );
+    }
+
+    private TransitiveDependencyManager( final int depth,
+                                         final Map<Object, String> managedVersions,
+                                         final Map<Object, String> managedScopes,
+                                         final Map<Object, Boolean> managedOptionals,
+                                         final Map<Object, String> managedLocalPaths,
+                                         final Map<Object, Collection<Exclusion>> managedExclusions )
+    {
+        super();
+        this.depth = depth;
+        this.managedVersions = managedVersions;
+        this.managedScopes = managedScopes;
+        this.managedOptionals = managedOptionals;
+        this.managedLocalPaths = managedLocalPaths;
+        this.managedExclusions = managedExclusions;
+    }
+
+    public DependencyManager deriveChildManager( final DependencyCollectionContext context )
+    {
+        Map<Object, String> versions = this.managedVersions;
+        Map<Object, String> scopes = this.managedScopes;
+        Map<Object, Boolean> optionals = this.managedOptionals;
+        Map<Object, String> localPaths = this.managedLocalPaths;
+        Map<Object, Collection<Exclusion>> exclusions = this.managedExclusions;
+
+        for ( Dependency managedDependency : context.getManagedDependencies() )
+        {
+            Artifact artifact = managedDependency.getArtifact();
+            Object key = getKey( artifact );
+
+            String version = artifact.getVersion();
+            if ( version.length() > 0 && !versions.containsKey( key ) )
+            {
+                if ( versions == this.managedVersions )
+                {
+                    versions = new HashMap<Object, String>( this.managedVersions );
+                }
+                versions.put( key, version );
+            }
+
+            String scope = managedDependency.getScope();
+            if ( scope.length() > 0 && !scopes.containsKey( key ) )
+            {
+                if ( scopes == this.managedScopes )
+                {
+                    scopes = new HashMap<Object, String>( this.managedScopes );
+                }
+                scopes.put( key, scope );
+            }
+
+            Boolean optional = managedDependency.getOptional();
+            if ( optional != null && !optionals.containsKey( key ) )
+            {
+                if ( optionals == this.managedOptionals )
+                {
+                    optionals = new HashMap<Object, Boolean>( this.managedOptionals );
+                }
+                optionals.put( key, optional );
+            }
+
+            String localPath = managedDependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null );
+            if ( localPath != null && !localPaths.containsKey( key ) )
+            {
+                if ( localPaths == this.managedLocalPaths )
+                {
+                    localPaths = new HashMap<Object, String>( this.managedLocalPaths );
+                }
+                localPaths.put( key, localPath );
+            }
+
+            if ( !managedDependency.getExclusions().isEmpty() )
+            {
+                if ( exclusions == this.managedExclusions )
+                {
+                    exclusions = new HashMap<Object, Collection<Exclusion>>( this.managedExclusions );
+                }
+                Collection<Exclusion> managed = exclusions.get( key );
+                if ( managed == null )
+                {
+                    managed = new LinkedHashSet<Exclusion>();
+                    exclusions.put( key, managed );
+                }
+                managed.addAll( managedDependency.getExclusions() );
+            }
+        }
+
+        return new TransitiveDependencyManager( this.depth + 1, versions, scopes, optionals, localPaths, exclusions );
+    }
+
+    public DependencyManagement manageDependency( Dependency dependency )
+    {
+        DependencyManagement management = null;
+
+        Object key = getKey( dependency.getArtifact() );
+
+        if ( depth >= 2 )
+        {
+            String version = managedVersions.get( key );
+            if ( version != null )
+            {
+                if ( management == null )
+                {
+                    management = new DependencyManagement();
+                }
+                management.setVersion( version );
+            }
+
+            String scope = managedScopes.get( key );
+            if ( scope != null )
+            {
+                if ( management == null )
+                {
+                    management = new DependencyManagement();
+                }
+                management.setScope( scope );
+
+                if ( !JavaScopes.SYSTEM.equals( scope )
+                         && dependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) != null )
+                {
+                    Map<String, String> properties =
+                        new HashMap<String, String>( dependency.getArtifact().getProperties() );
+                    properties.remove( ArtifactProperties.LOCAL_PATH );
+                    management.setProperties( properties );
+                }
+            }
+
+            if ( ( scope != null && JavaScopes.SYSTEM.equals( scope ) )
+                     || ( scope == null && JavaScopes.SYSTEM.equals( dependency.getScope() ) ) )
+            {
+                String localPath = managedLocalPaths.get( key );
+                if ( localPath != null )
+                {
+                    if ( management == null )
+                    {
+                        management = new DependencyManagement();
+                    }
+                    Map<String, String> properties =
+                        new HashMap<String, String>( dependency.getArtifact().getProperties() );
+                    properties.put( ArtifactProperties.LOCAL_PATH, localPath );
+                    management.setProperties( properties );
+                }
+            }
+
+            Boolean optional = managedOptionals.get( key );
+            if ( optional != null )
+            {
+                if ( management == null )
+                {
+                    management = new DependencyManagement();
+                }
+                management.setOptional( optional );
+            }
+        }
+
+        Collection<Exclusion> exclusions = managedExclusions.get( key );
+        if ( exclusions != null )
+        {
+            if ( management == null )
+            {
+                management = new DependencyManagement();
+            }
+            Collection<Exclusion> result = new LinkedHashSet<Exclusion>( dependency.getExclusions() );
+            result.addAll( exclusions );
+            management.setExclusions( result );
+        }
+
+        return management;
+    }
+
+    private Object getKey( Artifact a )
+    {
+        return new Key( a );
+    }
+
+    @Override
+    public boolean equals( final Object obj )
+    {
+        boolean equal = obj instanceof TransitiveDependencyManager;
+
+        if ( equal )
+        {
+            final TransitiveDependencyManager that = (TransitiveDependencyManager) obj;
+            return this.depth == that.depth
+                       && this.managedVersions.equals( that.managedVersions )
+                       && this.managedScopes.equals( that.managedScopes )
+                       && this.managedOptionals.equals( that.managedOptionals )
+                       && this.managedExclusions.equals( that.managedExclusions );
+
+        }
+
+        return equal;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        if ( this.hashCode == 0 )
+        {
+            int hash = 17;
+            hash = hash * 31 + this.depth;
+            hash = hash * 31 + this.managedVersions.hashCode();
+            hash = hash * 31 + this.managedScopes.hashCode();
+            hash = hash * 31 + this.managedOptionals.hashCode();
+            hash = hash * 31 + this.managedExclusions.hashCode();
+            this.hashCode = hash;
+        }
+        return this.hashCode;
+    }
+
+    static class Key
+    {
+
+        private final Artifact artifact;
+
+        private final int hashCode;
+
+        public Key( final Artifact artifact )
+        {
+            this.artifact = artifact;
+
+            int hash = 17;
+            hash = hash * 31 + artifact.getGroupId().hashCode();
+            hash = hash * 31 + artifact.getArtifactId().hashCode();
+            this.hashCode = hash;
+        }
+
+        @Override
+        public boolean equals( final Object obj )
+        {
+            boolean equal = obj instanceof Key;
+
+            if ( equal )
+            {
+                final Key that = (Key) obj;
+                return this.artifact.getArtifactId().equals( that.artifact.getArtifactId() )
+                           && this.artifact.getGroupId().equals( that.artifact.getGroupId() )
+                           && this.artifact.getExtension().equals( that.artifact.getExtension() )
+                           && this.artifact.getClassifier().equals( that.artifact.getClassifier() );
+
+            }
+
+            return equal;
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return this.hashCode;
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java
index 552fc09..2640c42 100644
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java
+++ b/aether-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java
@@ -40,7 +40,7 @@ public final class ScopeDependencySelector
     implements DependencySelector
 {
 
-    private final boolean transitive;
+    private final int depth;
 
     private final Collection<String> included;
 
@@ -54,7 +54,8 @@ public final class ScopeDependencySelector
      */
     public ScopeDependencySelector( Collection<String> included, Collection<String> excluded )
     {
-        transitive = false;
+        super();
+        this.depth = 0;
         this.included = clone( included );
         this.excluded = clone( excluded );
     }
@@ -89,32 +90,31 @@ public final class ScopeDependencySelector
         this( null, ( excluded != null ) ? Arrays.asList( excluded ) : null );
     }
 
-    private ScopeDependencySelector( boolean transitive, Collection<String> included, Collection<String> excluded )
+    private ScopeDependencySelector( int depth, Collection<String> included, Collection<String> excluded )
     {
-        this.transitive = transitive;
+        super();
+        this.depth = depth;
         this.included = included;
         this.excluded = excluded;
     }
 
     public boolean selectDependency( Dependency dependency )
     {
-        if ( !transitive )
-        {
-            return true;
-        }
+        // depth < 2 == direct dependency
+        // assert this.depth > 0 : "Unexpected depth.";
+        return this.depth < 2
+                   || ( ( included == null || included.contains( dependency.getScope() ) )
+                        && ( excluded == null || !excluded.contains( dependency.getScope() ) ) );
 
-        String scope = dependency.getScope();
-        return ( included == null || included.contains( scope ) ) && ( excluded == null || !excluded.contains( scope ) );
     }
 
     public DependencySelector deriveChildSelector( DependencyCollectionContext context )
     {
-        if ( this.transitive || context.getDependency() == null )
-        {
-            return this;
-        }
+        // First call is for direct dependencies, successive calls are for transitive dependencies.
+        return this.depth >= 2
+                   ? this
+                   : new ScopeDependencySelector( this.depth + 1, this.included, this.excluded );
 
-        return new ScopeDependencySelector( true, included, excluded );
     }
 
     @Override
@@ -130,7 +130,7 @@ public final class ScopeDependencySelector
         }
 
         ScopeDependencySelector that = (ScopeDependencySelector) obj;
-        return transitive == that.transitive && eq( included, that.included ) && eq( excluded, that.excluded );
+        return this.depth == that.depth && eq( included, that.included ) && eq( excluded, that.excluded );
     }
 
     private static <T> boolean eq( T o1, T o2 )
@@ -142,7 +142,7 @@ public final class ScopeDependencySelector
     public int hashCode()
     {
         int hash = 17;
-        hash = hash * 31 + ( transitive ? 1 : 0 );
+        hash = hash * 31 + ( this.depth );
         hash = hash * 31 + ( included != null ? included.hashCode() : 0 );
         hash = hash * 31 + ( excluded != null ? excluded.hashCode() : 0 );
         return hash;

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictIdSorter.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictIdSorter.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictIdSorter.java
index c2122fa..5cc6432 100644
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictIdSorter.java
+++ b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictIdSorter.java
@@ -63,7 +63,7 @@ public final class ConflictIdSorter
 
         @SuppressWarnings( "unchecked" )
         Map<String, Object> stats = (Map<String, Object>) context.get( TransformationContextKeys.STATS );
-        long time1 = System.currentTimeMillis();
+        long time1 = System.nanoTime();
 
         Map<Object, ConflictId> ids = new LinkedHashMap<Object, ConflictId>( 256 );
 
@@ -81,13 +81,13 @@ public final class ConflictIdSorter
             buildConflitIdDAG( ids, node, id, 0, visited, conflictIds );
         }
 
-        long time2 = System.currentTimeMillis();
+        long time2 = System.nanoTime();
 
         int cycles = topsortConflictIds( ids.values(), context );
 
         if ( stats != null )
         {
-            long time3 = System.currentTimeMillis();
+            long time3 = System.nanoTime();
             stats.put( "ConflictIdSorter.graphTime", time2 - time1 );
             stats.put( "ConflictIdSorter.topsortTime", time3 - time2 );
             stats.put( "ConflictIdSorter.conflictIdCount", ids.size() );

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictMarker.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictMarker.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictMarker.java
index a3fb483..fe2f5d5 100644
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictMarker.java
+++ b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictMarker.java
@@ -55,14 +55,14 @@ public final class ConflictMarker
     {
         @SuppressWarnings( "unchecked" )
         Map<String, Object> stats = (Map<String, Object>) context.get( TransformationContextKeys.STATS );
-        long time1 = System.currentTimeMillis();
+        long time1 = System.nanoTime();
 
         Map<DependencyNode, Object> nodes = new IdentityHashMap<DependencyNode, Object>( 1024 );
         Map<Object, ConflictGroup> groups = new HashMap<Object, ConflictGroup>( 1024 );
 
         analyze( node, nodes, groups, new int[] { 0 } );
 
-        long time2 = System.currentTimeMillis();
+        long time2 = System.nanoTime();
 
         Map<DependencyNode, Object> conflictIds = mark( nodes.keySet(), groups );
 
@@ -70,7 +70,7 @@ public final class ConflictMarker
 
         if ( stats != null )
         {
-            long time3 = System.currentTimeMillis();
+            long time3 = System.nanoTime();
             stats.put( "ConflictMarker.analyzeTime", time2 - time1 );
             stats.put( "ConflictMarker.markTime", time3 - time2 );
             stats.put( "ConflictMarker.nodeCount", nodes.size() );

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
index 5f9d8e0..6ccc508 100644
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
+++ b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
@@ -144,7 +144,7 @@ public final class ConflictResolver
 
         @SuppressWarnings( "unchecked" )
         Map<String, Object> stats = (Map<String, Object>) context.get( TransformationContextKeys.STATS );
-        long time1 = System.currentTimeMillis();
+        long time1 = System.nanoTime();
 
         @SuppressWarnings( "unchecked" )
         Collection<Collection<?>> conflictIdCycles =
@@ -231,7 +231,7 @@ public final class ConflictResolver
 
         if ( stats != null )
         {
-            long time2 = System.currentTimeMillis();
+            long time2 = System.nanoTime();
             stats.put( "ConflictResolver.totalTime", time2 - time1 );
             stats.put( "ConflictResolver.conflictItemCount", state.totalConflictItems );
         }

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index cd63de8..281a04f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
 
   <groupId>org.apache.maven.aether</groupId>
   <artifactId>aether</artifactId>
-  <version>1.1.0-SNAPSHOT</version>
+  <version>1.2.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>Aether</name>
@@ -119,7 +119,7 @@
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
-        <version>4.11</version>
+        <version>4.12</version>
         <scope>test</scope>
       </dependency>
       <dependency>
@@ -128,12 +128,6 @@
         <version>1.3</version>
         <scope>test</scope>
       </dependency>
-      <dependency>
-        <groupId>org.hamcrest</groupId>
-        <artifactId>hamcrest-library</artifactId>
-        <version>1.3</version>
-        <scope>test</scope>
-      </dependency>
 
       <dependency>
         <groupId>javax.inject</groupId>
@@ -144,7 +138,7 @@
       <dependency>
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-component-annotations</artifactId>
-        <version>1.5.5</version>
+        <version>1.6</version>
         <scope>provided</scope>
       </dependency>
 
@@ -184,7 +178,7 @@
       <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
-        <version>1.6.2</version>
+        <version>1.7.16</version>
       </dependency>
     </dependencies>
   </dependencyManagement>


[2/2] maven-aether git commit: Bugfix: DefaultDependencyCollector does not correctly handle dependency management. Blocks MNG-5227. Bugfix: ScopeDependencySelector incorrectly excludes direct dependencies. See MPLUGIN-296 for an example. Bugfix: Exceptio

Posted by sc...@apache.org.
Bugfix: DefaultDependencyCollector does not correctly handle dependency management. Blocks MNG-5227.
Bugfix: ScopeDependencySelector incorrectly excludes direct dependencies. See MPLUGIN-296 for an example.
Bugfix: Exceptions are suppressed incorrectly when closing resources.
Enhancement: Calculation of debug statistics in nanoseconds based on System.nanoTime. Blocks MNG-5729.
Feature: Addition of TransitiveDependencyManager. Blocks MNG-5761.
Maintenance: Dependency updates.

Comitting this now so that things are part of whatever refactorings are going to be performed.


Project: http://git-wip-us.apache.org/repos/asf/maven-aether/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-aether/commit/1ee92862
Tree: http://git-wip-us.apache.org/repos/asf/maven-aether/tree/1ee92862
Diff: http://git-wip-us.apache.org/repos/asf/maven-aether/diff/1ee92862

Branch: refs/heads/master
Commit: 1ee92862c67ec98564c4d8be1207355960f1dd5d
Parents: 11a061b
Author: Christian Schulte <sc...@apache.org>
Authored: Thu Jan 28 17:25:19 2016 +0100
Committer: Christian Schulte <sc...@apache.org>
Committed: Fri Jun 10 15:54:18 2016 +0200

----------------------------------------------------------------------
 aether-api/pom.xml                              |   4 +-
 aether-connector-basic/pom.xml                  |   4 +-
 .../connector/basic/ChecksumCalculator.java     |   9 +-
 .../aether/connector/basic/PartialFile.java     |  42 +--
 aether-impl/pom.xml                             |   4 +-
 .../impl/DefaultDependencyCollector.java        |  14 +-
 .../internal/impl/DefaultFileProcessor.java     |  73 +++--
 .../aether/internal/impl/SimpleDigest.java      |   2 +-
 .../internal/impl/TrackingFileManager.java      |  33 +-
 .../impl/DefaultDependencyCollectorTest.java    | 232 ++++++++++++++
 .../artifact-descriptions/managed/gid_0_ver.ini |   4 +
 .../artifact-descriptions/managed/gid_1_ver.ini |   4 +
 .../managed/gid_2_managed-by-0.ini              |   4 +
 .../managed/gid_3_managed-by-1.ini              |   4 +
 .../managed/gid_4_managed-by-2.ini              |   2 +
 .../managed/gid_5_managed-by-3.ini              |   1 +
 .../managed/management-tree.txt                 |   6 +
 .../selection/managed/all-nodes.txt             |   4 +
 .../selection/managed/direct-of-root.txt        |   1 +
 .../managed/gid_direct-of-root_ver.ini          |   2 +
 .../selection/managed/gid_root_ver.ini          |   2 +
 .../managed/gid_transitive-of-root_ver.ini      |   2 +
 ...gid_transitive-of-transitive-of-root_ver.ini |   1 +
 .../selection/managed/transitive-of-root.txt    |   2 +
 .../transitive-of-transitive-of-root.txt        |   3 +
 .../optional/gid_direct-of-root_ver.ini         |   2 +
 .../selection/optional/gid_root_ver.ini         |   2 +
 .../optional/gid_transitive-of-root_ver.ini     |   1 +
 .../selection/optional/no-selector-tree.txt     |   3 +
 .../optional/optional-exclusion-tree.txt        |   2 +
 .../selection/scope/all-nodes.txt               |   4 +
 .../selection/scope/gid_direct-of-root_ver.ini  |   2 +
 .../selection/scope/gid_root_ver.ini            |   2 +
 .../scope/gid_transitive-of-root_ver.ini        |   2 +
 ...gid_transitive-of-transitive-of-root_ver.ini |   1 +
 .../transitive-of-root-scope-exclusion-tree.txt |   2 +
 ...ive-of-transitive-of-root-exclusion-tree.txt |   3 +
 aether-spi/pom.xml                              |   4 +-
 .../transport/AbstractTransporter.java          | 107 ++++---
 aether-test-util/pom.xml                        |   4 +-
 .../test/util/DependencyGraphParser.java        |  16 +-
 .../test/util/IniArtifactDataReader.java        |  25 +-
 .../internal/test/util/TestFileProcessor.java   |  14 +-
 .../internal/test/util/TestFileUtils.java       |  20 +-
 aether-transport-classpath/pom.xml              |   4 +-
 aether-transport-file/pom.xml                   |   4 +-
 aether-transport-http/pom.xml                   |  12 +-
 aether-transport-wagon/pom.xml                  |   8 +-
 .../transport/wagon/WagonTransporter.java       |  66 ++--
 aether-util/pom.xml                             |   4 +-
 .../org/eclipse/aether/util/ChecksumUtils.java  |  59 ++--
 .../manager/TransitiveDependencyManager.java    | 321 +++++++++++++++++++
 .../graph/selector/ScopeDependencySelector.java |  34 +-
 .../graph/transformer/ConflictIdSorter.java     |   6 +-
 .../util/graph/transformer/ConflictMarker.java  |   6 +-
 .../graph/transformer/ConflictResolver.java     |   4 +-
 pom.xml                                         |  14 +-
 57 files changed, 963 insertions(+), 254 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-api/pom.xml
----------------------------------------------------------------------
diff --git a/aether-api/pom.xml b/aether-api/pom.xml
index c894a08..ff9860c 100644
--- a/aether-api/pom.xml
+++ b/aether-api/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-api</artifactId>
@@ -44,7 +44,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-connector-basic/pom.xml
----------------------------------------------------------------------
diff --git a/aether-connector-basic/pom.xml b/aether-connector-basic/pom.xml
index 2d2a250..578c0d6 100644
--- a/aether-connector-basic/pom.xml
+++ b/aether-connector-basic/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-connector-basic</artifactId>
@@ -68,7 +68,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java
----------------------------------------------------------------------
diff --git a/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java b/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java
index e76f8a9..89ba6f0 100644
--- a/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java
+++ b/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java
@@ -167,16 +167,21 @@ final class ChecksumCalculator
                     buffer.limit( read );
                     update( buffer );
                 }
+                fis.close();
+                fis = null;
             }
             finally
             {
                 try
                 {
-                    fis.close();
+                    if ( fis != null )
+                    {
+                        fis.close();
+                    }
                 }
                 catch ( IOException e )
                 {
-                    // irrelevant
+                    // Suppressed
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/PartialFile.java
----------------------------------------------------------------------
diff --git a/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/PartialFile.java b/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/PartialFile.java
index ad428d4..217ab5e 100644
--- a/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/PartialFile.java
+++ b/aether-connector-basic/src/main/java/org/eclipse/aether/connector/basic/PartialFile.java
@@ -129,44 +129,48 @@ final class PartialFile
         private static FileLock tryLock( File lockFile )
             throws IOException
         {
-            RandomAccessFile raf = new RandomAccessFile( lockFile, "rw" );
+            RandomAccessFile raf = null;
+            FileLock lock = null;
             try
             {
-                FileLock lock = raf.getChannel().tryLock( 0, 1, false );
+                raf = new RandomAccessFile( lockFile, "rw" );
+                lock = raf.getChannel().tryLock( 0, 1, false );
                 if ( lock == null )
                 {
-                    close( raf );
+                    raf.close();
+                    raf = null;
                 }
                 return lock;
             }
             catch ( OverlappingFileLockException e )
             {
-                close( raf );
                 return null;
             }
             catch ( RuntimeException e )
             {
-                close( raf );
                 lockFile.delete();
+                lock = null;
                 throw e;
             }
             catch ( IOException e )
             {
-                close( raf );
                 lockFile.delete();
+                lock = null;
                 throw e;
             }
-        }
-
-        private static void close( Closeable file )
-        {
-            try
-            {
-                file.close();
-            }
-            catch ( IOException e )
+            finally
             {
-                // irrelevant
+                try
+                {
+                    if ( lock == null && raf != null )
+                    {
+                        raf.close();
+                    }
+                }
+                catch ( final IOException e )
+                {
+                    // Suppressed
+                }
             }
         }
 
@@ -175,9 +179,9 @@ final class PartialFile
             return concurrent;
         }
 
-        public void close()
+        public void close() throws IOException
         {
-            close( lock.channel() );
+            lock.channel().close();
             lockFile.delete();
         }
 
@@ -277,7 +281,7 @@ final class PartialFile
         return lockFile != null && partFile.length() >= threshold;
     }
 
-    public void close()
+    public void close() throws IOException
     {
         if ( partFile.exists() && !isResume() )
         {

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/pom.xml
----------------------------------------------------------------------
diff --git a/aether-impl/pom.xml b/aether-impl/pom.xml
index 71821fa..eb7c83a 100644
--- a/aether-impl/pom.xml
+++ b/aether-impl/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-impl</artifactId>
@@ -81,7 +81,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java
----------------------------------------------------------------------
diff --git a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java
index f1fcbf2..62a8ff2 100644
--- a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java
+++ b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java
@@ -169,7 +169,7 @@ public class DefaultDependencyCollector
         List<Dependency> managedDependencies = request.getManagedDependencies();
 
         Map<String, Object> stats = logger.isDebugEnabled() ? new LinkedHashMap<String, Object>() : null;
-        long time1 = System.currentTimeMillis();
+        long time1 = System.nanoTime();
 
         DefaultDependencyNode node;
         if ( root != null )
@@ -269,7 +269,7 @@ public class DefaultDependencyCollector
             errorPath = results.errorPath;
         }
 
-        long time2 = System.currentTimeMillis();
+        long time2 = System.nanoTime();
 
         DependencyGraphTransformer transformer = session.getDependencyGraphTransformer();
         if ( transformer != null )
@@ -289,7 +289,7 @@ public class DefaultDependencyCollector
 
         if ( stats != null )
         {
-            long time3 = System.currentTimeMillis();
+            long time3 = System.nanoTime();
             stats.put( "DefaultDependencyCollector.collectTime", time2 - time1 );
             stats.put( "DefaultDependencyCollector.transformTime", time3 - time2 );
             logger.debug( "Dependency collection stats: " + stats );
@@ -378,16 +378,16 @@ public class DefaultDependencyCollector
                                     DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency,
                                     List<Artifact> relocations, boolean disableVersionManagement )
     {
+        PremanagedDependency preManaged =
+            PremanagedDependency.create( depManager, dependency, disableVersionManagement, args.premanagedState );
+
+        dependency = preManaged.managedDependency;
 
         if ( depSelector != null && !depSelector.selectDependency( dependency ) )
         {
             return;
         }
 
-        PremanagedDependency preManaged =
-            PremanagedDependency.create( depManager, dependency, disableVersionManagement, args.premanagedState );
-        dependency = preManaged.managedDependency;
-
         boolean noDescriptor = isLackingDescriptor( dependency.getArtifact() );
 
         boolean traverse = !noDescriptor && ( depTraverser == null || depTraverser.traverseDependency( dependency ) );

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultFileProcessor.java
----------------------------------------------------------------------
diff --git a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultFileProcessor.java b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultFileProcessor.java
index cfeac98..ea0665e 100644
--- a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultFileProcessor.java
+++ b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultFileProcessor.java
@@ -19,7 +19,6 @@ package org.eclipse.aether.internal.impl;
  * under the License.
  */
 
-import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -40,21 +39,6 @@ public class DefaultFileProcessor
     implements FileProcessor
 {
 
-    private static void close( Closeable closeable )
-    {
-        if ( closeable != null )
-        {
-            try
-            {
-                closeable.close();
-            }
-            catch ( IOException e )
-            {
-                // too bad but who cares
-            }
-        }
-    }
-
     /**
      * Thread-safe variant of {@link File#mkdirs()}. Creates the directory named by the given abstract pathname,
      * including any necessary but nonexistent parent directories. Note that if this operation fails it may have
@@ -111,10 +95,21 @@ public class DefaultFileProcessor
 
             // allow output to report any flush/close errors
             fos.close();
+            fos = null;
         }
         finally
         {
-            close( fos );
+            try
+            {
+                if ( fos != null )
+                {
+                    fos.close();
+                }
+            }
+            catch ( final IOException e )
+            {
+                // Suppressed
+            }
         }
     }
 
@@ -132,10 +127,21 @@ public class DefaultFileProcessor
 
             // allow output to report any flush/close errors
             fos.close();
+            fos = null;
         }
         finally
         {
-            close( fos );
+            try
+            {
+                if ( fos != null )
+                {
+                    fos.close();
+                }
+            }
+            catch ( final IOException e )
+            {
+                // Suppressed
+            }
         }
     }
 
@@ -164,11 +170,38 @@ public class DefaultFileProcessor
 
             // allow output to report any flush/close errors
             fos.close();
+            fos = null;
+
+            fis.close();
+            fis = null;
         }
         finally
         {
-            close( fis );
-            close( fos );
+            try
+            {
+                if ( fos != null )
+                {
+                    fos.close();
+                }
+            }
+            catch ( final IOException e )
+            {
+                // Suppressed
+            }
+            finally
+            {
+                try
+                {
+                    if ( fis != null )
+                    {
+                        fis.close();
+                    }
+                }
+                catch ( final IOException e )
+                {
+                    // Suppressed
+                }
+            }
         }
 
         return total;

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleDigest.java
----------------------------------------------------------------------
diff --git a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleDigest.java b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleDigest.java
index 9b51e98..1dcefa4 100644
--- a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleDigest.java
+++ b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleDigest.java
@@ -67,7 +67,7 @@ class SimpleDigest
             }
             catch ( UnsupportedEncodingException e )
             {
-                // broken JVM
+                throw new AssertionError( e );
             }
         }
         else

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java
----------------------------------------------------------------------
diff --git a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java
index 7b33f6e..9b17e3a 100644
--- a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java
+++ b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/TrackingFileManager.java
@@ -19,13 +19,12 @@ package org.eclipse.aether.internal.impl;
  * under the License.
  */
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.RandomAccessFile;
+import java.nio.channels.Channels;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
 import java.nio.channels.OverlappingFileLockException;
@@ -69,6 +68,12 @@ class TrackingFileManager
                 Properties props = new Properties();
                 props.load( stream );
 
+                lock.release();
+                lock = null;
+
+                stream.close();
+                stream = null;
+
                 return props;
             }
             catch ( IOException e )
@@ -107,13 +112,7 @@ class TrackingFileManager
 
                 if ( file.canRead() )
                 {
-                    byte[] buffer = new byte[(int) raf.length()];
-
-                    raf.readFully( buffer );
-
-                    ByteArrayInputStream stream = new ByteArrayInputStream( buffer );
-
-                    props.load( stream );
+                    props.load( Channels.newInputStream( raf.getChannel() ) );
                 }
 
                 for ( Map.Entry<String, String> update : updates.entrySet() )
@@ -128,15 +127,17 @@ class TrackingFileManager
                     }
                 }
 
-                ByteArrayOutputStream stream = new ByteArrayOutputStream( 1024 * 2 );
-
                 logger.debug( "Writing tracking file " + file );
-                props.store( stream, "NOTE: This is an Aether internal implementation file"
-                    + ", its format can be changed without prior notice." );
+                raf.setLength( 0 );
+                props.store( Channels.newOutputStream( raf.getChannel() ),
+                             "NOTE: This is an Aether internal implementation file"
+                                 + ", its format can be changed without prior notice." );
+
+                lock.release();
+                lock = null;
 
-                raf.seek( 0 );
-                raf.write( stream.toByteArray() );
-                raf.setLength( raf.getFilePointer() );
+                raf.close();
+                raf = null;
             }
             catch ( IOException e )
             {

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultDependencyCollectorTest.java
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultDependencyCollectorTest.java b/aether-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultDependencyCollectorTest.java
index b78838a..fd1302d 100644
--- a/aether-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultDependencyCollectorTest.java
+++ b/aether-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultDependencyCollectorTest.java
@@ -43,6 +43,7 @@ import org.eclipse.aether.collection.DependencyCollectionContext;
 import org.eclipse.aether.collection.DependencyCollectionException;
 import org.eclipse.aether.collection.DependencyManagement;
 import org.eclipse.aether.collection.DependencyManager;
+import org.eclipse.aether.collection.DependencySelector;
 import org.eclipse.aether.graph.Dependency;
 import org.eclipse.aether.graph.DependencyCycle;
 import org.eclipse.aether.graph.DependencyNode;
@@ -58,6 +59,9 @@ import org.eclipse.aether.resolution.ArtifactDescriptorResult;
 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
 import org.eclipse.aether.util.graph.manager.ClassicDependencyManager;
 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
+import org.eclipse.aether.util.graph.manager.TransitiveDependencyManager;
+import org.eclipse.aether.util.graph.selector.OptionalDependencySelector;
+import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
 import org.eclipse.aether.util.graph.version.HighestVersionFilter;
 import org.junit.Before;
 import org.junit.Test;
@@ -482,6 +486,157 @@ public class DefaultDependencyCollectorTest
     }
 
     @Test
+    public void testDependencyManagement_TransitiveDependencyManager()
+        throws DependencyCollectionException, IOException
+    {
+        collector.setArtifactDescriptorReader( newReader( "managed/" ) );
+        parser = new DependencyGraphParser( "artifact-descriptions/managed/" );
+        session.setDependencyManager( new TransitiveDependencyManager() );
+        final Dependency root = newDep( "gid:0:ext:ver" );
+        CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) );
+        CollectResult result = collector.collectDependencies( session, request );
+
+        DependencyNode expected = parser.parseResource( "management-tree.txt" );
+        assertEqualSubtree( expected, result.getRoot() );
+    }
+
+    @Test
+    public void testDependencyManagement_DependencySelectorProcessesManagedState()
+        throws DependencyCollectionException, IOException
+    {
+        collector.setArtifactDescriptorReader( newReader( "selection/managed/" ) );
+        parser = new DependencyGraphParser( "artifact-descriptions/selection/managed/" );
+
+        final Dependency root = newDep( "gid:root:ext:ver", "root-scope" );
+        CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) );
+        CollectResult result = collector.collectDependencies( session, request );
+
+        DependencyNode expected = parser.parseResource( "all-nodes.txt" );
+        assertEqualSubtree( expected, result.getRoot() );
+
+        this.session.setDependencySelector( new DependencySelector()
+        {
+
+            public boolean selectDependency( final Dependency dependency )
+            {
+                return dependency != null
+                           && !( "managed".equals( dependency.getScope() )
+                                 || "managed".equals( dependency.getArtifact().getVersion() )
+                                 || dependency.isOptional() );
+
+            }
+
+            public DependencySelector deriveChildSelector( final DependencyCollectionContext context )
+            {
+                return this;
+            }
+
+        } );
+
+        // Tests managed scope is processed by selector.
+        TestDependencyManager depMgmt = new TestDependencyManager();
+        depMgmt.scope( "gid:transitive-of-transitive-of-root:ext", "managed" );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "transitive-of-transitive-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        depMgmt = new TestDependencyManager();
+        depMgmt.scope( "gid:transitive-of-root:ext", "managed" );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "transitive-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        depMgmt = new TestDependencyManager();
+        depMgmt.scope( "gid:direct-of-root:ext", "managed" );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "direct-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        // Tests managed optionality is processed by selector.
+        depMgmt = new TestDependencyManager();
+        depMgmt.optional( "gid:transitive-of-transitive-of-root:ext", Boolean.TRUE );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "transitive-of-transitive-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        depMgmt = new TestDependencyManager();
+        depMgmt.optional( "gid:transitive-of-root:ext", Boolean.TRUE );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "transitive-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        depMgmt = new TestDependencyManager();
+        depMgmt.optional( "gid:direct-of-root:ext", Boolean.TRUE );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "direct-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        // Tests managed version is processed by selector.
+        depMgmt = new TestDependencyManager();
+        depMgmt.version( "gid:transitive-of-transitive-of-root:ext", "managed" );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "transitive-of-transitive-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        depMgmt = new TestDependencyManager();
+        depMgmt.version( "gid:transitive-of-root:ext", "managed" );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "transitive-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        depMgmt = new TestDependencyManager();
+        depMgmt.version( "gid:direct-of-root:ext", "managed" );
+        session.setDependencyManager( depMgmt );
+
+        expected = parser.parseResource( "direct-of-root.txt" );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+    }
+
+    @Test
     public void testVersionFilter()
         throws Exception
     {
@@ -491,6 +646,83 @@ public class DefaultDependencyCollectorTest
         assertEquals( 1, result.getRoot().getChildren().size() );
     }
 
+    @Test
+    public void testSelectionWithScopeDependencySelector()
+        throws DependencyCollectionException, IOException
+    {
+        collector.setArtifactDescriptorReader( newReader( "selection/scope/" ) );
+        parser = new DependencyGraphParser( "artifact-descriptions/selection/scope/" );
+
+        final Dependency root = newDep( "gid:root:ext:ver", "root-scope" );
+        CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) );
+        CollectResult result = collector.collectDependencies( session, request );
+
+        DependencyNode expected = parser.parseResource( "all-nodes.txt" );
+        assertEqualSubtree( expected, result.getRoot() );
+
+        /*
+         A dependency selector that filters transitive dependencies based on their scope. Direct dependencies are always
+         included regardless of their scope.
+         */
+        // Include all.
+        this.session.setDependencySelector( new ScopeDependencySelector() );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        // Exclude scope of direct dependency of root equals "include all" as direct dependencies are always included.
+        this.session.setDependencySelector( new ScopeDependencySelector( "direct-of-root-scope" ) );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        // Exclude scope of transitive dependency of direct dependency of root.
+        expected = parser.parseResource( "transitive-of-root-scope-exclusion-tree.txt" );
+        this.session.setDependencySelector( new ScopeDependencySelector( "transitive-of-root-scope" ) );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+
+        // Exclude scope of transitive dependency of transitive dependency of direct dependency of root.
+        expected = parser.parseResource( "transitive-of-transitive-of-root-exclusion-tree.txt" );
+        this.session.setDependencySelector( new ScopeDependencySelector( "transitive-of-transitive-of-root-scope" ) );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+    }
+
+    @Test
+    public void testSelectionWithOptionalDependencySelector()
+        throws DependencyCollectionException, IOException
+    {
+        collector.setArtifactDescriptorReader( newReader( "selection/optional/" ) );
+        parser = new DependencyGraphParser( "artifact-descriptions/selection/optional/" );
+
+        final Dependency root = newDep( "gid:root:ext:ver", "root-scope" );
+        CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) );
+        CollectResult result = collector.collectDependencies( session, request );
+
+        DependencyNode expected = parser.parseResource( "no-selector-tree.txt" );
+        assertEqualSubtree( expected, result.getRoot() );
+
+        // Exclude optional transitive dependencies.
+        expected = parser.parseResource( "optional-exclusion-tree.txt" );
+        this.session.setDependencySelector( new OptionalDependencySelector() );
+
+        request = new CollectRequest( root, Arrays.asList( repository ) );
+        result = collector.collectDependencies( session, request );
+
+        assertEqualSubtree( expected, result.getRoot() );
+    }
+
     static class TestDependencyManager
         implements DependencyManager
     {

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/managed/gid_0_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/managed/gid_0_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_0_ver.ini
new file mode 100644
index 0000000..1831746
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_0_ver.ini
@@ -0,0 +1,4 @@
+[dependencies]
+gid:1:ext:ver
+[manageddependencies]
+gid:2:ext:managed-by-0
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/managed/gid_1_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/managed/gid_1_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_1_ver.ini
new file mode 100644
index 0000000..805fd98
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_1_ver.ini
@@ -0,0 +1,4 @@
+[dependencies]
+gid:2:ext:ver
+[manageddependencies]
+gid:3:ext:managed-by-1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/managed/gid_2_managed-by-0.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/managed/gid_2_managed-by-0.ini b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_2_managed-by-0.ini
new file mode 100644
index 0000000..e6cc9a6
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_2_managed-by-0.ini
@@ -0,0 +1,4 @@
+[dependencies]
+gid:3:ext:ver
+[manageddependencies]
+gid:4:ext:managed-by-2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/managed/gid_3_managed-by-1.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/managed/gid_3_managed-by-1.ini b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_3_managed-by-1.ini
new file mode 100644
index 0000000..aa1cea4
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_3_managed-by-1.ini
@@ -0,0 +1,4 @@
+[dependencies]
+gid:4:ext:ver
+[manageddependencies]
+gid:5:ext:managed-by-3
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/managed/gid_4_managed-by-2.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/managed/gid_4_managed-by-2.ini b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_4_managed-by-2.ini
new file mode 100644
index 0000000..990c928
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_4_managed-by-2.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:5:ext:ver

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/managed/gid_5_managed-by-3.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/managed/gid_5_managed-by-3.ini b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_5_managed-by-3.ini
new file mode 100644
index 0000000..05ba453
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/managed/gid_5_managed-by-3.ini
@@ -0,0 +1 @@
+[dependencies]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/managed/management-tree.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/managed/management-tree.txt b/aether-impl/src/test/resources/artifact-descriptions/managed/management-tree.txt
new file mode 100644
index 0000000..7307a19
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/managed/management-tree.txt
@@ -0,0 +1,6 @@
+gid:0:ext:ver
++- gid:1:ext:ver compile
+   +- gid:2:ext:managed-by-0 compile
+      +- gid:3:ext:managed-by-1 compile
+         +- gid:4:ext:managed-by-2 compile
+            +- gid:5:ext:managed-by-3 compile

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/managed/all-nodes.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/managed/all-nodes.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/all-nodes.txt
new file mode 100644
index 0000000..6caeee1
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/all-nodes.txt
@@ -0,0 +1,4 @@
+gid:root:ext:ver root-scope
++- gid:direct-of-root:ext:ver direct-of-root-scope
+   +- gid:transitive-of-root:ext:ver transitive-of-root-scope
+      +- gid:transitive-of-transitive-of-root:ext:ver transitive-of-transitive-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/managed/direct-of-root.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/managed/direct-of-root.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/direct-of-root.txt
new file mode 100644
index 0000000..e7b354d
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/direct-of-root.txt
@@ -0,0 +1 @@
+gid:root:ext:ver root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_direct-of-root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_direct-of-root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_direct-of-root_ver.ini
new file mode 100644
index 0000000..a801f3f
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_direct-of-root_ver.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:transitive-of-root:ext:ver:transitive-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_root_ver.ini
new file mode 100644
index 0000000..37fe9ac
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_root_ver.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:direct-of-root:ext:ver:direct-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-root_ver.ini
new file mode 100644
index 0000000..e34fa04
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-root_ver.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:transitive-of-transitive-of-root:ext:ver:transitive-of-transitive-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-transitive-of-root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-transitive-of-root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-transitive-of-root_ver.ini
new file mode 100644
index 0000000..61a252c
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-transitive-of-root_ver.ini
@@ -0,0 +1 @@
+[dependencies]

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-root.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-root.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-root.txt
new file mode 100644
index 0000000..dbee99b
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-root.txt
@@ -0,0 +1,2 @@
+gid:root:ext:ver root-scope
++- gid:direct-of-root:ext:ver direct-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-transitive-of-root.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-transitive-of-root.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-transitive-of-root.txt
new file mode 100644
index 0000000..ef3dc74
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-transitive-of-root.txt
@@ -0,0 +1,3 @@
+gid:root:ext:ver root-scope
++- gid:direct-of-root:ext:ver direct-of-root-scope
+   +- gid:transitive-of-root:ext:ver transitive-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_direct-of-root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_direct-of-root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_direct-of-root_ver.ini
new file mode 100644
index 0000000..68e3240
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_direct-of-root_ver.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:transitive-of-root:ext:ver:transitive-of-root-scope:optional

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_root_ver.ini
new file mode 100644
index 0000000..fbdaab9
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_root_ver.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:direct-of-root:ext:ver:direct-of-root-scope:optional

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-of-root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-of-root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-of-root_ver.ini
new file mode 100644
index 0000000..61a252c
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-of-root_ver.ini
@@ -0,0 +1 @@
+[dependencies]

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/optional/no-selector-tree.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/optional/no-selector-tree.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/no-selector-tree.txt
new file mode 100644
index 0000000..890216c
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/no-selector-tree.txt
@@ -0,0 +1,3 @@
+gid:root:ext:ver root-scope
++- gid:direct-of-root:ext:ver direct-of-root-scope optional
+   +- gid:transitive-of-root:ext:ver transitive-of-root-scope optional

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/optional/optional-exclusion-tree.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/optional/optional-exclusion-tree.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/optional-exclusion-tree.txt
new file mode 100644
index 0000000..fe87f12
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/optional/optional-exclusion-tree.txt
@@ -0,0 +1,2 @@
+gid:root:ext:ver root-scope
++- gid:direct-of-root:ext:ver direct-of-root-scope optional

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/scope/all-nodes.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/scope/all-nodes.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/all-nodes.txt
new file mode 100644
index 0000000..6caeee1
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/all-nodes.txt
@@ -0,0 +1,4 @@
+gid:root:ext:ver root-scope
++- gid:direct-of-root:ext:ver direct-of-root-scope
+   +- gid:transitive-of-root:ext:ver transitive-of-root-scope
+      +- gid:transitive-of-transitive-of-root:ext:ver transitive-of-transitive-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_direct-of-root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_direct-of-root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_direct-of-root_ver.ini
new file mode 100644
index 0000000..a801f3f
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_direct-of-root_ver.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:transitive-of-root:ext:ver:transitive-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_root_ver.ini
new file mode 100644
index 0000000..37fe9ac
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_root_ver.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:direct-of-root:ext:ver:direct-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-of-root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-of-root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-of-root_ver.ini
new file mode 100644
index 0000000..e34fa04
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-of-root_ver.ini
@@ -0,0 +1,2 @@
+[dependencies]
+gid:transitive-of-transitive-of-root:ext:ver:transitive-of-transitive-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-of-transitive-of-root_ver.ini
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-of-transitive-of-root_ver.ini b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-of-transitive-of-root_ver.ini
new file mode 100644
index 0000000..61a252c
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-of-transitive-of-root_ver.ini
@@ -0,0 +1 @@
+[dependencies]

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-of-root-scope-exclusion-tree.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-of-root-scope-exclusion-tree.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-of-root-scope-exclusion-tree.txt
new file mode 100644
index 0000000..dbee99b
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-of-root-scope-exclusion-tree.txt
@@ -0,0 +1,2 @@
+gid:root:ext:ver root-scope
++- gid:direct-of-root:ext:ver direct-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-of-transitive-of-root-exclusion-tree.txt
----------------------------------------------------------------------
diff --git a/aether-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-of-transitive-of-root-exclusion-tree.txt b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-of-transitive-of-root-exclusion-tree.txt
new file mode 100644
index 0000000..ef3dc74
--- /dev/null
+++ b/aether-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-of-transitive-of-root-exclusion-tree.txt
@@ -0,0 +1,3 @@
+gid:root:ext:ver root-scope
++- gid:direct-of-root:ext:ver direct-of-root-scope
+   +- gid:transitive-of-root:ext:ver transitive-of-root-scope

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-spi/pom.xml
----------------------------------------------------------------------
diff --git a/aether-spi/pom.xml b/aether-spi/pom.xml
index 0b43c86..fde2d34 100644
--- a/aether-spi/pom.xml
+++ b/aether-spi/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-spi</artifactId>
@@ -48,7 +48,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-spi/src/main/java/org/eclipse/aether/spi/connector/transport/AbstractTransporter.java
----------------------------------------------------------------------
diff --git a/aether-spi/src/main/java/org/eclipse/aether/spi/connector/transport/AbstractTransporter.java b/aether-spi/src/main/java/org/eclipse/aether/spi/connector/transport/AbstractTransporter.java
index 21e54c9..acad985 100644
--- a/aether-spi/src/main/java/org/eclipse/aether/spi/connector/transport/AbstractTransporter.java
+++ b/aether-spi/src/main/java/org/eclipse/aether/spi/connector/transport/AbstractTransporter.java
@@ -19,7 +19,6 @@ package org.eclipse.aether.spi.connector.transport;
  * under the License.
  */
 
-import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -96,25 +95,47 @@ public abstract class AbstractTransporter
     protected void utilGet( GetTask task, InputStream is, boolean close, long length, boolean resume )
         throws IOException, TransferCancelledException
     {
+        OutputStream os = null;
         try
         {
+            os = task.newOutputStream( resume );
             task.getListener().transportStarted( resume ? task.getResumeOffset() : 0, length );
-            OutputStream os = task.newOutputStream( resume );
-            try
-            {
-                copy( os, is, task.getListener() );
-                os.close();
-            }
-            finally
+            copy( os, is, task.getListener() );
+            os.close();
+            os = null;
+
+            if ( close )
             {
-                close( os );
+                is.close();
+                is = null;
             }
         }
         finally
         {
-            if ( close )
+            try
+            {
+                if ( os != null )
+                {
+                    os.close();
+                }
+            }
+            catch ( final IOException e )
             {
-                close( is );
+                // Suppressed
+            }
+            finally
+            {
+                try
+                {
+                    if ( close && is != null )
+                    {
+                        is.close();
+                    }
+                }
+                catch ( final IOException e )
+                {
+                    // Suppressed
+                }
             }
         }
     }
@@ -147,35 +168,56 @@ public abstract class AbstractTransporter
      * @throws IOException If the transfer encountered an I/O error.
      * @throws TransferCancelledException If the transfer was cancelled.
      */
-    protected void utilPut( PutTask task, OutputStream os, boolean close )
+    protected void utilPut( PutTask task, OutputStream out, boolean close )
         throws IOException, TransferCancelledException
     {
+        InputStream in = null;
         try
         {
+            in = task.newInputStream();
             task.getListener().transportStarted( 0, task.getDataLength() );
-            InputStream is = task.newInputStream();
-            try
-            {
-                copy( os, is, task.getListener() );
-            }
-            finally
-            {
-                close( is );
-            }
+            copy( out, in, task.getListener() );
+
             if ( close )
             {
-                os.close();
+                out.close();
             }
             else
             {
-                os.flush();
+                out.flush();
             }
+
+            out = null;
+
+            in.close();
+            in = null;
         }
         finally
         {
-            if ( close )
+            try
+            {
+                if ( close && out != null )
+                {
+                    out.close();
+                }
+            }
+            catch ( final IOException e )
             {
-                close( os );
+                // Suppressed
+            }
+            finally
+            {
+                try
+                {
+                    if ( in != null )
+                    {
+                        in.close();
+                    }
+                }
+                catch ( final IOException e )
+                {
+                    // Suppressed
+                }
             }
         }
     }
@@ -215,19 +257,4 @@ public abstract class AbstractTransporter
         }
     }
 
-    private static void close( Closeable file )
-    {
-        if ( file != null )
-        {
-            try
-            {
-                file.close();
-            }
-            catch ( IOException e )
-            {
-                // irrelevant
-            }
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-test-util/pom.xml
----------------------------------------------------------------------
diff --git a/aether-test-util/pom.xml b/aether-test-util/pom.xml
index e47f125..a76176d 100644
--- a/aether-test-util/pom.xml
+++ b/aether-test-util/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-test-util</artifactId>
@@ -52,7 +52,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java
----------------------------------------------------------------------
diff --git a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java
index a745ccf..7976487 100644
--- a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java
+++ b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java
@@ -191,13 +191,23 @@ public class DependencyGraphParser
         try
         {
             stream = resource.openStream();
-            return parse( new BufferedReader( new InputStreamReader( stream, "UTF-8" ) ) );
+            final DependencyNode node = parse( new BufferedReader( new InputStreamReader( stream, "UTF-8" ) ) );
+            stream.close();
+            stream = null;
+            return node;
         }
         finally
         {
-            if ( stream != null )
+            try
+            {
+                if ( stream != null )
+                {
+                    stream.close();
+                }
+            }
+            catch ( final IOException e )
             {
-                stream.close();
+                // Suppressed
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java
----------------------------------------------------------------------
diff --git a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java
index 4253544..b38c4d6 100644
--- a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java
+++ b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java
@@ -107,18 +107,14 @@ class IniArtifactDataReader
     private ArtifactDescription parse( Reader reader )
         throws IOException
     {
-        String line = null;
-
         State state = State.NONE;
-
         Map<State, List<String>> sections = new HashMap<State, List<String>>();
-
-        BufferedReader in = new BufferedReader( reader );
+        BufferedReader in = null;
         try
         {
-            while ( ( line = in.readLine() ) != null )
+            in = new BufferedReader( reader );
+            for ( String line = in.readLine(); line != null; line = in.readLine() )
             {
-
                 line = cutComment( line );
                 if ( isEmpty( line ) )
                 {
@@ -149,10 +145,23 @@ class IniArtifactDataReader
                     lines.add( line.trim() );
                 }
             }
+
+            in.close();
+            in = null;
         }
         finally
         {
-            in.close();
+            try
+            {
+                if ( in != null )
+                {
+                    in.close();
+                }
+            }
+            catch ( final IOException e )
+            {
+                // Suppressed
+            }
         }
 
         Artifact relocation = relocation( sections.get( State.RELOCATION ) );

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileProcessor.java
----------------------------------------------------------------------
diff --git a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileProcessor.java b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileProcessor.java
index fe130a3..6744583 100644
--- a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileProcessor.java
+++ b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileProcessor.java
@@ -100,6 +100,7 @@ public class TestFileProcessor
 
             // allow output to report any flush/close errors
             fos.close();
+            fos = null;
         }
         finally
         {
@@ -121,6 +122,7 @@ public class TestFileProcessor
 
             // allow output to report any flush/close errors
             fos.close();
+            fos = null;
         }
         finally
         {
@@ -137,8 +139,6 @@ public class TestFileProcessor
     public long copy( File source, File target, ProgressListener listener )
         throws IOException
     {
-        long total = 0;
-
         InputStream fis = null;
         OutputStream fos = null;
         try
@@ -149,18 +149,22 @@ public class TestFileProcessor
 
             fos = new BufferedOutputStream( new FileOutputStream( target ) );
 
-            total = copy( fos, fis, listener );
+            final long total = copy( fos, fis, listener );
 
             // allow output to report any flush/close errors
             fos.close();
+            fos = null;
+
+            fis.close();
+            fis = null;
+
+            return total;
         }
         finally
         {
             close( fis );
             close( fos );
         }
-
-        return total;
     }
 
     private long copy( OutputStream os, InputStream is, ProgressListener listener )

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java
----------------------------------------------------------------------
diff --git a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java
index 9757daa..be04bdc 100644
--- a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java
+++ b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java
@@ -198,8 +198,6 @@ public class TestFileUtils
     public static long copyFile( File source, File target )
         throws IOException
     {
-        long total = 0;
-
         FileInputStream fis = null;
         OutputStream fos = null;
         try
@@ -210,7 +208,9 @@ public class TestFileUtils
 
             fos = new BufferedOutputStream( new FileOutputStream( target ) );
 
-            for ( byte[] buffer = new byte[1024 * 32];; )
+            long total = 0;
+
+            for ( byte[] buffer = new byte[ 1024 * 32 ];; )
             {
                 int bytes = fis.read( buffer );
                 if ( bytes < 0 )
@@ -224,14 +224,18 @@ public class TestFileUtils
             }
 
             fos.close();
+            fos = null;
+
+            fis.close();
+            fis = null;
+
+            return total;
         }
         finally
         {
             close( fis );
             close( fos );
         }
-
-        return total;
     }
 
     public static byte[] readBytes( File file )
@@ -243,6 +247,8 @@ public class TestFileUtils
             in = new RandomAccessFile( file, "r" );
             byte[] actual = new byte[(int) in.length()];
             in.readFully( actual );
+            in.close();
+            in = null;
             return actual;
         }
         finally
@@ -265,6 +271,7 @@ public class TestFileUtils
                 out.write( pattern );
             }
             out.close();
+            out = null;
         }
         finally
         {
@@ -293,6 +300,8 @@ public class TestFileUtils
         {
             fis = new FileInputStream( file );
             props.load( fis );
+            fis.close();
+            fis = null;
         }
         finally
         {
@@ -311,6 +320,7 @@ public class TestFileUtils
             fos = new FileOutputStream( file );
             props.store( fos, "aether-test" );
             fos.close();
+            fos = null;
         }
         finally
         {

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-transport-classpath/pom.xml
----------------------------------------------------------------------
diff --git a/aether-transport-classpath/pom.xml b/aether-transport-classpath/pom.xml
index f1d850f..f2e6579 100644
--- a/aether-transport-classpath/pom.xml
+++ b/aether-transport-classpath/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-transport-classpath</artifactId>
@@ -68,7 +68,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-transport-file/pom.xml
----------------------------------------------------------------------
diff --git a/aether-transport-file/pom.xml b/aether-transport-file/pom.xml
index d724da1..a88dc49 100644
--- a/aether-transport-file/pom.xml
+++ b/aether-transport-file/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-transport-file</artifactId>
@@ -68,7 +68,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-transport-http/pom.xml
----------------------------------------------------------------------
diff --git a/aether-transport-http/pom.xml b/aether-transport-http/pom.xml
index e8c29b6..835bce2 100644
--- a/aether-transport-http/pom.xml
+++ b/aether-transport-http/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-transport-http</artifactId>
@@ -52,7 +52,7 @@
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
-      <version>4.3.5</version>
+      <version>4.3.6</version>
       <exclusions>
         <exclusion>
           <!-- using jcl-over-slf4j instead -->
@@ -64,7 +64,7 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>jcl-over-slf4j</artifactId>
-      <version>1.6.2</version>
+      <version>1.7.16</version>
     </dependency>
     <dependency>
       <groupId>javax.inject</groupId>
@@ -85,7 +85,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -96,13 +96,13 @@
     <dependency>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-server</artifactId>
-      <version>7.6.15.v20140411</version>
+      <version>7.6.19.v20160209</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
-      <version>1.0.7</version>
+      <version>1.0.13</version>
       <scope>test</scope>
     </dependency>
   </dependencies>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-transport-wagon/pom.xml
----------------------------------------------------------------------
diff --git a/aether-transport-wagon/pom.xml b/aether-transport-wagon/pom.xml
index d2d9c9a..bd3ad2a 100644
--- a/aether-transport-wagon/pom.xml
+++ b/aether-transport-wagon/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-transport-wagon</artifactId>
@@ -73,13 +73,13 @@
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-classworlds</artifactId>
-      <version>2.4</version>
+      <version>2.4.2</version>
       <optional>true</optional>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
-      <version>2.1</version>
+      <version>3.0.24</version>
       <optional>true</optional>
     </dependency>
     <dependency>
@@ -100,7 +100,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporter.java
----------------------------------------------------------------------
diff --git a/aether-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporter.java b/aether-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporter.java
index e9f89c2..635f211 100644
--- a/aether-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporter.java
+++ b/aether-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporter.java
@@ -457,6 +457,7 @@ final class WagonTransporter
     {
         if ( path != null && !path.delete() && path.exists() )
         {
+            path.deleteOnExit();
             logger.debug( "Could not delete temorary file " + path );
         }
     }
@@ -594,23 +595,22 @@ final class WagonTransporter
         private void readTempFile( File dst )
             throws IOException
         {
-            FileInputStream fis = new FileInputStream( dst );
+            FileInputStream in = null;
+            OutputStream out = null;
             try
             {
-                OutputStream os = task.newOutputStream();
-                try
-                {
-                    copy( os, fis );
-                    os.close();
-                }
-                finally
-                {
-                    close( os );
-                }
+                in = new FileInputStream( dst );
+                out = task.newOutputStream();
+                copy( out, in );
+                out.close();
+                out = null;
+                in.close();
+                in = null;
             }
             finally
             {
-                close( fis );
+                close( out );
+                close( in );
             }
         }
 
@@ -634,11 +634,14 @@ final class WagonTransporter
             File file = task.getDataFile();
             if ( file == null && wagon instanceof StreamingWagon )
             {
-                InputStream src = task.newInputStream();
+                InputStream src = null;
                 try
                 {
+                    src = task.newInputStream();
                     // StreamingWagon uses an internal buffer on src input stream.
                     ( (StreamingWagon) wagon ).putFromStream( src, dst, task.getDataLength(), -1 );
+                    src.close();
+                    src = null;
                 }
                 finally
                 {
@@ -665,34 +668,31 @@ final class WagonTransporter
         private File createTempFile()
             throws IOException
         {
-            File tmp = newTempFile();
+            File tmp = null;
+            FileOutputStream out = null;
+            InputStream in = null;
             try
             {
-                FileOutputStream fos = new FileOutputStream( tmp );
-                try
-                {
-                    InputStream is = task.newInputStream();
-                    try
-                    {
-                        copy( fos, is );
-                        fos.close();
-                    }
-                    finally
-                    {
-                        close( is );
-                    }
-                }
-                finally
-                {
-                    close( fos );
-                }
+                tmp = newTempFile();
+                in = task.newInputStream();
+                out = new FileOutputStream( tmp );
+                copy( out, in );
+                out.close();
+                out = null;
+                in.close();
+                in = null;
+                return tmp;
             }
             catch ( IOException e )
             {
                 delTempFile( tmp );
                 throw e;
             }
-            return tmp;
+            finally
+            {
+                close( out );
+                close( in );
+            }
         }
 
     }

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-util/pom.xml
----------------------------------------------------------------------
diff --git a/aether-util/pom.xml b/aether-util/pom.xml
index 3bc25cc..2e3d0a5 100644
--- a/aether-util/pom.xml
+++ b/aether-util/pom.xml
@@ -25,7 +25,7 @@
   <parent>
     <groupId>org.apache.maven.aether</groupId>
     <artifactId>aether</artifactId>
-    <version>1.1.0-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>aether-util</artifactId>
@@ -47,7 +47,7 @@
     </dependency>
     <dependency>
       <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
+      <artifactId>hamcrest-core</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/1ee92862/aether-util/src/main/java/org/eclipse/aether/util/ChecksumUtils.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/ChecksumUtils.java b/aether-util/src/main/java/org/eclipse/aether/util/ChecksumUtils.java
index b629c8d..f4b9b74 100644
--- a/aether-util/src/main/java/org/eclipse/aether/util/ChecksumUtils.java
+++ b/aether-util/src/main/java/org/eclipse/aether/util/ChecksumUtils.java
@@ -52,49 +52,34 @@ public final class ChecksumUtils
         throws IOException
     {
         String checksum = "";
-
-        FileInputStream fis = new FileInputStream( checksumFile );
+        BufferedReader reader = null;
         try
         {
-            BufferedReader br = new BufferedReader( new InputStreamReader( fis, "UTF-8" ), 512 );
-            try
+            reader = new BufferedReader( new InputStreamReader( new FileInputStream( checksumFile ), "UTF-8" ), 512 );
+            for ( String line = reader.readLine(); line != null; line = reader.readLine() )
             {
-                while ( true )
+                line = line.trim();
+                if ( line.length() > 0 )
                 {
-                    String line = br.readLine();
-                    if ( line == null )
-                    {
-                        break;
-                    }
-                    line = line.trim();
-                    if ( line.length() > 0 )
-                    {
-                        checksum = line;
-                        break;
-                    }
-                }
-            }
-            finally
-            {
-                try
-                {
-                    br.close();
-                }
-                catch ( IOException e )
-                {
-                    // ignored
+                    checksum = line;
+                    break;
                 }
             }
+            reader.close();
+            reader = null;
         }
         finally
         {
             try
             {
-                fis.close();
+                if ( reader != null )
+                {
+                    reader.close();
+                }
             }
             catch ( IOException e )
             {
-                // ignored
+                // Suppressed
             }
         }
 
@@ -144,12 +129,13 @@ public final class ChecksumUtils
             }
         }
 
-        FileInputStream fis = new FileInputStream( dataFile );
+        FileInputStream in = null;
         try
         {
-            for ( byte[] buffer = new byte[32 * 1024];; )
+            in = new FileInputStream( dataFile );
+            for ( byte[] buffer = new byte[ 32 * 1024 ];; )
             {
-                int read = fis.read( buffer );
+                int read = in.read( buffer );
                 if ( read < 0 )
                 {
                     break;
@@ -159,16 +145,21 @@ public final class ChecksumUtils
                     digest.update( buffer, 0, read );
                 }
             }
+            in.close();
+            in = null;
         }
         finally
         {
             try
             {
-                fis.close();
+                if ( in != null )
+                {
+                    in.close();
+                }
             }
             catch ( IOException e )
             {
-                // ignored
+                // Suppressed
             }
         }