You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by el...@apache.org on 2020/08/14 12:20:06 UTC

[maven-dependency-plugin] branch master updated: [MDEP-644] Reintroduce the verbose option for dependency:tree (#92)

This is an automated email from the ASF dual-hosted git repository.

elharo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new 10398dd  [MDEP-644] Reintroduce the verbose option for dependency:tree (#92)
10398dd is described below

commit 10398ddae456ad921e361f822e80a7d05bf1279a
Author: ian-lavallee <34...@users.noreply.github.com>
AuthorDate: Fri Aug 14 08:19:55 2020 -0400

    [MDEP-644] Reintroduce the verbose option for dependency:tree (#92)
    
    Reintroduce the verbose option for dependency:tree
    
    Co-authored-by: Elliotte Rusty Harold <el...@ibiblio.org>
---
 pom.xml => dependency-reduced-pom.xml              | 571 +++++++++------------
 pom.xml                                            |  20 +-
 src/it/projects/analyze-report/invoker.properties  |   2 -
 .../invoker.properties                             |   2 -
 .../src/test/java/hello/HelloTest.java             |   3 -
 src/it/projects/tree-verbose-small/expected.txt    |   8 +
 .../invoker.properties                             |   5 +-
 .../{tree-verbose => tree-verbose-small}/pom.xml   |  46 +-
 .../verify.bsh                                     |   6 +-
 .../{expected.txt => expected-maven2version.txt}   |  15 +-
 src/it/projects/tree-verbose/expected.txt          |  34 +-
 src/it/projects/tree-verbose/pom.xml               |   2 +-
 src/it/projects/tree-verbose/verify.bsh            |   5 +-
 src/it/projects/unpack-custom-ear/pom.xml          |   6 +-
 src/it/projects/unpack-custom-ear/verify.groovy    |   1 +
 .../tree/CycleBreakerGraphTransformer.java         |  73 +++
 .../maven/plugins/dependency/tree/TreeMojo.java    | 143 +++++-
 .../tree/VerboseDependencyGraphBuilder.java        | 223 ++++++++
 .../dependency/tree/VerboseGraphSerializer.java    | 324 ++++++++++++
 src/main/resources/META-INF/plexus/components.xml  |   4 +
 .../plugins/dependency/TestListClassesMojo.java    |   2 +-
 .../tree/VerboseGraphSerializerTest.java           | 253 +++++++++
 .../unit/verbose-serializer-test/BasicCycle.txt    |   3 +
 .../unit/verbose-serializer-test/BasicTree.txt     |   3 +
 .../LargeGraphWithCycles.txt                       |  10 +
 .../unit/verbose-serializer-test/LargeTree.txt     |  11 +
 .../verbose-serializer-test/OptionalDependency.txt |   3 +
 .../unit/verbose-serializer-test/ScopeConflict.txt |   4 +
 .../verbose-serializer-test/VersionConflict.txt    |   4 +
 29 files changed, 1352 insertions(+), 434 deletions(-)

diff --git a/pom.xml b/dependency-reduced-pom.xml
similarity index 58%
copy from pom.xml
copy to dependency-reduced-pom.xml
index 230809a..432479d 100644
--- a/pom.xml
+++ b/dependency-reduced-pom.xml
@@ -1,51 +1,20 @@
-<?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>
-
+<?xml version="1.0" encoding="UTF-8"?>
+<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/maven-v4_0_0.xsd">
   <parent>
     <artifactId>maven-plugins</artifactId>
     <groupId>org.apache.maven.plugins</groupId>
     <version>34</version>
-    <relativePath>../../pom/maven/maven-plugins/pom.xml</relativePath>
+    <relativePath>../../pom/maven/maven-plugins/pom.xml/pom.xml</relativePath>
   </parent>
-
+  <modelVersion>4.0.0</modelVersion>
   <artifactId>maven-dependency-plugin</artifactId>
-  <version>3.1.3-SNAPSHOT</version>
   <packaging>maven-plugin</packaging>
-
   <name>Apache Maven Dependency Plugin</name>
+  <version>3.1.3-SNAPSHOT</version>
   <description>Provides utility goals to work with dependencies like copying, unpacking, analyzing, resolving and many more.</description>
-
   <prerequisites>
     <maven>${mavenVersion}</maven>
   </prerequisites>
-
-  <scm>
-    <connection>scm:git:https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git</connection>
-    <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git</developerConnection>
-    <url>https://github.com/apache/maven-dependency-plugin/tree/${project.scm.tag}</url>
-    <tag>HEAD</tag>
-  </scm>
   <issueManagement>
     <system>JIRA</system>
     <url>https://issues.apache.org/jira/browse/MDEP</url>
@@ -54,13 +23,6 @@ under the License.
     <system>Jenkins</system>
     <url>https://builds.apache.org/job/maven-box/job/maven-dependency-plugin/</url>
   </ciManagement>
-  <distributionManagement>
-    <site>
-      <id>apache.website</id>
-      <url>scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path}</url>
-    </site>
-  </distributionManagement>
-
   <contributors>
     <contributor>
       <name>Bakito</name>
@@ -87,261 +49,11 @@ under the License.
       <name>Maarten Mulders</name>
     </contributor>
   </contributors>
-
-  <properties>
-    <mavenVersion>3.1.1</mavenVersion>
-    <doxiaVersion>1.9.1</doxiaVersion>
-    <doxiaSiteVersion>1.9.2</doxiaSiteVersion>
-    <jettyVersion>9.2.28.v20190418</jettyVersion>
-    <pluginTestingVersion>3.1.0</pluginTestingVersion>
-    <javaVersion>7</javaVersion>
-    <project.build.outputTimestamp>2020-03-07T11:40:47Z</project.build.outputTimestamp>
-  </properties>
-
-  <dependencyManagement>
-    <dependencies>
-      <dependency>
-        <groupId>org.ow2.asm</groupId>
-        <artifactId>asm</artifactId>
-        <version>8.0.1</version>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
-
-  <dependencies>
-    <!-- maven -->
-    <!-- Remove once deprecated code has been replaced/removed  -->
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-artifact</artifactId>
-      <version>${mavenVersion}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-plugin-api</artifactId>
-      <version>${mavenVersion}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-model</artifactId>
-      <version>${mavenVersion}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-core</artifactId>
-      <version>${mavenVersion}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-repository-metadata</artifactId>
-      <version>${mavenVersion}</version>
-    </dependency>
-
-    <!-- reporting -->
-    <dependency>
-      <groupId>org.apache.maven.reporting</groupId>
-      <artifactId>maven-reporting-api</artifactId>
-      <version>3.0</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.reporting</groupId>
-      <artifactId>maven-reporting-impl</artifactId>
-      <version>3.0.0</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>maven-artifact-manager</artifactId>
-          <groupId>org.apache.maven</groupId>
-        </exclusion>
-        <exclusion>
-          <artifactId>maven-project</artifactId>
-          <groupId>org.apache.maven</groupId>
-        </exclusion>
-        <exclusion>
-          <artifactId>maven-profile</artifactId>
-          <groupId>org.apache.maven</groupId>
-        </exclusion>
-        <exclusion>
-          <artifactId>maven-plugin-registry</artifactId>
-          <groupId>org.apache.maven</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <version>2.6</version>
-    </dependency>
-
-    <!-- doxia -->
-    <dependency>
-      <groupId>org.apache.maven.doxia</groupId>
-      <artifactId>doxia-sink-api</artifactId>
-      <version>${doxiaVersion}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.doxia</groupId>
-      <artifactId>doxia-core</artifactId>
-      <version>${doxiaVersion}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.doxia</groupId>
-      <artifactId>doxia-site-renderer</artifactId>
-      <version>${doxiaSiteVersion}</version>
-    </dependency>
-
-    <!-- plexus -->
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-archiver</artifactId>
-      <version>4.2.2</version>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-utils</artifactId>
-      <version>3.3.0</version>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-io</artifactId>
-      <version>3.2.0</version>
-    </dependency>
-
-    <!-- shared -->
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-dependency-analyzer</artifactId>
-      <version>1.11.3-SNAPSHOT</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>maven-project</artifactId>
-          <groupId>org.apache.maven</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-dependency-tree</artifactId>
-      <version>3.0.1</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-common-artifact-filters</artifactId>
-      <version>3.1.0</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-artifact-transfer</artifactId>
-      <version>0.11.0</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-shared-utils</artifactId>
-      <version>3.3.3</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-lang3</artifactId>
-      <version>3.8.1</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-collections4</artifactId>
-      <version>4.2</version>
-    </dependency>
-
-    <dependency>
-      <groupId>classworlds</groupId>
-      <artifactId>classworlds</artifactId>
-      <version>1.1</version>
-    </dependency>
-
-    <!-- dependencies to annotations -->
-    <dependency>
-      <groupId>org.apache.maven.plugin-tools</groupId>
-      <artifactId>maven-plugin-annotations</artifactId>
-    </dependency>
-    
-    <dependency>
-      <groupId>org.eclipse.aether</groupId>
-      <artifactId>aether-connector-wagon</artifactId>
-      <version>0.9.0.M2</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-http-lightweight</artifactId>
-      <version>3.4.0</version>
-      <scope>provided</scope>
-    </dependency>
-
-    <!-- test -->
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.13</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.plugin-testing</groupId>
-      <artifactId>maven-plugin-testing-tools</artifactId>
-      <version>${pluginTestingVersion}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency> 
-      <groupId>org.apache.maven.plugin-testing</groupId>
-      <artifactId>maven-plugin-testing-harness</artifactId>
-      <version>${pluginTestingVersion}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-core</artifactId>
-      <version>2.28.2</version>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-interpolation</artifactId>
-      <version>1.26</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-compat</artifactId>
-      <version>${mavenVersion}</version>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>asm</groupId>
-          <artifactId>asm</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-
-    <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-server</artifactId>
-      <version>${jettyVersion}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
-      <version>${jettyVersion}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-webapp</artifactId>
-      <version>${jettyVersion}</version>
-      <scope>test</scope>
-    </dependency>
-
-  </dependencies>
-
+  <scm>
+    <connection>scm:git:https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git</connection>
+    <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git</developerConnection>
+    <url>https://github.com/apache/maven-dependency-plugin/tree/${project.scm.tag}</url>
+  </scm>
   <build>
     <pluginManagement>
       <plugins>
@@ -349,20 +61,13 @@ under the License.
           <groupId>org.apache.rat</groupId>
           <artifactId>apache-rat-plugin</artifactId>
           <configuration>
-            <excludes combine.children="append">
-              <!--
-                These files contain results for integration tests which can't contain license header
-                otherwise the IT's will fail.
-              -->
+            <excludes>
               <exclude>src/it/projects/tree/expected.txt</exclude>
               <exclude>src/it/projects/tree-includes/expected.txt</exclude>
               <exclude>src/it/projects/tree-multimodule/expected.txt</exclude>
               <exclude>src/it/projects/tree-multimodule/module-a/expected.txt</exclude>
               <exclude>src/it/projects/tree-multimodule/module-b/expected.txt</exclude>
               <exclude>src/it/projects/tree-verbose/expected.txt</exclude>
-              <!--
-                These files contain real repository artifacts.
-              -->
               <exclude>src/test/resources/unit/get-test/repository/test/test/1.0/test-1.0.jar.sha1</exclude>
               <exclude>src/test/resources/unit/get-test/repository/test/test/1.0/test-1.0.pom.sha1</exclude>
             </excludes>
@@ -372,7 +77,6 @@ under the License.
     </pluginManagement>
     <plugins>
       <plugin>
-        <groupId>org.apache.maven.plugins</groupId> 
         <artifactId>maven-enforcer-plugin</artifactId>
         <executions>
           <execution>
@@ -394,27 +98,92 @@ under the License.
         </executions>
       </plugin>
       <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <!-- Need more heap space in order to run the unit tests !-->
           <argLine>-Xmx384m</argLine>
           <systemPropertyVariables>
             <maven.home>${maven.home}</maven.home>
           </systemPropertyVariables>
         </configuration>
       </plugin>
+      <plugin>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>3.2.4</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <shadedArtifactAttached>false</shadedArtifactAttached>
+          <createDependencyReducedPom>true</createDependencyReducedPom>
+          <relocations>
+            <relocation>
+              <pattern>org.objectweb.asm</pattern>
+              <shadedPattern>plugin.org.objectweb.asm</shadedPattern>
+            </relocation>
+          </relocations>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
-
   <profiles>
     <profile>
       <id>run-its</id>
       <build>
         <plugins>
           <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-invoker-plugin</artifactId>
+            <version>3.2.1</version>
+            <executions>
+              <execution>
+                <id>integration-test</id>
+                <goals>
+                  <goal>install</goal>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+                <configuration>
+                  <goals>
+                    <goal>clean</goal>
+                    <goal>process-sources</goal>
+                  </goals>
+                  <projectsDirectory>src/it/projects</projectsDirectory>
+                  <pomExcludes>
+                    <pomExclude>purge-local-repository-bad-pom/pom.xml</pomExclude>
+                    <pomExclude>tree-verbose/pom.xml</pomExclude>
+                  </pomExcludes>
+                  <pomIncludes>
+                    <pomInclude>*/pom.xml</pomInclude>
+                    <pomInclude>analyze*/pom.xml</pomInclude>
+                    <pomInclude>analyze-testDependencyWithNonTestScope/pom.xml</pomInclude>
+                    <pomInclude>purge-local-repository-without-pom</pomInclude>
+                  </pomIncludes>
+                  <settingsFile>src/it/mrm/settings.xml</settingsFile>
+                  <filterProperties>
+                    <repository.proxy.url>${repository.proxy.url}</repository.proxy.url>
+                  </filterProperties>
+                  <addTestClassPath>true</addTestClassPath>
+                  <debug>true</debug>
+                  <cloneProjectsTo>C:\Users\ianla\Maven\maven-dependency-plugin\target/it</cloneProjectsTo>
+                  <preBuildHookScript>setup</preBuildHookScript>
+                  <postBuildHookScript>verify</postBuildHookScript>
+                  <localRepositoryPath>C:\Users\ianla\Maven\maven-dependency-plugin\target/local-repo</localRepositoryPath>
+                  <properties>
+                    <maven.compiler.source>1.7</maven.compiler.source>
+                    <maven.compiler.target>1.7</maven.compiler.target>
+                    <https.protocols>${https.protocols}</https.protocols>
+                  </properties>
+                  <ignoreFailures>false</ignoreFailures>
+                  <environmentVariables>
+                    <JENKINS_MAVEN_AGENT_DISABLED>true</JENKINS_MAVEN_AGENT_DISABLED>
+                  </environmentVariables>
+                </configuration>
+              </execution>
+            </executions>
             <configuration>
               <goals>
                 <goal>clean</goal>
@@ -423,19 +192,33 @@ under the License.
               <projectsDirectory>src/it/projects</projectsDirectory>
               <pomExcludes>
                 <pomExclude>purge-local-repository-bad-pom/pom.xml</pomExclude>
-                <!-- verbose was using Maven2 code, removed with MDEP-494, requires MSHARED-339 to be fixed first -->
                 <pomExclude>tree-verbose/pom.xml</pomExclude>
               </pomExcludes>
               <pomIncludes>
                 <pomInclude>*/pom.xml</pomInclude>
+                <pomInclude>analyze*/pom.xml</pomInclude>
+                <pomInclude>analyze-testDependencyWithNonTestScope/pom.xml</pomInclude>
                 <pomInclude>purge-local-repository-without-pom</pomInclude>
               </pomIncludes>
-              <!-- for mrm -->
               <settingsFile>src/it/mrm/settings.xml</settingsFile>
               <filterProperties>
                 <repository.proxy.url>${repository.proxy.url}</repository.proxy.url>
               </filterProperties>
               <addTestClassPath>true</addTestClassPath>
+              <debug>true</debug>
+              <cloneProjectsTo>C:\Users\ianla\Maven\maven-dependency-plugin\target/it</cloneProjectsTo>
+              <preBuildHookScript>setup</preBuildHookScript>
+              <postBuildHookScript>verify</postBuildHookScript>
+              <localRepositoryPath>C:\Users\ianla\Maven\maven-dependency-plugin\target/local-repo</localRepositoryPath>
+              <properties>
+                <maven.compiler.source>1.7</maven.compiler.source>
+                <maven.compiler.target>1.7</maven.compiler.target>
+                <https.protocols>${https.protocols}</https.protocols>
+              </properties>
+              <ignoreFailures>false</ignoreFailures>
+              <environmentVariables>
+                <JENKINS_MAVEN_AGENT_DISABLED>true</JENKINS_MAVEN_AGENT_DISABLED>
+              </environmentVariables>
             </configuration>
           </plugin>
           <plugin>
@@ -448,6 +231,15 @@ under the License.
                   <goal>start</goal>
                   <goal>stop</goal>
                 </goals>
+                <configuration>
+                  <propertyName>repository.proxy.url</propertyName>
+                  <repositories>
+                    <mockRepo>
+                      <source>src/it/mrm/repository</source>
+                    </mockRepo>
+                    <proxyRepo />
+                  </repositories>
+                </configuration>
               </execution>
             </executions>
             <configuration>
@@ -456,11 +248,6 @@ under the License.
                 <mockRepo>
                   <source>src/it/mrm/repository</source>
                 </mockRepo>
-                <!-- 
-                <mockRepo>
-                  <source>src/test/resources/m2repo</source>
-                </mockRepo>
-                 -->
                 <proxyRepo />
               </repositories>
             </configuration>
@@ -488,4 +275,152 @@ under the License.
       </reporting>
     </profile>
   </profiles>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.plugin-tools</groupId>
+      <artifactId>maven-plugin-annotations</artifactId>
+      <version>3.5.2</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.aether</groupId>
+      <artifactId>aether-connector-wagon</artifactId>
+      <version>0.9.0.M2</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-http-lightweight</artifactId>
+      <version>3.4.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>hamcrest-core</artifactId>
+          <groupId>org.hamcrest</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.plugin-testing</groupId>
+      <artifactId>maven-plugin-testing-tools</artifactId>
+      <version>3.1.0</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>maven-invoker</artifactId>
+          <groupId>org.apache.maven.shared</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.plugin-testing</groupId>
+      <artifactId>maven-plugin-testing-harness</artifactId>
+      <version>3.1.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <version>2.28.2</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>byte-buddy</artifactId>
+          <groupId>net.bytebuddy</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>byte-buddy-agent</artifactId>
+          <groupId>net.bytebuddy</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>objenesis</artifactId>
+          <groupId>org.objenesis</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-interpolation</artifactId>
+      <version>1.26</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-compat</artifactId>
+      <version>3.1.0</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>asm</artifactId>
+          <groupId>asm</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <version>9.2.28.v20190418</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>javax.servlet-api</artifactId>
+          <groupId>javax.servlet</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>jetty-http</artifactId>
+          <groupId>org.eclipse.jetty</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>jetty-io</artifactId>
+          <groupId>org.eclipse.jetty</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-servlet</artifactId>
+      <version>9.2.28.v20190418</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>jetty-security</artifactId>
+          <groupId>org.eclipse.jetty</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-webapp</artifactId>
+      <version>9.2.28.v20190418</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>jetty-xml</artifactId>
+          <groupId>org.eclipse.jetty</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+  <dependencyManagement />
+  <distributionManagement>
+    <site>
+      <id>apache.website</id>
+      <url>scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path}</url>
+    </site>
+  </distributionManagement>
+  <properties>
+    <pluginTestingVersion>3.1.0</pluginTestingVersion>
+    <jettyVersion>9.2.28.v20190418</jettyVersion>
+    <javaVersion>7</javaVersion>
+    <project.build.outputTimestamp>2020-03-07T11:40:47Z</project.build.outputTimestamp>
+    <mavenVersion>3.1.0</mavenVersion>
+    <doxiaSiteVersion>1.9.2</doxiaSiteVersion>
+    <doxiaVersion>1.9.1</doxiaVersion>
+  </properties>
 </project>
diff --git a/pom.xml b/pom.xml
index 230809a..6512557 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,16 +98,6 @@ under the License.
     <project.build.outputTimestamp>2020-03-07T11:40:47Z</project.build.outputTimestamp>
   </properties>
 
-  <dependencyManagement>
-    <dependencies>
-      <dependency>
-        <groupId>org.ow2.asm</groupId>
-        <artifactId>asm</artifactId>
-        <version>8.0.1</version>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
-
   <dependencies>
     <!-- maven -->
     <!-- Remove once deprecated code has been replaced/removed  -->
@@ -339,7 +329,6 @@ under the License.
       <version>${jettyVersion}</version>
       <scope>test</scope>
     </dependency>
-
   </dependencies>
 
   <build>
@@ -359,7 +348,10 @@ under the License.
               <exclude>src/it/projects/tree-multimodule/expected.txt</exclude>
               <exclude>src/it/projects/tree-multimodule/module-a/expected.txt</exclude>
               <exclude>src/it/projects/tree-multimodule/module-b/expected.txt</exclude>
-              <exclude>src/it/projects/tree-verbose/expected.txt</exclude>
+              <exclude>src/it/projects/tree-verbose/expected*.txt</exclude>
+              <exclude>src/it/projects/tree-verbose-small/expected.txt</exclude>
+              <!-- These files contain expected versions for unit tests -->
+              <exclude>src/test/resources/unit/verbose-serializer-test/*</exclude>
               <!--
                 These files contain real repository artifacts.
               -->
@@ -423,8 +415,6 @@ under the License.
               <projectsDirectory>src/it/projects</projectsDirectory>
               <pomExcludes>
                 <pomExclude>purge-local-repository-bad-pom/pom.xml</pomExclude>
-                <!-- verbose was using Maven2 code, removed with MDEP-494, requires MSHARED-339 to be fixed first -->
-                <pomExclude>tree-verbose/pom.xml</pomExclude>
               </pomExcludes>
               <pomIncludes>
                 <pomInclude>*/pom.xml</pomInclude>
@@ -456,7 +446,7 @@ under the License.
                 <mockRepo>
                   <source>src/it/mrm/repository</source>
                 </mockRepo>
-                <!-- 
+                <!--
                 <mockRepo>
                   <source>src/test/resources/m2repo</source>
                 </mockRepo>
diff --git a/src/it/projects/analyze-report/invoker.properties b/src/it/projects/analyze-report/invoker.properties
index 6e4c8f3..38edf1c 100644
--- a/src/it/projects/analyze-report/invoker.properties
+++ b/src/it/projects/analyze-report/invoker.properties
@@ -16,6 +16,4 @@
 # under the License.
 
 invoker.goals = clean ${project.groupId}:${project.artifactId}:${project.version}:analyze-report
-# don't know why it fails with Maven 2 on some weird java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
-# no time to investigate, Maven 2 is not supported any more
 invoker.maven.version = 3.0+
diff --git a/src/it/projects/analyze-testDependencyWithNonTestScope/invoker.properties b/src/it/projects/analyze-testDependencyWithNonTestScope/invoker.properties
index 6e4c8f3..38edf1c 100644
--- a/src/it/projects/analyze-testDependencyWithNonTestScope/invoker.properties
+++ b/src/it/projects/analyze-testDependencyWithNonTestScope/invoker.properties
@@ -16,6 +16,4 @@
 # under the License.
 
 invoker.goals = clean ${project.groupId}:${project.artifactId}:${project.version}:analyze-report
-# don't know why it fails with Maven 2 on some weird java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
-# no time to investigate, Maven 2 is not supported any more
 invoker.maven.version = 3.0+
diff --git a/src/it/projects/analyze-testDependencyWithNonTestScope/src/test/java/hello/HelloTest.java b/src/it/projects/analyze-testDependencyWithNonTestScope/src/test/java/hello/HelloTest.java
index c877aad..067c194 100644
--- a/src/it/projects/analyze-testDependencyWithNonTestScope/src/test/java/hello/HelloTest.java
+++ b/src/it/projects/analyze-testDependencyWithNonTestScope/src/test/java/hello/HelloTest.java
@@ -22,14 +22,11 @@ package hello;
 import org.junit.Test;
 import static org.junit.Assert.*;
 
-import static org.assertj.core.api.Assertions.assertThat;
-
 public class HelloTest {
 
   @Test
   public void testAdd() {
     assertEquals( 1 + 1, 2 );
-    assertThat( "aaa" ).contains( "a" );
   }
 
 }
diff --git a/src/it/projects/tree-verbose-small/expected.txt b/src/it/projects/tree-verbose-small/expected.txt
new file mode 100644
index 0000000..9cd9e38
--- /dev/null
+++ b/src/it/projects/tree-verbose-small/expected.txt
@@ -0,0 +1,8 @@
+org.apache.maven.its.dependency:tree-verbose2:jar:1.0-SNAPSHOT
++- commons-logging:commons-logging:jar:1.2:compile
+|  +- (log4j:log4j:jar:1.2.17:compile - omitted due to optional dependency)
+|  +- (logkit:logkit:jar:1.0.1:compile - omitted due to optional dependency)
+|  +- (avalon-framework:avalon-framework:jar:4.1.5:compile - omitted due to optional dependency)
+|  \- (javax.servlet:servlet-api:jar:2.3:provided - omitted due to optional dependency)
+\- junit:junit:jar:4.13:test
+   \- org.hamcrest:hamcrest-core:jar:1.3:compile
diff --git a/src/it/projects/analyze-report/invoker.properties b/src/it/projects/tree-verbose-small/invoker.properties
similarity index 71%
copy from src/it/projects/analyze-report/invoker.properties
copy to src/it/projects/tree-verbose-small/invoker.properties
index 6e4c8f3..5d9b8c0 100644
--- a/src/it/projects/analyze-report/invoker.properties
+++ b/src/it/projects/tree-verbose-small/invoker.properties
@@ -15,7 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 
-invoker.goals = clean ${project.groupId}:${project.artifactId}:${project.version}:analyze-report
-# don't know why it fails with Maven 2 on some weird java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
-# no time to investigate, Maven 2 is not supported any more
-invoker.maven.version = 3.0+
+invoker.goals = clean dependency:tree
diff --git a/src/it/projects/tree-verbose/pom.xml b/src/it/projects/tree-verbose-small/pom.xml
similarity index 62%
copy from src/it/projects/tree-verbose/pom.xml
copy to src/it/projects/tree-verbose-small/pom.xml
index 4514ad4..838977a 100644
--- a/src/it/projects/tree-verbose/pom.xml
+++ b/src/it/projects/tree-verbose-small/pom.xml
@@ -24,58 +24,30 @@
   <modelVersion>4.0.0</modelVersion>
 
   <groupId>org.apache.maven.its.dependency</groupId>
-  <artifactId>tree-verbose</artifactId>
+  <artifactId>tree-verbose2</artifactId>
   <version>1.0-SNAPSHOT</version>
 
-  <name>VerboseTest</name>
+  <name>VerboseTest2</name>
   <description>
-    Test verbose dependency:tree with actual Maven version.
+    Test verbose dependency:tree with current dependency-plugin Maven version.
   </description>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
 
-  <dependencyManagement>
-    <dependencies>
-      <dependency>
-        <groupId>org.apache.maven</groupId>
-        <artifactId>maven-model</artifactId>
-        <version>2.0.5</version>
-        <scope>test</scope>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
-
   <dependencies>
     <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-project</artifactId>
-      <version>2.0.6</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.maven</groupId>
-          <artifactId>maven-artifact</artifactId>
-        </exclusion>
-      </exclusions>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.2</version>
     </dependency>
     <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-profile</artifactId>
-      <version>2.0.4</version>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13</version>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-model</artifactId>
-      <version>2.0.7</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.xmlgraphics</groupId>
-      <artifactId>batik-bridge</artifactId>
-      <version>1.7</version>
-    </dependency>
   </dependencies>
 
   <build>
diff --git a/src/it/projects/tree-verbose/verify.bsh b/src/it/projects/tree-verbose-small/verify.bsh
similarity index 84%
copy from src/it/projects/tree-verbose/verify.bsh
copy to src/it/projects/tree-verbose-small/verify.bsh
index 39689ab..cf0ab8f 100644
--- a/src/it/projects/tree-verbose/verify.bsh
+++ b/src/it/projects/tree-verbose-small/verify.bsh
@@ -18,7 +18,6 @@
  */
 
 import java.io.*;
-
 import org.codehaus.plexus.util.*;
 
 String actual = FileUtils.fileRead( new File( basedir, "target/tree.txt" ) );
@@ -27,11 +26,10 @@ String expected = FileUtils.fileRead( new File( basedir, "expected.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" );
+    throw new Exception( "Unexpected dependency tree." + System.lineSeparator() + "Expected:" + System.lineSeparator()
+        + expected + System.lineSeparator() + "Actual:" + System.lineSeparator() + actual );
 }
 
 return true;
diff --git a/src/it/projects/tree-verbose/expected.txt b/src/it/projects/tree-verbose/expected-maven2version.txt
similarity index 91%
copy from src/it/projects/tree-verbose/expected.txt
copy to src/it/projects/tree-verbose/expected-maven2version.txt
index 3914457..436760a 100644
--- a/src/it/projects/tree-verbose/expected.txt
+++ b/src/it/projects/tree-verbose/expected-maven2version.txt
@@ -5,28 +5,31 @@ org.apache.maven.its.dependency:tree-verbose:jar:1.0-SNAPSHOT
 |  |  +- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 |  |  \- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile - omitted for duplicate)
 |  +- (org.apache.maven:maven-profile:jar:2.0.6:compile - omitted for conflict with 2.0.4)
