PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/maven-dependency-plugin-2.4/src/main/java/org/apache/maven/plugin/dependency/AbstractAnalyzeMojo.java

#
Java | 362 lines | 212 code | 51 blank | 99 comment | 29 complexity | fdd87ae8ec96e54814f301231e4fa04b MD5 | raw file
Possible License(s): Apache-2.0
  1. package org.apache.maven.plugin.dependency;
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. */
  20. import java.io.File;
  21. import java.io.StringWriter;
  22. import java.util.HashSet;
  23. import java.util.Iterator;
  24. import java.util.Set;
  25. import org.apache.commons.lang.StringUtils;
  26. import org.apache.maven.artifact.Artifact;
  27. import org.apache.maven.plugin.AbstractMojo;
  28. import org.apache.maven.plugin.MojoExecutionException;
  29. import org.apache.maven.plugin.MojoFailureException;
  30. import org.apache.maven.project.MavenProject;
  31. import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis;
  32. import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer;
  33. import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzerException;
  34. import org.codehaus.plexus.PlexusConstants;
  35. import org.codehaus.plexus.PlexusContainer;
  36. import org.codehaus.plexus.context.Context;
  37. import org.codehaus.plexus.context.ContextException;
  38. import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
  39. import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
  40. /**
  41. * Analyzes the dependencies of this project and determines which are: used and declared; used and undeclared; unused
  42. * and declared.
  43. *
  44. * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
  45. * @version $Id: AbstractAnalyzeMojo.java 1085777 2011-03-26 18:13:19Z hboutemy $
  46. * @since 2.0-alpha-5
  47. */
  48. public abstract class AbstractAnalyzeMojo
  49. extends AbstractMojo
  50. implements Contextualizable
  51. {
  52. // fields -----------------------------------------------------------------
  53. /**
  54. * The plexus context to look-up the right {@link ProjectDependencyAnalyzer} implementation depending on the mojo
  55. * configuration.
  56. */
  57. private Context context;
  58. /**
  59. * The Maven project to analyze.
  60. *
  61. * @parameter expression="${project}"
  62. * @required
  63. * @readonly
  64. */
  65. private MavenProject project;
  66. /**
  67. * Project dependency analyzer to use (plexus component role-hint).
  68. *
  69. * @parameter expression="${analyzer}" default-value="default"
  70. * @since 2.2
  71. */
  72. private String analyzer;
  73. /**
  74. * Whether to fail the build if a dependency warning is found.
  75. *
  76. * @parameter expression="${failOnWarning}" default-value="false"
  77. */
  78. private boolean failOnWarning;
  79. /**
  80. * Output used dependencies
  81. *
  82. * @parameter expression="${verbose}" default-value="false"
  83. */
  84. private boolean verbose;
  85. /**
  86. * Ignore Runtime,Provide,Test,System scopes for unused dependency analysis
  87. *
  88. * @parameter expression="${ignoreNonCompile}" default-value="false"
  89. */
  90. private boolean ignoreNonCompile;
  91. /**
  92. * Output the xml for the missing dependencies
  93. *
  94. * @parameter expression="${outputXML}" default-value="false"
  95. * @since 2.0-alpha-5
  96. */
  97. private boolean outputXML;
  98. /**
  99. * Output scriptable values
  100. *
  101. * @parameter expression="${scriptableOutput}" default-value="false"
  102. * @since 2.0-alpha-5
  103. */
  104. private boolean scriptableOutput;
  105. /**
  106. * Flag to use for scriptable output
  107. *
  108. * @parameter expression="${scriptableFlag}" default-value="$$$%%%"
  109. * @since 2.0-alpha-5
  110. */
  111. private String scriptableFlag;
  112. /**
  113. * Flag to use for scriptable output
  114. *
  115. * @parameter expression="${basedir}"
  116. * @readonly
  117. * @since 2.0-alpha-5
  118. */
  119. private File baseDir;
  120. /**
  121. * Target folder
  122. *
  123. * @parameter expression="${project.build.directory}"
  124. * @readonly
  125. * @since 2.0-alpha-5
  126. */
  127. private File outputDirectory;
  128. // Mojo methods -----------------------------------------------------------
  129. /*
  130. * @see org.apache.maven.plugin.Mojo#execute()
  131. */
  132. public void execute()
  133. throws MojoExecutionException, MojoFailureException
  134. {
  135. if ( "pom".equals( project.getPackaging() ) )
  136. {
  137. getLog().info( "Skipping pom project" );
  138. return;
  139. }
  140. if ( outputDirectory == null || !outputDirectory.exists() )
  141. {
  142. getLog().info( "Skipping project with no build directory" );
  143. return;
  144. }
  145. boolean warning = checkDependencies();
  146. if ( warning && failOnWarning )
  147. {
  148. throw new MojoExecutionException( "Dependency problems found" );
  149. }
  150. }
  151. protected ProjectDependencyAnalyzer createProjectDependencyAnalyzer()
  152. throws MojoExecutionException
  153. {
  154. final String role = ProjectDependencyAnalyzer.ROLE;
  155. final String roleHint = analyzer;
  156. try
  157. {
  158. final PlexusContainer container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
  159. return (ProjectDependencyAnalyzer) container.lookup( role, roleHint );
  160. }
  161. catch ( Exception exception )
  162. {
  163. throw new MojoExecutionException( "Failed to instantiate ProjectDependencyAnalyser with role " + role
  164. + " / role-hint " + roleHint,exception );
  165. }
  166. }
  167. public void contextualize( Context context )
  168. throws ContextException
  169. {
  170. this.context = context;
  171. }
  172. // private methods --------------------------------------------------------
  173. private boolean checkDependencies()
  174. throws MojoExecutionException
  175. {
  176. ProjectDependencyAnalysis analysis;
  177. try
  178. {
  179. analysis = createProjectDependencyAnalyzer().analyze( project );
  180. }
  181. catch ( ProjectDependencyAnalyzerException exception )
  182. {
  183. throw new MojoExecutionException( "Cannot analyze dependencies", exception );
  184. }
  185. Set<Artifact> usedDeclared = analysis.getUsedDeclaredArtifacts();
  186. Set<Artifact> usedUndeclared = analysis.getUsedUndeclaredArtifacts();
  187. Set<Artifact> unusedDeclared = analysis.getUnusedDeclaredArtifacts();
  188. if ( ignoreNonCompile )
  189. {
  190. Set<Artifact> filteredUnusedDeclared = new HashSet<Artifact>( unusedDeclared );
  191. Iterator<Artifact> iter = filteredUnusedDeclared.iterator();
  192. while ( iter.hasNext() )
  193. {
  194. Artifact artifact = iter.next();
  195. if ( !artifact.getScope().equals( Artifact.SCOPE_COMPILE ) )
  196. {
  197. iter.remove();
  198. }
  199. }
  200. unusedDeclared = filteredUnusedDeclared;
  201. }
  202. if ( ( !verbose || usedDeclared.isEmpty() ) && usedUndeclared.isEmpty() && unusedDeclared.isEmpty() )
  203. {
  204. getLog().info( "No dependency problems found" );
  205. return false;
  206. }
  207. if ( verbose && !usedDeclared.isEmpty() )
  208. {
  209. getLog().info( "Used declared dependencies found:" );
  210. logArtifacts( analysis.getUsedDeclaredArtifacts(), false );
  211. }
  212. if ( !usedUndeclared.isEmpty() )
  213. {
  214. getLog().warn( "Used undeclared dependencies found:" );
  215. logArtifacts( usedUndeclared, true );
  216. }
  217. if ( !unusedDeclared.isEmpty() )
  218. {
  219. getLog().warn( "Unused declared dependencies found:" );
  220. logArtifacts( unusedDeclared, true );
  221. }
  222. if ( outputXML )
  223. {
  224. writeDependencyXML( usedUndeclared );
  225. }
  226. if ( scriptableOutput )
  227. {
  228. writeScriptableOutput( usedUndeclared );
  229. }
  230. return !usedUndeclared.isEmpty() || !unusedDeclared.isEmpty();
  231. }
  232. private void logArtifacts( Set<Artifact> artifacts, boolean warn )
  233. {
  234. if ( artifacts.isEmpty() )
  235. {
  236. getLog().info( " None" );
  237. }
  238. else
  239. {
  240. for ( Artifact artifact : artifacts )
  241. {
  242. // called because artifact will set the version to -SNAPSHOT only if I do this. MNG-2961
  243. artifact.isSnapshot();
  244. if ( warn )
  245. {
  246. getLog().warn( " " + artifact );
  247. }
  248. else
  249. {
  250. getLog().info( " " + artifact );
  251. }
  252. }
  253. }
  254. }
  255. private void writeDependencyXML( Set<Artifact> artifacts )
  256. {
  257. if ( !artifacts.isEmpty() )
  258. {
  259. getLog().info( "Add the following to your pom to correct the missing dependencies: " );
  260. StringWriter out = new StringWriter();
  261. PrettyPrintXMLWriter writer = new PrettyPrintXMLWriter( out );
  262. for ( Artifact artifact : artifacts )
  263. {
  264. // called because artifact will set the version to -SNAPSHOT only if I do this. MNG-2961
  265. artifact.isSnapshot();
  266. writer.startElement( "dependency" );
  267. writer.startElement( "groupId" );
  268. writer.writeText( artifact.getGroupId() );
  269. writer.endElement();
  270. writer.startElement( "artifactId" );
  271. writer.writeText( artifact.getArtifactId() );
  272. writer.endElement();
  273. writer.startElement( "version" );
  274. writer.writeText( artifact.getBaseVersion() );
  275. if ( !StringUtils.isBlank( artifact.getClassifier() ) )
  276. {
  277. writer.startElement( "classifier" );
  278. writer.writeText( artifact.getClassifier() );
  279. writer.endElement();
  280. }
  281. writer.endElement();
  282. if ( !Artifact.SCOPE_COMPILE.equals( artifact.getScope() ) )
  283. {
  284. writer.startElement( "scope" );
  285. writer.writeText( artifact.getScope() );
  286. writer.endElement();
  287. }
  288. writer.endElement();
  289. }
  290. getLog().info( "\n" + out.getBuffer() );
  291. }
  292. }
  293. private void writeScriptableOutput( Set<Artifact> artifacts )
  294. {
  295. if ( !artifacts.isEmpty() )
  296. {
  297. getLog().info( "Missing dependencies: " );
  298. String pomFile = baseDir.getAbsolutePath() + File.separatorChar + "pom.xml";
  299. StringBuffer buf = new StringBuffer();
  300. for ( Artifact artifact : artifacts )
  301. {
  302. // called because artifact will set the version to -SNAPSHOT only if I do this. MNG-2961
  303. artifact.isSnapshot();
  304. buf.append( scriptableFlag + ":" + pomFile + ":" + artifact.getDependencyConflictId() + ":"
  305. + artifact.getClassifier() + ":" + artifact.getBaseVersion() + ":"
  306. + artifact.getScope() + "\n" );
  307. }
  308. getLog().info( "\n" + buf );
  309. }
  310. }
  311. }