]> source.dussan.org Git - archiva.git/blob
3e7d29e1058149f1faeba4a373ccfbedbff5febf
[archiva.git] /
1 package org.apache.maven.archiva.dependency.graph;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import junit.framework.Assert;
23 import org.apache.commons.collections.CollectionUtils;
24 import org.apache.commons.lang.StringEscapeUtils;
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.maven.archiva.dependency.DependencyGraphFactory;
27 import org.apache.maven.archiva.model.DependencyScope;
28 import org.apache.maven.archiva.model.VersionedReference;
29
30 import java.io.File;
31 import java.io.FileWriter;
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.util.Iterator;
35 import java.util.List;
36
37 /**
38  * GraphvizDotTool - testing utility to help understand the graph. 
39  *
40  * @version $Id$
41  */
42 public class GraphvizDotTool
43     implements GraphListener
44 {
45     private int phaseNumber = 0;
46
47     protected VersionedReference toVersionedReference( String key )
48     {
49         String parts[] = StringUtils.splitPreserveAllTokens( key, ':' );
50         Assert.assertEquals( "Versioned Reference [" + key + "] part count.", 3, parts.length );
51
52         VersionedReference ref = new VersionedReference();
53         ref.setGroupId( parts[0] );
54         ref.setArtifactId( parts[1] );
55         ref.setVersion( parts[2] );
56         return ref;
57     }
58
59     private DependencyGraph getDependencyGraph( MemoryRepository repository, String rootRefKey )
60         throws GraphTaskException
61     {
62         MemoryRepositoryDependencyGraphBuilder graphBuilder = new MemoryRepositoryDependencyGraphBuilder();
63         graphBuilder.setMemoryRepository( repository );
64
65         // Create the factory, and add the test resolver.
66         DependencyGraphFactory factory = new DependencyGraphFactory();
67         factory.setGraphBuilder( graphBuilder );
68         factory.setDesiredScope( DependencyScope.TEST );
69         factory.addGraphListener( this );
70
71         // Get the model to resolve from
72         VersionedReference rootRef = toVersionedReference( rootRefKey );
73
74         // Perform the resolution.
75         phaseNumber = 0;
76         DependencyGraph graph = factory.getGraph( rootRef );
77
78         // Test the results.
79         Assert.assertNotNull( "Graph shouldn't be null.", graph );
80
81         return graph;
82     }
83
84     public void testGenerateDots()
85         throws GraphTaskException
86     {
87         getDependencyGraph( new ArchivaWebappMemoryRepository(),
88                             "org.apache.maven.archiva:archiva-webapp:1.0-alpha-2-SNAPSHOT" );
89
90         //        getDependencyGraph( new ArchivaCommonMemoryRepository(),
91         //                            "org.apache.maven.archiva:archiva-common:1.0-alpha-2-SNAPSHOT" );
92         //
93         //        getDependencyGraph( new ArchivaXmlToolsMemoryRepository(),
94         //                            "org.apache.maven.archiva:archiva-xml-tools:1.0-alpha-2-SNAPSHOT" );
95         //
96         //        getDependencyGraph( new ContinuumStoreMemoryRepository(),
97         //                            "org.apache.maven.continuum:continuum-store:1.1-SNAPSHOT" );
98         //
99         //        getDependencyGraph( new MavenProjectInfoReportsPluginMemoryRepository(),
100         //                            "org.apache.maven.plugins:maven-project-info-reports-plugin:2.1-SNAPSHOT" );
101         //
102         //        getDependencyGraph( new WagonManagerMemoryRepository(), "org.apache.maven.wagon:wagon-manager:2.0-SNAPSHOT" );
103
104         getDependencyGraph( new DepManDeepVersionMemoryRepository(), "net.example.depman.deepversion:A:1.0" );
105     }
106
107     public void dependencyResolutionEvent( DependencyResolutionEvent event )
108     {
109         /* do nothing */
110     }
111
112     public void graphError( GraphTaskException e, DependencyGraph currentGraph )
113     {
114         /* do nothing */
115     }
116
117     public void graphPhaseEvent( GraphPhaseEvent event )
118     {
119         String graphId = event.getGraph().getRootNode().getArtifact().getArtifactId();
120         String title = "Graph: " + graphId;
121
122         switch ( event.getType() )
123         {
124             case GraphPhaseEvent.GRAPH_TASK_POST:
125                 phaseNumber++;
126                 title += " - Phase: " + phaseNumber + " - Task: " + event.getTask().getTaskId();
127                 writeDot( "target/graph_" + graphId + "_" + phaseNumber + "_" + event.getTask().getTaskId() + ".dot",
128                           event.getGraph(), title );
129                 break;
130             case GraphPhaseEvent.GRAPH_DONE:
131                 title += " FINISHED";
132                 writeDot( "target/graph_" + graphId + ".dot", event.getGraph(), title );
133                 break;
134         }
135     }
136
137     private void writeDot( String outputFilename, DependencyGraph graph, String title )
138     {
139         System.out.println( "Writing Graphviz output: " + outputFilename );
140         try
141         {
142             File outputFile = new File( outputFilename );
143             FileWriter writer = new FileWriter( outputFile );
144             PrintWriter dot = new PrintWriter( writer );
145
146             dot.println( "// Auto generated dot file from plexus-graph-visualizer-graphviz." );
147
148             dot.println( "digraph example {" );
149
150             dot.println( "" );
151
152             dot.println( "  // Graph Defaults" );
153             dot.println( "  graph [" );
154             dot.println( "    bgcolor=\"#ffffff\"," );
155             dot.println( "    fontname=\"Helvetica\"," );
156             dot.println( "    fontsize=\"11\"," );
157             dot.println( "    label=\"" + title + "\"," );
158             dot.println( "    labeljust=\"l\"" );
159             dot.println( "    rankdir=\"LR\"" );
160             dot.println( "  ];" );
161
162             // Node Defaults.
163
164             dot.println( "" );
165             dot.println( "  // Node Defaults." );
166             dot.println( "  node [" );
167             dot.println( "    fontname=\"Helvetica\"," );
168             dot.println( "    fontsize=\"11\"," );
169             dot.println( "    shape=\"box\"" );
170             dot.println( "  ];" );
171
172             // Edge Defaults.
173
174             dot.println( "" );
175             dot.println( "  // Edge Defaults." );
176             dot.println( "  edge [" );
177             dot.println( "    arrowsize=\"0.8\"" );
178             dot.println( "    fontsize=\"11\"," );
179             dot.println( "  ];" );
180
181             Iterator it;
182
183             it = graph.getNodes().iterator();
184             while ( it.hasNext() )
185             {
186                 DependencyGraphNode node = (DependencyGraphNode) it.next();
187
188                 writeNode( dot, graph, node );
189             }
190
191             it = graph.getEdges().iterator();
192             while ( it.hasNext() )
193             {
194                 DependencyGraphEdge edge = (DependencyGraphEdge) it.next();
195
196                 DependencyGraphNode from = graph.getNode( edge.getNodeFrom() );
197                 DependencyGraphNode to = graph.getNode( edge.getNodeTo() );
198
199                 writeEdge( dot, edge, from, to );
200             }
201
202             dot.println( "}" );
203             dot.flush();
204             dot.close();
205         }
206         catch ( IOException e )
207         {
208             System.err.println( "Unable to write GraphViz file " + outputFilename + " : " + e.getMessage() );
209             e.printStackTrace( System.err );
210         }
211     }
212
213     private String toLabel( DependencyGraphNode node )
214     {
215         StringBuffer lbl = new StringBuffer();
216
217         lbl.append( node.getArtifact().getGroupId() ).append( "\n" );
218         lbl.append( node.getArtifact().getArtifactId() ).append( "\n" );
219         lbl.append( node.getArtifact().getVersion() );
220
221         return StringEscapeUtils.escapeJava( lbl.toString() );
222     }
223
224     private String toId( DependencyGraphNode node )
225     {
226         StringBuffer id = new StringBuffer();
227
228         String raw = DependencyGraphKeys.toKey( node.getArtifact() );
229
230         for ( int i = 0; i < raw.length(); i++ )
231         {
232             char c = raw.charAt( i );
233             if ( Character.isLetterOrDigit( c ) )
234             {
235                 id.append( Character.toUpperCase( c ) );
236             }
237             else if ( ( c == '-' ) || ( c == '_' ) )
238             {
239                 id.append( "_" );
240             }
241         }
242
243         return id.toString();
244     }
245
246     private void writeNode( PrintWriter dot, DependencyGraph graph, DependencyGraphNode node )
247     {
248         dot.println( "" );
249         dot.println( "  // Node" );
250         dot.println( "  \"" + toId( node ) + "\" [" );
251         dot.println( "    label=\"" + toLabel( node ) + "\"," );
252
253         List edgesTo = graph.getEdgesTo( node );
254         boolean orphan = CollectionUtils.isEmpty( edgesTo );
255
256         if ( node.isFromParent() )
257         {
258             dot.println( "    color=\"#FF0000\"," );
259             dot.println( "    shape=ellipse," );
260         }
261         else
262         {
263             dot.println( "    shape=box," );
264         }
265
266         if ( node.isConflicted() )
267         {
268             // dot.println( "    fontcolor=\"#FF88FF\"," );
269             dot.println( "    style=filled," );
270             dot.println( "    fillcolor=\"#88FF88\"," );
271         }
272         else if ( orphan )
273         {
274             dot.println( "    style=filled," );
275             dot.println( "    fillcolor=\"#8888FF\"," );
276         }
277
278         dot.println( "  ];" );
279     }
280
281     private void writeEdge( PrintWriter dot, DependencyGraphEdge edge, DependencyGraphNode from, DependencyGraphNode to )
282     {
283         dot.println( "" );
284         dot.println( "  // Edge" );
285
286         dot.println( "  \"" + toId( from ) + "\" -> \"" + toId( to ) + "\" [" );
287
288         if ( edge.isDisabled() )
289         {
290             switch ( edge.getDisabledType() )
291             {
292                 case DependencyGraph.DISABLED_CYCLIC:
293                     dot.println( "    color=\"#FF0000\"," );
294                     break;
295                 case DependencyGraph.DISABLED_OPTIONAL:
296                     dot.println( "    color=\"#FF00FF\"," );
297                     break;
298                 case DependencyGraph.DISABLED_NEARER_DEP:
299                     dot.println( "    color=\"#00FF00\"," );
300                     break;
301                 case DependencyGraph.DISABLED_NEARER_EDGE:
302                     dot.println( "    color=\"#88FF88\"," );
303                     break;
304                 default:
305                 case DependencyGraph.DISABLED_EXCLUDED:
306                     dot.println( "    color=\"#0000FF\"," );
307                     break;
308             }
309
310             dot.println( "    label=\"" + edge.getDisabledReason() + "\"," );
311             dot.println( "    fontsize=\"8\"," );
312         }
313         else if ( DependencyScope.TEST.equals( edge.getScope() ) )
314         {
315             dot.println( "    style=\"dashed\"," );
316             dot.println( "    color=\"#DDDDDD\"," );
317         }
318         else if ( DependencyScope.RUNTIME.equals( edge.getScope() ) )
319         {
320             dot.println( "    style=\"dashed\"," );
321             dot.println( "    color=\"#DDFFDD\"," );
322             dot.println( "    label=\"runtime\"," );
323             dot.println( "    fontsize=\"8\"," );
324         }
325         else if ( DependencyScope.PROVIDED.equals( edge.getScope() ) )
326         {
327             dot.println( "    style=\"dashed\"," );
328             dot.println( "    color=\"#DDDDFF\"," );
329             dot.println( "    label=\"provided\"," );
330             dot.println( "    fontsize=\"8\"," );
331         }
332         else if ( DependencyScope.SYSTEM.equals( edge.getScope() ) )
333         {
334             dot.println( "    style=\"dashed\"," );
335             dot.println( "    color=\"#FFDDDD\"," );
336             dot.println( "    label=\"system\"," );
337             dot.println( "    fontsize=\"8\"," );
338         }
339
340         dot.println( "    arrowtail=none," );
341         dot.println( "    arrowhead=normal" );
342
343         dot.println( "  ];" );
344     }
345
346 }