This project has retired. For details please refer to its
Attic page.
AbstractRepositoryPurge xref
1 package org.apache.archiva.consumers.core.repository;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.archiva.common.utils.VersionUtil;
23 import org.apache.archiva.metadata.model.ArtifactMetadata;
24 import org.apache.archiva.metadata.model.facets.AuditEvent;
25 import org.apache.archiva.metadata.model.maven2.MavenArtifactFacet;
26 import org.apache.archiva.metadata.repository.*;
27 import org.apache.archiva.model.ArtifactReference;
28 import org.apache.archiva.repository.ContentNotFoundException;
29 import org.apache.archiva.repository.ManagedRepositoryContent;
30 import org.apache.archiva.metadata.audit.RepositoryListener;
31 import org.apache.archiva.repository.storage.StorageAsset;
32 import org.apache.archiva.repository.storage.StorageUtil;
33 import org.apache.commons.lang3.StringUtils;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import java.io.IOException;
38 import java.util.Collection;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Set;
44
45
46
47
48 public abstract class AbstractRepositoryPurge
49 implements RepositoryPurge
50 {
51 protected Logger log = LoggerFactory.getLogger( getClass( ) );
52
53 protected final ManagedRepositoryContent repository;
54
55 protected final RepositorySession repositorySession;
56
57 protected final List<RepositoryListener> listeners;
58
59 private Logger logger = LoggerFactory.getLogger( "org.apache.archiva.AuditLog" );
60
61 private static final char DELIM = ' ';
62
63 public AbstractRepositoryPurge( ManagedRepositoryContent repository, RepositorySession repositorySession,
64 List<RepositoryListener> listeners )
65 {
66 this.repository = repository;
67 this.repositorySession = repositorySession;
68 this.listeners = listeners;
69 }
70
71
72
73
74
75 class ArtifactInfo
76 {
77 final String namespace;
78 final String name;
79 final String projectVersion;
80 String version;
81 String classifier;
82
83 ArtifactInfo( String namespace, String name, String projectVersion, String version )
84 {
85 this.namespace = namespace;
86 this.name = name;
87 this.projectVersion = projectVersion;
88 this.version = version;
89 }
90
91 ArtifactInfo( String namespace, String name, String projectVersion )
92 {
93 this.namespace = namespace;
94 this.name = name;
95 this.projectVersion = projectVersion;
96 }
97
98
99
100
101 ArtifactInfo projectVersionLevel( )
102 {
103 return new ArtifactInfo( this.namespace, this.name, this.projectVersion );
104 }
105
106 public void setClassifier( String classifier )
107 {
108 this.classifier = classifier;
109 }
110
111 public String getNamespace( )
112 {
113 return namespace;
114 }
115
116 public String getName( )
117 {
118 return name;
119 }
120
121 public String getProjectVersion( )
122 {
123 return projectVersion;
124 }
125
126 public String getVersion( )
127 {
128 return version;
129 }
130
131 public String getClassifier( )
132 {
133 return classifier;
134 }
135
136 public boolean hasClassifier( )
137 {
138 return classifier != null && !"".equals( classifier );
139 }
140
141 @Override
142 public boolean equals( Object o )
143 {
144 if ( this == o ) return true;
145 if ( o == null || getClass( ) != o.getClass( ) ) return false;
146
147 ArtifactInfo that = (ArtifactInfo) o;
148
149 if ( !namespace.equals( that.namespace ) ) return false;
150 if ( !name.equals( that.name ) ) return false;
151 if ( !projectVersion.equals( that.projectVersion ) ) return false;
152 if ( !( version != null ? version.equals( that.version ) : that.version == null ) ) return false;
153 return classifier != null ? classifier.equals( that.classifier ) : that.classifier == null;
154 }
155
156 @Override
157 public int hashCode( )
158 {
159 int result = namespace.hashCode( );
160 result = 31 * result + name.hashCode( );
161 result = 31 * result + projectVersion.hashCode( );
162 result = 31 * result + ( version != null ? version.hashCode( ) : 0 );
163 result = 31 * result + ( classifier != null ? classifier.hashCode( ) : 0 );
164 return result;
165 }
166
167 @Override
168 public String toString( )
169 {
170 final StringBuilder sb = new StringBuilder( "ArtifactInfo{" );
171 sb.append( "namespace='" ).append( namespace ).append( '\'' );
172 sb.append( ", name='" ).append( name ).append( '\'' );
173 sb.append( ", projectVersion='" ).append( projectVersion ).append( '\'' );
174 sb.append( ", version='" ).append( version ).append( '\'' );
175 sb.append( ", classifier='" ).append( classifier ).append( '\'' );
176 sb.append( '}' );
177 return sb.toString( );
178 }
179 }
180
181
182
183
184
185
186 protected void purge( Set<ArtifactReference> references )
187 {
188 if ( references != null && !references.isEmpty( ) )
189 {
190 MetadataRepository metadataRepository = repositorySession.getRepository( );
191 Map<ArtifactInfo, ArtifactMetadata> metaRemovalList = new HashMap<>( );
192 Map<String, Collection<ArtifactMetadata>> metaResolved = new HashMap<>( );
193 for ( ArtifactReference reference : references )
194 {
195 String baseVersion = VersionUtil.getBaseVersion( reference.getVersion( ) );
196
197 String metaBaseId = reference.getGroupId( ) + "/" + reference.getArtifactId( ) + "/" + baseVersion;
198
199 if ( !metaResolved.containsKey( metaBaseId ) )
200 {
201 try
202 {
203 metaResolved.put( metaBaseId, metadataRepository.getArtifacts(repositorySession, repository.getId( ),
204 reference.getGroupId( ), reference.getArtifactId( ), baseVersion ) );
205 }
206 catch ( MetadataResolutionException e )
207 {
208 log.error( "Error during metadata retrieval {}: {}", metaBaseId, e.getMessage( ) );
209 }
210 }
211 StorageAsset artifactFile = repository.toFile( reference );
212
213 for ( RepositoryListener listener : listeners )
214 {
215 listener.deleteArtifact( metadataRepository, repository.getId( ), reference.getGroupId( ),
216 reference.getArtifactId( ), reference.getVersion( ),
217 artifactFile.getName( ));
218 }
219 try
220 {
221 artifactFile.getStorage().removeAsset(artifactFile);
222 log.debug( "File deleted: {}", artifactFile );
223 }
224 catch ( IOException e )
225 {
226 log.error( "Could not delete file {}: {}", artifactFile.toString(), e.getMessage( ), e );
227 continue;
228 }
229 try
230 {
231 repository.deleteArtifact( reference );
232 }
233 catch ( ContentNotFoundException e )
234 {
235 log.warn( "skip error deleting artifact {}: {}", reference, e.getMessage( ) );
236 }
237
238 boolean snapshotVersion = VersionUtil.isSnapshot( reference.getVersion( ) );
239
240
241
242 if ( snapshotVersion )
243 {
244 Collection<ArtifactMetadata> artifacts =
245 metaResolved.get( metaBaseId );
246 if ( artifacts != null )
247 {
248
249 for ( ArtifactMetadata artifactMetadata : artifacts )
250 {
251
252 if ( artifactMetadata.getVersion( ).equals( reference.getVersion( ) ) )
253 {
254 ArtifactInfo info = new ArtifactInfo( artifactMetadata.getNamespace( ), artifactMetadata.getProject( ), artifactMetadata.getProjectVersion( ), artifactMetadata.getVersion( ) );
255 if ( StringUtils.isNotBlank( reference.getClassifier( ) ) )
256 {
257 info.setClassifier( reference.getClassifier( ) );
258 metaRemovalList.put( info, artifactMetadata );
259 }
260 else
261 {
262
263 metaRemovalList.put( info, artifactMetadata );
264 }
265 }
266 }
267 }
268 }
269 else
270 {
271 ArtifactInfo info = new ArtifactInfo( reference.getGroupId( ), reference.getArtifactId( ), baseVersion, reference.getVersion( ) );
272 for ( ArtifactMetadata metadata : metaResolved.get( metaBaseId ) )
273 {
274 metaRemovalList.put( info, metadata );
275 }
276 }
277 triggerAuditEvent( repository.getRepository( ).getId( ), ArtifactReference.toKey( reference ),
278 AuditEvent.PURGE_ARTIFACT );
279 purgeSupportFiles( artifactFile );
280 }
281 purgeMetadata( metadataRepository, metaRemovalList );
282 try
283 {
284 repositorySession.save( );
285 }
286 catch ( org.apache.archiva.metadata.repository.MetadataSessionException e )
287 {
288 e.printStackTrace( );
289 }
290
291 }
292 }
293
294
295
296
297 private void purgeMetadata( MetadataRepository metadataRepository, Map<ArtifactInfo, ArtifactMetadata> dataList )
298 {
299 Set<ArtifactInfo> projectLevelMetadata = new HashSet<>( );
300 for ( Map.Entry<ArtifactInfo, ArtifactMetadata> infoEntry : dataList.entrySet( ) )
301 {
302 ArtifactInfo info = infoEntry.getKey( );
303 try
304 {
305 removeArtifact( metadataRepository, info, infoEntry.getValue( ) );
306 log.debug( "Removed artifact from MetadataRepository {}", info );
307 }
308 catch ( MetadataRepositoryException e )
309 {
310 log.error( "Could not remove artifact from MetadataRepository {}: {}", info, e.getMessage( ), e );
311 }
312 projectLevelMetadata.add( info.projectVersionLevel( ) );
313 }
314 try {
315 repositorySession.save( );
316 } catch (MetadataSessionException e) {
317 log.error("Could not save sesion {}", e.getMessage());
318 }
319 Collection<ArtifactMetadata> artifacts = null;
320
321 for ( ArtifactInfo info : projectLevelMetadata )
322 {
323 try
324 {
325 artifacts = metadataRepository.getArtifacts(repositorySession , repository.getId( ), info.getNamespace( ),
326 info.getName( ), info.getProjectVersion( ) );
327 if ( artifacts.size( ) == 0 )
328 {
329 metadataRepository.removeProjectVersion(repositorySession , repository.getId( ),
330 info.getNamespace( ), info.getName( ), info.getProjectVersion( ) );
331 log.debug( "Removed project version from MetadataRepository {}", info );
332 }
333 }
334 catch ( MetadataResolutionException | MetadataRepositoryException e )
335 {
336 log.error( "Could not remove project version from MetadataRepository {}: {}", info, e.getMessage( ), e );
337 }
338 }
339 try {
340 repositorySession.save( );
341 } catch (MetadataSessionException e) {
342 log.error("Could not save sesion {}", e.getMessage());
343
344 }
345
346 }
347
348
349
350
351 private void removeArtifact( MetadataRepository metadataRepository, ArtifactInfo artifactInfo, ArtifactMetadata artifactMetadata ) throws MetadataRepositoryException
352 {
353 if ( artifactInfo.hasClassifier( ) )
354 {
355
356 MavenArtifactFacet mavenArtifactFacet =
357 (MavenArtifactFacet) artifactMetadata.getFacet(
358 MavenArtifactFacet.FACET_ID );
359
360 if ( StringUtils.equals( artifactInfo.classifier,
361 mavenArtifactFacet.getClassifier( ) ) )
362 {
363 artifactMetadata.removeFacet( MavenArtifactFacet.FACET_ID );
364 String groupId = artifactInfo.getNamespace( ), artifactId =
365 artifactInfo.getName( ),
366 version = artifactInfo.getProjectVersion( );
367 MavenArtifactFacetacet.html#MavenArtifactFacet">MavenArtifactFacet mavenArtifactFacetToCompare = new MavenArtifactFacet( );
368 mavenArtifactFacetToCompare.setClassifier( artifactInfo.getClassifier( ) );
369 metadataRepository.removeFacetFromArtifact(repositorySession , repository.getId( ), groupId,
370 artifactId, version, mavenArtifactFacetToCompare );
371 try {
372 repositorySession.save( );
373 } catch (MetadataSessionException e) {
374 log.error("Could not save session {}", e.getMessage());
375 }
376 }
377 }
378 else
379 {
380 metadataRepository.removeTimestampedArtifact(repositorySession , artifactMetadata, artifactInfo.getProjectVersion( ) );
381 }
382 }
383
384 private void deleteSilently( StorageAsset path )
385 {
386 try
387 {
388 path.getStorage().removeAsset(path);
389 triggerAuditEvent( repository.getRepository( ).getId( ), path.toString( ), AuditEvent.PURGE_FILE );
390 }
391 catch ( IOException e )
392 {
393 log.error( "Error occured during file deletion {}: {} ", path, e.getMessage( ), e );
394 }
395 }
396
397
398
399
400
401
402
403
404
405
406
407 private void purgeSupportFiles( StorageAsset artifactFile )
408 {
409 StorageAsset parentDir = artifactFile.getParent( );
410
411 if ( !parentDir.exists() )
412 {
413 return;
414 }
415
416 final String artifactName = artifactFile.getName( );
417
418 try
419 {
420
421 StorageUtil.recurse(parentDir, a -> {
422 if (!a.isContainer() && a.getName().startsWith(artifactName)) deleteSilently(a);
423 }, true, 3 );
424 }
425 catch ( IOException e )
426 {
427 log.error( "Purge of support files failed {}: {}", artifactFile, e.getMessage( ), e );
428 }
429
430 }
431
432 private void triggerAuditEvent( String repoId, String resource, String action )
433 {
434 String msg =
435 repoId + DELIM + "<system-purge>" + DELIM + "<system>" + DELIM + '\"' + resource + '\"' + DELIM + '\"' +
436 action + '\"';
437
438 logger.info( msg );
439 }
440 }