-|  +- (org.apache.maven:maven-model:jar:2.0.5:test - version managed from 2.0.4; scope managed from compile; omitted for conflict with 2.0.7)
+|  +- (org.apache.maven:maven-model:jar:2.0.5:test - version managed from 2.0.6; scope managed from compile; omitted for conflict with 2.0.7)
 |  +- org.apache.maven:maven-artifact-manager:jar:2.0.6:compile
 |  |  +- org.apache.maven:maven-repository-metadata:jar:2.0.6:compile
 |  |  |  \- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 |  |  +- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
+|  |  +- (org.apache.maven:maven-artifact:jar:2.0.6:compile - omitted for duplicate)
 |  |  +- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile - omitted for duplicate)
 |  |  \- org.apache.maven.wagon:wagon-provider-api:jar:1.0-beta-2:compile
-|  |     \- (org.codehaus.plexus:plexus-utils:jar:1.0.4:compile - omitted for conflict with 1.4.1)
+|  |     \- (org.codehaus.plexus:plexus-utils:jar:1.0.4:compile - omitted for duplicate)
 |  +- org.apache.maven:maven-plugin-registry:jar:2.0.6:compile
 |  |  +- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 |  |  \- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile - omitted for duplicate)
 |  +- org.codehaus.plexus:plexus-utils:jar:1.4.1:compile
