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 org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.ArtifactUtils;
24 import org.apache.maven.artifact.factory.ArtifactFactory;
25 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
26 import org.apache.maven.artifact.repository.ArtifactRepository;
27 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
28 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
29 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
30 import org.apache.maven.artifact.resolver.ArtifactResolver;
31 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
32 import org.apache.maven.artifact.versioning.VersionRange;
33 import org.apache.maven.model.Dependency;
34 import org.apache.maven.plugin.AbstractMojo;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.plugin.MojoFailureException;
37 import org.apache.maven.project.MavenProject;
38 import org.codehaus.plexus.util.FileUtils;
39
40 import java.io.File;
41 import java.io.IOException;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collections;
45 import java.util.HashMap;
46 import java.util.HashSet;
47 import java.util.Iterator;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.Set;
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
175
176
177
178
179
180 private boolean snapshotsOnly;
181
182
183 public void execute()
184 throws MojoExecutionException, MojoFailureException
185 {
186 List<String> exclusionPatterns = buildExclusionPatternsList();
187
188 for ( MavenProject project : projects )
189 {
190 try
191 {
192 refreshDependenciesForProject( project, exclusionPatterns );
193 }
194 catch ( ArtifactResolutionException e )
195 {
196 MojoFailureException failure =
197 new MojoFailureException( this, "Failed to refresh project dependencies for: " + project.getId(),
198 "Artifact resolution failed for project: " + project.getId() );
199 failure.initCause( e );
200
201 throw failure;
202 }
203 }
204 }
205
206 private List<String> buildExclusionPatternsList()
207 {
208 List<String> patterns = new ArrayList<String>();
209
210 if ( exclude != null )
211 {
212 String[] elements = exclude.split( " ?, ?" );
213
214 patterns.addAll( Arrays.asList( elements ) );
215 }
216 else if ( excludes != null && !excludes.isEmpty() )
217 {
218 patterns.addAll( excludes );
219 }
220
221 return patterns;
222 }
223
224 private Map<String, Artifact> createArtifactMap( MavenProject project )
225 {
226 Map<String, Artifact> artifactMap = Collections.emptyMap();
227
228 List<Dependency> dependencies = project.getDependencies();
229
230 List<ArtifactRepository> remoteRepositories = Collections.emptyList();
231
232 Set<Artifact> dependencyArtifacts = new HashSet<Artifact>();
233
234 for ( Dependency dependency : dependencies )
235 {
236 VersionRange vr = VersionRange.createFromVersion( dependency.getVersion() );
237
238 Artifact artifact =
239 factory.createDependencyArtifact( dependency.getGroupId(), dependency.getArtifactId(), vr,
240 dependency.getType(), dependency.getClassifier(),
241 dependency.getScope() );
242 if ( snapshotsOnly && !artifact.isSnapshot() )
243 {
244 continue;
245 }
246 dependencyArtifacts.add( artifact );
247 }
248
249 if ( actTransitively )
250 {
251 try
252 {
253 ArtifactResolutionResult result;
254
255 if ( snapshotsOnly )
256 {
257 result = resolver.resolveTransitively( dependencyArtifacts, project.getArtifact(), localRepository,
258 remoteRepositories, source, new ArtifactFilter()
259 {
260 public boolean include( Artifact artifact )
261 {
262 return artifact.isSnapshot();
263 }
264 } );
265 }
266 else
267 {
268 result =
269 resolver.resolveTransitively( dependencyArtifacts, project.getArtifact(), remoteRepositories,
270 localRepository, source );
271 }
272
273 artifactMap = ArtifactUtils.artifactMapByVersionlessId( result.getArtifacts() );
274 }
275 catch ( ArtifactResolutionException e )
276 {
277 verbose( "Skipping: " + e.getArtifactId() + ". It cannot be resolved." );
278 }
279 catch ( ArtifactNotFoundException e )
280 {
281 verbose( "Skipping: " + e.getArtifactId() + ". It cannot be resolved." );
282 }
283 }
284 else
285 {
286 artifactMap = new HashMap<String, Artifact>();
287 for ( Artifact artifact : dependencyArtifacts )
288 {
289 try
290 {
291 resolver.resolve( artifact, remoteRepositories, localRepository );
292
293 artifactMap.put( ArtifactUtils.versionlessKey( artifact ), artifact );
294 }
295 catch ( ArtifactResolutionException e )
296 {
297 verbose( "Skipping: " + e.getArtifactId() + ". It cannot be resolved." );
298 }
299 catch ( ArtifactNotFoundException e )
300 {
301 verbose( "Skipping: " + e.getArtifactId() + ". It cannot be resolved." );
302 }
303 }
304 }
305
306 return artifactMap;
307 }
308
309 private void verbose( String message )
310 {
311 if ( verbose || getLog().isDebugEnabled() )
312 {
313 getLog().info( message );
314 }
315 }
316
317 private void refreshDependenciesForProject( MavenProject project, List<String> exclusionPatterns )
318 throws ArtifactResolutionException, MojoFailureException
319 {
320 Map<String, Artifact> deps = createArtifactMap( project );
321
322 if ( deps.isEmpty() )
323 {
324 getLog().info( "Nothing to do for project: " + project.getId() );
325 return;
326 }
327
328 if ( !exclusionPatterns.isEmpty() )
329 {
330 for ( String excludedKey : exclusionPatterns )
331 {
332 if ( GROUP_ID_FUZZINESS.equals( resolutionFuzziness ) )
333 {
334 verbose( "Excluding groupId: " + excludedKey + " from refresh operation for project: "
335 + project.getId() );
336
337 for ( Iterator<Map.Entry<String, Artifact>> deps_it = deps.entrySet().iterator();
338 deps_it.hasNext(); )
339 {
340 Map.Entry<String, Artifact> dependency = deps_it.next();
341
342 Artifact artifact = dependency.getValue();
343
344 if ( artifact.getGroupId().equals( excludedKey ) )
345 {
346 deps_it.remove();
347 }
348 }
349 }
350 else
351 {
352 verbose( "Excluding: " + excludedKey + " from refresh operation for project: " + project.getId() );
353
354 deps.remove( excludedKey );
355 }
356 }
357 }
358
359 verbose( "Processing dependencies for project: " + project.getId() );
360
361 List<Artifact> missingArtifacts = new ArrayList<Artifact>();
362 for ( Map.Entry<String, Artifact> entry : deps.entrySet() )
363 {
364 Artifact artifact = entry.getValue();
365
366 verbose( "Processing artifact: " + artifact.getId() );
367
368 File deleteTarget = findDeleteTarget( artifact );
369
370 verbose( "Deleting: " + deleteTarget );
371
372 if ( deleteTarget.isDirectory() )
373 {
374 try
375 {
376 FileUtils.deleteDirectory( deleteTarget );
377 }
378 catch ( IOException e )
379 {
380 throw new MojoFailureException( this, "Cannot delete dependency from the local repository: "
381 + artifact.getId(), "Failed to delete: " + deleteTarget );
382 }
383 }
384 else
385 {
386 deleteTarget.delete();
387 }
388
389 if ( reResolve )
390 {
391 verbose( "Re-resolving." );
392
393 artifact.setResolved( false );
394
395 try
396 {
397 resolver.resolveAlways( artifact, project.getRemoteArtifactRepositories(), localRepository );
398 }
399 catch ( ArtifactResolutionException e )
400 {
401 getLog().debug( e.getMessage() );
402 missingArtifacts.add( artifact );
403 }
404 catch ( ArtifactNotFoundException e )
405 {
406 getLog().debug( e.getMessage() );
407 missingArtifacts.add( artifact );
408 }
409 }
410 }
411
412 if ( missingArtifacts.size() > 0 )
413 {
414 String message = "required artifacts missing:\n";
415 for ( Artifact missingArtifact : missingArtifacts )
416 {
417 message += " " + missingArtifact.getId() + "\n";
418 }
419 message += "\nfor the artifact:";
420
421 throw new ArtifactResolutionException( message, project.getArtifact(),
422 project.getRemoteArtifactRepositories() );
423 }
424
425 }
426
427 private File findDeleteTarget( Artifact artifact )
428 {
429 File deleteTarget = artifact.getFile();
430
431 if ( GROUP_ID_FUZZINESS.equals( resolutionFuzziness ) )
432 {
433
434 deleteTarget = deleteTarget.getParentFile().getParentFile();
435
436
437 deleteTarget = deleteTarget.getParentFile();
438
439 String[] path = localRepository.pathOf( artifact ).split( "\\/" );
440
441
442
443
444 int groupParts = path.length - 4;
445
446 File parent = deleteTarget.getParentFile();
447 int count = 0;
448 while ( count++ < groupParts )
449 {
450
451
452
453
454
455 if ( parent.list().length < 2 )
456 {
457 deleteTarget = parent;
458
459
460 parent = deleteTarget.getParentFile();
461 }
462 else
463 {
464
465
466 break;
467 }
468 }
469
470 }
471 else if ( ARTIFACT_ID_FUZZINESS.equals( resolutionFuzziness ) )
472 {
473
474 deleteTarget = deleteTarget.getParentFile().getParentFile();
475 }
476 else if ( VERSION_FUZZINESS.equals( resolutionFuzziness ) )
477 {
478
479 deleteTarget = deleteTarget.getParentFile();
480 }
481
482
483 return deleteTarget;
484 }
485
486 }