1 package org.apache.maven.shared.dependency.analyzer;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.net.URL;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.LinkedHashMap;
28 import java.util.LinkedHashSet;
29 import java.util.Map;
30 import java.util.Set;
31
32 import org.apache.maven.artifact.Artifact;
33 import org.apache.maven.project.MavenProject;
34 import org.codehaus.plexus.component.annotations.Component;
35 import org.codehaus.plexus.component.annotations.Requirement;
36
37
38
39
40
41
42
43 @Component( role = ProjectDependencyAnalyzer.class )
44 public class DefaultProjectDependencyAnalyzer
45 implements ProjectDependencyAnalyzer
46 {
47
48
49
50
51
52 @Requirement
53 private ClassAnalyzer classAnalyzer;
54
55
56
57
58 @Requirement
59 private DependencyAnalyzer dependencyAnalyzer;
60
61
62
63
64
65
66 public ProjectDependencyAnalysis analyze( MavenProject project )
67 throws ProjectDependencyAnalyzerException
68 {
69 try
70 {
71 Map<Artifact, Set<String>> artifactClassMap = buildArtifactClassMap( project );
72
73 Set<String> dependencyClasses = buildDependencyClasses( project );
74
75 Set<Artifact> declaredArtifacts = buildDeclaredArtifacts( project );
76
77 Set<Artifact> usedArtifacts = buildUsedArtifacts( artifactClassMap, dependencyClasses );
78
79 Set<Artifact> usedDeclaredArtifacts = new LinkedHashSet<Artifact>( declaredArtifacts );
80 usedDeclaredArtifacts.retainAll( usedArtifacts );
81
82 Set<Artifact> usedUndeclaredArtifacts = new LinkedHashSet<Artifact>( usedArtifacts );
83 usedUndeclaredArtifacts = removeAll( usedUndeclaredArtifacts, declaredArtifacts );
84
85 Set<Artifact> unusedDeclaredArtifacts = new LinkedHashSet<Artifact>( declaredArtifacts );
86 unusedDeclaredArtifacts = removeAll( unusedDeclaredArtifacts, usedArtifacts );
87
88 return new ProjectDependencyAnalysis( usedDeclaredArtifacts, usedUndeclaredArtifacts,
89 unusedDeclaredArtifacts );
90 }
91 catch ( IOException exception )
92 {
93 throw new ProjectDependencyAnalyzerException( "Cannot analyze dependencies", exception );
94 }
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108 private Set<Artifact> removeAll( Set<Artifact> start, Set<Artifact> remove )
109 {
110 Set<Artifact> results = new LinkedHashSet<Artifact>( start.size() );
111
112 for ( Artifact artifact : start )
113 {
114 boolean found = false;
115
116 for ( Artifact artifact2 : remove )
117 {
118 if ( artifact.getDependencyConflictId().equals( artifact2.getDependencyConflictId() ) )
119 {
120 found = true;
121 break;
122 }
123 }
124
125 if ( !found )
126 {
127 results.add( artifact );
128 }
129 }
130
131 return results;
132 }
133
134
135
136 private Map<Artifact, Set<String>> buildArtifactClassMap( MavenProject project )
137 throws IOException
138 {
139 Map<Artifact, Set<String>> artifactClassMap = new LinkedHashMap<Artifact, Set<String>>();
140
141 @SuppressWarnings( "unchecked" )
142 Set<Artifact> dependencyArtifacts = project.getArtifacts();
143
144 for ( Artifact artifact : dependencyArtifacts )
145 {
146 File file = artifact.getFile();
147
148 if ( file != null && (file.getName().endsWith( ".jar" ) || file.isDirectory()))
149 {
150 URL url = file.toURL();
151
152 Set<String> classes = classAnalyzer.analyze( url );
153
154 artifactClassMap.put( artifact, classes );
155 }
156 }
157
158 return artifactClassMap;
159 }
160
161 protected Set<String> buildDependencyClasses( MavenProject project )
162 throws IOException
163 {
164 Set<String> dependencyClasses = new HashSet<String>();
165
166 String outputDirectory = project.getBuild().getOutputDirectory();
167 dependencyClasses.addAll( buildDependencyClasses( outputDirectory ) );
168
169 String testOutputDirectory = project.getBuild().getTestOutputDirectory();
170 dependencyClasses.addAll( buildDependencyClasses( testOutputDirectory ) );
171
172 return dependencyClasses;
173 }
174
175 private Set<String> buildDependencyClasses( String path )
176 throws IOException
177 {
178 URL url = new File( path ).toURI().toURL();
179
180 return dependencyAnalyzer.analyze( url );
181 }
182
183 private Set<Artifact> buildDeclaredArtifacts( MavenProject project )
184 {
185 @SuppressWarnings( "unchecked" )
186 Set<Artifact> declaredArtifacts = project.getDependencyArtifacts();
187
188 if ( declaredArtifacts == null )
189 {
190 declaredArtifacts = Collections.<Artifact>emptySet();
191 }
192
193 return declaredArtifacts;
194 }
195
196 private Set<Artifact> buildUsedArtifacts( Map<Artifact, Set<String>> artifactClassMap, Set<String> dependencyClasses )
197 {
198 Set<Artifact> usedArtifacts = new HashSet<Artifact>();
199
200 for ( String className : dependencyClasses )
201 {
202 Artifact artifact = findArtifactForClassName( artifactClassMap, className );
203
204 if ( artifact != null )
205 {
206 usedArtifacts.add( artifact );
207 }
208 }
209
210 return usedArtifacts;
211 }
212
213 protected Artifact findArtifactForClassName( Map<Artifact, Set<String>> artifactClassMap, String className )
214 {
215 for ( Map.Entry<Artifact, Set<String>> entry : artifactClassMap.entrySet() )
216 {
217 if ( entry.getValue().contains( className ) )
218 {
219 return entry.getKey();
220 }
221 }
222
223 return null;
224 }
225 }