+|  +- org.apache.maven:maven-artifact:jar:2.0.6:compile
+|  |  \- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 |  \- org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile
 |     +- junit:junit:jar:3.8.1:compile
 |     +- (org.codehaus.plexus:plexus-utils:jar:1.0.4:compile - omitted for conflict with 1.4.1)
 |     \- classworlds:classworlds:jar:1.1-alpha-2:compile
 +- org.apache.maven:maven-profile:jar:2.0.4:test (scope not updated to compile)
-|  +- (org.apache.maven:maven-model:jar:2.0.5:test - version managed from 2.0.4; scope managed from compile; omitted for duplicate)
-|  +- (org.codehaus.plexus:plexus-utils:jar:1.1:test - omitted for conflict with 1.4.1)
-|  \- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9:test - omitted for conflict with 1.0-alpha-9-stable-1)
+|  +- (org.apache.maven:maven-model:jar:2.0.5:test - version managed from 2.0.4; scope managed from compile; omitted for conflict with 2.0.7)
+|  +- (org.codehaus.plexus:plexus-utils:jar:1.1:compile - omitted for conflict with 1.4.1)
+|  \- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9:compile - omitted for conflict with 1.0-alpha-9-stable-1)
 +- org.apache.maven:maven-model:jar:2.0.7:runtime
