1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.nuxeo.build.maven.graph;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.io.UnsupportedEncodingException;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.tools.ant.BuildException;
31 import org.apache.tools.ant.Project;
32 import org.eclipse.aether.artifact.Artifact;
33 import org.eclipse.aether.graph.DefaultDependencyNode;
34 import org.eclipse.aether.graph.Dependency;
35 import org.eclipse.aether.graph.DependencyNode;
36 import org.eclipse.aether.resolution.ArtifactDescriptorException;
37 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
38 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
39 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
40 import org.eclipse.aether.util.artifact.JavaScopes;
41 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
42 import org.eclipse.aether.util.graph.transformer.ConflictResolver;
43 import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator;
44 import org.nuxeo.build.ant.AntClient;
45 import org.nuxeo.build.ant.artifact.PrintGraphTask;
46 import org.nuxeo.build.maven.AntBuildMojo;
47
48
49
50
51
52
53
54 public class TreePrinterDependencyVisitor extends AbstractDependencyVisitor {
55
56
57
58
59 public static final String TAB_STR = " |-- ";
60
61 protected String tabs = "";
62
63 protected int format;
64
65 protected OutputStream output;
66
67 protected Map<String, DependencyNode> dependencyMap = new HashMap<>();
68
69 protected Map<String, List<Dependency>> directDepsByArtifact = new HashMap<>();
70
71
72
73
74
75
76
77 public TreePrinterDependencyVisitor(OutputStream output, int format,
78 List<String> scopes, List<Node> roots) {
79 super(scopes);
80 this.output = output;
81 this.format = format;
82 PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
83 for (Node node : roots) {
84 node.accept(nlg);
85 }
86 for (DependencyNode node : nlg.getNodes()) {
87 dependencyMap.put(node.getArtifact().toString(), node);
88 }
89 }
90
91 @Override
92 protected void doVisit(DependencyNode node, boolean newNode) {
93 try {
94 print(node);
95 if (newNode) {
96 addMissingChildren(node);
97 }
98 incTabs();
99 } catch (IOException e) {
100 throw new BuildException(e);
101 }
102 }
103
104
105
106
107
108 protected void addMissingChildren(DependencyNode node) {
109 AntBuildMojo mojo = AntBuildMojo.getInstance();
110 incTabs();
111 try {
112 List<Dependency> directDeps = directDepsByArtifact.get(node.getArtifact().toString());
113 if (directDeps == null) {
114 ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest(
115 node.getArtifact(), mojo.getRemoteRepositories(), null);
116 ArtifactDescriptorResult descriptorResult = mojo.getSystem().readArtifactDescriptor(
117 mojo.getSession(), descriptorRequest);
118 directDeps = descriptorResult.getDependencies();
119 }
120 for (Dependency dependency : directDeps) {
121 boolean removed = true;
122 if (JavaScopes.TEST.equals(dependency.getScope())
123 && !JavaScopes.TEST.equals(node.getDependency().getScope())) {
124 continue;
125 }
126 for (DependencyNode childNode : node.getChildren()) {
127 if (childNode.getArtifact().toString().equals(
128 dependency.getArtifact().toString())) {
129 removed = false;
130 }
131 }
132 if (removed) {
133 DependencyNode childNode = dependencyMap.get(dependency.getArtifact().toString());
134 if (childNode == null) {
135 AntClient.getInstance().log(
136 "Ignored dependency " + dependency
137 + " not in graph", Project.MSG_DEBUG);
138
139 continue;
140 } else {
141 int managedBits = 0;
142 childNode = new DefaultDependencyNode(childNode);
143 childNode.setScope(childNode.getDependency().getScope());
144 String managedScope = dependency.getScope();
145 String scope = childNode.getDependency().getScope();
146 if (!managedScope.equals(scope)) {
147 managedBits |= DependencyNode.MANAGED_SCOPE;
148 childNode.setData(
149 DependencyManagerUtils.NODE_DATA_PREMANAGED_SCOPE,
150 managedScope);
151 }
152 String managedVersion = dependency.getArtifact().getBaseVersion();
153 String version = childNode.getArtifact().getBaseVersion();
154 if (!managedVersion.equals(version)) {
155 managedBits |= DependencyNode.MANAGED_VERSION;
156 childNode.setData(
157 DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION,
158 managedVersion);
159 }
160 ((DefaultDependencyNode) childNode).setManagedBits(managedBits);
161 }
162 childNode.setChildren(Collections.<DependencyNode> emptyList());
163 if (node.getChildren().isEmpty()) {
164 node.setChildren(new ArrayList<DependencyNode>());
165 }
166 node.getChildren().add(childNode);
167
168
169 setVisited(childNode);
170 }
171 }
172 } catch (ArtifactDescriptorException e) {
173 AntClient.getInstance().log(e.getMessage(), e, Project.MSG_ERR);
174 } finally {
175 decTabs();
176 }
177 }
178
179 protected void incTabs() {
180 tabs += TAB_STR;
181 }
182
183 @Override
184 public boolean visitLeave(DependencyNode node) {
185 boolean visit = super.visitLeave(node);
186 if (!ignores.contains(node)) {
187 decTabs();
188 }
189 return visit;
190 }
191
192 protected void decTabs() {
193 tabs = tabs.substring(0, tabs.length() - TAB_STR.length());
194 }
195
196 protected void print(DependencyNode node)
197 throws UnsupportedEncodingException, IOException {
198 String toString = tabs + toString(node)
199 + System.getProperty("line.separator");
200 output.write(toString.getBytes(AntBuildMojo.getInstance().getEncoding()));
201 }
202
203
204
205
206
207
208 public String toString(DependencyNode node) {
209 Artifact artifact = node.getArtifact();
210 Dependency dependency = node.getDependency();
211 StringBuilder sb = new StringBuilder();
212 switch (format) {
213 case 1:
214 sb.append(artifact.getFile().getName());
215 sb.append('=');
216
217 case 0:
218 sb.append(artifact.getGroupId());
219 sb.append(':').append(artifact.getArtifactId());
220 sb.append(':').append(artifact.getVersion());
221 sb.append(':').append(artifact.getExtension());
222 sb.append(':').append(artifact.getClassifier());
223 sb.append(':').append(dependency.getScope());
224 break;
225 default:
226 return "Unknown format: " + format + "!";
227 }
228 if (node.getDependency().isOptional()) {
229 sb.append(" [optional]");
230 }
231 String premanaged = DependencyManagerUtils.getPremanagedVersion(node);
232 if (premanaged != null && !premanaged.equals(artifact.getBaseVersion())) {
233 sb.append(" (version managed from ").append(premanaged).append(")");
234 }
235 premanaged = DependencyManagerUtils.getPremanagedScope(node);
236 if (premanaged != null && !premanaged.equals(dependency.getScope())) {
237 sb.append(" (scope managed from ").append(premanaged).append(")");
238 }
239 DependencyNode winner = (DependencyNode) node.getData().get(
240 ConflictResolver.NODE_DATA_WINNER);
241 if (winner != null
242 && !ArtifactIdUtils.equalsId(artifact, winner.getArtifact())) {
243 Artifact w = winner.getArtifact();
244 sb.append(" (superseded by ");
245 if (ArtifactIdUtils.toVersionlessId(artifact).equals(
246 ArtifactIdUtils.toVersionlessId(w))) {
247 sb.append(w.getVersion());
248 } else {
249 sb.append(w);
250 }
251 sb.append(")");
252 }
253 return sb.toString();
254 }
255
256 }