diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializer.java b/src/main/java/org/apache/maven/plugins/dependency/tree/AbstractVerboseGraphSerializer.java similarity index 53% rename from src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializer.java rename to src/main/java/org/apache/maven/plugins/dependency/tree/AbstractVerboseGraphSerializer.java index e7861870c..82ed864f4 100644 --- a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializer.java +++ b/src/main/java/org/apache/maven/plugins/dependency/tree/AbstractVerboseGraphSerializer.java @@ -33,45 +33,17 @@ import java.util.Set; /** - * Parses dependency graph and outputs in text format for end user to review. + * Base class for verbose Serializers */ -final class VerboseGraphSerializer +abstract class AbstractVerboseGraphSerializer { - private static final String LINE_START_LAST_CHILD = "\\- ", LINE_START_CHILD = "+- "; - private static final String PRE_MANAGED_SCOPE = "preManagedScope", PRE_MANAGED_VERSION = "preManagedVersion", + protected static final String LINE_START_LAST_CHILD = "\\- ", LINE_START_CHILD = "+- "; + protected static final String PRE_MANAGED_SCOPE = "preManagedScope", PRE_MANAGED_VERSION = "preManagedVersion", MANAGED_SCOPE = "managedScope"; - public String serialize( DependencyNode root ) - { - Set coordinateStrings = new HashSet<>(); - Map coordinateVersionMap = new HashMap<>(); - StringBuilder builder = new StringBuilder(); - - // Use BFS to mirror how Maven resolves dependencies and use DFS to print the tree easily - Map 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() ); + public abstract String serialize( DependencyNode root ); - 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 ) + protected static String getDependencyCoordinate( DependencyNode node ) { Artifact artifact = node.getArtifact(); @@ -140,7 +112,7 @@ private static String scopeConflict( DependencyNode node, Set coordinate return null; } - private Map getNodeConflictMessagesBfs( DependencyNode root, Set coordinateStrings + protected Map getNodeConflictMessagesBfs( DependencyNode root, Set coordinateStrings , Map coordinateVersionMap ) { Map nodeErrors = new HashMap<>(); @@ -166,8 +138,11 @@ private Map getNodeConflictMessagesBfs( DependencyNode r } else if ( scopeConflict( node, coordinateStrings ) != null ) { - nodeErrors.put( node, "omitted for conflict with " - + scopeConflict( node, coordinateStrings ) ); + 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 ( versionConflict( node, coordinateVersionMap ) != null ) { @@ -219,106 +194,4 @@ else if ( node.getDependency() != null && node.getDependency().isOptional() ) } return nodeErrors; } - - private void dfsPrint( DependencyNode node, String start, boolean transitive, StringBuilder builder, - Map 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 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/java/org/apache/maven/plugins/dependency/tree/TreeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/tree/TreeMojo.java index 3b0406765..1eb35b039 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 @@ -268,7 +268,7 @@ public void execute() // verboseGraphBuilder needs MavenProject project, RepositorySystemSession session, // ProjectDependenciesResolver resolver VerboseDependencyGraphBuilder builder = new VerboseDependencyGraphBuilder(); - VerboseGraphSerializer serializer = new VerboseGraphSerializer(); + AbstractVerboseGraphSerializer serializer = getSerializer(); org.eclipse.aether.graph.DependencyNode verboseRootNode = builder.buildVerboseGraph( project, resolver, repoSession ); @@ -350,6 +350,25 @@ public void setSkip( boolean skip ) // private methods -------------------------------------------------------- + private AbstractVerboseGraphSerializer getSerializer( ) + { + if ( "graphml".equals( outputType ) ) + { + return new VerboseGraphGraphmlSerializer(); + } + else if ( "tgf".equals( outputType ) ) + { + return new VerboseGraphTgfSerializer(); + } + else if ( "dot".equals( outputType ) ) + { + return new VerboseGraphDotSerializer(); + } + else + { + return new VerboseGraphTextSerializer(); + } + } private DependencyNode convertToCustomDependencyNode( org.eclipse.aether.graph.DependencyNode node ) { 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 index 9a5b50d01..192c941d9 100644 --- a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseDependencyGraphBuilder.java +++ b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseDependencyGraphBuilder.java @@ -57,7 +57,7 @@ class VerboseDependencyGraphBuilder MANAGED_SCOPE = "managedScope"; public DependencyNode buildVerboseGraph( MavenProject project, ProjectDependenciesResolver resolver, - RepositorySystemSession repositorySystemSession ) + RepositorySystemSession repositorySystemSession ) throws DependencyResolutionException { DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); @@ -66,13 +66,12 @@ public DependencyNode buildVerboseGraph( MavenProject project, ProjectDependenci DependencySelector dependencySelector = new AndDependencySelector( // ScopeDependencySelector takes exclusions. 'Provided' scope is not here to avoid // false positive in LinkageChecker. - new ScopeDependencySelector(), - new ExclusionDependencySelector() ); + new ScopeDependencySelector(), new ExclusionDependencySelector() ); session.setDependencySelector( dependencySelector ); - session.setDependencyGraphTransformer( new ChainedDependencyGraphTransformer( - new CycleBreakerGraphTransformer(), // Avoids StackOverflowError - new JavaDependencyContextRefiner() ) ); + session.setDependencyGraphTransformer( + new ChainedDependencyGraphTransformer( new CycleBreakerGraphTransformer(), // Avoids StackOverflowError + new JavaDependencyContextRefiner() ) ); session.setDependencyManager( null ); DependencyResolutionRequest request = new DefaultDependencyResolutionRequest(); @@ -152,26 +151,26 @@ private static Map createDependencyMa 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() ); + StringBuilder builder = new StringBuilder(); + builder.append( dependency.getGroupId() ).append( ":" ).append( dependency.getArtifactId() ).append( ":" ) + .append( dependency.getType() ); if ( dependency.getClassifier() != null && !dependency.getClassifier().equals( "" ) ) { - string.append( ":" ).append( dependency.getClassifier() ); + builder.append( ":" ).append( dependency.getClassifier() ); } - return string.toString(); + return builder.toString(); } private static String getDependencyManagementCoordinate( Artifact artifact ) { - StringBuilder string = new StringBuilder(); - string.append( artifact.getGroupId() ).append( ":" ).append( artifact.getArtifactId() ).append( ":" ) - .append( artifact.getExtension() ); + StringBuilder builder = new StringBuilder(); + builder.append( artifact.getGroupId() ).append( ":" ).append( artifact.getArtifactId() ).append( ":" ).append( + artifact.getExtension() ); if ( artifact.getClassifier() != null && !artifact.getClassifier().equals( "" ) ) { - string.append( ":" ).append( artifact.getClassifier() ); + builder.append( ":" ).append( artifact.getClassifier() ); } - return string.toString(); + return builder.toString(); } private Dependency getProjectDependency( MavenProject project ) @@ -199,7 +198,7 @@ private DependencyNode pruneTransitiveTestDependencies( DependencyNode rootNode, return newRoot; } - private void pruneTransitiveTestDependenciesDfs( DependencyNode node , Set visitedNodes ) + private void pruneTransitiveTestDependenciesDfs( DependencyNode node, Set visitedNodes ) { if ( !visitedNodes.contains( node ) ) { diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphDotSerializer.java b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphDotSerializer.java new file mode 100644 index 000000000..fce1b4dc2 --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphDotSerializer.java @@ -0,0 +1,114 @@ +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.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + +/** + * Parses dependency graph and outputs in DOT format for end user to review. + */ +class VerboseGraphDotSerializer extends AbstractVerboseGraphSerializer +{ + @Override + public String serialize( DependencyNode root ) + { + Set coordinateStrings = new HashSet<>(); + Map coordinateVersionMap = new HashMap<>(); + Map nodeErrors = getNodeConflictMessagesBfs( root, coordinateStrings, + coordinateVersionMap ); + Set visitedNodes = new HashSet<>(); + Queue queue = new LinkedList<>(); + queue.add( root ); + Artifact rootArtifact = root.getArtifact(); + + StringBuilder result = new StringBuilder( "digraph" ); + result.append( " \"" ).append( rootArtifact.getGroupId() ).append( ":" ).append( + rootArtifact.getArtifactId() ).append( ":" ).append( rootArtifact.getExtension() ).append( ":" ).append( + rootArtifact.getVersion() ).append( "\" {" ).append( "\n" ); + + while ( !queue.isEmpty() ) + { + DependencyNode node = queue.poll(); + for ( DependencyNode child : node.getChildren() ) + { + result.append( " \"" ); + String coordString = ""; + boolean messageAdded = false; + + if ( child.getArtifact().getProperties().containsKey( PRE_MANAGED_VERSION ) ) + { + coordString += + " - version managed from " + child.getArtifact().getProperties().get( + PRE_MANAGED_VERSION ); + messageAdded = true; + } + if ( child.getArtifact().getProperties().containsKey( PRE_MANAGED_SCOPE ) ) + { + if ( messageAdded ) + { + coordString += "; "; + } + else + { + coordString += " - "; + messageAdded = true; + } + coordString += + "scope managed from " + child.getArtifact().getProperties().get( PRE_MANAGED_SCOPE ); + } + coordString = getDependencyCoordinate( child ) + coordString; + result.append( getDependencyCoordinate( node ) ).append( "\"" ).append( " -> \"" ).append( + coordString ); + if ( child.getArtifact().getProperties().containsKey( "Cycle" ) ) + { + if ( !messageAdded ) + { + result.append( " -" ); + } + result.append( " omitted due to cycle" ); + } + else if ( nodeErrors.get( child ) != null ) + { + if ( !messageAdded ) + { + result.append( " - " ); + } + result.append( nodeErrors.get( child ) ); + } + else if ( !visitedNodes.contains( child ) ) + { + visitedNodes.add( child ); + queue.add( child ); + } + result.append( "\" ;" ).append( "\n" ); + } + } + result.append( "}" ); + return result.toString(); + } +} diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphGraphmlSerializer.java b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphGraphmlSerializer.java new file mode 100644 index 000000000..6f6e7e9c6 --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphGraphmlSerializer.java @@ -0,0 +1,174 @@ +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.graph.DependencyNode; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + +/** + * Parses dependency graph and outputs in GraphML format for end user to review. + */ +public class VerboseGraphGraphmlSerializer extends AbstractVerboseGraphSerializer +{ + @Override + public String serialize( DependencyNode root ) + { + Set coordinateStrings = new HashSet<>(); + Map coordinateVersionMap = new HashMap<>(); + Map nodeErrors = getNodeConflictMessagesBfs( root, coordinateStrings, + coordinateVersionMap ); + + Set visitedNodes = new HashSet<>(); + Queue queue = new LinkedList<>(); + queue.add( root ); + StringBuilder result = new StringBuilder( " " + + "" + + "\n" + + " " + + "\n" + + " " + + "\n" + + "" + "\n" ); + + StringBuilder nodes = new StringBuilder(); + StringBuilder edges = new StringBuilder(); + while ( !queue.isEmpty() ) + { + DependencyNode node = queue.poll(); + nodes.append( getGraphmlNodeLine( node, nodeErrors ) ); + if ( nodeErrors.get( node ) == null && !node.getArtifact().getProperties().containsKey( "Cycle" ) ) + { + for ( DependencyNode child : node.getChildren() ) + { + if ( !visitedNodes.contains( child ) ) + { + visitedNodes.add( child ); + queue.add( child ); + } + edges.append( getGraphmlEdgeLine( node, child, nodeErrors ) ); + } + } + } + result.append( nodes ).append( edges ); + result.append( "" ); + return result.toString(); + } + + private String getGraphmlEdgeLine( DependencyNode parent, DependencyNode child, + Map nodeErrors ) + { + StringBuilder builder = new StringBuilder(); + builder.append( "" ); + + + boolean messageAdded = false; + + if ( child.getArtifact().getProperties().containsKey( PRE_MANAGED_SCOPE ) ) + { + messageAdded = true; + builder.append( child.getArtifact().getProperties().get( MANAGED_SCOPE ) ); + builder.append( ", scope managed from " ).append( + child.getArtifact().getProperties().get( PRE_MANAGED_SCOPE ) ); + } + else + { + builder.append( child.getDependency().getScope() ); + } + if ( child.getArtifact().getProperties().containsKey( "Cycle" ) ) + { + if ( messageAdded ) + { + builder.append( "," ); + } + builder.append( " omitted due to cycle" ); + } + else if ( nodeErrors.get( child ) != null ) + { + if ( messageAdded ) + { + builder.append( "," ); + } + builder.append( " " ).append( nodeErrors.get( child ) ); + } + builder.append( "" ).append( "\n" ); + return builder.toString(); + } + + private String getGraphmlNodeLine( DependencyNode node, Map nodeErrors ) + { + StringBuilder builder = new StringBuilder(); + builder.append( "" + "" ); + + String coordString = ""; + boolean messageAdded = false; + + if ( node.getArtifact().getProperties().containsKey( PRE_MANAGED_VERSION ) ) + { + coordString += + " - version managed from " + node.getArtifact().getProperties().get( PRE_MANAGED_VERSION ); + messageAdded = true; + } + if ( node.getArtifact().getProperties().containsKey( PRE_MANAGED_SCOPE ) ) + { + if ( messageAdded ) + { + coordString += "; "; + } + else + { + coordString += " - "; + messageAdded = true; + } + coordString += + "scope managed from " + node.getArtifact().getProperties().get( PRE_MANAGED_SCOPE ); + } + builder.append( getDependencyCoordinate( node ) ).append( coordString ); + if ( node.getArtifact().getProperties().containsKey( "Cycle" ) ) + { + if ( !messageAdded ) + { + builder.append( " - " ); + } + builder.append( "omitted due to cycle" ); + } + else if ( nodeErrors.get( node ) != null ) + { + if ( !messageAdded ) + { + builder.append( " - " ); + } + builder.append( nodeErrors.get( node ) ); + } + builder.append( "" ).append( "\n" ); + return builder.toString(); + } +} diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphTextSerializer.java b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphTextSerializer.java new file mode 100644 index 000000000..70e41eeb1 --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphTextSerializer.java @@ -0,0 +1,160 @@ +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.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Parses dependency graph and outputs in text format for end user to review. + */ +class VerboseGraphTextSerializer extends AbstractVerboseGraphSerializer +{ + @Override + public String serialize( DependencyNode root ) + { + Set coordinateStrings = new HashSet<>(); + Map coordinateVersionMap = new HashMap<>(); + Map nodeErrors = getNodeConflictMessagesBfs( root, coordinateStrings, + coordinateVersionMap ); + + StringBuilder builder = new StringBuilder(); + + // 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( + "\n" ); + + for ( int i = 0; i < root.getChildren().size(); i++ ) + { + if ( i == root.getChildren().size() - 1 ) + { + dfsPrint( root.getChildren().get( i ), LINE_START_LAST_CHILD, builder, nodeErrors ); + } + else + { + dfsPrint( root.getChildren().get( i ), LINE_START_CHILD, builder, nodeErrors ); + } + } + return builder.toString(); + } + + private void dfsPrint( DependencyNode node, String start, StringBuilder builder, + Map 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( "\n" ); + callDfsPrint( node, start, builder, nodeErrors ); + } + + String coordString = ""; + boolean messageAdded = false; + + if ( node.getArtifact().getProperties().containsKey( PRE_MANAGED_VERSION ) ) + { + coordString += " - version managed from " + + node.getArtifact().getProperties().get( PRE_MANAGED_VERSION ); + messageAdded = true; + } + if ( node.getArtifact().getProperties().containsKey( PRE_MANAGED_SCOPE ) ) + { + if ( messageAdded ) + { + coordString += "; "; + } + else + { + coordString += " - "; + messageAdded = true; + } + coordString += + "scope managed from " + node.getArtifact().getProperties().get( PRE_MANAGED_SCOPE ); + } + + coordString = getDependencyCoordinate( node ) + coordString; + + if ( node.getArtifact().getProperties().containsKey( "Cycle" ) ) + { + if ( messageAdded ) + { + coordString += "; "; + } + else + { + coordString += " - "; + } + coordString += "omitted for cycle"; + builder.append( "(" ).append( coordString ).append( ")" ).append( "\n" ); + } + 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( "\n" ); + } + else + { + builder.append( coordString ).append( "\n" ); + callDfsPrint( node, start, builder, nodeErrors ); + } + } + + private void callDfsPrint( DependencyNode node, String start, StringBuilder builder, + Map 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 ), builder, nodeErrors ); + } + else + { + dfsPrint( node.getChildren().get( i ), start.concat( LINE_START_CHILD ), builder, nodeErrors ); + } + } + } +} diff --git a/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphTgfSerializer.java b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphTgfSerializer.java new file mode 100644 index 000000000..f44cfe6ec --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/dependency/tree/VerboseGraphTgfSerializer.java @@ -0,0 +1,148 @@ +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.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Parses dependency graph and outputs in TGF format for end user to review. + */ +class VerboseGraphTgfSerializer extends AbstractVerboseGraphSerializer +{ + + @Override + public String serialize( DependencyNode root ) + { + Set coordinateStrings = new HashSet<>(); + Map coordinateVersionMap = new HashMap<>(); + Map nodeErrors = getNodeConflictMessagesBfs( root, coordinateStrings, + coordinateVersionMap ); + + StringBuilder nodes = new StringBuilder(); + StringBuilder edges = new StringBuilder( "#" ); + edges.append( "\n" ); + + // deal with root first + Artifact rootArtifact = root.getArtifact(); + nodes.append( root.hashCode() ).append( " " ).append( rootArtifact.getGroupId() ).append( ":" ).append( + rootArtifact.getArtifactId() ).append( ":" ).append( rootArtifact.getExtension() ).append( ":" ).append( + rootArtifact.getVersion() ).append( "\n" ); + + for ( DependencyNode child : root.getChildren() ) + { + edges.append( root.hashCode() ).append( " " ).append( child.hashCode() ).append( " " ).append( + child.getDependency().getScope() ).append( "\n" ); + serializeTgfDfs( child, nodeErrors, nodes, edges ); + } + + return nodes.append( edges ).toString(); + } + + private void serializeTgfDfs( DependencyNode node, Map nodeErrors, StringBuilder nodes, + StringBuilder edges ) + { + nodes.append( node.hashCode() ).append( " " ); + String coordString = ""; + boolean messageAdded = false; + + if ( node.getArtifact().getProperties().containsKey( PRE_MANAGED_VERSION ) ) + { + coordString += " - version managed from " + node.getArtifact().getProperties().get( PRE_MANAGED_VERSION ); + messageAdded = true; + } + if ( node.getArtifact().getProperties().containsKey( PRE_MANAGED_SCOPE ) ) + { + if ( messageAdded ) + { + coordString += "; "; + } + else + { + coordString += " - "; + messageAdded = true; + } + coordString += + "scope managed from " + node.getArtifact().getProperties().get( PRE_MANAGED_SCOPE ); + } + coordString = getDependencyCoordinate( node ) + coordString; + + + if ( node.getArtifact().getProperties().containsKey( "Cycle" ) ) + { + if ( messageAdded ) + { + coordString += "; "; + } + else + { + coordString += " - "; + } + coordString += "omitted for cycle"; + nodes.append( "(" ).append( coordString ).append( ")" ).append( "\n" ); + } + else if ( nodeErrors.get( node ) != null ) + { + nodes.append( "(" ); + if ( messageAdded ) + { + nodes.append( coordString ).append( "; " ).append( nodeErrors.get( node ) ); + } + else + { + nodes.append( coordString ).append( " - " ).append( nodeErrors.get( node ) ); + } + nodes.append( ")" ).append( "\n" ); + } + else + { + nodes.append( coordString ).append( "\n" ); + for ( DependencyNode child : node.getChildren() ) + { + edges.append( node.hashCode() ).append( " " ).append( child.hashCode() ).append( " " ); + if ( child.getArtifact().getProperties().get( MANAGED_SCOPE ) != null ) + { + edges.append( child.getArtifact().getProperties().get( MANAGED_SCOPE ) ).append( " managed from " ) + .append( child.getArtifact().getProperties().get( PRE_MANAGED_SCOPE ) ); + } + else + { + edges.append( child.getDependency().getScope() ); + } + + if ( child.getArtifact().getProperties().containsKey( "Cycle" ) ) + { + edges.append( " omitted for cycle" ); + } + else if ( nodeErrors.get( child ) != null ) + { + edges.append( " " ).append( nodeErrors.get( child ) ); + } + edges.append( "\n" ); + serializeTgfDfs( child, nodeErrors, nodes, edges ); + } + } + } +} 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 index d0abf3fbd..3af4dab54 100644 --- a/src/test/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializerTest.java +++ b/src/test/java/org/apache/maven/plugins/dependency/tree/VerboseGraphSerializerTest.java @@ -18,9 +18,8 @@ * 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.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; @@ -28,17 +27,23 @@ import org.junit.Assert; import org.junit.Test; -import java.io.File; import java.io.IOException; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; public class VerboseGraphSerializerTest extends AbstractMojoTestCase { - private final VerboseGraphSerializer serializer = new VerboseGraphSerializer(); + private AbstractVerboseGraphSerializer serializer; + + private static final String PRE_MANAGED_SCOPE = "preManagedScope", PRE_MANAGED_VERSION = "preManagedVersion", + MANAGED_SCOPE = "managedScope"; @Test public void testBasicTree() throws IOException { + serializer = new VerboseGraphTextSerializer(); DependencyNode root = new DefaultDependencyNode( new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), null) ); @@ -52,8 +57,8 @@ public void testBasicTree() throws IOException 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 ); + String expected = "com.google:rootArtifact:jar:1.0.0\n" + "+- org.apache:left:xml:0.1-SNAPSHOT:test\n" + + "\\- org.xyz:right:zip:1:provided\n"; Assert.assertEquals(expected, actual); } @@ -61,6 +66,7 @@ public void testBasicTree() throws IOException @Test public void testLargeTree() throws IOException { + serializer = new VerboseGraphTextSerializer(); // 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 ) @@ -108,8 +114,12 @@ public void testLargeTree() throws IOException 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); + String expected = "com.google:rootArtifact:jar:1.0.0\n" + "+- org.apache:left:xml:0.1-SNAPSHOT:test\n" + + "| +- org.maven:a4:jar:2.2.1:system\n" + "| \\- com.google:a5:zip:0:import\n" + + "| \\- com.xyz:a6:xml:1.2.1:provided\n" + "| \\- com.example:a7:jar:2.2.2:provided\n" + + "| +- com.comm:a7:jar:1:compile\n" + "| | \\- com.example:a8:xml:2.1:compile\n" + + "| \\- (com.comm:a7:jar:1:compile - omitted for duplicate)\n" + + "\\- org.xyz:right:zip:1:provided\n" + " \\- com.xyz:a9:xml:1.2:runtime\n"; Assert.assertEquals(expected, actual); } @@ -117,6 +127,7 @@ public void testLargeTree() throws IOException @Test public void testLargeGraphWithCycles() throws IOException { + serializer = new VerboseGraphTextSerializer(); // 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 ) @@ -167,9 +178,12 @@ public void testLargeGraphWithCycles() throws IOException 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); + String expected = "com.google:rootArtifact:jar:1.0.0\n" + "+- org.apache:left:xml:0.1-SNAPSHOT:test\n" + + "| +- org.maven:a4:jar:2.2.1:system\n" + "| \\- com.google:a5:zip:0:import\n" + + "| \\- com.xyz:a6:xml:1.2.1:compile\n" + "| \\- com.example:a7:jar:2.2.2:provided\n" + + "| +- (com.comm:a7:jar:1:compile - omitted for introducing a cycle with org.maven:a4:" + + "jar:2.2.1:system)\n" + "| \\- (com.comm:a7:jar:1:compile - omitted for duplicate)\n" + + "\\- org.xyz:right:zip:1:provided\n" + " \\- com.xyz:a9:xml:1.2:runtime\n"; Assert.assertEquals(expected, actual); } @@ -177,6 +191,7 @@ public void testLargeGraphWithCycles() throws IOException @Test public void testTreeWithOptional() throws IOException { + serializer = new VerboseGraphTextSerializer(); DependencyNode root = new DefaultDependencyNode( new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), "") ); @@ -190,9 +205,9 @@ public void testTreeWithOptional() throws IOException 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); + String expected = "com.google:rootArtifact:jar:1.0.0\n" + + "+- (org.apache:left:xml:0.1-SNAPSHOT:test - omitted due to optional dependency)\n" + + "\\- org.xyz:right:zip:1:provided\n"; Assert.assertEquals(expected, actual); } @@ -200,6 +215,7 @@ public void testTreeWithOptional() throws IOException @Test public void testTreeWithScopeConflict() throws IOException { + serializer = new VerboseGraphTextSerializer(); DependencyNode root = new DefaultDependencyNode( new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), null ) ); @@ -217,8 +233,9 @@ public void testTreeWithScopeConflict() throws IOException 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); + String expected = "com.google:rootArtifact:jar:1.0.0\n" + "+- org.apache:left:xml:0.1-SNAPSHOT:test\n" + + "| \\- (com.google:conflictArtifact:jar:1.0.0:compile - omitted for conflict with test)\n" + + "\\- com.google:conflictArtifact:jar:1.0.0:test\n"; Assert.assertEquals(expected, actual); } @@ -226,6 +243,7 @@ public void testTreeWithScopeConflict() throws IOException @Test public void testTreeWithVersionConflict() throws IOException { + serializer = new VerboseGraphTextSerializer(); DependencyNode root = new DefaultDependencyNode( new Dependency( new DefaultArtifact( "com.google", "rootArtifact", "jar", "1.0.0" ), "rootScope" ) ); @@ -244,10 +262,399 @@ public void testTreeWithVersionConflict() throws IOException 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); + String expected = "com.google:rootArtifact:jar:1.0.0\n" + "+- org.apache:left:xml:0.1-SNAPSHOT:test\n" + + "| \\- (org.apache:left:xml:0.3.1:compile - omitted for conflict with 0.1-SNAPSHOT)\n" + + "\\- com.google:artifact:jar:2.0.0:test\n"; + + Assert.assertEquals(expected, actual); + } + @Test + public void testDotOutput() + { + serializer = new VerboseGraphDotSerializer(); + DependencyNode root = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.example", "root", "jar", "3.1.1" ), "" ) + ); + + DependencyNode l1left = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.duplicate", "duplicate", "xml", "2" ), "compile" ) + ); + DependencyNode l2left = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.duplicate", "duplicate", "xml", "2" ), "compile" ) + ); + Artifact cycleArtifact = new DefaultArtifact( "org.cycle", "cycle", "zip", "3" ); + cycleArtifact = cycleArtifact.setProperties( Collections.singletonMap( "Cycle", "true" ) ); + DependencyNode l2middleLeft = new DefaultDependencyNode( + new Dependency( cycleArtifact, "compile" ) + ); + + DependencyNode l1middle = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven", "jar", "1.0-SNAPSHOT" ), "test" ) + ); + // should have scope conflict with l1middle, check to make sure its not version + DependencyNode l2middleRight = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "1.0-SNAPSHOT" ), "compile" ) + ); + + DependencyNode l1right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "1.0-SNAPSHOT" ), "test" ) + ); + DependencyNode l5right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "2.1" ), "test" ) + ); + DependencyNode l6right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.abc", "shouldn't show", "xml", "1" ), "compile" ) + ); + + Artifact scopeManaged = new DefaultArtifact( "org.scopeManaged", "scope-managed", "zip", "2.1" ); + Map artifactProperties = new HashMap<>( scopeManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_SCOPE, "runtime" ); + artifactProperties.put( MANAGED_SCOPE, "compile" ); + scopeManaged = scopeManaged.setProperties( artifactProperties ); + DependencyNode l2right = new DefaultDependencyNode( + new Dependency( scopeManaged, "scope" ) + ); + + Artifact versionManaged = new DefaultArtifact( "org.versionManaged", "version-manged", "pom", "3.3.3" ); + artifactProperties = new HashMap<>( versionManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_VERSION, "1.1.0" ); + versionManaged = versionManaged.setProperties( artifactProperties ); + DependencyNode l3right = new DefaultDependencyNode( + new Dependency( versionManaged, "provided" ) + ); + + Artifact scopeVersionManaged = new DefaultArtifact( "org.scopeVersionManaged", "scope-version-managed", + "xml", "2" ); + artifactProperties = new HashMap<>( scopeVersionManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_SCOPE, "runtime" ); + artifactProperties.put( MANAGED_SCOPE, "compile" ); + artifactProperties.put( PRE_MANAGED_VERSION, "3.1" ); + scopeVersionManaged = scopeVersionManaged.setProperties( artifactProperties ); + + DependencyNode l4right = new DefaultDependencyNode( + new Dependency( scopeVersionManaged, "runtime" ) + ); + + + Dependency optionalDependency = new Dependency( + new DefaultArtifact( "org.apache", "optional", "jar", "1.1" ), "test" ); + optionalDependency = optionalDependency.setOptional( true ); + DependencyNode l1Optional = new DefaultDependencyNode( optionalDependency ); + + root.setChildren( Arrays.asList( l1left, l1middle, l1right, l1Optional ) ); + l1left.setChildren( Arrays.asList( l2left, l2middleLeft ) ); + l2left.setChildren( Collections.singletonList( l6right ) ); // l6right shouldn't show due to omitted parent node + l2middleLeft.setChildren( Collections.singletonList( l6right ) ); + l1Optional.setChildren( Collections.singletonList( l6right ) ); + l1middle.setChildren( Collections.singletonList( l2middleRight ) ); + l1right.setChildren( Collections.singletonList( l2right ) ); + l2right.setChildren( Collections.singletonList( l3right ) ); + l3right.setChildren( Collections.singletonList( l4right ) ); + l4right.setChildren( Collections.singletonList( l5right ) ); + l5right.setChildren( Collections.singletonList( l6right ) ); + + String actual = serializer.serialize( root ); + String expected = "digraph \"org.example:root:jar:3.1.1\" {" + + "\n" + + " \"org.example:root:jar:3.1.1\" -> \"org.duplicate:duplicate:xml:2:compile\" ;" + + "\n" + + " \"org.example:root:jar:3.1.1\" -> \"org.apache:maven:jar:1.0-SNAPSHOT:test\" ;" + + "\n" + + " \"org.example:root:jar:3.1.1\" -> \"org.apache:maven-dependency:jar:1.0-SNAPSHOT:test\" ;" + + "\n" + + " \"org.example:root:jar:3.1.1\" -> \"org.apache:optional:jar:1.1:test - omitted due to optional " + + "dependency\" ;" + "\n" + + " \"org.duplicate:duplicate:xml:2:compile\" -> \"org.duplicate:duplicate" + + ":xml:2:compile - omitted for duplicate\" ;" + "\n" + + " \"org.duplicate:duplicate:xml:2:compile\" -> \"org.cycle:cycle:zip:3:compile - omitted due " + + "to cycle\" ;" + "\n" + + " \"org.apache:maven:jar:1.0-SNAPSHOT:test\" -> \"org.apache:maven-dependency" + + ":jar:1.0-SNAPSHOT:compile - omitted for conflict with test\" ;" + "\n" + + " \"org.apache:maven-dependency:jar:1.0-SNAPSHOT:test\" -> \"org.scopeManaged:scope-managed:zip" + + ":2.1:compile - scope managed from runtime\" ;" + "\n" + + " \"org.scopeManaged:scope-managed:zip:2.1:compile\" -> \"org.versionManaged:version-manged:" + + "pom:3.3.3:provided - version managed from 1.1.0\" ;" + "\n" + + " \"org.versionManaged:version-manged:pom:3.3.3:provided\" -> \"org.scopeVersionManaged:" + + "scope-version-managed:xml:2:compile - version managed from 3.1; scope managed from runtime\" ;" + + "\n" + " \"org.scopeVersionManaged:scope-version-managed:xml:2:compile\" -> " + + "\"org.apache:maven-dependency:jar:2.1:test - omitted for conflict with 1.0-SNAPSHOT\" ;" + + "\n" + "}"; + Assert.assertEquals(expected, actual); + } + + @Test + public void testTgfOutput() + { + serializer = new VerboseGraphTgfSerializer(); + DependencyNode root = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.example", "root", "jar", "3.1.1" ), "" ) + ); + + DependencyNode l1left = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.duplicate", "duplicate", "xml", "2" ), "compile" ) + ); + DependencyNode l2left = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.duplicate", "duplicate", "xml", "2" ), "compile" ) + ); + Artifact cycleArtifact = new DefaultArtifact( "org.cycle", "cycle", "zip", "3" ); + cycleArtifact = cycleArtifact.setProperties( Collections.singletonMap( "Cycle", "true" ) ); + DependencyNode l2middleLeft = new DefaultDependencyNode( + new Dependency( cycleArtifact, "compile" ) + ); + + DependencyNode l1middle = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven", "jar", "1.0-SNAPSHOT" ), "test" ) + ); + // should have scope conflict with l1middle, check to make sure its not version + DependencyNode l2middleRight = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "1.0-SNAPSHOT" ), "compile" ) + ); + + DependencyNode l1right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "1.0-SNAPSHOT" ), "test" ) + ); + DependencyNode l5right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "2.1" ), "test" ) + ); + DependencyNode l6right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.abc", "shouldn't show", "xml", "1" ), "compile" ) + ); + + Artifact scopeManaged = new DefaultArtifact( "org.scopeManaged", "scope-managed", "zip", "2.1" ); + Map artifactProperties = new HashMap<>( scopeManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_SCOPE, "runtime" ); + artifactProperties.put( MANAGED_SCOPE, "compile" ); + scopeManaged = scopeManaged.setProperties( artifactProperties ); + DependencyNode l2right = new DefaultDependencyNode( + new Dependency( scopeManaged, "scope" ) + ); + + Artifact versionManaged = new DefaultArtifact( "org.versionManaged", "version-manged", "pom", "3.3.3" ); + artifactProperties = new HashMap<>( versionManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_VERSION, "1.1.0" ); + versionManaged = versionManaged.setProperties( artifactProperties ); + DependencyNode l3right = new DefaultDependencyNode( + new Dependency( versionManaged, "provided" ) + ); + + Artifact scopeVersionManaged = new DefaultArtifact( "org.scopeVersionManaged", "scope-version-managed", + "xml", "2" ); + artifactProperties = new HashMap<>( scopeVersionManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_SCOPE, "runtime" ); + artifactProperties.put( MANAGED_SCOPE, "compile" ); + artifactProperties.put( PRE_MANAGED_VERSION, "3.1" ); + scopeVersionManaged = scopeVersionManaged.setProperties( artifactProperties ); + + DependencyNode l4right = new DefaultDependencyNode( + new Dependency( scopeVersionManaged, "runtime" ) + ); + + + Dependency optionalDependency = new Dependency( + new DefaultArtifact( "org.apache", "optional", "jar", "1.1" ), "test" ); + optionalDependency = optionalDependency.setOptional( true ); + DependencyNode l1Optional = new DefaultDependencyNode( optionalDependency ); + + root.setChildren( Arrays.asList( l1left, l1middle, l1right, l1Optional ) ); + l1left.setChildren( Arrays.asList( l2left, l2middleLeft ) ); + l2left.setChildren( Collections.singletonList( l6right ) ); // l6right shouldn't show due to omitted parent node + l2middleLeft.setChildren( Collections.singletonList( l6right ) ); + l1Optional.setChildren( Collections.singletonList( l6right ) ); + l1middle.setChildren( Collections.singletonList( l2middleRight ) ); + l1right.setChildren( Collections.singletonList( l2right ) ); + l2right.setChildren( Collections.singletonList( l3right ) ); + l3right.setChildren( Collections.singletonList( l4right ) ); + l4right.setChildren( Collections.singletonList( l5right ) ); + l5right.setChildren( Collections.singletonList( l6right ) ); + + String actual = serializer.serialize( root ); + String expected = root.hashCode() + " org.example:root:jar:3.1.1" + "\n" + + l1left.hashCode() + " org.duplicate:duplicate:xml:2:compile" + "\n" + + l2left.hashCode() + " (org.duplicate:duplicate:xml:2:compile - omitted for duplicate)" + + "\n" + l2middleLeft.hashCode() + + " (org.cycle:cycle:zip:3:compile - omitted for cycle)" + "\n" + + l1middle.hashCode() + " org.apache:maven:jar:1.0-SNAPSHOT:test" + "\n" + + l2middleRight.hashCode() + + " (org.apache:maven-dependency:jar:1.0-SNAPSHOT:compile - omitted for conflict with test)" + + "\n" + l1right.hashCode() + " org.apache:maven-dependency:jar:1.0-SNAPSHOT:test" + + "\n" + l2right.hashCode() + + " org.scopeManaged:scope-managed:zip:2.1:compile - scope managed from runtime" + + "\n" + l3right.hashCode() + + " org.versionManaged:version-manged:pom:3.3.3:provided - version managed from 1.1.0" + + "\n" + l4right.hashCode() + + " org.scopeVersionManaged:scope-version-managed:xml:2:compile - version managed from 3.1; " + + "scope managed from runtime" + "\n" + l5right.hashCode() + + " (org.apache:maven-dependency:jar:2.1:test - omitted for conflict with 1.0-SNAPSHOT)" + + "\n" + l1Optional.hashCode() + + " (org.apache:optional:jar:1.1:test - omitted due to optional dependency)" + + "\n" + "#" + "\n" + root.hashCode() + " " + l1left.hashCode() + + " compile" + "\n" + + l1left.hashCode() + " " + l2left.hashCode() + " compile omitted for duplicate" + + "\n" + l1left.hashCode() + " " + l2middleLeft.hashCode() + + " compile omitted for cycle" + "\n" + root.hashCode() + " " + l1middle.hashCode() + + " test" + "\n" + l1middle.hashCode() + " " + l2middleRight.hashCode() + + " compile omitted for conflict with test" + "\n" + root.hashCode() + " " + + l1right.hashCode() + " test" + "\n" + l1right.hashCode() + " " + l2right.hashCode() + + " compile managed from runtime" + "\n" + l2right.hashCode() + " " + + l3right.hashCode() + " provided" + "\n" + l3right.hashCode() + " " + + l4right.hashCode() + " compile managed from runtime" + "\n" + l4right.hashCode() + + " " + l5right.hashCode() + " test omitted for conflict with 1.0-SNAPSHOT" + "\n" + + root.hashCode() + " " + l1Optional.hashCode() + " test" + "\n"; + Assert.assertEquals(expected, actual); + } + + @Test + public void testGraphmlOutput() + { + serializer = new VerboseGraphGraphmlSerializer(); + DependencyNode root = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.example", "root", "jar", "3.1.1" ), "" ) + ); + + DependencyNode l1left = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.duplicate", "duplicate", "xml", "2" ), "compile" ) + ); + DependencyNode l2left = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.duplicate", "duplicate", "xml", "2" ), "compile" ) + ); + Artifact cycleArtifact = new DefaultArtifact( "org.cycle", "cycle", "zip", "3" ); + cycleArtifact = cycleArtifact.setProperties( Collections.singletonMap( "Cycle", "true" ) ); + DependencyNode l2middleLeft = new DefaultDependencyNode( + new Dependency( cycleArtifact, "compile" ) + ); + + DependencyNode l1middle = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven", "jar", "1.0-SNAPSHOT" ), "test" ) + ); + // should have scope conflict with l1middle, check to make sure its not version + DependencyNode l2middleRight = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "1.0-SNAPSHOT" ), "compile" ) + ); + + DependencyNode l1right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "1.0-SNAPSHOT" ), "test" ) + ); + DependencyNode l5right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.apache", "maven-dependency", "jar", "2.1" ), "test" ) + ); + DependencyNode l6right = new DefaultDependencyNode( + new Dependency( new DefaultArtifact( "org.abc", "shouldn't show", "xml", "1" ), "compile" ) + ); + + Artifact scopeManaged = new DefaultArtifact( "org.scopeManaged", "scope-managed", "zip", "2.1" ); + Map artifactProperties = new HashMap<>( scopeManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_SCOPE, "runtime" ); + artifactProperties.put( MANAGED_SCOPE, "compile" ); + scopeManaged = scopeManaged.setProperties( artifactProperties ); + DependencyNode l2right = new DefaultDependencyNode( + new Dependency( scopeManaged, "scope" ) + ); + + Artifact versionManaged = new DefaultArtifact( "org.versionManaged", "version-manged", "pom", "3.3.3" ); + artifactProperties = new HashMap<>( versionManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_VERSION, "1.1.0" ); + versionManaged = versionManaged.setProperties( artifactProperties ); + DependencyNode l3right = new DefaultDependencyNode( + new Dependency( versionManaged, "provided" ) + ); + + Artifact scopeVersionManaged = new DefaultArtifact( "org.scopeVersionManaged", "scope-version-managed", + "xml", "2" ); + artifactProperties = new HashMap<>( scopeVersionManaged.getProperties() ); + artifactProperties.put( PRE_MANAGED_SCOPE, "runtime" ); + artifactProperties.put( MANAGED_SCOPE, "compile" ); + artifactProperties.put( PRE_MANAGED_VERSION, "3.1" ); + scopeVersionManaged = scopeVersionManaged.setProperties( artifactProperties ); + + DependencyNode l4right = new DefaultDependencyNode( + new Dependency( scopeVersionManaged, "runtime" ) + ); + + Dependency optionalDependency = new Dependency( + new DefaultArtifact( "org.apache", "optional", "jar", "1.1" ), "test" ); + optionalDependency = optionalDependency.setOptional( true ); + DependencyNode l1Optional = new DefaultDependencyNode( optionalDependency ); + + root.setChildren( Arrays.asList( l1left, l1middle, l1right, l1Optional ) ); + l1left.setChildren( Arrays.asList( l2left, l2middleLeft ) ); + l2left.setChildren( Collections.singletonList( l6right ) ); // l6right shouldn't show due to omitted parent node + l2middleLeft.setChildren( Collections.singletonList( l6right ) ); + l1Optional.setChildren( Collections.singletonList( l6right ) ); + l1middle.setChildren( Collections.singletonList( l2middleRight ) ); + l1right.setChildren( Collections.singletonList( l2right ) ); + l2right.setChildren( Collections.singletonList( l3right ) ); + l3right.setChildren( Collections.singletonList( l4right ) ); + l4right.setChildren( Collections.singletonList( l5right ) ); + l5right.setChildren( Collections.singletonList( l6right ) ); + + String actual = serializer.serialize( root ); + String expected = " " + "\n" + " " + "\n" + " " + "\n" + + "" + + "\n" + "" + + "" + "org.example:root:jar:3.1.1" + + "\n" + "" + + "org.duplicate:duplicate:xml:" + "2:compile" + + "\n" + + "org.apache:" + + "maven:jar:1.0-SNAPSHOT:test" + "\n" + + "org.apache:maven" + + "-dependency:jar:1.0-SNAPSHOT:test" + "\n" + + "org.apache:" + + "optional:jar:1.1:test - omitted due to optional dependency" + + "\n" + "" + + "org.duplicate:duplicate:xml:2:compile - omitted for duplicate" + + "" + "\n" + "org.cycle:cycle:zip:3:compile - omitted due to cycle" + + "" + "\n" + + "" + + "org.apache:maven-dependency:jar:1.0-SNAPSHOT:compile " + + "- omitted for conflict with test" + "\n" + + "org.scopeManaged" + + ":scope-managed:zip:2.1:compile - scope managed from runtime" + + "" + "\n" + "" + + "org.versionManaged:version-manged:pom:3.3.3:provided - version managed " + + "from 1.1.0" + "\n" + + "org.scopeVersionManaged:scope-version-managed:xml:" + + "2:compile - version managed from 3.1; scope managed from runtime" + + "" + "\n" + "org.apache:maven-dependency:jar:2.1:test - omitted for" + + " conflict with 1.0-SNAPSHOT" + "\n" + + "compile" + + "" + "\n" + "test" + + "" + "\n" + "test" + + "" + "\n" + "" + + "test omitted due to optional dependency" + + "\n" + "compile omitted " + + "for duplicate" + "\n" + + "compile omitted due to cycle" + + "" + "\n" + "compile omitted" + + " for conflict with test" + "\n" + + "" + + "compile, scope managed from runtime" + + "" + "\n" + "provided" + + "" + "\n" + "" + + "compile, scope managed from runtime" + + "" + "\n" + "test omitted " + + "for conflict with 1.0-SNAPSHOT" + "\n" + + ""; 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 deleted file mode 100644 index 37d528bf1..000000000 --- a/src/test/resources/unit/verbose-serializer-test/BasicCycle.txt +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index c1c1c1e5d..000000000 --- a/src/test/resources/unit/verbose-serializer-test/BasicTree.txt +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 87d35908b..000000000 --- a/src/test/resources/unit/verbose-serializer-test/LargeGraphWithCycles.txt +++ /dev/null @@ -1,10 +0,0 @@ -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 deleted file mode 100644 index 6480fa6e4..000000000 --- a/src/test/resources/unit/verbose-serializer-test/LargeTree.txt +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index 4c4f11ff4..000000000 --- a/src/test/resources/unit/verbose-serializer-test/OptionalDependency.txt +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 81f2977bf..000000000 --- a/src/test/resources/unit/verbose-serializer-test/ScopeConflict.txt +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index 640e3f3d2..000000000 --- a/src/test/resources/unit/verbose-serializer-test/VersionConflict.txt +++ /dev/null @@ -1,4 +0,0 @@ -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