MSHARED-336: Added an overloaded method to DependencyGraphBuilder that accepts the reactor projects and resolves dependencies from within the reactor.
- Added multi-module-test to validate that the new method works against both direct and transitive deps.
- Added multi-module-plugin to be used to validate multi-module-test
- Added ProjectReferenceKeyGenerator as there is currently no public method to generate the key for MavenProject#projectReferences, MavenSession#projectMap or the Map of reactor projects that we will use.
- Separated the reflective invocation out into the Invoker class.
- Made maven-project dependency scope=provided as at runtime we want the version in the maven install, not 2.2.0
Submitted by: William Ferguson <william.ferguson@xandar.com.au>



git-svn-id: https://svn.apache.org/repos/asf/maven/shared/trunk@1595491 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 3669141..e56f514 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,7 @@
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-project</artifactId>
       <version>${mavenVersion}</version>
+      <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
@@ -145,10 +146,15 @@
           <postBuildHookScript>verify</postBuildHookScript>
           <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
           <settingsFile>src/it/settings.xml</settingsFile>
+          <goals>
+            <goal>install</goal> <!-- So that the multi-module-plugin is installed into the integration-test repo -->
+          </goals>
           <pomIncludes>
-            <pomInclude>*/pom.xml</pomInclude>
+            <!--pomInclude>*/pom.xml</pomInclude-->
             <pomInclude>maven-version/pom.xml</pomInclude>
             <pomInclude>mshared-167/pom.xml</pomInclude>
+            <pomInclude>multi-module-plugin/pom.xml</pomInclude>
+            <pomInclude>multi-module-test/pom.xml</pomInclude>
           </pomIncludes>
         </configuration>
         <executions>
