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.ManagedRepositoryContent;
29 import org.apache.archiva.repository.events.RepositoryListener;
30 import org.apache.archiva.repository.layout.LayoutException;
31 import org.apache.commons.lang.time.DateUtils;
33 import java.io.IOException;
34 import java.nio.file.Files;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.text.ParseException;
38 import java.text.SimpleDateFormat;
39 import java.util.ArrayList;
40 import java.util.Calendar;
41 import java.util.Collections;
42 import java.util.Date;
43 import java.util.HashSet;
44 import java.util.List;
46 import java.util.regex.Matcher;
49 * Purge from repository all snapshots older than the specified days in the repository configuration.
51 public class DaysOldRepositoryPurge
52 extends AbstractRepositoryPurge
54 private SimpleDateFormat timestampParser;
56 private int retentionPeriod;
58 private int retentionCount;
60 public DaysOldRepositoryPurge( ManagedRepositoryContent repository, int retentionPeriod, int retentionCount,
61 RepositorySession repositorySession, List<RepositoryListener> listeners )
63 super( repository, repositorySession, listeners );
64 this.retentionPeriod = retentionPeriod;
65 this.retentionCount = retentionCount;
66 timestampParser = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
67 timestampParser.setTimeZone( DateUtils.UTC_TIME_ZONE );
71 public void process( String path )
72 throws RepositoryPurgeException
76 Path artifactFile = Paths.get( repository.getRepoRoot( ), path );
78 if ( !Files.exists(artifactFile) )
83 ArtifactReference artifact = repository.toArtifactReference( path );
85 Calendar olderThanThisDate = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
86 olderThanThisDate.add( Calendar.DATE, -retentionPeriod );
88 // respect retention count
89 VersionedReference reference = new VersionedReference( );
90 reference.setGroupId( artifact.getGroupId( ) );
91 reference.setArtifactId( artifact.getArtifactId( ) );
92 reference.setVersion( artifact.getVersion( ) );
94 List<String> versions = new ArrayList<>( repository.getVersions( reference ) );
96 Collections.sort( versions, VersionComparator.getInstance( ) );
98 if ( retentionCount > versions.size( ) )
100 // Done. nothing to do here. skip it.
104 int countToPurge = versions.size( ) - retentionCount;
106 Set<ArtifactReference> artifactsToDelete = new HashSet<>( );
107 for ( String version : versions )
109 if ( countToPurge-- <= 0 )
114 ArtifactReference newArtifactReference = repository.toArtifactReference(
115 artifactFile.toAbsolutePath( ).toString() );
116 newArtifactReference.setVersion( version );
118 Path newArtifactFile = repository.toFile( newArtifactReference );
120 // Is this a generic snapshot "1.0-SNAPSHOT" ?
121 if ( VersionUtil.isGenericSnapshot( newArtifactReference.getVersion( ) ) )
123 if ( Files.getLastModifiedTime( newArtifactFile ).toMillis() < olderThanThisDate.getTimeInMillis( ) )
125 artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) );
128 // Is this a timestamp snapshot "1.0-20070822.123456-42" ?
129 else if ( VersionUtil.isUniqueSnapshot( newArtifactReference.getVersion( ) ) )
131 Calendar timestampCal = uniqueSnapshotToCalendar( newArtifactReference.getVersion( ) );
133 if ( timestampCal.getTimeInMillis( ) < olderThanThisDate.getTimeInMillis( ) )
135 artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) );
139 purge( artifactsToDelete );
141 catch ( ContentNotFoundException | IOException e )
143 throw new RepositoryPurgeException( e.getMessage( ), e );
145 catch ( LayoutException e )
147 log.debug( "Not processing file that is not an artifact: {}", e.getMessage( ) );
151 private Calendar uniqueSnapshotToCalendar( String version )
153 // The latestVersion will contain the full version string "1.0-alpha-5-20070821.213044-8"
154 // This needs to be broken down into ${base}-${timestamp}-${build_number}
156 Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( version );
159 Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
160 if ( mtimestamp.matches( ) )
162 String tsDate = mtimestamp.group( 1 );
163 String tsTime = mtimestamp.group( 2 );
168 versionDate = timestampParser.parse( tsDate + "." + tsTime );
169 Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
170 cal.setTime( versionDate );
174 catch ( ParseException e )