-|  \- (org.codehaus.plexus:plexus-utils:jar:1.4.1:runtime - omitted for duplicate)
+|  \- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 \- org.apache.xmlgraphics:batik-bridge:jar:1.7:compile
    +- org.apache.xmlgraphics:batik-anim:jar:1.7:compile
    |  +- (org.apache.xmlgraphics:batik-awt-util:jar:1.7:compile - omitted for duplicate)
diff --git a/src/it/projects/tree-verbose/expected.txt b/src/it/projects/tree-verbose/expected.txt
index 3914457..2a55256 100644
--- a/src/it/projects/tree-verbose/expected.txt
+++ b/src/it/projects/tree-verbose/expected.txt
@@ -5,14 +5,14 @@ org.apache.maven.its.dependency:tree-verbose:jar:1.0-SNAPSHOT
 |  |  +- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 |  |  \- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile - omitted for duplicate)
 |  +- (org.apache.maven:maven-profile:jar:2.0.6:compile - omitted for conflict with 2.0.4)
-|  +- (org.apache.maven:maven-model:jar:2.0.5:test - version managed from 2.0.4; scope managed from compile; omitted for conflict with 2.0.7)
+|  +- (org.apache.maven:maven-model:jar:2.0.5:test - version managed from 2.0.6; scope managed from compile; omitted for conflict with 2.0.7)
 |  +- org.apache.maven:maven-artifact-manager:jar:2.0.6:compile
 |  |  +- org.apache.maven:maven-repository-metadata:jar:2.0.6:compile
 |  |  |  \- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 |  |  +- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 |  |  +- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile - omitted for duplicate)
 |  |  \- org.apache.maven.wagon:wagon-provider-api:jar:1.0-beta-2:compile
-|  |     \- (org.codehaus.plexus:plexus-utils:jar:1.0.4:compile - omitted for conflict with 1.4.1)
+|  |     \- (org.codehaus.plexus:plexus-utils:jar:1.0.4:compile - omitted for duplicate)
 |  +- org.apache.maven:maven-plugin-registry:jar:2.0.6:compile
 |  |  +- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 |  |  \- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile - omitted for duplicate)
@@ -21,19 +21,18 @@ org.apache.maven.its.dependency:tree-verbose:jar:1.0-SNAPSHOT
 |     +- junit:junit:jar:3.8.1:compile
 |     +- (org.codehaus.plexus:plexus-utils:jar:1.0.4:compile - omitted for conflict with 1.4.1)
 |     \- classworlds:classworlds:jar:1.1-alpha-2:compile
-+- org.apache.maven:maven-profile:jar:2.0.4:test (scope not updated to compile)
++- org.apache.maven:maven-profile:jar:2.0.4:test
 |  +- (org.apache.maven:maven-model:jar:2.0.5:test - version managed from 2.0.4; scope managed from compile; omitted for duplicate)
-|  +- (org.codehaus.plexus:plexus-utils:jar:1.1:test - omitted for conflict with 1.4.1)
-|  \- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9:test - omitted for conflict with 1.0-alpha-9-stable-1)
+|  +- (org.codehaus.plexus:plexus-utils:jar:1.1:compile - omitted for conflict with 1.4.1)
+|  \- (org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9:compile - omitted for conflict with 1.0-alpha-9-stable-1)
 +- org.apache.maven:maven-model:jar:2.0.7:runtime
-|  \- (org.codehaus.plexus:plexus-utils:jar:1.4.1:runtime - omitted for duplicate)
+|  \- (org.codehaus.plexus:plexus-utils:jar:1.4.1:compile - omitted for duplicate)
 \- org.apache.xmlgraphics:batik-bridge:jar:1.7:compile
    +- org.apache.xmlgraphics:batik-anim:jar:1.7:compile
    |  +- (org.apache.xmlgraphics:batik-awt-util:jar:1.7:compile - omitted for duplicate)
    |  +- (org.apache.xmlgraphics:batik-dom:jar:1.7:compile - omitted for duplicate)
    |  +- (org.apache.xmlgraphics:batik-ext:jar:1.7:compile - omitted for duplicate)
    |  +- (org.apache.xmlgraphics:batik-parser:jar:1.7:compile - omitted for duplicate)
-   |  +- (org.apache.xmlgraphics:batik-anim:jar:1.7:compile - omitted for cycle)
    |  +- (org.apache.xmlgraphics:batik-svg-dom:jar:1.7:compile - omitted for duplicate)
    |  +- (org.apache.xmlgraphics:batik-util:jar:1.7:compile - omitted for duplicate)
    |  +- (xml-apis:xml-apis:jar:1.3.04:compile - omitted for duplicate)
@@ -55,18 +54,26 @@ org.apache.maven.its.dependency:tree-verbose:jar:1.0-SNAPSHOT
    |  \- (xml-apis:xml-apis-ext:jar:1.3.04:compile - omitted for duplicate)
    +- org.apache.xmlgraphics:batik-ext:jar:1.7:compile
    |  \- (xml-apis:xml-apis:jar:1.3.04:compile - omitted for duplicate)
-   +- (org.apache.xmlgraphics:batik-bridge:jar:1.7:compile - omitted for cycle)
    +- org.apache.xmlgraphics:batik-gvt:jar:1.7:compile
-   |  \- (org.apache.xmlgraphics:batik-awt-util:jar:1.7:compile - omitted for duplicate)
+   |  +- (org.apache.xmlgraphics:batik-awt-util:jar:1.7:compile - omitted for duplicate)
+   |  +- (org.apache.xmlgraphics:batik-bridge:jar:1.7:compile - omitted for cycle)
+   |  +- (org.apache.xmlgraphics:batik-util:jar:1.7:compile - omitted for duplicate)
+   |  \- (xml-apis:xml-apis:jar:1.3.04:compile - omitted for duplicate)
    +- org.apache.xmlgraphics:batik-parser:jar:1.7:compile
    |  +- (org.apache.xmlgraphics:batik-awt-util:jar:1.7:compile - omitted for duplicate)
    |  +- (org.apache.xmlgraphics:batik-util:jar:1.7:compile - omitted for duplicate)
    |  \- (org.apache.xmlgraphics:batik-xml:jar:1.7:compile - omitted for duplicate)
-   +- (org.apache.xmlgraphics:batik-bridge:jar:1.7:compile - omitted for cycle)
    +- org.apache.xmlgraphics:batik-script:jar:1.7:compile
+   |  +- (org.apache.xmlgraphics:batik-bridge:jar:1.7:compile - omitted for cycle)
+   |  +- (org.apache.xmlgraphics:batik-dom:jar:1.7:compile - omitted for duplicate)
+   |  +- (org.apache.xmlgraphics:batik-ext:jar:1.7:compile - omitted for duplicate)
+   |  +- (org.apache.xmlgraphics:batik-svg-dom:jar:1.7:compile - omitted for duplicate)
+   |  +- (org.apache.xmlgraphics:batik-util:jar:1.7:compile - omitted for duplicate)
+   |  +- org.apache.xmlgraphics:batik-js:jar:1.7:compile
+   |  |  \- (xml-apis:xml-apis:jar:1.3.04:compile - omitted for duplicate)
+   |  \- (xml-apis:xml-apis:jar:1.3.04:compile - omitted for duplicate)
    +- org.apache.xmlgraphics:batik-svg-dom:jar:1.7:compile
-   |  +- (org.apache.xmlgraphics:batik-svg-dom:jar:1.7:compile - omitted for cycle)
-   |  +- (org.apache.xmlgraphics:batik-anim:jar:1.7:compile - omitted for duplicate)
+   |  +- (org.apache.xmlgraphics:batik-anim:jar:1.7:compile - omitted for cycle)
    |  +- (org.apache.xmlgraphics:batik-awt-util:jar:1.7:compile - omitted for duplicate)
    |  +- (org.apache.xmlgraphics:batik-css:jar:1.7:compile - omitted for duplicate)
    |  +- (org.apache.xmlgraphics:batik-dom:jar:1.7:compile - omitted for duplicate)
@@ -79,6 +86,7 @@ org.apache.maven.its.dependency:tree-verbose:jar:1.0-SNAPSHOT
    +- org.apache.xmlgraphics:batik-xml:jar:1.7:compile
    |  \- (org.apache.xmlgraphics:batik-util:jar:1.7:compile - omitted for duplicate)
    +- xalan:xalan:jar:2.6.0:compile
-   |  \- (xml-apis:xml-apis:jar:1.0.b2:compile - omitted for conflict with 1.3.04)
+   |  +- (xml-apis:xml-apis:jar:1.0.b2:compile - omitted for conflict with 1.3.04)
+   |  \- (xerces:xercesImpl:jar:2.6.0:compile - omitted due to optional dependency)
    +- xml-apis:xml-apis:jar:1.3.04:compile
    \- xml-apis:xml-apis-ext:jar:1.3.04:compile
diff --git a/src/it/projects/tree-verbose/pom.xml b/src/it/projects/tree-verbose/pom.xml
index 4514ad4..ef618b9 100644
--- a/src/it/projects/tree-verbose/pom.xml
+++ b/src/it/projects/tree-verbose/pom.xml
@@ -29,7 +29,7 @@
 
   <name>VerboseTest</name>
   <description>
-    Test verbose dependency:tree with actual Maven version.
+    Test verbose dependency:tree with current dependency-plugin Maven version.
   </description>
 
   <properties>
diff --git a/src/it/projects/tree-verbose/verify.bsh b/src/it/projects/tree-verbose/verify.bsh
index 39689ab..26391a4 100644
--- a/src/it/projects/tree-verbose/verify.bsh
+++ b/src/it/projects/tree-verbose/verify.bsh
@@ -27,11 +27,10 @@ String expected = FileUtils.fileRead( new File( basedir, "expected.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" );
+    throw new Exception( "Unexpected dependency tree." + System.lineSeparator() + "Expected:" + System.lineSeparator()
+    + expected + System.lineSeparator() + "Actual:" + System.lineSeparator() + actual );
 }
 
 return true;
diff --git a/src/it/projects/unpack-custom-ear/pom.xml b/src/it/projects/unpack-custom-ear/pom.xml
index cdcc592..33737a5 100644
--- a/src/it/projects/unpack-custom-ear/pom.xml
+++ b/src/it/projects/unpack-custom-ear/pom.xml
@@ -31,7 +31,7 @@
   </properties>
 
   <build>
-    <!-- 
+    <!--
     <extensions>
       <extension>
         <groupId>org.apache.maven.plugins.dependency.its</groupId>
@@ -71,10 +71,10 @@
           </execution>
         </executions>
         <dependencies>
-          <dependency>
+          <dependency>
             <groupId>org.apache.maven.plugins.dependency.its</groupId>
             <artifactId>maven-custom-ear-manager</artifactId>
