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         buildingRequest.setPluginArtifactRepositories( pluginRepositories );
146 
147         RepositoryUtils repoUtils =
148             new RepositoryUtils( getLog(), projectBuilder, repositorySystem, resolver,
149                                  project.getRemoteArtifactRepositories(), project.getPluginArtifactRepositories(),
150                                  buildingRequest, repositoryMetadataManager );
151 
152         DependencyNode dependencyNode = resolveProject();
153 
154         Dependencies dependencies = new Dependencies( project, dependencyNode, classesAnalyzer );
155 
156         DependenciesReportConfiguration config =
157             new DependenciesReportConfiguration( dependencyDetailsEnabled );
158 
159         DependenciesRenderer r =
160             new DependenciesRenderer( getSink(), locale, getI18N( locale ), getLog(), dependencies,
161                                       dependencyNode, config, repoUtils, repositorySystem, projectBuilder,
162                                       buildingRequest );
163         r.render();
164     }
165 
166     /**
167      * {@inheritDoc}
168      */
169     public String getOutputName()
170     {
171         return "dependencies";
172     }
173 
174     @Override
175     protected String getI18Nsection()
176     {
177         return "dependencies";
178     }
179 
180     // ----------------------------------------------------------------------
181     // Private methods
182     // ----------------------------------------------------------------------
183 
184     /**
185      * @return resolve the dependency tree
186      */
187     private DependencyNode resolveProject()
188     {
189         try
190         {
191             ArtifactFilter artifactFilter = new ScopeArtifactFilter( Artifact.SCOPE_TEST );
192             return dependencyGraphBuilder.buildDependencyGraph( project, artifactFilter );
193         }
194         catch ( DependencyGraphBuilderException e )
195         {
196             getLog().error( "Unable to build dependency tree.", e );
197             return null;
198         }
199     }
200 
201     /**
202      * @param outputDirectory the wanted output directory
203      * @throws IOException if any
204      */
205     private void copyResources( File outputDirectory )
206         throws IOException
207     {
208         InputStream resourceList = null;
209         InputStream in = null;
210         BufferedReader reader = null;
211         OutputStream out = null;
212         try
213         {
214             resourceList = getClass().getClassLoader().getResourceAsStream( RESOURCES_DIR + "/resources.txt" );
215 
216             if ( resourceList != null )
217             {
218                 reader = new LineNumberReader( new InputStreamReader( resourceList, ReaderFactory.US_ASCII ) );
219 
220                 for ( String line = reader.readLine(); line != null; line = reader.readLine() )
221                 {
222                     in = getClass().getClassLoader().getResourceAsStream( RESOURCES_DIR + "/" + line );
223 
224                     if ( in == null )
225                     {
226                         throw new IOException( "The resource " + line + " doesn't exist." );
227                     }
228 
229                     File outputFile = new File( outputDirectory, line );
230 
231                     if ( !outputFile.getParentFile().exists() )
232                     {
233                         outputFile.getParentFile().mkdirs();
234                     }
235 
236                     out = new FileOutputStream( outputFile );
237                     IOUtil.copy( in, out );
238                     out.close();
239                     out = null;
240                     in.close();
241                     in = null;
242                 }
243 
244                 reader.close();
245                 reader = null;
246             }
247         }
248         finally
249         {
250             IOUtil.close( out );
251             IOUtil.close( reader );
252             IOUtil.close( in );
253             IOUtil.close( resourceList );
254         }
255     }
256 }