1 package org.apache.maven.plugin.dependency;
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.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33
34 import org.apache.maven.artifact.Artifact;
35 import org.apache.maven.artifact.ArtifactUtils;
36 import org.apache.maven.artifact.factory.ArtifactFactory;
37 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
38 import org.apache.maven.artifact.repository.ArtifactRepository;
39 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
40 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
41 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
42 import org.apache.maven.artifact.resolver.ArtifactResolver;
43 import org.apache.maven.artifact.versioning.VersionRange;
44 import org.apache.maven.model.Dependency;
45 import org.apache.maven.plugin.AbstractMojo;
46 import org.apache.maven.plugin.MojoExecutionException;
47 import org.apache.maven.plugin.MojoFailureException;
48 import org.apache.maven.project.MavenProject;
49 import org.codehaus.plexus.util.FileUtils;
50
51
52
53
54
55
56
57
58
59
60
61
62 public class PurgeLocalRepositoryMojo
63 extends AbstractMojo
64 {
65
66 public static final String FILE_FUZZINESS = "file";
67
68 public static final String VERSION_FUZZINESS = "version";
69
70 public static final String ARTIFACT_ID_FUZZINESS = "artifactId";
71
72 public static final String GROUP_ID_FUZZINESS = "groupId";
73
74
75
76
77
78
79
80
81
82 private List<MavenProject> projects;
83
84
85
86
87
88
89
90 private List<String> excludes;
91
92
93
94
95
96
97
98
99
100 private String exclude;
101
102
103
104
105
106
107
108
109 private boolean reResolve;
110
111
112
113
114
115
116
117
118 private ArtifactRepository localRepository;
119
120
121
122
123
124
125
126 private ArtifactResolver resolver;
127
128
129
130
131
132
133 private ArtifactMetadataSource source;
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 private String resolutionFuzziness;
151
152
153
154
155
156
157
158 private boolean actTransitively;
159
160
161
162
163
164
165 private ArtifactFactory factory;
166
167
168
169
170
171
172 private boolean verbose;
173
174 public void execute()
175 throws MojoExecutionException, MojoFailureException
176 {
177 List<String> exclusionPatterns = buildExclusionPatternsList();
178
179 for ( MavenProject project : projects )
180 {
181 try
182 {
183 refreshDependenciesForProject( project, exclusionPatterns );
184 }
185 catch ( ArtifactResolutionException e )
186 {
187 MojoFailureException failure = new MojoFailureException( this,
188 "Failed to refresh project dependencies for: "
189 + project.getId(),
190 "Artifact resolution failed for project: "
191 + project.getId() );
192 failure.initCause( e );
193
194 throw failure;
195 }
196 }
197 }
198
199 private List<String> buildExclusionPatternsList()
200 {
201 List<String> patterns = new ArrayList<String>();
202
203 if ( exclude != null )
204 {
205 String[] elements = exclude.split( " ?, ?" );
206
207 patterns.addAll( Arrays.asList( elements ) );
208 }
209 else if ( excludes != null && !excludes.isEmpty() )
210 {
211 patterns.addAll( excludes );
212 }
213
214 return patterns;
215 }
216
217 private Map<String, Artifact> createArtifactMap( MavenProject project )
218 {
219 Map<String, Artifact> artifactMap = Collections.emptyMap();
220
221 List<Dependency> dependencies = project.getDependencies();
222
223 List<ArtifactRepository> remoteRepositories = Collections.emptyList();
224
225 Set<Artifact> dependencyArtifacts = new HashSet<Artifact>();
226
227 for ( Dependency dependency : dependencies )
228 {
229 VersionRange vr = VersionRange.createFromVersion( dependency.getVersion() );
230
231 Artifact artifact = factory.createDependencyArtifact( dependency.getGroupId(), dependency.getArtifactId(),
232 vr, dependency.getType(), dependency.getClassifier(),
233 dependency.getScope() );
234 dependencyArtifacts.add( artifact );
235 }
236
237 if ( actTransitively )
238 {
239 try
240 {
241 ArtifactResolutionResult result = resolver.resolveTransitively( dependencyArtifacts, project
242 .getArtifact(), remoteRepositories, localRepository, source );
243
244 artifactMap = ArtifactUtils.artifactMapByVersionlessId( result.getArtifacts() );
245 }
246 catch ( ArtifactResolutionException e )
247 {
248 verbose( "Skipping: " + e.getArtifactId() + ". It cannot be resolved." );
249 }
250 catch ( ArtifactNotFoundException e )
251 {
252 verbose( "Skipping: " + e.getArtifactId() + ". It cannot be resolved." );
253 }
254 }
255 else
256 {
257 artifactMap = new HashMap<String, Artifact>();
258 for ( Artifact artifact : dependencyArtifacts )
259 {
260 try
261 {
262 resolver.resolve( artifact, remoteRepositories, localRepository );
263
264 artifactMap.put( ArtifactUtils.versionlessKey( artifact ), artifact );
265 }
266 catch ( ArtifactResolutionException e )
267 {
268 verbose( "Skipping: " + e.getArtifactId() + ". It cannot be resolved." );
269 }
270 catch ( ArtifactNotFoundException e )
271 {
272 verbose( "Skipping: " + e.getArtifactId() + ". It cannot be resolved." );
273 }
274 }
275 }
276
277 return artifactMap;
278 }
279
280 private void verbose( String message )
281 {
282 if ( verbose || getLog().isDebugEnabled() )
283 {
284 getLog().info( message );
285 }
286 }
287
288 private void refreshDependenciesForProject( MavenProject project, List<String> exclusionPatterns )
289 throws ArtifactResolutionException, MojoFailureException
290 {
291 Map<String, Artifact> deps = createArtifactMap( project );
292
293 if ( deps.isEmpty() )
294 {
295 getLog().info( "Nothing to do for project: " + project.getId() );
296 return;
297 }
298
299 if ( !exclusionPatterns.isEmpty() )
300 {
301 for ( String excludedKey : exclusionPatterns )
302 {
303 if ( GROUP_ID_FUZZINESS.equals( resolutionFuzziness ) )
304 {
305 verbose( "Excluding groupId: " + excludedKey + " from refresh operation for project: "
306 + project.getId() );
307
308 for ( Iterator<Map.Entry<String, Artifact>> deps_it = deps.entrySet().iterator(); deps_it.hasNext(); )
309 {
310 Map.Entry<String, Artifact> dependency = deps_it.next();
311
312 Artifact artifact = dependency.getValue();
313
314 if ( artifact.getGroupId().equals( excludedKey ) )
315 {
316 deps_it.remove();
317 }
318 }
319 }
320 else
321 {
322 verbose( "Excluding: " + excludedKey + " from refresh operation for project: " + project.getId() );
323
324 deps.remove( excludedKey );
325 }
326 }
327 }
328
329 verbose( "Processing dependencies for project: " + project.getId() );
330
331 List<Artifact> missingArtifacts = new ArrayList<Artifact>();
332 for ( Map.Entry<String, Artifact> entry : deps.entrySet() )
333 {
334 Artifact artifact = entry.getValue();
335
336 verbose( "Processing artifact: " + artifact.getId() );
337
338 File deleteTarget = findDeleteTarget( artifact );
339
340 verbose( "Deleting: " + deleteTarget );
341
342 if ( deleteTarget.isDirectory() )
343 {
344 try
345 {
346 FileUtils.deleteDirectory( deleteTarget );
347 }
348 catch ( IOException e )
349 {
350 throw new MojoFailureException( this, "Cannot delete dependency from the local repository: "
351 + artifact.getId(), "Failed to delete: " + deleteTarget );
352 }
353 }
354 else
355 {
356 deleteTarget.delete();
357 }
358
359 if ( reResolve )
360 {
361 verbose( "Re-resolving." );
362
363 artifact.setResolved( false );
364
365 try
366 {
367 resolver.resolveAlways( artifact, project.getRemoteArtifactRepositories(), localRepository );
368 }
369 catch ( ArtifactResolutionException e )
370 {
371 getLog().debug( e.getMessage() );
372 missingArtifacts.add( artifact );
373 }
374 catch ( ArtifactNotFoundException e )
375 {
376 getLog().debug( e.getMessage() );
377 missingArtifacts.add( artifact );
378 }
379 }
380 }
381
382 if ( missingArtifacts.size() > 0 )
383 {
384 String message = "required artifacts missing:\n";
385 for ( Artifact missingArtifact : missingArtifacts )
386 {
387 message += " " + missingArtifact.getId() + "\n";
388 }
389 message += "\nfor the artifact:";
390
391 throw new ArtifactResolutionException( message, project.getArtifact(), project
392 .getRemoteArtifactRepositories() );
393 }
394
395 }
396
397 private File findDeleteTarget( Artifact artifact )
398 {
399 File deleteTarget = artifact.getFile();
400
401 if ( GROUP_ID_FUZZINESS.equals( resolutionFuzziness ) )
402 {
403
404 deleteTarget = deleteTarget.getParentFile().getParentFile();
405
406
407 deleteTarget = deleteTarget.getParentFile();
408
409 String[] path = localRepository.pathOf( artifact ).split( "\\/" );
410
411
412
413
414 int groupParts = path.length - 4;
415
416 File parent = deleteTarget.getParentFile();
417 int count = 0;
418 while ( count++ < groupParts )
419 {
420
421
422
423
424
425 if ( parent.list().length < 2 )
426 {
427 deleteTarget = parent;
428
429
430 parent = deleteTarget.getParentFile();
431 }
432 else
433 {
434
435
436 break;
437 }
438 }
439
440 }
441 else if ( ARTIFACT_ID_FUZZINESS.equals( resolutionFuzziness ) )
442 {
443
444 deleteTarget = deleteTarget.getParentFile().getParentFile();
445 }
446 else if ( VERSION_FUZZINESS.equals( resolutionFuzziness ) )
447 {
448
449 deleteTarget = deleteTarget.getParentFile();
450 }
451
452
453 return deleteTarget;
454 }
455
456 }