001package org.apache.maven.resolver.examples.util; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.PrintStream; 023import java.util.ArrayList; 024import java.util.Iterator; 025import java.util.List; 026 027import org.eclipse.aether.artifact.Artifact; 028import org.eclipse.aether.graph.Dependency; 029import org.eclipse.aether.graph.DependencyNode; 030import org.eclipse.aether.graph.DependencyVisitor; 031import org.eclipse.aether.util.artifact.ArtifactIdUtils; 032import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; 033import org.eclipse.aether.util.graph.transformer.ConflictResolver; 034 035/** 036 * A dependency visitor that dumps the graph to the console. 037 */ 038public class ConsoleDependencyGraphDumper 039 implements DependencyVisitor 040{ 041 042 private final PrintStream out; 043 044 private final List<ChildInfo> childInfos = new ArrayList<>(); 045 046 public ConsoleDependencyGraphDumper() 047 { 048 this( null ); 049 } 050 051 public ConsoleDependencyGraphDumper( PrintStream out ) 052 { 053 this.out = ( out != null ) ? out : System.out; 054 } 055 056 public boolean visitEnter( DependencyNode node ) 057 { 058 out.println( formatIndentation() + formatNode( node ) ); 059 childInfos.add( new ChildInfo( node.getChildren().size() ) ); 060 return true; 061 } 062 063 private String formatIndentation() 064 { 065 StringBuilder buffer = new StringBuilder( 128 ); 066 for ( Iterator<ChildInfo> it = childInfos.iterator(); it.hasNext(); ) 067 { 068 buffer.append( it.next().formatIndentation( !it.hasNext() ) ); 069 } 070 return buffer.toString(); 071 } 072 073 private String formatNode( DependencyNode node ) 074 { 075 StringBuilder buffer = new StringBuilder( 128 ); 076 Artifact a = node.getArtifact(); 077 Dependency d = node.getDependency(); 078 buffer.append( a ); 079 if ( d != null && d.getScope().length() > 0 ) 080 { 081 buffer.append( " [" ).append( d.getScope() ); 082 if ( d.isOptional() ) 083 { 084 buffer.append( ", optional" ); 085 } 086 buffer.append( "]" ); 087 } 088 String premanaged = DependencyManagerUtils.getPremanagedVersion( node ); 089 if ( premanaged != null && !premanaged.equals( a.getBaseVersion() ) ) 090 { 091 buffer.append( " (version managed from " ).append( premanaged ).append( ")" ); 092 } 093 094 premanaged = DependencyManagerUtils.getPremanagedScope( node ); 095 if ( premanaged != null && !premanaged.equals( d.getScope() ) ) 096 { 097 buffer.append( " (scope managed from " ).append( premanaged ).append( ")" ); 098 } 099 DependencyNode winner = (DependencyNode) node.getData().get( ConflictResolver.NODE_DATA_WINNER ); 100 if ( winner != null && !ArtifactIdUtils.equalsId( a, winner.getArtifact() ) ) 101 { 102 Artifact w = winner.getArtifact(); 103 buffer.append( " (conflicts with " ); 104 if ( ArtifactIdUtils.toVersionlessId( a ).equals( ArtifactIdUtils.toVersionlessId( w ) ) ) 105 { 106 buffer.append( w.getVersion() ); 107 } 108 else 109 { 110 buffer.append( w ); 111 } 112 buffer.append( ")" ); 113 } 114 return buffer.toString(); 115 } 116 117 public boolean visitLeave( DependencyNode node ) 118 { 119 if ( !childInfos.isEmpty() ) 120 { 121 childInfos.remove( childInfos.size() - 1 ); 122 } 123 if ( !childInfos.isEmpty() ) 124 { 125 childInfos.get( childInfos.size() - 1 ).index++; 126 } 127 return true; 128 } 129 130 private static class ChildInfo 131 { 132 133 final int count; 134 135 int index; 136 137 ChildInfo( int count ) 138 { 139 this.count = count; 140 } 141 142 public String formatIndentation( boolean end ) 143 { 144 boolean last = index + 1 >= count; 145 if ( end ) 146 { 147 return last ? "\\- " : "+- "; 148 } 149 return last ? " " : "| "; 150 } 151 152 } 153 154}