1 package org.apache.archiva.consumers.core.repository;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.common.utils.VersionComparator;
23 import org.apache.archiva.common.utils.VersionUtil;
24 import org.apache.archiva.metadata.repository.RepositorySession;
25 import org.apache.archiva.model.ArtifactReference;
26 import org.apache.archiva.model.VersionedReference;
27 import org.apache.archiva.repository.ContentNotFoundException;
28 import org.apache.archiva.repository.LayoutException;
29 import org.apache.archiva.repository.ManagedRepositoryContent;
30 import org.apache.archiva.repository.events.RepositoryListener;
31 import org.apache.archiva.repository.storage.StorageAsset;
32 import org.apache.commons.lang3.time.DateUtils;
34 import java.io.IOException;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.text.ParseException;
39 import java.text.SimpleDateFormat;
41 import java.util.regex.Matcher;
44 * Purge from repository all snapshots older than the specified days in the repository configuration.
46 public class DaysOldRepositoryPurge
47 extends AbstractRepositoryPurge
49 private SimpleDateFormat timestampParser;
51 private int retentionPeriod;
53 private int retentionCount;
55 public DaysOldRepositoryPurge( ManagedRepositoryContent repository, int retentionPeriod, int retentionCount,
56 RepositorySession repositorySession, List<RepositoryListener> listeners )
58 super( repository, repositorySession, listeners );
59 this.retentionPeriod = retentionPeriod;
60 this.retentionCount = retentionCount;
61 timestampParser = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
62 timestampParser.setTimeZone( TimeZone.getTimeZone("UTC"));
66 public void process( String path )
67 throws RepositoryPurgeException
71 Path artifactFile = Paths.get( repository.getRepoRoot( ), path );
73 if ( !Files.exists(artifactFile) )
78 ArtifactReference artifact = repository.toArtifactReference( path );
80 Calendar olderThanThisDate = Calendar.getInstance( TimeZone.getTimeZone("UTC") );
81 olderThanThisDate.add( Calendar.DATE, -retentionPeriod );
83 // respect retention count
84 VersionedReference reference = new VersionedReference( );
85 reference.setGroupId( artifact.getGroupId( ) );
86 reference.setArtifactId( artifact.getArtifactId( ) );
87 reference.setVersion( artifact.getVersion( ) );
89 List<String> versions = new ArrayList<>( repository.getVersions( reference ) );
91 Collections.sort( versions, VersionComparator.getInstance( ) );
93 if ( retentionCount > versions.size( ) )
95 // Done. nothing to do here. skip it.
99 int countToPurge = versions.size( ) - retentionCount;
101 Set<ArtifactReference> artifactsToDelete = new HashSet<>( );
102 for ( String version : versions )
104 if ( countToPurge-- <= 0 )
109 ArtifactReference newArtifactReference = repository.toArtifactReference(
110 artifactFile.toAbsolutePath( ).toString() );
111 newArtifactReference.setVersion( version );
113 StorageAsset newArtifactFile = repository.toFile( newArtifactReference );
115 // Is this a generic snapshot "1.0-SNAPSHOT" ?
116 if ( VersionUtil.isGenericSnapshot( newArtifactReference.getVersion( ) ) )
118 if ( newArtifactFile.getModificationTime().toEpochMilli() < olderThanThisDate.getTimeInMillis( ) )
120 artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) );
123 // Is this a timestamp snapshot "1.0-20070822.123456-42" ?
124 else if ( VersionUtil.isUniqueSnapshot( newArtifactReference.getVersion( ) ) )
126 Calendar timestampCal = uniqueSnapshotToCalendar( newArtifactReference.getVersion( ) );
128 if ( timestampCal.getTimeInMillis( ) < olderThanThisDate.getTimeInMillis( ) )
130 artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) );
134 purge( artifactsToDelete );
136 catch ( ContentNotFoundException e )
138 throw new RepositoryPurgeException( e.getMessage( ), e );
140 catch ( LayoutException e )
142 log.debug( "Not processing file that is not an artifact: {}", e.getMessage( ) );
146 private Calendar uniqueSnapshotToCalendar( String version )
148 // The latestVersion will contain the full version string "1.0-alpha-5-20070821.213044-8"
149 // This needs to be broken down into ${base}-${timestamp}-${build_number}
151 Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( version );
154 Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
155 if ( mtimestamp.matches( ) )
157 String tsDate = mtimestamp.group( 1 );
158 String tsTime = mtimestamp.group( 2 );
163 versionDate = timestampParser.parse( tsDate + "." + tsTime );
164 Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("UTC") );
165 cal.setTime( versionDate );
169 catch ( ParseException e )