001    /**************************************************************************************
002     * Copyright (C) 2009 Progress Software, Inc. All rights reserved.                    *
003     * http://fusesource.com                                                              *
004     * ---------------------------------------------------------------------------------- *
005     * The software in this package is published under the terms of the AGPL license      *
006     * a copy of which has been included with this distribution in the license.txt file.  *
007     **************************************************************************************/
008    package org.fusesource.mvnplugins.graph;
009    
010    import org.apache.maven.project.MavenProject;
011    import org.apache.maven.plugin.MojoExecutionException;
012    import org.apache.maven.plugin.AbstractMojo;
013    import org.apache.maven.artifact.repository.ArtifactRepository;
014    import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
015    import org.apache.maven.artifact.resolver.ArtifactCollector;
016    import org.apache.maven.artifact.resolver.ArtifactResolver;
017    import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
018    import org.apache.maven.artifact.factory.ArtifactFactory;
019    import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
020    import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
021    import org.apache.maven.shared.dependency.tree.DependencyNode;
022    
023    import java.util.ArrayList;
024    import java.io.File;
025    
026    /**
027     * Generates a graph image of the dependencies of the project using the graphviz
028     * tool 'dot'.  You must have the 'dot' executable installed and in your path
029     * before using this goal.
030     * <p/>
031     *
032     * @author chirino
033     * @goal project
034     * @requiresDependencyResolution compile|test|runtime
035     */
036    public class ProjectMojo extends AbstractMojo {
037    
038        /**
039         * @required
040         * @readonly
041         * @parameter expression="${project}"
042         * @since 1.0
043         */
044        private MavenProject project;
045    
046        /**
047         * @required
048         * @readonly
049         * @parameter expression="${localRepository}"
050         * @since 1.0
051         */
052        private ArtifactRepository localRepository;
053    
054        /**
055         * @required
056         * @component
057         * @since 1.0
058         */
059        private ArtifactResolver artifactResolver;
060    
061        /**
062         * @required
063         * @readonly
064         * @component
065         * @since 1.0
066         */
067        private ArtifactFactory artifactFactory;
068    
069        /**
070         * @required
071         * @readonly
072         * @component
073         * @since 1.0
074         */
075        private ArtifactMetadataSource artifactMetadataSource;
076    
077        /**
078         * @required
079         * @readonly
080         * @component
081         */
082        private ArtifactCollector artifactCollector;
083    
084        /**
085         * @required
086         * @readonly
087         * @component
088         * @since 1.0
089         */
090        private DependencyTreeBuilder treeBuilder;
091    
092        /**
093         * The file the diagram will be written to.  Must use a file extension that the dot command supports or just the
094         * '.dot' extension.
095         * <br/>
096         * @parameter default-value="${project.build.directory}/project-graph.png" expression="${graph.target}"
097         */
098        private File target;
099    
100        /**
101         * If set to true, ommitted dependencies will not be drawn.  Dependencies are marked
102         * as ommitted if it would result in a resolution conflict.
103         * <br/>
104         * @parameter default-value="true" expression="${hide-omitted}"
105         */
106        private boolean hideOmitted;
107    
108        /**
109         * If set to true optional dependencies are not drawn.
110         * <br/>
111         * @parameter default-value="false" expression="${hide-optional}"
112         */
113        private boolean hideOptional;
114    
115        /**
116         * If set to true pom dependencies are not drawn.
117         * <br/>
118         * @parameter default-value="true" expression="${hide-poms}"
119         */
120        private boolean hidePoms;
121    
122        /**
123         * A comma seperated list of scopes.  Dependencies which
124         * mach the specified scopes will not be drawn.
125         * <br/>
126         * For example: <code>runtime,test</code>
127         * <br/>
128         * @parameter expression="${hide-scope}"
129         */
130        private String hideScopes;
131    
132        /**
133         * If set to true then depdencies not explicitly defined in the projects
134         * pom will not be drawn.
135         * <br/>
136         * @parameter default-value="false" expression="${hide-transitive}"
137         */
138        private boolean hideTransitive;
139    
140        /**
141         * The label for the graph.
142         * <br/>
143         * @parameter default-value="Depedency Graph for ${project.name}" expression="${graph.label}"
144         */
145        private String label;
146    
147        public void execute() throws MojoExecutionException {
148            try {
149                DependencyVisualizer visualizer = new DependencyVisualizer();
150                visualizer.hideOptional = hideOptional;
151                visualizer.hidePoms = hidePoms;
152                visualizer.hideOmitted = hideOmitted;
153                visualizer.label = label;
154                visualizer.hideTransitive = hideTransitive;
155    
156                if (hideScopes != null) {
157                    for (String scope : hideScopes.split(",")) {
158                        visualizer.hideScopes.add(scope);
159                    }
160                }
161    
162                ArrayList<MavenProject> projects = new ArrayList<MavenProject>();
163                collectProjects(projects);
164    
165                for (MavenProject p : projects) {
166                    ArtifactFilter filter = null;
167                    DependencyNode node = treeBuilder.buildDependencyTree(p, localRepository, artifactFactory, artifactMetadataSource, filter, artifactCollector);
168                    visualizer.add(node);
169                }
170    
171                getTarget().getParentFile().mkdirs();
172                visualizer.export(getTarget());
173                getLog().info("Dependency graph exported to: " + getTarget());
174            } catch (DependencyTreeBuilderException e) {
175                throw new MojoExecutionException("Could not build the depedency tree.", e);
176            }
177        }
178    
179        protected void collectProjects(ArrayList<MavenProject> projects) {
180            projects.add(project);
181        }
182    
183        public File getTarget() {
184            return target;
185        }
186    
187    }