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