View Javadoc

1   package org.apache.maven.report.projectinfo.dependencies;
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.IOException;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.jar.JarEntry;
28  
29  import org.apache.maven.artifact.Artifact;
30  import org.apache.maven.project.MavenProject;
31  import org.apache.maven.shared.dependency.tree.DependencyNode;
32  import org.apache.maven.shared.jar.JarAnalyzer;
33  import org.apache.maven.shared.jar.JarData;
34  import org.apache.maven.shared.jar.classes.JarClasses;
35  import org.apache.maven.shared.jar.classes.JarClassesAnalysis;
36  
37  /**
38   * @version $Id: Dependencies.java 1103555 2011-05-15 22:08:21Z hboutemy $
39   * @since 2.1
40   */
41  public class Dependencies
42  {
43      private final MavenProject project;
44  
45      private final DependencyNode dependencyTreeNode;
46  
47      private final JarClassesAnalysis classesAnalyzer;
48  
49      /**
50       * @since 2.1
51       */
52      private List<Artifact> projectDependencies;
53  
54      /**
55       * @since 2.1
56       */
57      private List<Artifact> projectTransitiveDependencies;
58  
59      /**
60       * @since 2.1
61       */
62      private List<Artifact> allDependencies;
63  
64      /**
65       * @since 2.1
66       */
67      private Map<String, List<Artifact>> dependenciesByScope;
68  
69      /**
70       * @since 2.1
71       */
72      private Map<String, List<Artifact>> transitiveDependenciesByScope;
73  
74      /**
75       * @since 2.1
76       */
77      private Map<String, JarData> dependencyDetails;
78  
79      /**
80       * Default constructor
81       *
82       * @param project the MavenProject.
83       * @param dependencyTreeNode the DependencyNode.
84       * @param classesAnalyzer the JarClassesAnalysis.
85       */
86      public Dependencies( MavenProject project, DependencyNode dependencyTreeNode, JarClassesAnalysis classesAnalyzer )
87      {
88          this.project = project;
89          this.dependencyTreeNode = dependencyTreeNode;
90          this.classesAnalyzer = classesAnalyzer;
91      }
92  
93      /**
94       * Getter for the project
95       *
96       * @return the project
97       */
98      public MavenProject getProject()
99      {
100         return project;
101     }
102 
103     /**
104      * @return <code>true</code> if getProjectDependencies() is not empty, <code>false</code> otherwise.
105      */
106     public boolean hasDependencies()
107     {
108         return ( getProjectDependencies() != null ) && ( !getProjectDependencies().isEmpty() );
109     }
110 
111     /**
112      * @return a list of <code>Artifact</code> from the project.
113      */
114     public List<Artifact> getProjectDependencies()
115     {
116         if ( projectDependencies != null )
117         {
118             return projectDependencies;
119         }
120 
121         projectDependencies = new ArrayList<Artifact>();
122         @SuppressWarnings( "unchecked" )
123         List<DependencyNode> deps = dependencyTreeNode.getChildren();
124         for ( DependencyNode dep : deps )
125         {
126             projectDependencies.add( dep.getArtifact() );
127         }
128 
129         return projectDependencies;
130     }
131 
132     /**
133      * @return a list of transitive <code>Artifact</code> from the project.
134      */
135     public List<Artifact> getTransitiveDependencies()
136     {
137         if ( projectTransitiveDependencies != null )
138         {
139             return projectTransitiveDependencies;
140         }
141 
142         projectTransitiveDependencies = new ArrayList<Artifact>( getAllDependencies() );
143         projectTransitiveDependencies.removeAll( getProjectDependencies() );
144 
145         return projectTransitiveDependencies;
146     }
147 
148     /**
149      * @return a list of included <code>Artifact</code> returned by the dependency tree.
150      */
151     public List<Artifact> getAllDependencies()
152     {
153         if ( allDependencies != null )
154         {
155             return allDependencies;
156         }
157 
158         allDependencies = new ArrayList<Artifact>();
159 
160         addAllChildrenDependencies( dependencyTreeNode );
161 
162         return allDependencies;
163     }
164 
165     /**
166      * @param isTransitively <code>true</code> to return transitive dependencies, <code>false</code> otherwise.
167      * @return a map with supported scopes as key and a list of <code>Artifact</code> as values.
168      * @see Artifact#SCOPE_COMPILE
169      * @see Artifact#SCOPE_PROVIDED
170      * @see Artifact#SCOPE_RUNTIME
171      * @see Artifact#SCOPE_SYSTEM
172      * @see Artifact#SCOPE_TEST
173      */
174     public Map<String, List<Artifact>> getDependenciesByScope( boolean isTransitively )
175     {
176         if ( isTransitively )
177         {
178             if ( transitiveDependenciesByScope != null )
179             {
180                 return transitiveDependenciesByScope;
181             }
182 
183             transitiveDependenciesByScope = new HashMap<String, List<Artifact>>();
184             for ( Artifact artifact : getTransitiveDependencies() )
185             {
186                 List<Artifact> multiValue = transitiveDependenciesByScope.get( artifact.getScope() );
187                 if ( multiValue == null )
188                 {
189                     multiValue = new ArrayList<Artifact>();
190                 }
191 
192                 if ( !multiValue.contains( artifact ) )
193                 {
194                     multiValue.add( artifact );
195                 }
196                 transitiveDependenciesByScope.put( artifact.getScope(), multiValue );
197             }
198 
199             return transitiveDependenciesByScope;
200         }
201 
202         if ( dependenciesByScope != null )
203         {
204             return dependenciesByScope;
205         }
206 
207         dependenciesByScope = new HashMap<String, List<Artifact>>();
208         for ( Artifact artifact : getProjectDependencies() )
209         {
210             List<Artifact> multiValue = dependenciesByScope.get( artifact.getScope() );
211             if ( multiValue == null )
212             {
213                 multiValue = new ArrayList<Artifact>();
214             }
215 
216             if ( !multiValue.contains( artifact ) )
217             {
218                 multiValue.add( artifact );
219             }
220             dependenciesByScope.put( artifact.getScope(), multiValue );
221         }
222 
223         return dependenciesByScope;
224     }
225 
226     /**
227      * @param artifact the artifact.
228      * @return the jardata object from the artifact
229      * @throws IOException if any
230      */
231     public JarData getJarDependencyDetails( Artifact artifact )
232         throws IOException
233     {
234         if ( dependencyDetails == null )
235         {
236             dependencyDetails = new HashMap<String, JarData>();
237         }
238 
239         JarData jarData = dependencyDetails.get( artifact.getId() );
240         if ( jarData != null )
241         {
242             return jarData;
243         }
244 
245         if ( artifact.getFile().isDirectory() )
246         {
247             jarData = new JarData( artifact.getFile(), null, new ArrayList<JarEntry>() );
248 
249             jarData.setJarClasses( new JarClasses() );
250         }
251         else
252         {
253             JarAnalyzer jarAnalyzer = new JarAnalyzer( artifact.getFile() );
254 
255             try
256             {
257                 classesAnalyzer.analyze( jarAnalyzer );
258             }
259             finally
260             {
261                 jarAnalyzer.closeQuietly();
262             }
263             
264             jarData = jarAnalyzer.getJarData();
265         }
266 
267         dependencyDetails.put( artifact.getId(), jarData );
268     
269         return jarData;
270     }
271 
272     // ----------------------------------------------------------------------
273     // Private methods
274     // ----------------------------------------------------------------------
275 
276     /**
277      * Recursive method to get all dependencies from a given <code>dependencyNode</code>
278      *
279      * @param dependencyNode not null
280      */
281     private void addAllChildrenDependencies( DependencyNode dependencyNode )
282     {
283         @SuppressWarnings( "unchecked" )
284         List<DependencyNode> deps = dependencyNode.getChildren();
285         for ( DependencyNode subdependencyNode : deps )
286         {
287             if ( subdependencyNode.getState() != DependencyNode.INCLUDED )
288             {
289                 continue;
290             }
291 
292             Artifact artifact = subdependencyNode.getArtifact();
293 
294             if ( artifact.getGroupId().equals( project.getGroupId() )
295                 && artifact.getArtifactId().equals( project.getArtifactId() )
296                 && artifact.getVersion().equals( project.getVersion() ) )
297             {
298                 continue;
299             }
300 
301             if ( !allDependencies.contains( artifact ) )
302             {
303                 allDependencies.add( artifact );
304             }
305 
306             addAllChildrenDependencies( subdependencyNode );
307         }
308     }
309 }