diff --git a/src/it/multi-module-plugin/pom.xml b/src/it/multi-module-plugin/pom.xml
new file mode 100644
index 0000000..3e1fcf3
--- /dev/null
+++ b/src/it/multi-module-plugin/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency-tree</groupId>
+  <artifactId>multi-module-test-plugin</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Multi-Module Test-Plugin</name>
+  <description>
+    Creates a maven-plugin that can be used to verify that maven-dep-tree resolves deps that only exist within the reactor.
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <maven.version>3.0.4</maven.version>
+  </properties>
+
+  <dependencyManagement>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+<!--
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-project</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+-->
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-container-default</artifactId>
+      <version>1.0-alpha-9-stable-1</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.shared</groupId>
+      <artifactId>maven-dependency-tree</artifactId>
+      <version>2.2-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-component-metadata</artifactId>
+          <version>1.5.5</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-component-metadata</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>generate-metadata</goal>
+              <goal>generate-test-metadata</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/multi-module-plugin/resources/META-INF/plexus/components.xml b/src/it/multi-module-plugin/resources/META-INF/plexus/components.xml
new file mode 100644
index 0000000..db3ac61
--- /dev/null
+++ b/src/it/multi-module-plugin/resources/META-INF/plexus/components.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2009 Jayway AB
+ Copyright (C) 2007-2008 JVending Masa
+
+  Licensed 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.
+-->
+<component-set>
+    <components></components>
+</component-set>
diff --git a/src/it/multi-module-plugin/src/main/java/org/apache/maven/its/deptree/DummyMojo.java b/src/it/multi-module-plugin/src/main/java/org/apache/maven/its/deptree/DummyMojo.java
new file mode 100644
index 0000000..c770d2f
--- /dev/null
+++ b/src/it/multi-module-plugin/src/main/java/org/apache/maven/its/deptree/DummyMojo.java
@@ -0,0 +1,34 @@
+package org.apache.maven.its.deptree;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+/**
+ * Does absolutely nothing.
+ *
+ * @goal dummy
+ * @phase package
+ * @requiresDependencyResolution compile
+ */
+public class DummyMojo extends AbstractMojo
+{
+    /**
+     * The maven project.
+     *
+     * @parameter property="${project}"
+     * @required
+     * @readonly
+     */
+    private MavenProject project;
+
+    /**
+     * @throws MojoExecutionException
+     * @throws MojoFailureException
+     */
+    public void execute() throws MojoExecutionException, MojoFailureException
+    {
+        getLog().info( "Running DummyMojo : " + project.getArtifactId() );
+    }
+}
diff --git a/src/it/multi-module-plugin/src/main/java/org/apache/maven/its/deptree/ResolveDependenciesLifecycleParticipant.java b/src/it/multi-module-plugin/src/main/java/org/apache/maven/its/deptree/ResolveDependenciesLifecycleParticipant.java
new file mode 100644
index 0000000..65ac94c
--- /dev/null
+++ b/src/it/multi-module-plugin/src/main/java/org/apache/maven/its/deptree/ResolveDependenciesLifecycleParticipant.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2011 Sonatype Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Sonatype Inc. - initial API and implementation
+ *******************************************************************************/
+package org.apache.maven.its.deptree;
+
+import org.apache.maven.AbstractMavenLifecycleParticipant;
+import org.apache.maven.MavenExecutionException;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
+import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
+import org.apache.maven.shared.dependency.graph.ProjectReferenceKeyGenerator;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Resolves all the dependencies in the project immediately after the Project has been read.
+ *
+ * It needs to resolve dependencies from the reactor because in a multi-module build
+ * sibling modules may never have been built yet, so will not exist in any repo.
+ *
+ * It is crucial that reactor dependencies can be found at this point in the build because
+ * this is the only time at which we can modify the classpath. And for modules that produce
+ * archives (eg Android AAR) which contain the actual Java Jar dependency, we need to know
+ * that they exist so that we can add a placeholder for them onto the classpath,
+ * which we can replace with the real classes once they are built.
+ */
+@Component( role = AbstractMavenLifecycleParticipant.class, hint = "default" )
+public final class ResolveDependenciesLifecycleParticipant extends AbstractMavenLifecycleParticipant
+{
+    @Requirement( hint = "default" )
+    private DependencyGraphBuilder dependencyGraphBuilder;
+
+    @Requirement
+    private Logger log;
+
+    @Override
+    public void afterProjectsRead( MavenSession session ) throws MavenExecutionException
+    {
+        log.debug( "" );
+        log.info( "ResolveDependenciesLifecycleParticipant#afterProjectsRead" );
+        log.debug( "" );
+
+        final List<MavenProject> projects = session.getProjects();
+
+        // NB We could get this from session.getProjectMap() but it doesn't exist in Maven-2.2.1 or 3.0.4
+        final Map<String, MavenProject> reactorProjects = new HashMap<String, MavenProject>();
+        final ProjectReferenceKeyGenerator keyGenerator = new ProjectReferenceKeyGenerator();
+
+        log.debug( "Reactor projects:" );
+        for ( MavenProject project : projects )
+        {
+            log.debug( " - " + project );
+            reactorProjects.put( keyGenerator.getProjectReferenceKey( project ), project );
+        }
+        log.debug( "" );
+
+        for ( MavenProject project : projects )
+        {
+            log.debug( "" );
+            log.debug( "project=" + project.getArtifact() );
+
+            try
+            {
+                // No need to filter our search. We want to resolve all artifacts.
+                dependencyGraphBuilder.buildDependencyGraph( project, null, reactorProjects );
+            }
+            catch ( DependencyGraphBuilderException e )
+            {
+                throw new MavenExecutionException( "Could not resolve dependencies for project : " + project, e );
+            }
+        }
+    }
+}
+  
diff --git a/src/it/multi-module-test/expected-tree.txt b/src/it/multi-module-test/expected-tree.txt
new file mode 100644
index 0000000..2db1d03
--- /dev/null
+++ b/src/it/multi-module-test/expected-tree.txt
@@ -0,0 +1,3 @@
+org.apache.maven.its.dependency-tree:module-z-deps-y:jar:1.0-SNAPSHOT
+\- org.apache.maven.its.dependency-tree:module-y-deps-x:jar:1.0-SNAPSHOT:compile
+   \- org.apache.maven.its.dependency-tree:module-x:jar:1.0-SNAPSHOT:compile
diff --git a/src/it/multi-module-test/invoker.properties b/src/it/multi-module-test/invoker.properties
new file mode 100644
index 0000000..60a1991
--- /dev/null
+++ b/src/it/multi-module-test/invoker.properties
@@ -0,0 +1 @@
+invoker.goals = clean install
diff --git a/src/it/multi-module-test/moduleX/pom.xml b/src/it/multi-module-test/moduleX/pom.xml
new file mode 100644
index 0000000..407c043
--- /dev/null
+++ b/src/it/multi-module-test/moduleX/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency-tree</groupId>
+  <artifactId>module-x</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencyManagement>
+  </dependencyManagement>
+
+  <dependencies>
+  </dependencies>
+
+  <build>
+  </build>
+</project>
diff --git a/src/it/multi-module-test/moduleX/src/main/java/org/apache/maven/shared/dependency/SimpleClass.java b/src/it/multi-module-test/moduleX/src/main/java/org/apache/maven/shared/dependency/SimpleClass.java
new file mode 100644
index 0000000..6a38f19
--- /dev/null
+++ b/src/it/multi-module-test/moduleX/src/main/java/org/apache/maven/shared/dependency/SimpleClass.java
@@ -0,0 +1,9 @@
+package org.apache.maven.shared.dependency;
+
+public final class SimpleClass
+{
+    public String someMethod()
+    {
+        return "fun";
+    }
+}
diff --git a/src/it/multi-module-test/moduleYDepsX/pom.xml b/src/it/multi-module-test/moduleYDepsX/pom.xml
new file mode 100644
index 0000000..a780f2b
--- /dev/null
+++ b/src/it/multi-module-test/moduleYDepsX/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency-tree</groupId>
+  <artifactId>module-y-deps-x</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.maven.its.dependency-tree</groupId>
+        <artifactId>module-x</artifactId>
+        <version>1.0-SNAPSHOT</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.its.dependency-tree</groupId>
+      <artifactId>module-x</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>2.8</version>
+        <dependencies>
+          <dependency>
+            <groupId>@project.groupId@</groupId>
+            <artifactId>@project.artifactId@</artifactId>
+            <version>@project.version@</version>
+          </dependency>
+        </dependencies>
+        <executions>
+          <execution>
+            <id>default</id>
+            <phase>validate</phase>
+            <configuration>
+              <outputFile>target/tree.txt</outputFile>
+            </configuration>
+            <goals>
+              <goal>tree</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.its.dependency-tree</groupId>
+        <artifactId>multi-module-test-plugin</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <extensions>true</extensions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/multi-module-test/moduleYDepsX/src/main/java/org/apache/maven/shared/dependency/DependentClass.java b/src/it/multi-module-test/moduleYDepsX/src/main/java/org/apache/maven/shared/dependency/DependentClass.java
new file mode 100644
index 0000000..dc9d863
--- /dev/null
+++ b/src/it/multi-module-test/moduleYDepsX/src/main/java/org/apache/maven/shared/dependency/DependentClass.java
@@ -0,0 +1,10 @@
+package org.apache.maven.shared.dependency;
+
+public final class DependentClass
+{
+    public String someOtherMethod()
+    {
+        final SimpleClass clazz = new SimpleClass();
+        return "bar" + clazz.someMethod();
+    }
+}
diff --git a/src/it/multi-module-test/moduleZDepsY/pom.xml b/src/it/multi-module-test/moduleZDepsY/pom.xml
new file mode 100644
index 0000000..ef6d4f8
--- /dev/null
+++ b/src/it/multi-module-test/moduleZDepsY/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency-tree</groupId>
+  <artifactId>module-z-deps-y</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.maven.its.dependency-tree</groupId>
+        <artifactId>module-y-deps-x</artifactId>
+        <version>1.0-SNAPSHOT</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.its.dependency-tree</groupId>
+      <artifactId>module-y-deps-x</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>2.8</version>
+        <dependencies>
+          <dependency>
+            <groupId>@project.groupId@</groupId>
+            <artifactId>@project.artifactId@</artifactId>
+            <version>@project.version@</version>
+          </dependency>
+        </dependencies>
+        <executions>
+          <execution>
+            <id>default</id>
+            <phase>validate</phase>
+            <configuration>
+              <outputFile>target/tree.txt</outputFile>
+            </configuration>
+            <goals>
+              <goal>tree</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.its.dependency-tree</groupId>
+        <artifactId>multi-module-test-plugin</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <extensions>true</extensions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/multi-module-test/moduleZDepsY/src/main/java/org/apache/maven/shared/dependency/ContainingClass.java b/src/it/multi-module-test/moduleZDepsY/src/main/java/org/apache/maven/shared/dependency/ContainingClass.java
new file mode 100644
index 0000000..51c3f37
--- /dev/null
+++ b/src/it/multi-module-test/moduleZDepsY/src/main/java/org/apache/maven/shared/dependency/ContainingClass.java
@@ -0,0 +1,10 @@
+package org.apache.maven.shared.dependency;
+
+public final class ContainingClass
+{
+    public String someOtherMethod()
+    {
+        final DependentClass clazz = new DependentClass();
+        return "foo" + clazz.someOtherMethod();
+    }
+}
diff --git a/src/it/multi-module-test/pom.xml b/src/it/multi-module-test/pom.xml
new file mode 100644
index 0000000..8ec4173
--- /dev/null
+++ b/src/it/multi-module-test/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency-tree</groupId>
+  <artifactId>multi-module</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <name>VerboseTest</name>
+  <description>
+    Test verbose dependency-tree with actual Maven version through old dependency:tree 2.4, before the feature was removed.
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencyManagement>
+  </dependencyManagement>
+
+  <dependencies>
+  </dependencies>
+
+  <modules>
+    <module>moduleX</module>
+    <module>moduleYDepsX</module>
+    <module>moduleZDepsY</module>
+  </modules>
+
+</project>
diff --git a/src/it/multi-module-test/verify.bsh b/src/it/multi-module-test/verify.bsh
new file mode 100644
index 0000000..4342d2c
--- /dev/null
+++ b/src/it/multi-module-test/verify.bsh
@@ -0,0 +1,18 @@
+import java.io.*;
+
+import org.codehaus.plexus.util.*;
+
+String actual = FileUtils.fileRead( new File( basedir, "moduleZDepsY/target/tree.txt" ) );
+String expected = FileUtils.fileRead( new File( basedir, "expected-tree.txt" ) );
+
+actual = actual.replaceAll( "[\n\r]+", "\n" );
+expected = expected.replaceAll( "[\n\r]+", "\n" );
+
+System.out.println( "Checking dependency tree..." );
+
+if ( !actual.equals( expected ) )
+{
+    throw new Exception( "Unexpected dependency tree" );
+}
+
+return true;
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/DependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/DependencyGraphBuilder.java
index 2c9a460..9ab2c8c 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/DependencyGraphBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/DependencyGraphBuilder.java
@@ -22,6 +22,8 @@
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.project.MavenProject;
 
