View Javadoc
1   package org.apache.maven.report.projectinfo;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.artifact.Artifact;
23  import org.apache.maven.artifact.factory.ArtifactFactory;
24  import org.apache.maven.artifact.manager.WagonManager;
25  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
26  import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager;
27  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
28  import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
29  import org.apache.maven.plugins.annotations.Component;
30  import org.apache.maven.plugins.annotations.Mojo;
31  import org.apache.maven.plugins.annotations.Parameter;
32  import org.apache.maven.plugins.annotations.ResolutionScope;
33  import org.apache.maven.project.MavenProjectBuilder;
34  import org.apache.maven.report.projectinfo.dependencies.Dependencies;
35  import org.apache.maven.report.projectinfo.dependencies.DependenciesReportConfiguration;
36  import org.apache.maven.report.projectinfo.dependencies.RepositoryUtils;
37  import org.apache.maven.report.projectinfo.dependencies.renderer.DependenciesRenderer;
38  import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
39  import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
40  import org.apache.maven.shared.dependency.graph.DependencyNode;
41  import org.apache.maven.shared.jar.classes.JarClassesAnalysis;
42  import org.codehaus.plexus.util.IOUtil;
43  import org.codehaus.plexus.util.ReaderFactory;
44  
45  import java.io.File;
46  import java.io.FileOutputStream;
47  import java.io.IOException;
48  import java.io.InputStream;
49  import java.io.InputStreamReader;
50  import java.io.LineNumberReader;
51  import java.util.Locale;
52  
53  /**
54   * Generates the Project Dependencies report.
55   *
56   * @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
57   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton </a>
58   * @version $Id: DependenciesReport.html 935177 2015-01-05 21:05:55Z michaelo $
59   * @since 2.0
60   */
61  @Mojo( name = "dependencies", requiresDependencyResolution = ResolutionScope.TEST )
62  public class DependenciesReport
63      extends AbstractProjectInfoReport
64  {
65      /**
66       * Images resources dir
67       */
68      private static final String RESOURCES_DIR = "org/apache/maven/report/projectinfo/resources";
69  
70      // ----------------------------------------------------------------------
71      // Mojo components
72      // ----------------------------------------------------------------------
73  
74      /**
75       * Maven Project Builder component.
76       */
77      @Component
78      private MavenProjectBuilder mavenProjectBuilder;
79  
80      /**
81       * Artifact metadata source component.
82       */
83      @Component
84      protected ArtifactMetadataSource artifactMetadataSource;
85  
86      /**
87       * Wagon manager component.
88       *
89       * @since 2.1
90       */
91      @Component
92      private WagonManager wagonManager;
93  
94      /**
95       * Dependency graph builder component.
96       *
97       * @since 2.5
98       */
99      @Component( hint = "default" )
100     private DependencyGraphBuilder dependencyGraphBuilder;
101 
102     /**
103      * Jar classes analyzer component.
104      *
105      * @since 2.1
106      */
107     @Component
108     private JarClassesAnalysis classesAnalyzer;
109 
110     /**
111      * Repository metadata component.
112      *
113      * @since 2.1
114      */
115     @Component
116     private RepositoryMetadataManager repositoryMetadataManager;
117 
118     /**
119      * Maven Artifact Factory component.
120      *
121      * @since 2.1
122      */
123     @Component
124     private ArtifactFactory artifactFactory;
125 
126     // ----------------------------------------------------------------------
127     // Mojo parameters
128     // ----------------------------------------------------------------------
129 
130     /**
131      * Display file details for each dependency, such as: file size, number of
132      * classes, number of packages etc.
133      *
134      * @since 2.1
135      */
136     @Parameter( property = "dependency.details.enabled", defaultValue = "true" )
137     private boolean dependencyDetailsEnabled;
138 
139     /**
140      * Display the repository locations of the dependencies. If Maven is configured to be offline, this parameter
141      * will be ignored.
142      *
143      * @since 2.1
144      */
145     @Parameter( property = "dependency.locations.enabled", defaultValue = "true" )
146     private boolean dependencyLocationsEnabled;
147 
148     // ----------------------------------------------------------------------
149     // Public methods
150     // ----------------------------------------------------------------------
151 
152     @Override
153     public boolean canGenerateReport()
154     {
155         boolean result = super.canGenerateReport();
156         if ( result && skipEmptyReport )
157         {
158             // This seems to be a bit too much but the DependenciesRenderer applies the same logic
159             DependencyNode dependencyNode = resolveProject();
160             Dependencies dependencies = new Dependencies( project, dependencyNode, classesAnalyzer );
161             result = dependencies.hasDependencies();
162         }
163 
164         return result;
165     }
166 
167     @Override
168     public void executeReport( Locale locale )
169     {
170         if ( settings.isOffline() && dependencyLocationsEnabled )
171         {
172             getLog().warn( "The parameter 'dependencyLocationsEnabled' is ignored in offline mode." );
173             dependencyLocationsEnabled = false;
174         }
175 
176         try
177         {
178             copyResources( new File( getOutputDirectory() ) );
179         }
180         catch ( IOException e )
181         {
182             getLog().error( "Cannot copy ressources", e );
183         }
184 
185         @SuppressWarnings( "unchecked" ) RepositoryUtils repoUtils =
186             new RepositoryUtils( getLog(), wagonManager, settings, mavenProjectBuilder, factory, resolver,
187                                  project.getRemoteArtifactRepositories(), project.getPluginArtifactRepositories(),
188                                  localRepository, repositoryMetadataManager );
189 
190         DependencyNode dependencyNode = resolveProject();
191 
192         Dependencies dependencies = new Dependencies( project, dependencyNode, classesAnalyzer );
193 
194         DependenciesReportConfiguration config =
195             new DependenciesReportConfiguration( dependencyDetailsEnabled, dependencyLocationsEnabled );
196 
197         DependenciesRenderer r =
198             new DependenciesRenderer( getSink(), locale, getI18N( locale ), getLog(), settings, dependencies,
199                                       dependencyNode, config, repoUtils, artifactFactory, mavenProjectBuilder,
200                                       remoteRepositories, localRepository );
201         r.render();
202     }
203 
204     /**
205      * {@inheritDoc}
206      */
207     public String getOutputName()
208     {
209         return "dependencies";
210     }
211 
212     @Override
213     protected String getI18Nsection()
214     {
215         return "dependencies";
216     }
217 
218     // ----------------------------------------------------------------------
219     // Private methods
220     // ----------------------------------------------------------------------
221 
222     /**
223      * @return resolve the dependency tree
224      */
225     private DependencyNode resolveProject()
226     {
227         try
228         {
229             ArtifactFilter artifactFilter = new ScopeArtifactFilter( Artifact.SCOPE_TEST );
230             return dependencyGraphBuilder.buildDependencyGraph( project, artifactFilter );
231         }
232         catch ( DependencyGraphBuilderException e )
233         {
234             getLog().error( "Unable to build dependency tree.", e );
235             return null;
236         }
237     }
238 
239     /**
240      * @param outputDirectory the wanted output directory
241      * @throws IOException if any
242      */
243     private void copyResources( File outputDirectory )
244         throws IOException
245     {
246         InputStream resourceList = null;
247         LineNumberReader reader = null;
248         try
249         {
250             resourceList = getClass().getClassLoader().getResourceAsStream( RESOURCES_DIR + "/resources.txt" );
251 
252             if ( resourceList != null )
253             {
254                 reader = new LineNumberReader( new InputStreamReader( resourceList, ReaderFactory.US_ASCII ) );
255 
256                 String line = reader.readLine();
257 
258                 while ( line != null )
259                 {
260                     InputStream is = getClass().getClassLoader().getResourceAsStream( RESOURCES_DIR + "/" + line );
261 
262                     if ( is == null )
263                     {
264                         throw new IOException( "The resource " + line + " doesn't exist." );
265                     }
266 
267                     File outputFile = new File( outputDirectory, line );
268 
269                     if ( !outputFile.getParentFile().exists() )
270                     {
271                         outputFile.getParentFile().mkdirs();
272                     }
273 
274                     FileOutputStream w = null;
275                     try
276                     {
277                         w = new FileOutputStream( outputFile );
278                         IOUtil.copy( is, w );
279                     }
280                     finally
281                     {
282                         IOUtil.close( is );
283 
284                         IOUtil.close( w );
285                     }
286 
287                     line = reader.readLine();
288                 }
289             }
290         }
291         finally
292         {
293             IOUtil.close( resourceList );
294             IOUtil.close( reader );
295         }
296     }
297 }