]> source.dussan.org Git - archiva.git/blob
6c6607d2d282268f83cb0dcc39a8883f027bf6d8
[archiva.git] /
1 package org.apache.archiva.consumers.core.repository;
2
3 /*
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
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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.commons.lang.time.DateUtils;
32
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;
45 import java.util.Set;
46 import java.util.regex.Matcher;
47
48 /**
49  * Purge from repository all snapshots older than the specified days in the repository configuration.
50  */
51 public class DaysOldRepositoryPurge
52     extends AbstractRepositoryPurge
53 {
54     private SimpleDateFormat timestampParser;
55
56     private int retentionPeriod;
57
58     private int retentionCount;
59
60     public DaysOldRepositoryPurge( ManagedRepositoryContent repository, int retentionPeriod, int retentionCount,
61                                    RepositorySession repositorySession, List<RepositoryListener> listeners )
62     {
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 );
68     }
69
70     @Override
71     public void process( String path )
72         throws RepositoryPurgeException
73     {
74         try
75         {
76             Path artifactFile = Paths.get( repository.getRepoRoot( ), path );
77
78             if ( !Files.exists(artifactFile) )
79             {
80                 return;
81             }
82
83             ArtifactReference artifact = repository.toArtifactReference( path );
84
85             Calendar olderThanThisDate = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
86             olderThanThisDate.add( Calendar.DATE, -retentionPeriod );
87
88             // respect retention count
89             VersionedReference reference = new VersionedReference( );
90             reference.setGroupId( artifact.getGroupId( ) );
91             reference.setArtifactId( artifact.getArtifactId( ) );
92             reference.setVersion( artifact.getVersion( ) );
93
94             List<String> versions = new ArrayList<>( repository.getVersions( reference ) );
95
96             Collections.sort( versions, VersionComparator.getInstance( ) );
97
98             if ( retentionCount > versions.size( ) )
99             {
100                 // Done. nothing to do here. skip it.
101                 return;
102             }
103
104             int countToPurge = versions.size( ) - retentionCount;
105
106             Set<ArtifactReference> artifactsToDelete = new HashSet<>( );
107             for ( String version : versions )
108             {
109                 if ( countToPurge-- <= 0 )
110                 {
111                     break;
112                 }
113
114                 ArtifactReference newArtifactReference = repository.toArtifactReference(
115                     artifactFile.toAbsolutePath( ).toString() );
116                 newArtifactReference.setVersion( version );
117
118                 Path newArtifactFile = repository.toFile( newArtifactReference );
119
120                 // Is this a generic snapshot "1.0-SNAPSHOT" ?
121                 if ( VersionUtil.isGenericSnapshot( newArtifactReference.getVersion( ) ) )
122                 {
123                     if ( Files.getLastModifiedTime( newArtifactFile ).toMillis() < olderThanThisDate.getTimeInMillis( ) )
124                     {
125                         artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) );
126                     }
127                 }
128                 // Is this a timestamp snapshot "1.0-20070822.123456-42" ?
129                 else if ( VersionUtil.isUniqueSnapshot( newArtifactReference.getVersion( ) ) )
130                 {
131                     Calendar timestampCal = uniqueSnapshotToCalendar( newArtifactReference.getVersion( ) );
132
133                     if ( timestampCal.getTimeInMillis( ) < olderThanThisDate.getTimeInMillis( ) )
134                     {
135                         artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) );
136                     }
137                 }
138             }
139             purge( artifactsToDelete );
140         }
141         catch ( ContentNotFoundException | IOException e )
142         {
143             throw new RepositoryPurgeException( e.getMessage( ), e );
144         }
145         catch ( LayoutException e )
146         {
147             log.debug( "Not processing file that is not an artifact: {}", e.getMessage( ) );
148         }
149     }
150
151     private Calendar uniqueSnapshotToCalendar( String version )
152     {
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}
155
156         Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( version );
157         if ( m.matches( ) )
158         {
159             Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
160             if ( mtimestamp.matches( ) )
161             {
162                 String tsDate = mtimestamp.group( 1 );
163                 String tsTime = mtimestamp.group( 2 );
164
165                 Date versionDate;
166                 try
167                 {
168                     versionDate = timestampParser.parse( tsDate + "." + tsTime );
169                     Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
170                     cal.setTime( versionDate );
171
172                     return cal;
173                 }
174                 catch ( ParseException e )
175                 {
176                     // Invalid Date/Time
177                     return null;
178                 }
179             }
180         }
181         return null;
182     }
183
184 }