+import java.util.Map;
+
 /**
  * Maven project dependency graph builder API, neutral against Maven 2 or Maven 3.
  *
@@ -31,7 +33,10 @@
 public interface DependencyGraphBuilder
 {
     /**
-     * Build the dependency graph.
+     * Build the dependency graph from the repository.
+     *
+     * This is the same as {@link #buildDependencyGraph(org.apache.maven.project.MavenProject,
+     * org.apache.maven.artifact.resolver.filter.ArtifactFilter, java.util.Map)} with an empty reactorProjects Map.
      *
      * @param project the project
      * @param filter artifact filter (can be <code>null</code>
@@ -40,4 +45,18 @@
      */
     DependencyNode buildDependencyGraph( MavenProject project, ArtifactFilter filter )
         throws DependencyGraphBuilderException;
+
+    /**
+     * Build the dependency graph including any dependencies contained in the reactor projects.
+     *
+     * @param project the project
+     * @param filter artifact filter (can be <code>null</code>
+     * @param reactorProjects Map of those projects contained in the reactor.
+     *                        Key is made up of groupId-artifactId-version.
+     * @return the dependency graph
+     * @throws DependencyGraphBuilderException
+     */
+    DependencyNode buildDependencyGraph(
+            MavenProject project, ArtifactFilter filter, Map<String, MavenProject> reactorProjects )
+            throws DependencyGraphBuilderException;
 }
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/ProjectReferenceKeyGenerator.java b/src/main/java/org/apache/maven/shared/dependency/graph/ProjectReferenceKeyGenerator.java
new file mode 100644
index 0000000..feef92d
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/ProjectReferenceKeyGenerator.java
@@ -0,0 +1,25 @@
+package org.apache.maven.shared.dependency.graph;
+
+import org.apache.maven.project.MavenProject;
+
+/**
+ * Generates the key used by {@link org.apache.maven.project.MavenProject#getProjectReferences()}
+ * , {@link org.apache.maven.execution.MavenSession#getProjectMap()} and the Map passed into
+ * {@link org.apache.maven.shared.dependency.graph.DependencyGraphBuilder#buildDependencyGraph
+ * (org.apache.maven.project.MavenProject, org.apache.maven.artifact.resolver.filter.ArtifactFilter, java.util.Map)}.
+ */
+public final class ProjectReferenceKeyGenerator
+{
+    // NB Copied here from MavenProject - because MavenProject#getProjectReferenceId is private
+    public String getProjectReferenceKey( String groupId, String artifactId, String version )
+    {
+        final StringBuilder buffer = new StringBuilder( 128 );
+        buffer.append( groupId ).append( ':' ).append( artifactId ).append( ':' ).append( version );
+        return buffer.toString();
+    }
+
+    public String getProjectReferenceKey( MavenProject project )
+    {
+        return getProjectReferenceKey( project.getGroupId(), project.getArtifactId(), project.getVersion() );
+    }
+}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyGraphBuilder.java
index 9caacf0..508b18b 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyGraphBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyGraphBuilder.java
@@ -33,6 +33,9 @@
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 
+import java.util.Collections;
+import java.util.Map;
+
 /**
  * Default dependency graph builder that detects current Maven version to delegate to either
  * Maven 2 or Maven 3 specific code.
@@ -52,15 +55,23 @@
     public DependencyNode buildDependencyGraph( MavenProject project, ArtifactFilter filter )
         throws DependencyGraphBuilderException
     {
+        return buildDependencyGraph( project, filter, Collections.EMPTY_MAP );
+    }
+
+    public DependencyNode buildDependencyGraph(
+            MavenProject project, ArtifactFilter filter, Map<String, MavenProject> reactorProjects )
+            throws DependencyGraphBuilderException
+    {
         try
         {
             String hint = isMaven31() ? "maven31" : isMaven2x() ? "maven2" : "maven3";
-            getLogger().debug( "building " + hint + " dependency graph for " + project.getId() );
 
             DependencyGraphBuilder effectiveGraphBuilder =
-                (DependencyGraphBuilder) container.lookup( DependencyGraphBuilder.class.getCanonicalName(), hint );
+                    (DependencyGraphBuilder) container.lookup( DependencyGraphBuilder.class.getCanonicalName(), hint );
+            getLogger().debug( "building " + hint + " dependency graph for " + project.getId()
+                    + " with " + effectiveGraphBuilder.getClass() );
 
-            return effectiveGraphBuilder.buildDependencyGraph( project, filter );
+            return effectiveGraphBuilder.buildDependencyGraph( project, filter, reactorProjects );
         }
         catch ( ComponentLookupException e )
         {
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Invoker.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Invoker.java
new file mode 100644
index 0000000..93a3e45
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Invoker.java
@@ -0,0 +1,48 @@
+package org.apache.maven.shared.dependency.graph.internal;
+
+import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Invokes method on objects using reflection.
+ */
+final class Invoker
+{
+    public Object invoke( Class objectClazz, Object object, String method )
+            throws DependencyGraphBuilderException
+    {
+        try
+        {
+            return objectClazz.getMethod( method ).invoke( object );
+        } catch ( IllegalAccessException e )
+        {
+            throw new DependencyGraphBuilderException( e.getMessage(), e );
+        } catch ( InvocationTargetException e )
+        {
+            throw new DependencyGraphBuilderException( e.getMessage(), e );
+        } catch ( NoSuchMethodException e )
+        {
+            throw new DependencyGraphBuilderException( e.getMessage(), e );
+        }
+    }
+
+    public Object invoke( Object object, String method, Class<?> clazz, Object arg )
+            throws DependencyGraphBuilderException
+    {
+        try
+        {
+            final Class objectClazz = object.getClass();
+            return objectClazz.getMethod( method, clazz ).invoke( object, arg );
+        } catch ( IllegalAccessException e )
+        {
+            throw new DependencyGraphBuilderException( e.getMessage(), e );
+        } catch ( InvocationTargetException e )
+        {
+            throw new DependencyGraphBuilderException( e.getMessage(), e );
+        } catch ( NoSuchMethodException e )
+        {
+            throw new DependencyGraphBuilderException( e.getMessage(), e );
+        }
+    }
+}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven2DependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven2DependencyGraphBuilder.java
index 3787f9a..6a6e49c 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven2DependencyGraphBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven2DependencyGraphBuilder.java
@@ -22,6 +22,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.project.MavenProject;
@@ -32,6 +33,7 @@
 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
 import org.codehaus.plexus.component.annotations.Component;
 import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
 
 /**
  * Wrapper around Maven 2 dependency tree builder.
@@ -42,6 +44,7 @@
  */
 @Component( role = DependencyGraphBuilder.class, hint = "maven2" )
 public class Maven2DependencyGraphBuilder
