You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DaysOldRepositoryPurge.java 6.9KB

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