1 package org.apache.continuum.purge.executor;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.lang.time.DateUtils;
23 import org.apache.continuum.purge.repository.content.RepositoryManagedContent;
24 import org.apache.maven.archiva.common.utils.VersionComparator;
25 import org.apache.maven.archiva.common.utils.VersionUtil;
26 import org.apache.maven.archiva.model.ArtifactReference;
27 import org.apache.maven.archiva.model.VersionedReference;
28 import org.apache.maven.archiva.repository.ContentNotFoundException;
29 import org.apache.maven.archiva.repository.layout.LayoutException;
30
31 import java.io.File;
32 import java.text.ParseException;
33 import java.text.SimpleDateFormat;
34 import java.util.ArrayList;
35 import java.util.Calendar;
36 import java.util.Collections;
37 import java.util.Date;
38 import java.util.List;
39 import java.util.Set;
40 import java.util.regex.Matcher;
41
42
43
44
45
46
47 public class DaysOldRepositoryPurgeExecutor
48 extends AbstractContinuumPurgeExecutor
49 implements ContinuumPurgeExecutor
50 {
51 private final int daysOlder;
52
53 private final int retentionCount;
54
55 private final RepositoryManagedContent repository;
56
57 private final SimpleDateFormat timestampParser;
58
59 public DaysOldRepositoryPurgeExecutor( RepositoryManagedContent repository, int daysOlder, int retentionCount )
60 {
61 this.repository = repository;
62 this.daysOlder = daysOlder;
63 this.retentionCount = retentionCount;
64 timestampParser = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
65 timestampParser.setTimeZone( DateUtils.UTC_TIME_ZONE );
66 }
67
68 public void purge( String path )
69 throws ContinuumPurgeExecutorException
70 {
71 try
72 {
73 File artifactFile = new File( repository.getRepoRoot(), path );
74
75 if ( !artifactFile.exists() )
76 {
77 return;
78 }
79
80 ArtifactReference artifact = repository.toArtifactReference( path );
81
82 Calendar olderThanThisDate = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
83 olderThanThisDate.add( Calendar.DATE, -daysOlder );
84
85
86 VersionedReference reference = new VersionedReference();
87 reference.setGroupId( artifact.getGroupId() );
88 reference.setArtifactId( artifact.getArtifactId() );
89 reference.setVersion( artifact.getVersion() );
90
91 List<String> versions = new ArrayList<String>( repository.getVersions( reference ) );
92
93 Collections.sort( versions, VersionComparator.getInstance() );
94
95 if ( retentionCount > versions.size() )
96 {
97
98 return;
99 }
100
101 int countToPurge = versions.size() - retentionCount;
102
103 for ( String version : versions )
104 {
105 if ( countToPurge <= 0 )
106 {
107 break;
108 }
109
110 ArtifactReference newArtifactReference = repository.toArtifactReference(
111 artifactFile.getAbsolutePath() );
112 newArtifactReference.setVersion( version );
113
114 File newArtifactFile = repository.toFile( newArtifactReference );
115
116
117 if ( VersionUtil.isGenericSnapshot( newArtifactReference.getVersion() ) )
118 {
119 if ( newArtifactFile.lastModified() < olderThanThisDate.getTimeInMillis() )
120 {
121 doPurgeAllRelated( newArtifactReference );
122 countToPurge--;
123 }
124 }
125
126 else if ( VersionUtil.isUniqueSnapshot( newArtifactReference.getVersion() ) )
127 {
128 Calendar timestampCal = uniqueSnapshotToCalendar( newArtifactReference.getVersion() );
129
130 if ( timestampCal.getTimeInMillis() < olderThanThisDate.getTimeInMillis() )
131 {
132 doPurgeAllRelated( newArtifactReference );
133 countToPurge--;
134 }
135 else if ( newArtifactFile.lastModified() < olderThanThisDate.getTimeInMillis() )
136 {
137 doPurgeAllRelated( newArtifactReference );
138 countToPurge--;
139 }
140 }
141 }
142 }
143 catch ( LayoutException e )
144 {
145 throw new ContinuumPurgeExecutorException( e.getMessage() + ": " + path, e );
146 }
147 catch ( ContentNotFoundException e )
148 {
149 throw new ContinuumPurgeExecutorException( e.getMessage(), e );
150 }
151 }
152
153 private Calendar uniqueSnapshotToCalendar( String version )
154 {
155
156
157
158 Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( version );
159 if ( m.matches() )
160 {
161 Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
162 if ( mtimestamp.matches() )
163 {
164 String tsDate = mtimestamp.group( 1 );
165 String tsTime = mtimestamp.group( 2 );
166
167 Date versionDate;
168 try
169 {
170 versionDate = timestampParser.parse( tsDate + "." + tsTime );
171 Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
172 cal.setTime( versionDate );
173
174 return cal;
175 }
176 catch ( ParseException e )
177 {
178
179 return null;
180 }
181 }
182 }
183 return null;
184 }
185
186 private void doPurgeAllRelated( ArtifactReference reference )
187 throws LayoutException
188 {
189 try
190 {
191 Set<ArtifactReference> related = repository.getRelatedArtifacts( reference );
192 purge( related, repository );
193 }
194 catch ( ContentNotFoundException e )
195 {
196
197
198 }
199 }
200 }