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 }