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 | 5 | 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 | 5 | Map<Artifact, Set<String>> artifactClassMap = buildArtifactClassMap( project ); |
72 | |
|
73 | 5 | Set<String> dependencyClasses = buildDependencyClasses( project ); |
74 | |
|
75 | 5 | Set<Artifact> declaredArtifacts = buildDeclaredArtifacts( project ); |
76 | |
|
77 | 5 | Set<Artifact> usedArtifacts = buildUsedArtifacts( artifactClassMap, dependencyClasses ); |
78 | |
|
79 | 5 | Set<Artifact> usedDeclaredArtifacts = new LinkedHashSet<Artifact>( declaredArtifacts ); |
80 | 5 | usedDeclaredArtifacts.retainAll( usedArtifacts ); |
81 | |
|
82 | 5 | Set<Artifact> usedUndeclaredArtifacts = new LinkedHashSet<Artifact>( usedArtifacts ); |
83 | 5 | usedUndeclaredArtifacts = removeAll( usedUndeclaredArtifacts, declaredArtifacts ); |
84 | |
|
85 | 5 | Set<Artifact> unusedDeclaredArtifacts = new LinkedHashSet<Artifact>( declaredArtifacts ); |
86 | 5 | unusedDeclaredArtifacts = removeAll( unusedDeclaredArtifacts, usedArtifacts ); |
87 | |
|
88 | 5 | return new ProjectDependencyAnalysis( usedDeclaredArtifacts, usedUndeclaredArtifacts, |
89 | |
unusedDeclaredArtifacts ); |
90 | |
} |
91 | 0 | catch ( IOException exception ) |
92 | |
{ |
93 | 0 | 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 | 10 | Set<Artifact> results = new LinkedHashSet<Artifact>( start.size() ); |
111 | |
|
112 | 10 | for ( Artifact artifact : start ) |
113 | |
{ |
114 | 8 | boolean found = false; |
115 | |
|
116 | 8 | for ( Artifact artifact2 : remove ) |
117 | |
{ |
118 | 9 | if ( artifact.getDependencyConflictId().equals( artifact2.getDependencyConflictId() ) ) |
119 | |
{ |
120 | 6 | found = true; |
121 | 6 | break; |
122 | |
} |
123 | |
} |
124 | |
|
125 | 8 | if ( !found ) |
126 | |
{ |
127 | 2 | results.add( artifact ); |
128 | |
} |
129 | 8 | } |
130 | |
|
131 | 10 | return results; |
132 | |
} |
133 | |
|
134 | |
|
135 | |
|
136 | |
private Map<Artifact, Set<String>> buildArtifactClassMap( MavenProject project ) |
137 | |
throws IOException |
138 | |
{ |
139 | 5 | Map<Artifact, Set<String>> artifactClassMap = new LinkedHashMap<Artifact, Set<String>>(); |
140 | |
|
141 | |
@SuppressWarnings( "unchecked" ) |
142 | 5 | Set<Artifact> dependencyArtifacts = project.getArtifacts(); |
143 | |
|
144 | 5 | for ( Artifact artifact : dependencyArtifacts ) |
145 | |
{ |
146 | 5 | File file = artifact.getFile(); |
147 | |
|
148 | 5 | if ( file != null && file.getName().endsWith( ".jar" ) ) |
149 | |
{ |
150 | 5 | URL url = file.toURL(); |
151 | |
|
152 | 5 | Set<String> classes = classAnalyzer.analyze( url ); |
153 | |
|
154 | 5 | artifactClassMap.put( artifact, classes ); |
155 | |
} |
156 | 5 | } |
157 | |
|
158 | 5 | return artifactClassMap; |
159 | |
} |
160 | |
|
161 | |
protected Set<String> buildDependencyClasses( MavenProject project ) |
162 | |
throws IOException |
163 | |
{ |
164 | 5 | Set<String> dependencyClasses = new HashSet<String>(); |
165 | |
|
166 | 5 | String outputDirectory = project.getBuild().getOutputDirectory(); |
167 | 5 | dependencyClasses.addAll( buildDependencyClasses( outputDirectory ) ); |
168 | |
|
169 | 5 | String testOutputDirectory = project.getBuild().getTestOutputDirectory(); |
170 | 5 | dependencyClasses.addAll( buildDependencyClasses( testOutputDirectory ) ); |
171 | |
|
172 | 5 | return dependencyClasses; |
173 | |
} |
174 | |
|
175 | |
private Set<String> buildDependencyClasses( String path ) |
176 | |
throws IOException |
177 | |
{ |
178 | 10 | URL url = new File( path ).toURI().toURL(); |
179 | |
|
180 | 10 | return dependencyAnalyzer.analyze( url ); |
181 | |
} |
182 | |
|
183 | |
private Set<Artifact> buildDeclaredArtifacts( MavenProject project ) |
184 | |
{ |
185 | |
@SuppressWarnings( "unchecked" ) |
186 | 5 | Set<Artifact> declaredArtifacts = project.getDependencyArtifacts(); |
187 | |
|
188 | 5 | if ( declaredArtifacts == null ) |
189 | |
{ |
190 | 0 | declaredArtifacts = Collections.<Artifact>emptySet(); |
191 | |
} |
192 | |
|
193 | 5 | return declaredArtifacts; |
194 | |
} |
195 | |
|
196 | |
private Set<Artifact> buildUsedArtifacts( Map<Artifact, Set<String>> artifactClassMap, Set<String> dependencyClasses ) |
197 | |
{ |
198 | 5 | Set<Artifact> usedArtifacts = new HashSet<Artifact>(); |
199 | |
|
200 | 5 | for ( String className : dependencyClasses ) |
201 | |
{ |
202 | 12 | Artifact artifact = findArtifactForClassName( artifactClassMap, className ); |
203 | |
|
204 | 12 | if ( artifact != null ) |
205 | |
{ |
206 | 4 | usedArtifacts.add( artifact ); |
207 | |
} |
208 | 12 | } |
209 | |
|
210 | 5 | return usedArtifacts; |
211 | |
} |
212 | |
|
213 | |
protected Artifact findArtifactForClassName( Map<Artifact, Set<String>> artifactClassMap, String className ) |
214 | |
{ |
215 | 12 | for ( Map.Entry<Artifact, Set<String>> entry : artifactClassMap.entrySet() ) |
216 | |
{ |
217 | 16 | if ( entry.getValue().contains( className ) ) |
218 | |
{ |
219 | 4 | return entry.getKey(); |
220 | |
} |
221 | |
} |
222 | |
|
223 | 8 | return null; |
224 | |
} |
225 | |
} |