-            <version>1.0</version>
+            <version>1.0</version>
           </dependency>
         </dependencies>
       </plugin>
diff --git a/src/it/projects/unpack-custom-ear/verify.groovy b/src/it/projects/unpack-custom-ear/verify.groovy
index 9e867a0..36eb835 100644
--- a/src/it/projects/unpack-custom-ear/verify.groovy
+++ b/src/it/projects/unpack-custom-ear/verify.groovy
@@ -18,4 +18,5 @@
  */
 def buildLog = new File( basedir, 'build.log' )
 assert buildLog.exists()
+assert buildLog.length() != 0
 assert buildLog.text.contains( "[DEBUG] Found unArchiver by type: " )
diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/CycleBreakerGraphTransformer.java b/src/main/java/org/apache/maven/plugins/dependency/tree/CycleBreakerGraphTransformer.java
new file mode 100644
index 0000000..d9afc45
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/dependency/tree/CycleBreakerGraphTransformer.java
@@ -0,0 +1,73 @@
+package org.apache.maven.plugins.dependency.tree;
+
+/*
+ * 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 org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.collection.DependencyGraphTransformationContext;
+import org.eclipse.aether.collection.DependencyGraphTransformer;
+import org.eclipse.aether.graph.DependencyNode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Transforms a dependency graph so that it does not contain cycles.
+ *
+ * <p>A cycle in a dependency graph is a situation where a path to a node from the root contains the
+ * same node. For example, jaxen 1.1-beta-6 is known to have cycle with dom4j 1.6.1.
+ */
+final class CycleBreakerGraphTransformer implements DependencyGraphTransformer
+{
+    @Override
+    public DependencyNode transformGraph( DependencyNode dependencyNode, DependencyGraphTransformationContext context )
+    {
+
+        flagCycle( dependencyNode, new HashSet<Artifact>(), new HashSet<DependencyNode>() );
+        return dependencyNode;
+    }
+
+    private void flagCycle( DependencyNode node, Set<Artifact> ancestors, Set<DependencyNode> visitedNodes )
+    {
+        Artifact artifact = node.getArtifact();
+
+        if ( ancestors.contains( artifact ) )
+        {
+            node.setChildren( new ArrayList<DependencyNode>() );
+            Map<String, String> newProperties = new HashMap<>( node.getArtifact().getProperties() );
+            newProperties.put( "Cycle", "True" );
+            node.setArtifact( node.getArtifact().setProperties( newProperties ) );
+            return;
+        }
+
+        if ( visitedNodes.add( node ) )
+        {
+            ancestors.add( artifact );
+            for ( DependencyNode child : node.getChildren() )
+            {
+                flagCycle( child, ancestors, visitedNodes );
+            }
+            ancestors.remove( artifact );
+        }
+    }
+}
diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/TreeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/tree/TreeMojo.java
index 1e8fd2b..3b04067 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/tree/TreeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/tree/TreeMojo.java
@@ -19,31 +19,28 @@ package org.apache.maven.plugins.dependency.tree;
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
 import org.apache.maven.artifact.versioning.ArtifactVersion;
 import org.apache.maven.artifact.versioning.Restriction;
 import org.apache.maven.artifact.versioning.VersionRange;
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Exclusion;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.dependency.utils.DependencyUtil;
 import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.plugins.dependency.utils.DependencyUtil;
 import org.apache.maven.project.DefaultProjectBuildingRequest;
+import org.apache.maven.project.DependencyResolutionException;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.ProjectBuildingRequest;
+import org.apache.maven.project.ProjectDependenciesResolver;
 import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter;
 import org.apache.maven.shared.artifact.filter.StrictPatternIncludesArtifactFilter;
 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
@@ -53,12 +50,24 @@ import org.apache.maven.shared.dependency.graph.filter.AncestorOrSelfDependencyN
 import org.apache.maven.shared.dependency.graph.filter.AndDependencyNodeFilter;
 import org.apache.maven.shared.dependency.graph.filter.ArtifactDependencyNodeFilter;
 import org.apache.maven.shared.dependency.graph.filter.DependencyNodeFilter;
+import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyNode;
 import org.apache.maven.shared.dependency.graph.traversal.BuildingDependencyNodeVisitor;
 import org.apache.maven.shared.dependency.graph.traversal.CollectingDependencyNodeVisitor;
 import org.apache.maven.shared.dependency.graph.traversal.DependencyNodeVisitor;
 import org.apache.maven.shared.dependency.graph.traversal.FilteringDependencyNodeVisitor;
 import org.apache.maven.shared.dependency.graph.traversal.SerializingDependencyNodeVisitor;
 import org.apache.maven.shared.dependency.graph.traversal.SerializingDependencyNodeVisitor.GraphTokens;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.repository.RemoteRepository;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Displays the dependency tree for this project. Multiple formats are supported: text (by default), but also
@@ -90,6 +99,24 @@ public class TreeMojo
     @Parameter( defaultValue = "${reactorProjects}", readonly = true, required = true )
     private List<MavenProject> reactorProjects;
 
+    @Component
+    private RepositorySystem repositorySystem;
+
+    @Parameter ( defaultValue = "${repositorySystem}" )
+    RepositorySystem repositorySystemParam;
+
+    /**
+     * The current repository/network configuration of Maven.
+     */
+    @Parameter( defaultValue = "${repositorySystemSession}" )
+    private RepositorySystemSession repoSession;
+
+    /**
+     * The project's remote repositories to use for the resolution of project dependencies.
+     */
+    @Parameter( defaultValue = "${project.remoteProjectRepositories}" )
+    private List<RemoteRepository> projectRepos;
+
     /**
      * The dependency tree builder to use.
      */
@@ -207,9 +234,10 @@ public class TreeMojo
      */
     @Parameter( property = "skip", defaultValue = "false" )
     private boolean skip;
-
     // Mojo methods -----------------------------------------------------------
 
+    @Component
+    ProjectDependenciesResolver resolver;
     /*
      * @see org.apache.maven.plugin.Mojo#execute()
      */
@@ -230,23 +258,32 @@ public class TreeMojo
             // TODO: note that filter does not get applied due to MSHARED-4
             ArtifactFilter artifactFilter = createResolvingArtifactFilter();
 
-            if ( verbose )
-            {
-                // To fix we probably need a different DependencyCollector in Aether, which doesn't remove nodes which
-                // have already been resolved.
-                getLog().info( "Verbose not supported since maven-dependency-plugin 3.0" );
-            }
-
             ProjectBuildingRequest buildingRequest =
-                new DefaultProjectBuildingRequest( session.getProjectBuildingRequest() );
+                    new DefaultProjectBuildingRequest( session.getProjectBuildingRequest() );
 
             buildingRequest.setProject( project );
 
-            // non-verbose mode use dependency graph component, which gives consistent results with Maven version
-            // running
-            rootNode = dependencyGraphBuilder.buildDependencyGraph( buildingRequest, artifactFilter, reactorProjects );
+            if ( verbose )
+            {
+                // verboseGraphBuilder needs MavenProject project, RepositorySystemSession session,
+                // ProjectDependenciesResolver resolver
+                VerboseDependencyGraphBuilder builder = new VerboseDependencyGraphBuilder();
+                VerboseGraphSerializer serializer = new VerboseGraphSerializer();
+
+                org.eclipse.aether.graph.DependencyNode verboseRootNode = builder.buildVerboseGraph(
+                        project, resolver, repoSession );
+                dependencyTreeString = serializer.serialize( verboseRootNode );
+                rootNode = convertToCustomDependencyNode( verboseRootNode );
+            }
+            else
+            {
+                // non-verbose mode use dependency graph component, which gives consistent results with Maven version
+                // running
+                rootNode = dependencyGraphBuilder.buildDependencyGraph( buildingRequest, artifactFilter,
+                        reactorProjects );
 
-            dependencyTreeString = serializeDependencyTree( rootNode );
+                dependencyTreeString = serializeDependencyTree( rootNode );
+            }
 
             if ( outputFile != null )
             {
@@ -267,6 +304,10 @@ public class TreeMojo
         {
             throw new MojoExecutionException( "Cannot serialise project dependency graph", exception );
         }
+        catch ( DependencyResolutionException exception )
+        {
+            throw new MojoExecutionException( "Cannot resolve dependencies", exception );
+        }
     }
 
     // public methods ---------------------------------------------------------
@@ -309,6 +350,64 @@ public class TreeMojo
 
     // private methods --------------------------------------------------------
 
