001 /**
002 * Copyright (C) 2009 Progress Software, Inc.
003 * http://fusesource.com
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.fusesource.mvnplugins.graph;
018
019 import org.apache.maven.project.MavenProject;
020 import org.apache.maven.plugin.MojoExecutionException;
021 import org.apache.maven.plugin.AbstractMojo;
022 import org.apache.maven.artifact.repository.ArtifactRepository;
023 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
024 import org.apache.maven.artifact.resolver.ArtifactCollector;
025 import org.apache.maven.artifact.resolver.ArtifactResolver;
026 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
027 import org.apache.maven.artifact.factory.ArtifactFactory;
028 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
029 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
030 import org.apache.maven.shared.dependency.tree.DependencyNode;
031
032 import java.util.ArrayList;
033 import java.io.File;
034
035 /**
036 * Generates a graph image of the dependencies of the project using the graphviz
037 * tool 'dot'. You must have the 'dot' executable installed and in your path
038 * before using this goal.
039 * <p/>
040 *
041 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
042 * @goal project
043 * @requiresDependencyResolution compile|test|runtime
044 */
045 public class ProjectMojo extends AbstractMojo {
046
047 /**
048 * @required
049 * @readonly
050 * @parameter expression="${project}"
051 * @since 1.0
052 */
053 private MavenProject project;
054
055 /**
056 * @required
057 * @readonly
058 * @parameter expression="${localRepository}"
059 * @since 1.0
060 */
061 private ArtifactRepository localRepository;
062
063 /**
064 * @required
065 * @component
066 * @since 1.0
067 */
068 private ArtifactResolver artifactResolver;
069
070 /**
071 * @required
072 * @readonly
073 * @component
074 * @since 1.0
075 */
076 private ArtifactFactory artifactFactory;
077
078 /**
079 * @required
080 * @readonly
081 * @component
082 * @since 1.0
083 */
084 private ArtifactMetadataSource artifactMetadataSource;
085
086 /**
087 * @required
088 * @readonly
089 * @component
090 */
091 private ArtifactCollector artifactCollector;
092
093 /**
094 * @required
095 * @readonly
096 * @component
097 * @since 1.0
098 */
099 private DependencyTreeBuilder treeBuilder;
100
101 /**
102 * The file the diagram will be written to. Must use a file extension that the dot command supports or just the
103 * '.dot' extension.
104 * <br/>
105 * @parameter default-value="${project.build.directory}/project-graph.png" expression="${graph.target}"
106 */
107 private File target;
108
109 /**
110 * If set to true, ommitted dependencies will not be drawn. Dependencies are marked
111 * as ommitted if it would result in a resolution conflict.
112 * <br/>
113 * @parameter default-value="true" expression="${hide-omitted}"
114 */
115 private boolean hideOmitted;
116
117 /**
118 * If set to true optional dependencies are not drawn.
119 * <br/>
120 * @parameter default-value="false" expression="${hide-optional}"
121 */
122 private boolean hideOptional;
123
124 /**
125 * If set to true pom dependencies are not drawn.
126 * <br/>
127 * @parameter default-value="true" expression="${hide-poms}"
128 */
129 private boolean hidePoms;
130
131 /**
132 * A comma seperated list of scopes. Dependencies which
133 * mach the specified scopes will not be drawn.
134 * <br/>
135 * For example: <code>runtime,test</code>
136 * <br/>
137 * @parameter expression="${hide-scope}"
138 */
139 private String hideScopes;
140
141 /**
142 * If set to true then depdencies not explicitly defined in the projects
143 * pom will not be drawn.
144 * <br/>
145 * @parameter default-value="false" expression="${hide-transitive}"
146 */
147 private boolean hideTransitive;
148
149 /**
150 * The label for the graph.
151 * <br/>
152 * @parameter default-value="Depedency Graph for ${project.name}" expression="${graph.label}"
153 */
154 private String label;
155
156 /**
157 * If true then the 'test scope' and 'optional' attributes are cascaded
158 * down to the dependencies of the original node.
159 *
160 * <br/>
161 * @parameter default-value="true" expression="${graph.cascade}"
162 */
163 boolean cascade;
164
165 /**
166 * The direction that the graph will be laid out in.
167 * it can be one of the following values:
168 * <br/>
169 * <code>TB LR BT RL <code>
170 * <br/>
171 * top to bottom, from left to right, from bottom to top, and from right to left, respectively
172 *
173 * <br/>
174 * @parameter default-value="TB" expression="${graph.direction}"
175 */
176 String direction;
177
178 public void execute() throws MojoExecutionException {
179 try {
180 DependencyVisualizer visualizer = new DependencyVisualizer();
181 visualizer.cascade = cascade;
182 visualizer.direction = direction;
183 visualizer.hideOptional = hideOptional;
184 visualizer.hidePoms = hidePoms;
185 visualizer.hideOmitted = hideOmitted;
186 visualizer.label = label;
187 visualizer.hideTransitive = hideTransitive;
188 visualizer.log = getLog();
189
190 if (hideScopes != null) {
191 for (String scope : hideScopes.split(",")) {
192 visualizer.hideScopes.add(scope);
193 }
194 }
195
196 ArrayList<MavenProject> projects = new ArrayList<MavenProject>();
197 collectProjects(projects);
198
199 for (MavenProject p : projects) {
200 ArtifactFilter filter = null;
201 DependencyNode node = treeBuilder.buildDependencyTree(p, localRepository, artifactFactory, artifactMetadataSource, filter, artifactCollector);
202 visualizer.add(node);
203 }
204
205 getTarget().getParentFile().mkdirs();
206 visualizer.export(getTarget());
207 getLog().info("Dependency graph exported to: " + getTarget());
208 } catch (DependencyTreeBuilderException e) {
209 throw new MojoExecutionException("Could not build the depedency tree.", e);
210 }
211 }
212
213 protected void collectProjects(ArrayList<MavenProject> projects) {
214 projects.add(project);
215 }
216
217 public File getTarget() {
218 return target;
219 }
220
221 }