+    extends AbstractLogEnabled
     implements DependencyGraphBuilder
 {
     @Requirement
@@ -60,6 +63,14 @@
         }
     }
 
+    public DependencyNode buildDependencyGraph(
+            MavenProject project, ArtifactFilter filter, Map<String, MavenProject> reactorProjects )
+            throws DependencyGraphBuilderException
+    {
+        getLogger().warn( "Reactor projects ignored - reactor dependencies cannot be resolved in Maven2" );
+        return buildDependencyGraph( project, filter );
+    }
+
     private DependencyNode buildDependencyNode( DependencyNode parent,
                                                 org.apache.maven.shared.dependency.tree.DependencyNode node,
                                                 ArtifactFilter filter )
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyGraphBuilder.java
index 30eec1e..80f2782 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyGraphBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyGraphBuilder.java
@@ -19,11 +19,6 @@
  * under the License.

  */

 

-import java.lang.reflect.InvocationTargetException;

-import java.util.ArrayList;

-import java.util.Collections;

-import java.util.List;

-

 import org.apache.maven.artifact.Artifact;

 import org.apache.maven.artifact.factory.ArtifactFactory;

 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;

@@ -38,14 +33,20 @@
 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;

 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;

 import org.apache.maven.shared.dependency.graph.DependencyNode;