+
+    private DependencyNode convertToCustomDependencyNode( org.eclipse.aether.graph.DependencyNode node )
+    {
+        DefaultDependencyNode rootNode = new DefaultDependencyNode( null,
+                convertAetherArtifactToMavenArtifact( node ), null, null, null );
+
+        rootNode.setChildren( new ArrayList<DependencyNode>() );
+
+        for ( org.eclipse.aether.graph.DependencyNode child : node.getChildren() )
+        {
+            rootNode.getChildren().add( buildTree( rootNode, child ) );
+        }
+
+        return rootNode;
+    }
+
+    private DependencyNode buildTree( DependencyNode parent, org.eclipse.aether.graph.DependencyNode child )
+    {
+        List<org.apache.maven.model.Exclusion> exclusions = new ArrayList<>();
+
+        for ( org.eclipse.aether.graph.Exclusion exclusion : child.getDependency().getExclusions() )
+        {
+            exclusions.add( convertAetherExclusionToMavenExclusion( exclusion ) );
+        }
+
+        DefaultDependencyNode newChild = new DefaultDependencyNode( parent,
+                convertAetherArtifactToMavenArtifact( child ),
+                child.getArtifact().getProperties().get( "preManagedVersion" ),
+                child.getArtifact().getProperties().get( "preManagedScope" ), null,
+                child.getDependency().isOptional() );
+
+        newChild.setChildren( new ArrayList<DependencyNode>() );
+
+        for ( org.eclipse.aether.graph.DependencyNode grandChild : child.getChildren() )
+        {
+            newChild.getChildren().add( buildTree( newChild, grandChild ) );
+        }
+
+        return newChild;
+    }
+
+    private static Artifact convertAetherArtifactToMavenArtifact( org.eclipse.aether.graph.DependencyNode node )
+    {
+        org.eclipse.aether.artifact.Artifact artifact = node.getArtifact();
+        return new DefaultArtifact( artifact.getGroupId(), artifact.getArtifactId(),
+                artifact.getVersion(), node.getDependency().getScope(), artifact.getExtension(),
+                artifact.getClassifier(), null );
+    }
+
+    private static Exclusion convertAetherExclusionToMavenExclusion ( org.eclipse.aether.graph.Exclusion exclusion )
+    {
+        Exclusion mavenExclusion = new Exclusion();
+        mavenExclusion.setArtifactId( exclusion.getArtifactId() );
+        mavenExclusion.setGroupId( exclusion.getGroupId() );
+        // don't do anything with locations yet
+        return  mavenExclusion;
+    }
+
     /**
      * Gets the artifact filter to use when resolving the dependency tree.
      *
diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseDependencyGraphBuilder.java b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseDependencyGraphBuilder.java
new file mode 100644
index 0000000..9a5b50d
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseDependencyGraphBuilder.java
@@ -0,0 +1,223 @@
+package org.apache.maven.plugins.dependency.tree;
+
+/*
+ * 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 org.apache.maven.model.DependencyManagement;
+import org.apache.maven.model.Model;
+import org.apache.maven.project.DefaultDependencyResolutionRequest;
+import org.apache.maven.project.DependencyResolutionException;
+import org.apache.maven.project.DependencyResolutionRequest;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectDependenciesResolver;
+import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.collection.DependencySelector;
+import org.eclipse.aether.graph.DefaultDependencyNode;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.util.graph.selector.AndDependencySelector;
+import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
+import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
+import org.eclipse.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
+import org.eclipse.aether.util.graph.transformer.JavaDependencyContextRefiner;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Builds the VerboseDependencyGraph
+ */
+class VerboseDependencyGraphBuilder
+{
+    private static final String PRE_MANAGED_SCOPE = "preManagedScope", PRE_MANAGED_VERSION = "preManagedVersion",
+            MANAGED_SCOPE = "managedScope";
+
+    public DependencyNode buildVerboseGraph( MavenProject project, ProjectDependenciesResolver resolver,
+                                                         RepositorySystemSession repositorySystemSession )
+            throws DependencyResolutionException
+    {
+        DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
+        session.setLocalRepositoryManager( repositorySystemSession.getLocalRepositoryManager() );
+
+        DependencySelector dependencySelector = new AndDependencySelector(
+                // ScopeDependencySelector takes exclusions. 'Provided' scope is not here to avoid
+                // false positive in LinkageChecker.
+                new ScopeDependencySelector(),
+                new ExclusionDependencySelector() );
+
+        session.setDependencySelector( dependencySelector );
+        session.setDependencyGraphTransformer( new ChainedDependencyGraphTransformer(
+                new CycleBreakerGraphTransformer(), // Avoids StackOverflowError
+                new JavaDependencyContextRefiner() ) );
+        session.setDependencyManager( null );
+
+        DependencyResolutionRequest request = new DefaultDependencyResolutionRequest();
+        request.setMavenProject( project );
+        request.setRepositorySession( session );
+        request.setResolutionFilter( null );
+
+        DependencyNode rootNode = resolver.resolve( request ).getDependencyGraph();
+        // Don't want transitive test dependencies included in analysis
+        DependencyNode prunedRoot = pruneTransitiveTestDependencies( rootNode, project );
+        applyDependencyManagement( project, prunedRoot );
+        return prunedRoot;
+    }
+
+    private void applyDependencyManagement( MavenProject project, DependencyNode root )
+    {
+        Map<String, org.apache.maven.model.Dependency> dependencyManagementMap = createDependencyManagementMap(
+                project.getDependencyManagement() );
+
+        for ( DependencyNode child : root.getChildren() )
+        {
+            for ( DependencyNode nonTransitiveDependencyNode : child.getChildren() )
+            {
+                applyDependencyManagementDfs( dependencyManagementMap, nonTransitiveDependencyNode );
+            }
+        }
+    }
+
+    private void applyDependencyManagementDfs( Map<String, org.apache.maven.model.Dependency> dependencyManagementMap,
+                                               DependencyNode node )
+    {
+        if ( dependencyManagementMap.containsKey( getDependencyManagementCoordinate( node.getArtifact() ) ) )
+        {
+            org.apache.maven.model.Dependency manager = dependencyManagementMap.get(
+                    getDependencyManagementCoordinate( node.getArtifact() ) );
+            Map<String, String> artifactProperties = new HashMap<>();
+            for ( Map.Entry<String, String> entry : node.getArtifact().getProperties().entrySet() )
+            {
+                artifactProperties.put( entry.getKey(), entry.getValue() );
+            }
+
+            if ( !manager.getVersion().equals( node.getArtifact().getVersion() ) )
+            {
+                artifactProperties.put( PRE_MANAGED_VERSION, node.getArtifact().getVersion() );
+                node.setArtifact( node.getArtifact().setVersion( manager.getVersion() ) );
+            }
+
+            if ( !manager.getScope().equals( node.getDependency().getScope() ) )
+            {
+                artifactProperties.put( PRE_MANAGED_SCOPE, node.getDependency().getScope() );
+                // be aware this does not actually change the node's scope, it may need to be fixed in the future
+                artifactProperties.put( MANAGED_SCOPE, manager.getScope() );
+            }
+            node.setArtifact( node.getArtifact().setProperties( artifactProperties ) );
+            node.getDependency().setArtifact( node.getDependency().getArtifact().setProperties( artifactProperties ) );
+        }
+        for ( DependencyNode child : node.getChildren() )
+        {
+            applyDependencyManagementDfs( dependencyManagementMap, child );
+        }
+    }
+
+    private static Map<String, org.apache.maven.model.Dependency> createDependencyManagementMap(
+            DependencyManagement dependencyManagement )
+    {
+        Map<String, org.apache.maven.model.Dependency> dependencyManagementMap = new HashMap<>();
+        if ( dependencyManagement == null )
+        {
+            return dependencyManagementMap;
+        }
+        for ( org.apache.maven.model.Dependency dependency : dependencyManagement.getDependencies() )
+        {
+            dependencyManagementMap.put( getDependencyManagementCoordinate( dependency ), dependency );
+        }
+        return dependencyManagementMap;
+    }
+
+    private static String getDependencyManagementCoordinate( org.apache.maven.model.Dependency dependency )
+    {
+        StringBuilder string = new StringBuilder();
+        string.append( dependency.getGroupId() ).append( ":" ).append( dependency.getArtifactId() )
+                .append( ":" ).append( dependency.getType() );
+        if ( dependency.getClassifier() != null && !dependency.getClassifier().equals( "" ) )
+        {
+            string.append( ":" ).append( dependency.getClassifier() );
+        }
+        return string.toString();
+    }
+
+    private static String getDependencyManagementCoordinate( Artifact artifact )
+    {
+        StringBuilder string = new StringBuilder();
+        string.append( artifact.getGroupId() ).append( ":" ).append( artifact.getArtifactId() ).append( ":" )
+                .append( artifact.getExtension() );
+        if ( artifact.getClassifier() != null && !artifact.getClassifier().equals( "" ) )
+        {
+            string.append( ":" ).append( artifact.getClassifier() );
+        }
+        return string.toString();
+    }
+
+    private Dependency getProjectDependency( MavenProject project )
+    {
+        Model model = project.getModel();
+
+        return new Dependency( new DefaultArtifact( model.getGroupId(), model.getArtifactId(), model.getPackaging(),
+                model.getVersion() ), "" );
+    }
+
+    private DependencyNode pruneTransitiveTestDependencies( DependencyNode rootNode, MavenProject project )
+    {
+        Set<DependencyNode> visitedNodes = new HashSet<>();
+        DependencyNode newRoot = new DefaultDependencyNode( getProjectDependency( project ) );
+        newRoot.setChildren( new ArrayList<DependencyNode>() );
+
+        for ( int i = 0; i < rootNode.getChildren().size(); i++ )
+        {
+            DependencyNode childNode = rootNode.getChildren().get( i );
+            newRoot.getChildren().add( childNode );
+
+            pruneTransitiveTestDependenciesDfs( childNode, visitedNodes );
+        }
+
+        return newRoot;
+    }
+
+    private void pruneTransitiveTestDependenciesDfs( DependencyNode node , Set<DependencyNode> visitedNodes )
+    {
+        if ( !visitedNodes.contains( node ) )
+        {
+            visitedNodes.add( node );
+            // iterator needed to avoid concurrentModificationException
+            Iterator<DependencyNode> iterator = node.getChildren().iterator();
+            while ( iterator.hasNext() )
+            {
+                DependencyNode child = iterator.next();
+                if ( child.getDependency().getScope().equals( "test" ) )
+                {
+                    iterator.remove();
+                }
+                else
+                {
+                    pruneTransitiveTestDependenciesDfs( child, visitedNodes );
+                }
+            }
+        }
+    }
+}
diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializer.java b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializer.java
new file mode 100644
index 0000000..e786187
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializer.java
@@ -0,0 +1,324 @@
+package org.apache.maven.plugins.dependency.tree;
+
+/*
+ * 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 org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.graph.DependencyNode;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+/**
+ * Parses dependency graph and outputs in text format for end user to review.
+ */
+final class VerboseGraphSerializer
+{
+    private static final String LINE_START_LAST_CHILD = "\\- ", LINE_START_CHILD = "+- ";
+    private static final String PRE_MANAGED_SCOPE = "preManagedScope", PRE_MANAGED_VERSION = "preManagedVersion",
+            MANAGED_SCOPE = "managedScope";
+
+    public String serialize( DependencyNode root )
+    {
+        Set<String> coordinateStrings = new HashSet<>();
+        Map<String, String> coordinateVersionMap = new HashMap<>();
+        StringBuilder builder = new StringBuilder();
+
+        // Use BFS to mirror how Maven resolves dependencies and use DFS to print the tree easily
+        Map<DependencyNode, String> nodeErrors = getNodeConflictMessagesBfs( root, coordinateStrings,
+                coordinateVersionMap );
+
+        // deal with root first
+        Artifact rootArtifact = root.getArtifact();
+        builder.append( rootArtifact.getGroupId() ).append( ":" ).append( rootArtifact.getArtifactId() ).append( ":" )
+                .append( rootArtifact.getExtension() ).append( ":" ).append( rootArtifact.getVersion() ).append(
+                        System.lineSeparator() );
+
+        for ( int i = 0; i < root.getChildren().size(); i++ )
+        {
+            if ( i == root.getChildren().size() - 1 )
+            {
+                dfsPrint( root.getChildren().get( i ), LINE_START_LAST_CHILD, false, builder, nodeErrors );
+            }
+            else
+            {
+                dfsPrint( root.getChildren().get( i ), LINE_START_CHILD, false, builder, nodeErrors );
+            }
+        }
+        return builder.toString();
+    }
+
+    private static String getDependencyCoordinate( DependencyNode node )
+    {
+        Artifact artifact = node.getArtifact();
+
+        if ( node.getDependency() == null )
+        {
+            // should only get here if node is root
+            return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getExtension() + ":"
+                    + artifact.getVersion();
+        }
+
+        String scope;
+        if ( artifact.getProperties().containsKey( MANAGED_SCOPE ) )
+        {
+            scope = artifact.getProperties().get( MANAGED_SCOPE );
+        }
+        else
+        {
+            scope = node.getDependency().getScope();
+        }
+
+        String coords = artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getExtension() + ":"
+                + artifact.getVersion();
+
+        if ( scope != null && !scope.isEmpty() )
+        {
+            coords = coords.concat( ":" + scope );
+        }
+        return coords;
+    }
+
+    private static String getVersionlessScopelessCoordinate( DependencyNode node )
+    {
+        Artifact artifact = node.getArtifact();
+        // scope not included because we check for scope conflicts separately
+        return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getExtension();
+    }
+
+    private static boolean isDuplicateDependencyCoordinate( DependencyNode node, Set<String> coordinateStrings )
+    {
+        return coordinateStrings.contains( getDependencyCoordinate( node ) );
+    }
+
+    private static String versionConflict( DependencyNode node, Map<String, String> coordinateVersionMap )
+    {
+        if ( coordinateVersionMap.containsKey( getVersionlessScopelessCoordinate( node ) ) )
+        {
+            return coordinateVersionMap.get( getVersionlessScopelessCoordinate( node ) );
+        }
+        return null;
+    }
+
+    private static String scopeConflict( DependencyNode node, Set<String> coordinateStrings )
+    {
+        Artifact artifact = node.getArtifact();
+        List<String> scopes = Arrays.asList( "compile", "provided", "runtime", "test", "system" );
+
+        for ( String scope : scopes )
+        {
+            String coordinate = artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getExtension()
+                    + ":" + artifact.getVersion() + ":" + scope;
+            if ( coordinateStrings.contains( coordinate ) )
+            {
+                return scope;
+            }
+        }
+        return null;
+    }
+
+    private Map<DependencyNode, String> getNodeConflictMessagesBfs( DependencyNode root, Set<String> coordinateStrings
+            , Map<String, String> coordinateVersionMap )
+    {
+        Map<DependencyNode, String> nodeErrors = new HashMap<>();
+        Set<DependencyNode> visitedNodes = new HashSet<>( 512 );
+        Queue<DependencyNode> queue = new LinkedList<>();
+        visitedNodes.add( root );
+        queue.add( root );
+
+        while ( !queue.isEmpty() )
+        {
+            DependencyNode node = queue.poll();
+
+            if ( node == null || node.getArtifact() == null )
+            {
+                // Should never reach hit this condition with a proper graph sent in
+                nodeErrors.put( node, "Null Artifact Node" );
+                break;
+            }
+
+            if ( isDuplicateDependencyCoordinate( node, coordinateStrings ) )
+            {
+                nodeErrors.put( node, "omitted for duplicate" );
+            }
+            else if ( scopeConflict( node, coordinateStrings ) != null )
+            {
+                nodeErrors.put( node, "omitted for conflict with "
+                        + scopeConflict( node, coordinateStrings ) );
+            }
+            else if ( versionConflict( node, coordinateVersionMap ) != null )
+            {
+                nodeErrors.put( node, "omitted for conflict with "
+                        + versionConflict( node, coordinateVersionMap ) );
+            }
+            else if ( node.getDependency() != null && node.getDependency().isOptional() )
+            {
+                nodeErrors.put( node, "omitted due to optional dependency" );
+            }
+            else
+            {
+                boolean ignoreNode = false;
+                nodeErrors.put( node, null );
+
+                if ( node.getArtifact() != null )
+                {
+                    coordinateVersionMap.put( getVersionlessScopelessCoordinate( node ),
+                            node.getArtifact().getVersion() );
+                }
+
+                for ( DependencyNode child : node.getChildren() )
+                {
+                    if ( visitedNodes.contains( child ) )
+                    {
+                        ignoreNode = true;
+                        nodeErrors.put( node, "omitted for introducing a cycle with "
+                                + getDependencyCoordinate( child ) );
+                        node.setChildren( new ArrayList<DependencyNode>() );
+                        break;
+                    }
+                }
+
+                if ( !ignoreNode )
+                {
+                    for ( int i = 0; i < node.getChildren().size(); ++i )
+                    {
+                        DependencyNode child = node.getChildren().get( i );
+
+                        if ( !visitedNodes.contains( child ) )
+                        {
+                            visitedNodes.add( child );
+                            queue.add( child );
+                        }
+                    }
+                }
+            }
+            coordinateStrings.add( getDependencyCoordinate( node ) );
+        }
+        return nodeErrors;
+    }
+
+    private void dfsPrint( DependencyNode node, String start, boolean transitive, StringBuilder builder,
+                           Map<DependencyNode, String> nodeErrors )
+    {
+        builder.append( start );
+        if ( node.getArtifact() == null )
+        {
+            // Should never hit this condition with a proper graph sent in
+            builder.append( "Null Artifact Node" ).append( System.lineSeparator() );
+            callDfsPrint( node, start, builder, nodeErrors );
+        }
+
+        String coordString = "";
+        boolean messageAdded = false;
+
+        if ( transitive && node.getArtifact().getProperties().containsKey( PRE_MANAGED_VERSION ) )
+        {
+            coordString = coordString.concat( " - version managed from "
+                    + node.getArtifact().getProperties().get( PRE_MANAGED_VERSION ) );
+            messageAdded = true;
+        }
+
+        if ( transitive && node.getArtifact().getProperties().containsKey( PRE_MANAGED_SCOPE ) )
+        {
+            if ( messageAdded )
+            {
+                coordString = coordString.concat( "; " );
+            }
+            else
+            {
+                coordString = coordString.concat( " - " );
+                messageAdded = true;
+            }
+            coordString = coordString.concat( "scope managed from "
+                    + node.getArtifact().getProperties().get( PRE_MANAGED_SCOPE ) );
+        }
+
+        coordString = getDependencyCoordinate( node ) + coordString;
+
+        if ( !( node.getDependency().getScope().equals( "test" ) && transitive ) )
+        {
+            if ( node.getArtifact().getProperties().containsKey( "Cycle" ) )
+            {
+                if ( messageAdded )
+                {
+                    coordString = coordString.concat( "; " );
+                }
+                else
+                {
+                    coordString = coordString.concat( " - " );
+                }
+                coordString = coordString.concat( "omitted for cycle" );
+                builder.append( "(" ).append( coordString ).append( ")" ).append( System.lineSeparator() );
+            }
+            else if ( nodeErrors.get( node ) != null )
+            {
+                builder.append( "(" );
+                if ( messageAdded )
+                {
+                    builder.append( coordString ).append( "; " ).append( nodeErrors.get( node ) );
+                }
+                else
+                {
+                    builder.append( coordString ).append( " - " ).append( nodeErrors.get( node ) );
+                }
+                builder.append( ")" );
+                builder.append( System.lineSeparator() );
+            }
+            else
+            {
+                builder.append( coordString ).append( System.lineSeparator() );
+                callDfsPrint( node, start, builder, nodeErrors );
+            }
+        }
+    }
+
+    private void callDfsPrint( DependencyNode node, String start, StringBuilder builder,
+                               Map<DependencyNode, String> nodeErrors )
+    {
+        for ( int i = 0; i < node.getChildren().size(); i++ )
+        {
+            if ( start.endsWith( LINE_START_CHILD ) )
+            {
+                start = start.replace( LINE_START_CHILD, "|  " );
+            }
+            else if ( start.endsWith( LINE_START_LAST_CHILD ) )
+            {
+                start = start.replace( LINE_START_LAST_CHILD, "   " );
+            }
+
+            if ( i == node.getChildren().size() - 1 )
+            {
+                dfsPrint( node.getChildren().get( i ), start.concat( LINE_START_LAST_CHILD ), true, builder,
+                        nodeErrors );
+            }
+            else
+            {
+                dfsPrint( node.getChildren().get( i ), start.concat( LINE_START_CHILD ), true, builder,
+                        nodeErrors );
+            }
+        }
+    }
+}
diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml
index 5dbba8c..91ef15d 100644
--- a/src/main/resources/META-INF/plexus/components.xml
+++ b/src/main/resources/META-INF/plexus/components.xml
@@ -95,6 +95,10 @@ under the License.
       <implementation>org.codehaus.plexus.archiver.zip.ZipUnArchiver</implementation>
       <instantiation-strategy>per-lookup</instantiation-strategy>
     </component>
