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 java.io.BufferedReader;
23  import java.io.File;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.InputStreamReader;
28  import java.io.LineNumberReader;
29  import java.io.OutputStream;
30  import java.util.Locale;
31  
32  import org.apache.maven.artifact.Artifact;
33  import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager;
34  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
35  import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
36  import org.apache.maven.plugins.annotations.Component;
37  import org.apache.maven.plugins.annotations.Mojo;
38  import org.apache.maven.plugins.annotations.Parameter;
39  import org.apache.maven.plugins.annotations.ResolutionScope;
40  import org.apache.maven.project.DefaultProjectBuildingRequest;
41  import org.apache.maven.project.ProjectBuildingRequest;
42  import org.apache.maven.report.projectinfo.dependencies.Dependencies;
43  import org.apache.maven.report.projectinfo.dependencies.DependenciesReportConfiguration;
44  import org.apache.maven.report.projectinfo.dependencies.RepositoryUtils;
45  import org.apache.maven.report.projectinfo.dependencies.renderer.DependenciesRenderer;
46  import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
47  import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
48  import org.apache.maven.shared.dependency.graph.DependencyNode;
49  import org.apache.maven.shared.jar.classes.JarClassesAnalysis;
50  import org.codehaus.plexus.util.IOUtil;
51  import org.codehaus.plexus.util.ReaderFactory;
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   * @since 2.0
59   */
60  @Mojo( name = "dependencies", requiresDependencyResolution = ResolutionScope.TEST )
61  public class DependenciesReport
62      extends AbstractProjectInfoReport
63  {
64      /**
65       * Images resources dir
66       */
67      private static final String RESOURCES_DIR = "org/apache/maven/report/projectinfo/resources";
68  
69      // ----------------------------------------------------------------------
70      // Mojo components
71      // ----------------------------------------------------------------------
72  
73      /**
74       * Dependency graph builder component.
75       *
76       * @since 2.5
77       */
78      @Component( hint = "default" )
79      private DependencyGraphBuilder dependencyGraphBuilder;
80  
81      /**
82       * Jar classes analyzer component.
83       *
84       * @since 2.1
85       */
86      @Component
87      private JarClassesAnalysis classesAnalyzer;
88  
89      /**
90       * Repository metadata component.
91       *
92       * @since 2.1
93       */
94      @Component
95      private RepositoryMetadataManager repositoryMetadataManager;
96  
97      // ----------------------------------------------------------------------
98      // Mojo parameters
99      // ----------------------------------------------------------------------
100 
101     /**
102      * Display file details for each dependency, such as: file size, number of
103      * classes, number of packages etc.
104      *
105      * @since 2.1
106      */
107     @Parameter( property = "dependency.details.enabled", defaultValue = "true" )
108     private boolean dependencyDetailsEnabled;
109 
110     // ----------------------------------------------------------------------
111     // Public methods
112     // ----------------------------------------------------------------------
113 
114     @Override
115     public boolean canGenerateReport()
116     {
117         boolean result = super.canGenerateReport();
118         if ( result && skipEmptyReport )
119         {
120             // This seems to be a bit too much but the DependenciesRenderer applies the same logic
121             DependencyNode dependencyNode = resolveProject();
122             Dependencies dependencies = new Dependencies( project, dependencyNode, classesAnalyzer );
123             result = dependencies.hasDependencies();
124         }
125 
126         return result;
127     }
128 
129     @Override
130     public void executeReport( Locale locale )
131     {
132         try
133         {
134             copyResources( new File( getOutputDirectory() ) );
135         }
136         catch ( IOException e )
137         {
138             getLog().error( "Cannot copy ressources", e );
139         }
140         
141         ProjectBuildingRequest buildingRequest =
142             new DefaultProjectBuildingRequest( getSession().getProjectBuildingRequest() );
143         buildingRequest.setLocalRepository( localRepository );
144         buildingRequest.setRemoteRepositories( remoteRepositories );
145 
146         RepositoryUtils repoUtils =
147             new RepositoryUtils( getLog(), projectBuilder, repositorySystem, resolver,
148                                  project.getRemoteArtifactRepositories(), project.getPluginArtifactRepositories(),
149                                  buildingRequest, repositoryMetadataManager );
150 
151         DependencyNode dependencyNode = resolveProject();
152 
153         Dependencies dependencies = new Dependencies( project, dependencyNode, classesAnalyzer );
154 
155         DependenciesReportConfiguration config =
156             new DependenciesReportConfiguration( dependencyDetailsEnabled );
157 
158         DependenciesRenderer r =
159             new DependenciesRenderer( getSink(), locale, getI18N( locale ), getLog(), dependencies,
160                                       dependencyNode, config, repoUtils, repositorySystem, projectBuilder,
161                                       buildingRequest );
162         r.render();
163     }
164 
165     /**
166      * {@inheritDoc}
167      */
168     public String getOutputName()
169     {
170         return "dependencies";
171     }
172 
173     @Override
174     protected String getI18Nsection()
175     {
176         return "dependencies";
177     }
178 
179     // ----------------------------------------------------------------------
180     // Private methods
181     // ----------------------------------------------------------------------
182 
183     /**
184      * @return resolve the dependency tree
185      */
186     private DependencyNode resolveProject()
187     {
188         try
189         {
190             ArtifactFilter artifactFilter = new ScopeArtifactFilter( Artifact.SCOPE_TEST );
191             return dependencyGraphBuilder.buildDependencyGraph( project, artifactFilter );
192         }
193         catch ( DependencyGraphBuilderException e )
194         {
195             getLog().error( "Unable to build dependency tree.", e );
196             return null;
197         }
198     }
199 
200     /**
201      * @param outputDirectory the wanted output directory
202      * @throws IOException if any
203      */
204     private void copyResources( File outputDirectory )
205         throws IOException
206     {
207         InputStream resourceList = null;
208         InputStream in = null;
209         BufferedReader reader = null;
210         OutputStream out = null;
211         try
212         {
213             resourceList = getClass().getClassLoader().getResourceAsStream( RESOURCES_DIR + "/resources.txt" );
214 
215             if ( resourceList != null )
216             {
217                 reader = new LineNumberReader( new InputStreamReader( resourceList, ReaderFactory.US_ASCII ) );
218 
219                 for ( String line = reader.readLine(); line != null; line = reader.readLine() )
220                 {
221                     in = getClass().getClassLoader().getResourceAsStream( RESOURCES_DIR + "/" + line );
222 
223                     if ( in == null )
224                     {
225                         throw new IOException( "The resource " + line + " doesn't exist." );
226                     }
227 
228                     File outputFile = new File( outputDirectory, line );
229 
230                     if ( !outputFile.getParentFile().exists() )
231                     {
232                         outputFile.getParentFile().mkdirs();
233                     }
234 
235                     out = new FileOutputStream( outputFile );
236                     IOUtil.copy( in, out );
237                     out.close();
238                     out = null;
239                     in.close();
240                     in = null;
241                 }
242 
243                 reader.close();
244                 reader = null;
245             }
246         }
247         finally
248         {
249             IOUtil.close( out );
250             IOUtil.close( reader );
251             IOUtil.close( in );
252             IOUtil.close( resourceList );
253         }
254     }
255 }