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 org.apache.maven.artifact.Artifact;
23  import org.apache.maven.artifact.ArtifactUtils;
24  import org.apache.maven.project.MavenProject;
25  import org.apache.maven.shared.dependency.tree.DependencyNode;
26  import org.apache.maven.shared.jar.JarAnalyzer;
27  import org.apache.maven.shared.jar.JarData;
28  import org.apache.maven.shared.jar.classes.JarClassesAnalysis;
29  
30  import java.io.IOException;
31  import java.util.ArrayList;
32  import java.util.HashMap;
33  import java.util.Iterator;
34  import java.util.List;
35  import java.util.Map;
36  
37  /**
38   * @version $Id: Dependencies.java 675813 2008-07-11 00:05:39Z vsiveton $
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 projectDependencies;
53  
54      /**
55       * @since 2.1
56       */
57      private List projectTransitiveDependencies;
58  
59      /**
60       * @since 2.1
61       */
62      private List allDependencies;
63  
64      /**
65       * @since 2.1
66       */
67      private Map dependenciesByScope;
68  
69      /**
70       * @since 2.1
71       */
72      private Map transitiveDependenciesByScope;
73  
74      /**
75       * @since 2.1
76       */
77      private Map dependencyDetails;
78  
79      /**
80       * Default constructor
81       *
82       * @param project
83       * @param dependencyTreeNode
84       * @param classesAnalyzer
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           * Workaround to ensure proper File objects in the Artifacts from the ReportResolutionListener
94           */
95          Map projectMap = new HashMap();
96          Iterator it = project.getArtifacts().iterator();
97          while ( it.hasNext() )
98          {
99              Artifact artifact = (Artifact) it.next();
100             projectMap.put( ArtifactUtils.versionlessKey( artifact ), artifact );
101         }
102 
103         mapArtifactFiles( dependencyTreeNode, projectMap );
104     }
105 
106     /**
107      * Getter for the project
108      *
109      * @return the project
110      */
111     public MavenProject getProject()
112     {
113         return project;
114     }
115 
116     /**
117      * @return <code>true</code> if getProjectDependencies() is not empty, <code>false</code> otherwise.
118      */
119     public boolean hasDependencies()
120     {
121         return ( getProjectDependencies() != null ) && ( !getProjectDependencies().isEmpty() );
122     }
123 
124     /**
125      * @return a list of <code>Artifact</code> from the project.
126      */
127     public List getProjectDependencies()
128     {
129         if ( projectDependencies != null )
130         {
131             return projectDependencies;
132         }
133 
134         projectDependencies = new ArrayList();
135         for ( Iterator i = dependencyTreeNode.getChildren().iterator(); i.hasNext(); )
136         {
137             DependencyNode dependencyNode = (DependencyNode) i.next();
138 
139             projectDependencies.add( dependencyNode.getArtifact() );
140         }
141 
142         return projectDependencies;
143     }
144 
145     /**
146      * @return a list of transitive <code>Artifact</code> from the project.
147      */
148     public List getTransitiveDependencies()
149     {
150         if ( projectTransitiveDependencies != null )
151         {
152             return projectTransitiveDependencies;
153         }
154 
155         projectTransitiveDependencies = new ArrayList( getAllDependencies() );
156         projectTransitiveDependencies.removeAll( getProjectDependencies() );
157 
158         return projectTransitiveDependencies;
159     }
160 
161     /**
162      * @return a list of included <code>Artifact</code> returned by the dependency tree.
163      */
164     public List getAllDependencies()
165     {
166         if ( allDependencies != null )
167         {
168             return allDependencies;
169         }
170 
171         allDependencies = new ArrayList();
172         for ( Iterator i = dependencyTreeNode.getChildren().iterator(); i.hasNext(); )
173         {
174             DependencyNode dependencyNode = (DependencyNode) i.next();
175 
176             if ( dependencyNode.getState() != DependencyNode.INCLUDED )
177             {
178                 continue;
179             }
180 
181             if ( dependencyNode.getArtifact().getGroupId().equals( project.getGroupId() )
182                 && dependencyNode.getArtifact().getArtifactId().equals( project.getArtifactId() )
183                 && dependencyNode.getArtifact().getVersion().equals( project.getVersion() ) )
184             {
185                 continue;
186             }
187 
188             if ( !allDependencies.contains( dependencyNode.getArtifact() ) )
189             {
190                 allDependencies.add( dependencyNode.getArtifact() );
191             }
192             getAllDependencies( dependencyNode );
193         }
194 
195         return allDependencies;
196     }
197 
198     /**
199      * @param isTransitively <code>true</code> to return transitive dependencies, <code>false</code> otherwise.
200      * @return a map with supported scopes as key and a list of <code>Artifact</code> as values.
201      * @see Artifact#SCOPE_COMPILE
202      * @see Artifact#SCOPE_PROVIDED
203      * @see Artifact#SCOPE_RUNTIME
204      * @see Artifact#SCOPE_SYSTEM
205      * @see Artifact#SCOPE_TEST
206      */
207     public Map getDependenciesByScope( boolean isTransitively )
208     {
209         if ( isTransitively )
210         {
211             if ( transitiveDependenciesByScope != null )
212             {
213                 return transitiveDependenciesByScope;
214             }
215 
216             transitiveDependenciesByScope = new HashMap();
217             for ( Iterator i = getTransitiveDependencies().iterator(); i.hasNext(); )
218             {
219                 Artifact artifact = (Artifact) i.next();
220 
221                 List multiValue = (List) transitiveDependenciesByScope.get( artifact.getScope() );
222                 if ( multiValue == null )
223                 {
224                     multiValue = new ArrayList();
225                 }
226 
227                 if ( !multiValue.contains( artifact ) )
228                 {
229                     multiValue.add( artifact );
230                 }
231                 transitiveDependenciesByScope.put( artifact.getScope(), multiValue );
232             }
233 
234             return transitiveDependenciesByScope;
235         }
236 
237         if ( dependenciesByScope != null )
238         {
239             return dependenciesByScope;
240         }
241 
242         dependenciesByScope = new HashMap();
243         for ( Iterator i = getProjectDependencies().iterator(); i.hasNext(); )
244         {
245             Artifact artifact = (Artifact) i.next();
246 
247             List multiValue = (List) dependenciesByScope.get( artifact.getScope() );
248             if ( multiValue == null )
249             {
250                 multiValue = new ArrayList();
251             }
252 
253             if ( !multiValue.contains( artifact ) )
254             {
255                 multiValue.add( artifact );
256             }
257             dependenciesByScope.put( artifact.getScope(), multiValue );
258         }
259 
260         return dependenciesByScope;
261     }
262 
263     /**
264      * @param artifact
265      * @return the jardata object from the artifact
266      * @throws IOException if any
267      */
268     public JarData getJarDependencyDetails( Artifact artifact )
269         throws IOException
270     {
271         if ( dependencyDetails == null )
272         {
273             dependencyDetails = new HashMap();
274         }
275 
276         JarData old = (JarData) dependencyDetails.get( artifact.getId() );
277         if ( dependencyDetails.get( artifact.getId() ) != null )
278         {
279             return old;
280         }
281 
282         JarAnalyzer jarAnalyzer = new JarAnalyzer( artifact.getFile() );
283         try
284         {
285             classesAnalyzer.analyze( jarAnalyzer );
286         }
287         finally
288         {
289             jarAnalyzer.closeQuietly();
290         }
291 
292         dependencyDetails.put( artifact.getId(), jarAnalyzer.getJarData() );
293 
294         return jarAnalyzer.getJarData();
295     }
296 
297     // ----------------------------------------------------------------------
298     // Private methods
299     // ----------------------------------------------------------------------
300 
301     private void mapArtifactFiles( DependencyNode node, Map projectMap )
302     {
303         List childs = node.getChildren();
304         if ( ( childs == null ) || childs.isEmpty() )
305         {
306             return;
307         }
308 
309         Iterator it = childs.iterator();
310         while ( it.hasNext() )
311         {
312             DependencyNode anode = (DependencyNode) it.next();
313             String key = ArtifactUtils.versionlessKey( anode.getArtifact() );
314             Artifact projartifact = (Artifact) projectMap.get( key );
315             if ( projartifact != null )
316             {
317                 anode.getArtifact().setFile( projartifact.getFile() );
318             }
319 
320             mapArtifactFiles( anode, projectMap );
321         }
322     }
323 
324     /**
325      * Recursive method to get all dependencies from a given <code>dependencyNode</code>
326      *
327      * @param dependencyNode not null
328      */
329     private void getAllDependencies( DependencyNode dependencyNode )
330     {
331         if ( dependencyNode == null || dependencyNode.getChildren() == null )
332         {
333             if ( !allDependencies.contains( dependencyNode.getArtifact() ) )
334             {
335                 allDependencies.add( dependencyNode.getArtifact() );
336             }
337             return;
338         }
339 
340         for ( Iterator i = dependencyNode.getChildren().iterator(); i.hasNext(); )
341         {
342             DependencyNode subdependencyNode = (DependencyNode) i.next();
343 
344             if ( subdependencyNode.getState() != DependencyNode.INCLUDED )
345             {
346                 continue;
347             }
348 
349             if ( subdependencyNode.getArtifact().getGroupId().equals( project.getGroupId() )
350                 && subdependencyNode.getArtifact().getArtifactId().equals( project.getArtifactId() )
351                 && subdependencyNode.getArtifact().getVersion().equals( project.getVersion() ) )
352             {
353                 continue;
354             }
355 
356             if ( !allDependencies.contains( subdependencyNode.getArtifact() ) )
357             {
358                 allDependencies.add( subdependencyNode.getArtifact() );
359             }
360             getAllDependencies( subdependencyNode );
361         }
362     }
363 }