+    <component>
+      <role>org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer</role>
+      <implementation>org.apache.maven.shared.dependency.analyzer.DefaultProjectDependencyAnalyzer</implementation>
+    </component>
 
   </components>
 </component-set>
diff --git a/src/test/java/org/apache/maven/plugins/dependency/TestListClassesMojo.java b/src/test/java/org/apache/maven/plugins/dependency/TestListClassesMojo.java
index df990fe..49a7eaa 100644
--- a/src/test/java/org/apache/maven/plugins/dependency/TestListClassesMojo.java
+++ b/src/test/java/org/apache/maven/plugins/dependency/TestListClassesMojo.java
@@ -57,7 +57,7 @@ public class TestListClassesMojo
 
         setVariableValueToObject( mojo, "session", legacySupport.getSession() );
     }
-
+    
     public void testListClassesNotTransitive()
             throws Exception
     {
diff --git a/src/test/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializerTest.java b/src/test/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializerTest.java
new file mode 100644
index 0000000..d0abf3f
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializerTest.java
@@ -0,0 +1,253 @@
+package org.apache.maven.plugins.dependency.tree;
+/*
+ * 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 org.apache.commons.io.FileUtils;
+import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.apache.maven.plugins.dependency.tree.VerboseGraphSerializer;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.graph.DefaultDependencyNode;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.graph.DependencyNode;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+public class VerboseGraphSerializerTest extends AbstractMojoTestCase
+{
+    private final VerboseGraphSerializer serializer = new VerboseGraphSerializer();
+
+    @Test
+    public void testBasicTree() throws IOException
+    {
+        DependencyNode root = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), null)
+        );
+        DependencyNode left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.apache", "left", "xml", "0.1-SNAPSHOT" ), "test" )
+        );
+        DependencyNode right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.xyz", "right", "zip", "1" ), "provided" )
+        );
+
+        root.setChildren( Arrays.asList( left, right ) );
+
+        String actual = serializer.serialize( root );
+        File file = new File(getBasedir(), "/target/test-classes/unit/verbose-serializer-test/BasicTree.txt");
+        String expected = FileUtils.readFileToString( file );
+
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testLargeTree() throws IOException
+    {
+        // Construct nodes for tree l1 = level 1 with the root being l0
+        DependencyNode root = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), null )
+        );
+        DependencyNode l1left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.apache", "left", "xml", "0.1-SNAPSHOT" ), "test" )
+        );
+        DependencyNode l1right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.xyz", "right", "zip", "1" ), "provided" )
+        );
+        DependencyNode l2left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.maven", "a4", "jar", "2.2.1" ), "system" )
+        );
+        DependencyNode l2middle = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "a5", "zip", "0" ), "import" )
+        );
+        DependencyNode l2right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.xyz", "a9", "xml", "1.2" ), "runtime" )
+        );
+        DependencyNode l3 = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.xyz", "a6", "xml", "1.2.1" ), "provided" )
+        );
+        DependencyNode l4 = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.example", "a7", "jar", "2.2.2" ), "provided" )
+        );
+        DependencyNode l5right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.comm", "a7", "jar", "1" ), "compile" )
+        );
+        DependencyNode l5left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.comm", "a7", "jar", "1" ), "compile" )
+        );
+        DependencyNode l6left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.example", "a8", "xml", "2.1" ), "compile" )
+        );
+
+        // Set Node Relationships
+        l5left.setChildren( Arrays.asList( l6left ) );
+        l4.setChildren( Arrays.asList( l5left, l5right ) );
+        l3.setChildren( Arrays.asList( l4 ) );
+        l2middle.setChildren( Arrays.asList( l3 ) );
+
+        l1left.setChildren( Arrays.asList( l2left, l2middle ) );
+        l1right.setChildren( Arrays.asList( l2right ) );
+
+        root.setChildren( Arrays.asList( l1left, l1right ) );
+
+        String actual = serializer.serialize( root );
+        File file = new File(getBasedir(), "/target/test-classes/unit/verbose-serializer-test/LargeTree.txt");
+        String expected = FileUtils.readFileToString(file);
+
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testLargeGraphWithCycles() throws IOException
+    {
+        // Construct nodes for tree l1 = level 1 with the root being l0
+        DependencyNode root = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), null )
+        );
+        DependencyNode l1left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.apache", "left", "xml", "0.1-SNAPSHOT" ), "test" )
+        );
+        DependencyNode l1right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.xyz", "right", "zip", "1" ), "provided" )
+        );
+        DependencyNode l2left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.maven", "a4", "jar", "2.2.1" ), "system" )
+        );
+        DependencyNode l2middle = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "a5", "zip", "0" ), "import" )
+        );
+        DependencyNode l2right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.xyz", "a9", "xml", "1.2" ), "runtime" )
+        );
+        DependencyNode l3 = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.xyz", "a6", "xml", "1.2.1" ), "compile" )
+        );
+        DependencyNode l4 = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.example", "a7", "jar", "2.2.2" ), "provided" )
+        );
+        DependencyNode l5right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.comm", "a7", "jar", "1" ), "compile" )
+        );
+        DependencyNode l5left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.comm", "a7", "jar", "1" ), "compile" )
+        );
+        DependencyNode l6left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.example", "a8", "xml", "2.1" ), "runtime" )
+        );
+
+        // Set Node Relationships
+        l5left.setChildren( Arrays.asList( l6left ) );
+        l4.setChildren( Arrays.asList( l5left, l5right ) );
+        l3.setChildren( Arrays.asList( l4 ) );
+        l2middle.setChildren( Arrays.asList( l3 ) );
+
+        l1left.setChildren( Arrays.asList( l2left, l2middle ) );
+        l1right.setChildren( Arrays.asList( l2right ) );
+
+        root.setChildren( Arrays.asList( l1left, l1right ) );
+
+        // Introduce cycles
+        l5left.setChildren( Arrays.asList( l2left, l1right, l3 ) );
+
+        String actual = serializer.serialize( root );
+        File file = new File(getBasedir(),
+                "/target/test-classes/unit/verbose-serializer-test/LargeGraphWithCycles.txt");
+        String expected = FileUtils.readFileToString(file);
+
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testTreeWithOptional() throws IOException
+    {
+        DependencyNode root = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), "")
+        );
+        DependencyNode left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.apache", "left", "xml", "0.1-SNAPSHOT" ), "test", true )
+        );
+        DependencyNode right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.xyz", "right", "zip", "1" ), "provided" )
+        );
+
+        root.setChildren( Arrays.asList( left, right ) );
+
+        String actual = serializer.serialize( root );
+        File file = new File(getBasedir(),
+                "/target/test-classes/unit/verbose-serializer-test/OptionalDependency.txt");
+        String expected = FileUtils.readFileToString(file);
+
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testTreeWithScopeConflict() throws IOException
+    {
+        DependencyNode root = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), null )
+        );
+        DependencyNode left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.apache", "left", "xml", "0.1-SNAPSHOT" ), "test" )
+        );
+        DependencyNode right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "conflictArtifact", "jar", "1.0.0" ), "test" )
+        );
+        DependencyNode leftChild = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "conflictArtifact", "jar", "1.0.0" ), "compile" )
+        );
+
+        left.setChildren( Arrays.asList( leftChild ) );
+        root.setChildren( Arrays.asList( left, right ) );
+
+        String actual = serializer.serialize( root );
+        File file = new File(getBasedir(), "/target/test-classes/unit/verbose-serializer-test/ScopeConflict.txt");
+        String expected = FileUtils.readFileToString(file);
+
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testTreeWithVersionConflict() throws IOException
+    {
+        DependencyNode root = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), "rootScope" )
+        );
+        DependencyNode left = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.apache", "left", "xml", "0.1-SNAPSHOT" ), "test" )
+        );
+        DependencyNode right = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "com.google", "artifact", "jar", "2.0.0" ), "test" )
+        );
+        // Note that as of now the serializer does not deal with conflicts with the project/root node itself
+        DependencyNode leftChild = new DefaultDependencyNode(
+                new Dependency( new DefaultArtifact( "org.apache", "left", "xml", "0.3.1" ), "compile" )
+        );
+
+        left.setChildren( Arrays.asList( leftChild ) );
+        root.setChildren( Arrays.asList( left, right ) );
+
+        String actual = serializer.serialize( root );
+        File file = new File(getBasedir(),
+                "/target/test-classes/unit/verbose-serializer-test/VersionConflict.txt");
+        String expected = FileUtils.readFileToString(file);
+
+        Assert.assertEquals(expected, actual);
+    }
+}
diff --git a/src/test/resources/unit/verbose-serializer-test/BasicCycle.txt b/src/test/resources/unit/verbose-serializer-test/BasicCycle.txt
new file mode 100644
index 0000000..37d528b
--- /dev/null
+++ b/src/test/resources/unit/verbose-serializer-test/BasicCycle.txt
@@ -0,0 +1,3 @@
+com.google:rootArtifact:jar:1.0.0
++- (org.apache:left:xml:0.1-SNAPSHOT:test - omitted for introducing a cycle with com.google:rootArtifact:jar:1.0.0)
+\- org.xyz:right:zip:1:provided
diff --git a/src/test/resources/unit/verbose-serializer-test/BasicTree.txt b/src/test/resources/unit/verbose-serializer-test/BasicTree.txt
new file mode 100644
index 0000000..c1c1c1e
--- /dev/null
+++ b/src/test/resources/unit/verbose-serializer-test/BasicTree.txt
@@ -0,0 +1,3 @@
+com.google:rootArtifact:jar:1.0.0
++- org.apache:left:xml:0.1-SNAPSHOT:test
+\- org.xyz:right:zip:1:provided
diff --git a/src/test/resources/unit/verbose-serializer-test/LargeGraphWithCycles.txt b/src/test/resources/unit/verbose-serializer-test/LargeGraphWithCycles.txt
new file mode 100644
index 0000000..87d3590
--- /dev/null
+++ b/src/test/resources/unit/verbose-serializer-test/LargeGraphWithCycles.txt
@@ -0,0 +1,10 @@
+com.google:rootArtifact:jar:1.0.0
++- org.apache:left:xml:0.1-SNAPSHOT:test
+|  +- org.maven:a4:jar:2.2.1:system
+|  \- com.google:a5:zip:0:import
+|     \- com.xyz:a6:xml:1.2.1:compile
+|        \- com.example:a7:jar:2.2.2:provided
+|           +- (com.comm:a7:jar:1:compile - omitted for introducing a cycle with org.maven:a4:jar:2.2.1:system)
+|           \- (com.comm:a7:jar:1:compile - omitted for duplicate)
+\- org.xyz:right:zip:1:provided
+   \- com.xyz:a9:xml:1.2:runtime
diff --git a/src/test/resources/unit/verbose-serializer-test/LargeTree.txt b/src/test/resources/unit/verbose-serializer-test/LargeTree.txt
new file mode 100644
index 0000000..6480fa6
--- /dev/null
+++ b/src/test/resources/unit/verbose-serializer-test/LargeTree.txt
@@ -0,0 +1,11 @@
+com.google:rootArtifact:jar:1.0.0
++- org.apache:left:xml:0.1-SNAPSHOT:test
+|  +- org.maven:a4:jar:2.2.1:system
+|  \- com.google:a5:zip:0:import
+|     \- com.xyz:a6:xml:1.2.1:provided
+|        \- com.example:a7:jar:2.2.2:provided
+|           +- com.comm:a7:jar:1:compile
+|           |  \- com.example:a8:xml:2.1:compile
+|           \- (com.comm:a7:jar:1:compile - omitted for duplicate)
+\- org.xyz:right:zip:1:provided
+   \- com.xyz:a9:xml:1.2:runtime
diff --git a/src/test/resources/unit/verbose-serializer-test/OptionalDependency.txt b/src/test/resources/unit/verbose-serializer-test/OptionalDependency.txt
new file mode 100644
index 0000000..4c4f11f
--- /dev/null
+++ b/src/test/resources/unit/verbose-serializer-test/OptionalDependency.txt
@@ -0,0 +1,3 @@
+com.google:rootArtifact:jar:1.0.0
++- (org.apache:left:xml:0.1-SNAPSHOT:test - omitted due to optional dependency)
+\- org.xyz:right:zip:1:provided
diff --git a/src/test/resources/unit/verbose-serializer-test/ScopeConflict.txt b/src/test/resources/unit/verbose-serializer-test/ScopeConflict.txt
new file mode 100644
index 0000000..81f2977
--- /dev/null
+++ b/src/test/resources/unit/verbose-serializer-test/ScopeConflict.txt
@@ -0,0 +1,4 @@
+com.google:rootArtifact:jar:1.0.0
++- org.apache:left:xml:0.1-SNAPSHOT:test
+|  \- (com.google:conflictArtifact:jar:1.0.0:compile - omitted for conflict with test)
+\- com.google:conflictArtifact:jar:1.0.0:test
diff --git a/src/test/resources/unit/verbose-serializer-test/VersionConflict.txt b/src/test/resources/unit/verbose-serializer-test/VersionConflict.txt
new file mode 100644
index 0000000..640e3f3
--- /dev/null
+++ b/src/test/resources/unit/verbose-serializer-test/VersionConflict.txt
@@ -0,0 +1,4 @@
+com.google:rootArtifact:jar:1.0.0
++- org.apache:left:xml:0.1-SNAPSHOT:test
+|  \- (org.apache:left:xml:0.3.1:compile - omitted for conflict with 0.1-SNAPSHOT)
+\- com.google:artifact:jar:2.0.0:test