Author: pisong Date: Mon Feb 16 08:17:03 2009 New Revision: 744852 URL: http://svn.apache.org/viewvc?rev=744852&view=rev Log: (empty)
Added: maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/ maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/AbstractSerializingVisitor.java maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/DOTDependencyNodeVisitor.java maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/GraphmlDependencyNodeVisitor.java maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/TGFDependencyNodeVisitor.java Modified: maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/TreeMojo.java maven/sandbox/branches/MDEP-145/src/test/java/org/apache/maven/plugin/dependency/TestTreeMojo.java Modified: maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/TreeMojo.java URL: http://svn.apache.org/viewvc/maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/TreeMojo.java?rev=744852&r1=744851&r2=744852&view=diff ============================================================================== --- maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/TreeMojo.java (original) +++ maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/TreeMojo.java Mon Feb 16 08:17:03 2009 @@ -22,6 +22,7 @@ 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.Iterator; @@ -42,6 +43,9 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.dependency.utils.DependencyUtil; +import org.apache.maven.plugin.dependency.treeSerializers.GraphmlDependencyNodeVisitor; +import org.apache.maven.plugin.dependency.treeSerializers.TGFDependencyNodeVisitor; +import org.apache.maven.plugin.dependency.treeSerializers.DOTDependencyNodeVisitor; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter; import org.apache.maven.shared.artifact.filter.StrictPatternIncludesArtifactFilter; @@ -142,6 +146,18 @@ * @since 2.0-alpha-5 */ private File outputFile; + + /** + * If specified, this parameter will cause the dependency tree to be written using the specified format. Currently + * supported format are text, dot, graphml and tgf. + * + * These formats can be plotted to image files. An example of how to plot a dot file using + * pygraphviz can be found <a href="http://networkx.lanl.gov/pygraphviz/tutorial.html#layout-and-drawing">here</a> + * + * @parameter expression="${outputType}" default-value="text" + * @since 2.1 + */ + private String outputType; /** * The scope to filter by when resolving the dependency tree, or <code>null</code> to include dependencies from @@ -333,7 +349,7 @@ StringWriter writer = new StringWriter(); TreeTokens treeTokens = toTreeTokens( tokens ); - DependencyNodeVisitor visitor = new SerializingDependencyNodeVisitor( writer, treeTokens ); + DependencyNodeVisitor visitor = getSerializingDependencyNodeVisitor( writer ); // TODO: remove the need for this when the serializer can calculate last nodes from visitor calls only visitor = new BuildingDependencyNodeVisitor( visitor ); @@ -355,6 +371,26 @@ return writer.toString(); } + public DependencyNodeVisitor getSerializingDependencyNodeVisitor( Writer writer ) + { + if ( "graphml".equals( outputType ) ) + { + return new GraphmlDependencyNodeVisitor( writer ); + } + else if ( "tgf".equals( outputType ) ) + { + return new TGFDependencyNodeVisitor( writer ); + } + else if ( "dot".equals( outputType ) ) + { + return new DOTDependencyNodeVisitor( writer ) ; + } + else + { + return new SerializingDependencyNodeVisitor( writer, toTreeTokens( tokens ) ); + } + } + /** * Gets the tree tokens instance for the specified name. * Added: maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/AbstractSerializingVisitor.java URL: http://svn.apache.org/viewvc/maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/AbstractSerializingVisitor.java?rev=744852&view=auto ============================================================================== --- maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/AbstractSerializingVisitor.java (added) +++ maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/AbstractSerializingVisitor.java Mon Feb 16 08:17:03 2009 @@ -0,0 +1,57 @@ +package org.apache.maven.plugin.dependency.treeSerializers ; + +/* + * 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 java.io.PrintWriter; +import java.io.Writer; + +/** + * Abstract class for visitors performing serialization. + * + * @author <a href="mailto:jerome.creig...@gmail.com">Jerome Creignou</a> + */ +public abstract class AbstractSerializingVisitor +{ + + /** + * The writer to serialize to. + */ + protected final PrintWriter writer; + + /** + * Constructor. + * <p> + * Build a new AbstractSerializingDependencyNodeVisitor with the writer to serialize to. + * </p> + * + * @param writer the writer to serialize to. + */ + public AbstractSerializingVisitor( Writer writer ) + { + if ( writer instanceof PrintWriter ) + { + this.writer = (PrintWriter) writer; + } + else + { + this.writer = new PrintWriter( writer, true ); + } + } +} Added: maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/DOTDependencyNodeVisitor.java URL: http://svn.apache.org/viewvc/maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/DOTDependencyNodeVisitor.java?rev=744852&view=auto ============================================================================== --- maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/DOTDependencyNodeVisitor.java (added) +++ maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/DOTDependencyNodeVisitor.java Mon Feb 16 08:17:03 2009 @@ -0,0 +1,91 @@ +package org.apache.maven.plugin.dependency.treeSerializers; + +/* + * 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.shared.dependency.tree.traversal.DependencyNodeVisitor; +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.project.MavenProject; + +import java.io.Writer; +import java.util.List; +import java.util.Iterator; + +/** + * A dependency node visitor that serializes visited nodes to DOT format + * http://en.wikipedia.org/wiki/DOT_language + * + * @author <a href="mailto:pi.so...@gmail.com">Pi Song</a> + * @since 2.1 + */ +public class DOTDependencyNodeVisitor extends AbstractSerializingVisitor + implements DependencyNodeVisitor { + + /** + * Constructor. + * + * @param writer the writer to write to. + */ + public DOTDependencyNodeVisitor( Writer writer) + { + super( writer ); + } + + + /** + * {...@inheritdoc} + */ + public boolean visit( DependencyNode node ) + { + if ( node.getParent() == null || node.getParent() == node ) + { + writer.write( "digraph \"" + node.toNodeString() + "\" { \n" ); + } + + // Generate "currentNode -> Child" lines + + List children = node.getChildren() ; + + for ( Iterator it = children.iterator () ; it.hasNext (); ) + { + StringBuffer sb = new StringBuffer() ; + sb.append( "\t\"" ) ; + sb.append(node.toNodeString()) ; + sb.append( "\" -> \"" ) ; + sb.append( ((DependencyNode)it.next()).toNodeString() ) ; + sb.append( "\" ; " ) ; + writer.println( sb.toString() ) ; + } + + return true; + } + + /** + * {...@inheritdoc} + */ + public boolean endVisit( DependencyNode node ) + { + if ( node.getParent() == null || node.getParent() == node ) + { + writer.write( " } " ); + } + return true; + } + +} Added: maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/GraphmlDependencyNodeVisitor.java URL: http://svn.apache.org/viewvc/maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/GraphmlDependencyNodeVisitor.java?rev=744852&view=auto ============================================================================== --- maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/GraphmlDependencyNodeVisitor.java (added) +++ maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/GraphmlDependencyNodeVisitor.java Mon Feb 16 08:17:03 2009 @@ -0,0 +1,122 @@ +package org.apache.maven.plugin.dependency.treeSerializers ; + +/* + * 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 java.io.Writer; + +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor; +import org.apache.maven.shared.dependency.tree.traversal.SerializingDependencyNodeVisitor; + +/** + * A dependency node visitor that serializes visited nodes to a writer using the graphml format. + * {...@link http://graphml.graphdrawing.org/} + * + * @author <a href="mailto:jerome.creig...@gmail.com">Jerome Creignou</a> + * @since 2.1 + */ +public class GraphmlDependencyNodeVisitor extends AbstractSerializingVisitor + implements DependencyNodeVisitor +{ + + /** + * Graphml xml file header. Define Schema and root element. We also define 2 key as meta data. + */ + private static final String GRAPHML_HEADER = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?> " + "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" " + + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + + "xmlns:y=\"http://www.yworks.com/xml/graphml\" " + + "xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns " + + "http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n" + + " <key for=\"node\" id=\"d0\" yfiles.type=\"nodegraphics\"/> \n" + + " <key for=\"edge\" id=\"d1\" yfiles.type=\"edgegraphics\"/> \n" + + "<graph id=\"dependencies\" edgedefault=\"directed\">\n"; + + /** + * Graphml xml file footer. + */ + private static final String GRAPHML_FOOTER = "</graph></graphml>"; + + /** + * Constructor. + * + * @param writer the writer to write to. + */ + public GraphmlDependencyNodeVisitor( Writer writer ) + { + super( writer ); + } + + /** + * {...@inheritdoc} + */ + public boolean endVisit( DependencyNode node ) + { + if ( node.getParent() == null || node.getParent() == node ) + { + writer.write( GRAPHML_FOOTER ); + } + else + { + DependencyNode p = node.getParent(); + writer.print( "<edge source=\"" + generateId( p ) + "\" target=\"" + generateId( node ) + "\">" ); + if ( node.getArtifact().getScope() != null ) + { + // add Edge label + writer.print( "<data key=\"d1\"><y:PolyLineEdge><y:EdgeLabel>" + node.getArtifact().getScope() + + "</y:EdgeLabel></y:PolyLineEdge></data>" ); + } + writer.println( "</edge>" ); + } + return true; + } + + /** + * {...@inheritdoc} + */ + public boolean visit( DependencyNode node ) + { + if ( node.getParent() == null || node.getParent() == node ) + { + writer.write( GRAPHML_HEADER ); + } + // write node + writer.print( "<node id=\"" + generateId( node ) + "\">" ); + // add node label + writer.print( "<data key=\"d0\"><y:ShapeNode><y:NodeLabel>" + node.toNodeString() + + "</y:NodeLabel></y:ShapeNode></data>" ); + writer.println( "</node>" ); + return true; + } + + /** + * Generate a unique id from a DependencyNode. + * <p> + * Current implementation is rather simple and uses hashcode. + * </p> + * + * @param node the DependencyNode to use. + * @return the unique id. + */ + private static String generateId( DependencyNode node ) + { + return String.valueOf( node.hashCode() ); + } +} Added: maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/TGFDependencyNodeVisitor.java URL: http://svn.apache.org/viewvc/maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/TGFDependencyNodeVisitor.java?rev=744852&view=auto ============================================================================== --- maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/TGFDependencyNodeVisitor.java (added) +++ maven/sandbox/branches/MDEP-145/src/main/java/org/apache/maven/plugin/dependency/treeSerializers/TGFDependencyNodeVisitor.java Mon Feb 16 08:17:03 2009 @@ -0,0 +1,158 @@ +package org.apache.maven.plugin.dependency.treeSerializers ; + +/* + * 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 java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor; + +/** + * A dependency node visitor that serializes visited nodes to a writer using the TGF format. + * + * http://en.wikipedia.org/wiki/Trivial_Graph_Format + * + * @author <a href="mailto:jerome.creig...@gmail.com">Jerome Creignou</a> + * @since 2.1 + */ +public class TGFDependencyNodeVisitor extends AbstractSerializingVisitor + implements DependencyNodeVisitor +{ + + /** + * Utiity class to write an Edge. + * + * @author <a href="mailto:jerome.creig...@gmail.com">Jerome Creignou</a> + */ + final static class EdgeAppender + { + /** + * Edge start. + */ + private DependencyNode from; + + /** + * Edge end. + */ + private DependencyNode to; + + /** + * Edge label. (optional) + */ + private String label; + + /** + * Build a new EdgeAppender. + * + * @param from edge start. + * @param to edge end + * @param label optional label. + */ + public EdgeAppender( DependencyNode from, DependencyNode to, String label ) + { + super(); + this.from = from; + this.to = to; + this.label = label; + } + + /** + * build a string representing the edge. + */ + public String toString() + { + StringBuffer result = new StringBuffer( generateId( from ) ); + result.append( ' ' ).append( generateId( to ) ); + if ( label != null ) + { + result.append( ' ' ).append( label ); + } + return result.toString(); + } + + } + + /** + * List of edges. + */ + private List edges = new ArrayList(); + + /** + * Constructor. + * + * @param writer the writer to write to. + */ + public TGFDependencyNodeVisitor( Writer writer ) + { + super( writer ); + } + + /** + * {...@inheritdoc} + */ + public boolean endVisit( DependencyNode node ) + { + if ( node.getParent() == null || node.getParent() == node ) + { + // dump edges on last node endVisit + writer.println( "#" ); + for ( Iterator iterator = edges.iterator(); iterator.hasNext(); ) + { + writer.println( iterator.next().toString() ); + } + } + else + { + DependencyNode p = node.getParent(); + // using scope as edge label. + edges.add( new EdgeAppender( p, node, node.getArtifact().getScope() ) ); + } + return true; + } + + /** + * {...@inheritdoc} + */ + public boolean visit( DependencyNode node ) + { + // write node + writer.write( generateId( node ) ); + writer.write( " " ); + writer.println( node.toNodeString() ); + return true; + } + + /** + * Generate a unique id from a DependencyNode. + * <p> + * Current implementation is rather simple and uses hashcode. + * </p> + * + * @param node the DependencyNode to use. + * @return the unique id. + */ + private static String generateId( DependencyNode node ) + { + return String.valueOf( node.hashCode() ); + } +} Modified: maven/sandbox/branches/MDEP-145/src/test/java/org/apache/maven/plugin/dependency/TestTreeMojo.java URL: http://svn.apache.org/viewvc/maven/sandbox/branches/MDEP-145/src/test/java/org/apache/maven/plugin/dependency/TestTreeMojo.java?rev=744852&r1=744851&r2=744852&view=diff ============================================================================== --- maven/sandbox/branches/MDEP-145/src/test/java/org/apache/maven/plugin/dependency/TestTreeMojo.java (original) +++ maven/sandbox/branches/MDEP-145/src/test/java/org/apache/maven/plugin/dependency/TestTreeMojo.java Mon Feb 16 08:17:03 2009 @@ -20,7 +20,12 @@ */ import java.io.File; +import java.io.BufferedReader; +import java.io.FileReader; import java.util.Set; +import java.util.List; +import java.util.ArrayList; +import java.util.Iterator; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.testing.stubs.StubArtifactRepository; @@ -83,6 +88,116 @@ assertChildNodeEquals( "testGroupId:snapshot:jar:2.0-SNAPSHOT:compile", rootNode, 0 ); assertChildNodeEquals( "testGroupId:release:jar:1.0:compile", rootNode, 1 ); } + + /** + * Test the DOT format serialization + * + * @throws Exception + */ + public void testTreeDotSerializing() + throws Exception + { + List contents = runTreeMojo("tree1.dot", "dot") ; + assertTrue(findString(contents, "digraph \"testGroupId:project:jar:1.0:compile\" {")); + assertTrue(findString(contents, "\"testGroupId:project:jar:1.0:compile\" -> \"testGroupId:snapshot:jar:2.0-SNAPSHOT:compile\"")); + assertTrue(findString(contents, "\"testGroupId:project:jar:1.0:compile\" -> \"testGroupId:release:jar:1.0:compile\"")); + } + + /** + * Test the GraphML format serialization + * + * @throws Exception + */ + public void testTreeGraphMLSerializing() + throws Exception + { + List contents = runTreeMojo("tree1.graphml", "graphml") ; + + assertTrue(findString(contents, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")); + assertTrue(findString(contents, "<y:NodeLabel>testGroupId:project:jar:1.0:compile</y:NodeLabel>")); + assertTrue(findString(contents, "<y:NodeLabel>testGroupId:snapshot:jar:2.0-SNAPSHOT:compile</y:NodeLabel>")); + assertTrue(findString(contents, "<y:NodeLabel>testGroupId:release:jar:1.0:compile</y:NodeLabel>")); + assertTrue(findString(contents, "<key for=\"node\" id=\"d0\" yfiles.type=\"nodegraphics\"/>")); + assertTrue(findString(contents, "<key for=\"edge\" id=\"d1\" yfiles.type=\"edgegraphics\"/>")); + } + + /** + * Test the TGF format serialization + * + * @throws Exception + */ + public void testTreeTGFSerializing() + throws Exception + { + List contents = runTreeMojo("tree1.tgf", "tgf") ; + assertTrue(findString(contents, "testGroupId:project:jar:1.0:compile")); + assertTrue(findString(contents, "testGroupId:snapshot:jar:2.0-SNAPSHOT:compile")); + assertTrue(findString(contents, "testGroupId:release:jar:1.0:compile")); + } + + /** + * Help finding content in the given list of string + * @param outputFile + * @param format + * @return list of strings in the output file + */ + private List runTreeMojo(String outputFile, String format) + throws Exception + { + File testPom = new File( getBasedir(), "target/test-classes/unit/tree-test/plugin-config.xml" ); + String outputFileName = testDir.getAbsolutePath() + outputFile ; + TreeMojo mojo = (TreeMojo) lookupMojo( "tree", testPom ); + setVariableValueToObject( mojo, "localRepository", new StubArtifactRepository( testDir.getAbsolutePath() ) ); + setVariableValueToObject( mojo, "outputType", format ); + setVariableValueToObject( mojo, "outputFile", new File( outputFileName) ); + + assertNotNull( mojo ); + assertNotNull( mojo.getProject() ); + MavenProject project = mojo.getProject(); + project.setArtifact( this.stubFactory.createArtifact( "testGroupId", "project", "1.0" ) ); + + Set artifacts = this.stubFactory.getScopedArtifacts(); + Set directArtifacts = this.stubFactory.getReleaseAndSnapshotArtifacts(); + artifacts.addAll( directArtifacts ); + + project.setArtifacts( artifacts ); + project.setDependencyArtifacts( directArtifacts ); + + mojo.execute(); + + BufferedReader fp1 = new BufferedReader(new FileReader(outputFileName)); + List contents = new ArrayList() ; + + String line = null; + while ((line = fp1.readLine()) != null) + { + contents.add(line); + } + fp1.close(); + + return contents ; + } + + /** + * Help finding content in the given list of string + * @param contents + * @param str + */ + private boolean findString(List contents, String str) + { + for ( Iterator it = contents.iterator () ; it.hasNext (); ) + { + String line = (String) it.next() ; + if ( line.indexOf(str) != -1 ) + { + // if match then return here + return true ; + } + } + + // in case no match for the whole list + return false ; + } // private methods --------------------------------------------------------