+import org.apache.maven.shared.dependency.graph.ProjectReferenceKeyGenerator;

 import org.codehaus.plexus.component.annotations.Component;

 import org.codehaus.plexus.component.annotations.Requirement;

-import org.eclipse.aether.DefaultRepositorySystemSession;

+import org.codehaus.plexus.logging.AbstractLogEnabled;

 import org.eclipse.aether.RepositorySystemSession;

 import org.eclipse.aether.graph.Dependency;

-import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;

 import org.eclipse.aether.version.VersionConstraint;

 

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.List;

+import java.util.Map;

+

 /**

  * Wrapper around Eclipse Aether dependency resolver, used in Maven 3.1.

  *

@@ -55,6 +56,7 @@
  */

 @Component( role = DependencyGraphBuilder.class, hint = "maven31" )

 public class Maven31DependencyGraphBuilder

+    extends AbstractLogEnabled

     implements DependencyGraphBuilder

 {

     @Requirement

@@ -63,17 +65,25 @@
     @Requirement

     private ArtifactFactory factory;

 

+    private final Invoker invoker = new Invoker();

+    private final ProjectReferenceKeyGenerator keyGenerator = new ProjectReferenceKeyGenerator();

+

     public DependencyNode buildDependencyGraph( MavenProject project, ArtifactFilter filter )

         throws DependencyGraphBuilderException

     {

-        try

-        {

-            ProjectBuildingRequest projectBuildingRequest =

-                (ProjectBuildingRequest) invoke( project.getClass(), project, "getProjectBuildingRequest" );

+        return buildDependencyGraph( project, filter, Collections.EMPTY_MAP );

+    }

 

-            RepositorySystemSession session =

-                (RepositorySystemSession) invoke( ProjectBuildingRequest.class, projectBuildingRequest,

-                                                  "getRepositorySession" );

+    public DependencyNode buildDependencyGraph(

+            MavenProject project, ArtifactFilter filter, Map<String, MavenProject> reactorProjects )

+            throws DependencyGraphBuilderException

+    {

+        ProjectBuildingRequest projectBuildingRequest =

+                (ProjectBuildingRequest) invoker.invoke( project.getClass(), project, "getProjectBuildingRequest" );

+

+        RepositorySystemSession session =

+                (RepositorySystemSession) invoker.invoke( ProjectBuildingRequest.class, projectBuildingRequest,

+                        "getRepositorySession" );

 

             /*if ( Boolean.TRUE != ( (Boolean) session.getConfigProperties().get( DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION ) ) )

             {

@@ -82,47 +92,68 @@
                 session = newSession;

             }*/

 

-            DependencyResolutionRequest request =

-                new DefaultDependencyResolutionRequest();

-            request.setMavenProject( project );

-            invoke( request, "setRepositorySession", RepositorySystemSession.class, session );

+        final DependencyResolutionRequest request = new DefaultDependencyResolutionRequest();

+        request.setMavenProject( project );

+        invoker.invoke( request, "setRepositorySession", RepositorySystemSession.class, session );

 

-            DependencyResolutionResult result = resolver.resolve( request );

+        final DependencyResolutionResult result = resolveDependencies( request, reactorProjects );

+        org.eclipse.aether.graph.DependencyNode graph =

+                ( org.eclipse.aether.graph.DependencyNode ) invoker.invoke( DependencyResolutionResult.class, result,

+                        "getDependencyGraph" );

 

-            org.eclipse.aether.graph.DependencyNode graph =

-                (org.eclipse.aether.graph.DependencyNode) invoke( DependencyResolutionResult.class, result,

-                                                                  "getDependencyGraph" );

+        return buildDependencyNode( null, graph, project.getArtifact(), filter );

+    }

 

-            return buildDependencyNode( null, graph, project.getArtifact(), filter );

+    private DependencyResolutionResult resolveDependencies(DependencyResolutionRequest request,

+                                                           Map<String, MavenProject> reactorProjects)

+            throws DependencyGraphBuilderException

+    {

+        try

+        {

+            return resolver.resolve( request );

         }

         catch ( DependencyResolutionException e )

         {

-            throw new DependencyGraphBuilderException( e.getMessage(), e );

-        }

-        catch ( IllegalAccessException e )

-        {

-            throw new DependencyGraphBuilderException( e.getMessage(), e );

-        }

-        catch ( InvocationTargetException e )

-        {

-            throw new DependencyGraphBuilderException( e.getMessage(), e );

-        }

-        catch ( NoSuchMethodException e )

-        {

-            throw new DependencyGraphBuilderException( e.getMessage(), e );

+            // Ignore any resolution failure for deps that are part of the reactor but have not yet been built.

+            // NB Typing has been removed because DependencyResolutionResult returns Sonatype aether in 3.0.4 and

+            // Eclipse aether in 3.1.1 and while dep-tree is a single module we can only compile against one of them.

+            //

+            // NB While applying this code to Maven3DependencyGraphBuilder is trivial it won't work because

+            // in Maven 3, MavenProject.getProjectReferences isn't populated. So we would need to have the reactor

+            // modules passed in separately which would change the API for DependencyGraphBuilder. If

+            // MavenProject.getProjectReferences were populated (like it should be) then this would work for Maven3 too.

+            //

+            // NB There doesn't seem to be any way to apply this to Maven2DependencyGraphBuilder as there is no

+            // concept of partial resolution like there is is 3 and 3.1

+            final DependencyResolutionResult result = e.getResult();

+            final List<Dependency> reactorDeps = getReactorDependencies( reactorProjects, result.getUnresolvedDependencies() );

+            invoker.invoke( result.getUnresolvedDependencies(), "removeAll", Collection.class, reactorDeps );

+            invoker.invoke( result.getResolvedDependencies(), "addAll", Collection.class, reactorDeps );

+

+            if ( !result.getUnresolvedDependencies().isEmpty() ) {

+                throw new DependencyGraphBuilderException( "Could not resolve the following dependencies : "

+                        + result.getUnresolvedDependencies(), e );

+            }

+            getLogger().debug( "Resolved dependencies after ignoring reactor dependencies : " + reactorDeps );

+            return result;

         }

     }

 

-    private Object invoke( Class<?> clazz, Object object, String method )

-        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException

+    private List<Dependency> getReactorDependencies( Map<String, MavenProject> reactorProjects, List<?> dependencies )

     {

-        return clazz.getMethod( method ).invoke( object );

-    }

-

-    private Object invoke( Object object, String method, Class<?> clazz, Object arg )

-        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException

-    {

-        return object.getClass().getMethod( method, clazz ).invoke( object, arg );

+        final List<Dependency> reactorDeps = new ArrayList<Dependency>();

+        for ( final Object untypedDependency : dependencies )

+        {

+            final Dependency dependency = (Dependency) untypedDependency;

+            final org.eclipse.aether.artifact.Artifact depArtifact = dependency.getArtifact();

+            final String projectRefId = keyGenerator.getProjectReferenceKey(

+                    depArtifact.getGroupId(), depArtifact.getArtifactId(), depArtifact.getVersion()

+            );

+            if ( reactorProjects.containsKey( projectRefId ) ) {

+                reactorDeps.add( dependency );

+            }

+        }

+        return reactorDeps;

     }

 

     private Artifact getDependencyArtifact( Dependency dep )

diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyGraphBuilder.java
index b6f49e7..823b45c 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyGraphBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyGraphBuilder.java
@@ -21,8 +21,10 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.factory.ArtifactFactory;
@@ -38,8 +40,10 @@
 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
 import org.apache.maven.shared.dependency.graph.DependencyNode;
+import org.apache.maven.shared.dependency.graph.ProjectReferenceKeyGenerator;
 import org.codehaus.plexus.component.annotations.Component;
 import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.sonatype.aether.graph.Dependency;
 import org.sonatype.aether.version.VersionConstraint;
 
@@ -52,6 +56,7 @@
  */
 @Component( role = DependencyGraphBuilder.class, hint = "maven3" )
 public class Maven3DependencyGraphBuilder
+    extends AbstractLogEnabled
     implements DependencyGraphBuilder
 {
     @Requirement
@@ -60,24 +65,87 @@
     @Requirement
     private ArtifactFactory factory;
 
+    private final Invoker invoker = new Invoker();
+    private final ProjectReferenceKeyGenerator keyGenerator = new ProjectReferenceKeyGenerator();
+
     public DependencyNode buildDependencyGraph( MavenProject project, ArtifactFilter filter )
         throws DependencyGraphBuilderException
     {
-        try
-        {
-            ProjectBuildingRequest projectBuildingRequest =
+        return buildDependencyGraph( project, filter, Collections.EMPTY_MAP );
+    }
+
+    public DependencyNode buildDependencyGraph(
+            MavenProject project, ArtifactFilter filter, Map<String, MavenProject> reactorProjects )
+            throws DependencyGraphBuilderException
+    {
+        ProjectBuildingRequest projectBuildingRequest =
                 (ProjectBuildingRequest) invoke( project, "getProjectBuildingRequest" );
 
-            DependencyResolutionRequest request =
+        DependencyResolutionRequest request =
                 new DefaultDependencyResolutionRequest( project, projectBuildingRequest.getRepositorySession() );
 
-            DependencyResolutionResult result = resolver.resolve( request );
+        final DependencyResolutionResult result = resolveDependencies( request, reactorProjects );
 
-            return buildDependencyNode( null, result.getDependencyGraph(), project.getArtifact(), filter );
+        return buildDependencyNode( null, result.getDependencyGraph(), project.getArtifact(), filter );
+    }
+
+    private DependencyResolutionResult resolveDependencies(DependencyResolutionRequest request,
+                                                           Map<String, MavenProject> reactorProjects)
+            throws DependencyGraphBuilderException
+    {
+        try
+        {
+            return resolver.resolve( request );
         }
         catch ( DependencyResolutionException e )
         {
-            throw new DependencyGraphBuilderException( e.getMessage(), e );
+            // Ignore any resolution failure for deps that are part of the reactor but have not yet been built.
+            // NB Typing has been removed because DependencyResolutionResult returns Sonatype aether in 3.0.4 and
+            // Eclipse aether in 3.1.1 and while dep-tree is a single module we can only compile against one of them.
+            //
+            // NB While applying this code to Maven3DependencyGraphBuilder is trivial it won't work because
+            // in Maven 3, MavenProject.getProjectReferences isn't populated. So we would need to have the reactor
+            // modules passed in separately which would change the API for DependencyGraphBuilder. If
+            // MavenProject.getProjectReferences were populated (like it should be) then this would work for Maven3 too.
+            //
+            // NB There doesn't seem to be any way to apply this to Maven2DependencyGraphBuilder as there is no
+            // concept of partial resolution like there is is 3 and 3.1
+            final DependencyResolutionResult result = e.getResult();
+            final List<Dependency> reactorDeps = getReactorDependencies( reactorProjects, result.getUnresolvedDependencies() );
+            invoker.invoke( result.getUnresolvedDependencies(), "removeAll", Collection.class, reactorDeps );
+            invoker.invoke( result.getResolvedDependencies(), "addAll", Collection.class, reactorDeps );
+
+            if ( !result.getUnresolvedDependencies().isEmpty() ) {
+                throw new DependencyGraphBuilderException( "Could not resolve the following dependencies : "
+                        + result.getUnresolvedDependencies(), e );
+            }
+            getLogger().debug( "Resolved dependencies after ignoring reactor dependencies : " + reactorDeps );
+            return result;
+        }
+    }
+
+    private List<org.sonatype.aether.graph.Dependency> getReactorDependencies( Map<String, MavenProject> reactorProjects, List<?> dependencies )
+    {
+        final List<org.sonatype.aether.graph.Dependency> reactorDeps = new ArrayList<org.sonatype.aether.graph.Dependency>();
+        for ( final Object untypedDependency : dependencies )
+        {
+            final org.sonatype.aether.graph.Dependency dependency = ( org.sonatype.aether.graph.Dependency ) untypedDependency;
+            final org.sonatype.aether.artifact.Artifact depArtifact = dependency.getArtifact();
+            final String projectRefId = keyGenerator.getProjectReferenceKey(
+                    depArtifact.getGroupId(), depArtifact.getArtifactId(), depArtifact.getVersion()
+            );
+            if ( reactorProjects.containsKey( projectRefId ) ) {
+                reactorDeps.add( dependency );
+            }
+        }
+        return reactorDeps;
+    }
+
+    private Object invoke( Object object, String method ) throws DependencyGraphBuilderException
+    {
+        try
+        {
+            return object.getClass().getMethod( method ).invoke( object );
         }
         catch ( IllegalAccessException e )
         {
@@ -93,12 +161,6 @@
         }
     }
 
-    private Object invoke( Object object, String method )
-        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
-    {
-        return object.getClass().getMethod( method ).invoke( object );
-    }
-
     private Artifact getDependencyArtifact( Dependency dep )
     {
         org.sonatype.aether.artifact.Artifact artifact = dep.getArtifact();