This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.consumers.core.repository;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.archiva.common.utils.VersionComparator;
023import org.apache.archiva.common.utils.VersionUtil;
024import org.apache.archiva.metadata.repository.RepositorySession;
025import org.apache.archiva.model.ArtifactReference;
026import org.apache.archiva.model.VersionedReference;
027import org.apache.archiva.repository.ContentNotFoundException;
028import org.apache.archiva.repository.ManagedRepositoryContent;
029import org.apache.archiva.repository.events.RepositoryListener;
030import org.apache.archiva.repository.layout.LayoutException;
031import org.apache.commons.lang.time.DateUtils;
032
033import java.io.File;
034import java.text.ParseException;
035import java.text.SimpleDateFormat;
036import java.util.ArrayList;
037import java.util.Calendar;
038import java.util.Collections;
039import java.util.Date;
040import java.util.HashSet;
041import java.util.List;
042import java.util.Set;
043import java.util.regex.Matcher;
044
045/**
046 * Purge from repository all snapshots older than the specified days in the repository configuration.
047 */
048public class DaysOldRepositoryPurge
049    extends AbstractRepositoryPurge
050{
051    private SimpleDateFormat timestampParser;
052
053    private int daysOlder;
054
055    private int retentionCount;
056
057    public DaysOldRepositoryPurge( ManagedRepositoryContent repository, int daysOlder, int retentionCount,
058                                   RepositorySession repositorySession, List<RepositoryListener> listeners )
059    {
060        super( repository, repositorySession, listeners );
061        this.daysOlder = daysOlder;
062        this.retentionCount = retentionCount;
063        timestampParser = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
064        timestampParser.setTimeZone( DateUtils.UTC_TIME_ZONE );
065    }
066
067    @Override
068    public void process( String path )
069        throws RepositoryPurgeException
070    {
071        try
072        {
073            File artifactFile = new File( repository.getRepoRoot( ), path );
074
075            if ( !artifactFile.exists( ) )
076            {
077                return;
078            }
079
080            ArtifactReference artifact = repository.toArtifactReference( path );
081
082            Calendar olderThanThisDate = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
083            olderThanThisDate.add( Calendar.DATE, -daysOlder );
084
085            // respect retention count
086            VersionedReference reference = new VersionedReference( );
087            reference.setGroupId( artifact.getGroupId( ) );
088            reference.setArtifactId( artifact.getArtifactId( ) );
089            reference.setVersion( artifact.getVersion( ) );
090
091            List<String> versions = new ArrayList<>( repository.getVersions( reference ) );
092
093            Collections.sort( versions, VersionComparator.getInstance( ) );
094
095            if ( retentionCount > versions.size( ) )
096            {
097                // Done. nothing to do here. skip it.
098                return;
099            }
100
101            int countToPurge = versions.size( ) - retentionCount;
102
103            Set<ArtifactReference> artifactsToDelete = new HashSet<>( );
104            for ( String version : versions )
105            {
106                if ( countToPurge-- <= 0 )
107                {
108                    break;
109                }
110
111                ArtifactReference newArtifactReference = repository.toArtifactReference(
112                    artifactFile.getAbsolutePath( ) );
113                newArtifactReference.setVersion( version );
114
115                File newArtifactFile = repository.toFile( newArtifactReference );
116
117                // Is this a generic snapshot "1.0-SNAPSHOT" ?
118                if ( VersionUtil.isGenericSnapshot( newArtifactReference.getVersion( ) ) )
119                {
120                    if ( newArtifactFile.lastModified( ) < olderThanThisDate.getTimeInMillis( ) )
121                    {
122                        artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) );
123                    }
124                }
125                // Is this a timestamp snapshot "1.0-20070822.123456-42" ?
126                else if ( VersionUtil.isUniqueSnapshot( newArtifactReference.getVersion( ) ) )
127                {
128                    Calendar timestampCal = uniqueSnapshotToCalendar( newArtifactReference.getVersion( ) );
129
130                    if ( timestampCal.getTimeInMillis( ) < olderThanThisDate.getTimeInMillis( ) )
131                    {
132                        artifactsToDelete.addAll( repository.getRelatedArtifacts( newArtifactReference ) );
133                    }
134                }
135            }
136            purge( artifactsToDelete );
137        }
138        catch ( ContentNotFoundException e )
139        {
140            throw new RepositoryPurgeException( e.getMessage( ), e );
141        }
142        catch ( LayoutException e )
143        {
144            log.debug( "Not processing file that is not an artifact: {}", e.getMessage( ) );
145        }
146    }
147
148    private Calendar uniqueSnapshotToCalendar( String version )
149    {
150        // The latestVersion will contain the full version string "1.0-alpha-5-20070821.213044-8"
151        // This needs to be broken down into ${base}-${timestamp}-${build_number}
152
153        Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( version );
154        if ( m.matches( ) )
155        {
156            Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
157            if ( mtimestamp.matches( ) )
158            {
159                String tsDate = mtimestamp.group( 1 );
160                String tsTime = mtimestamp.group( 2 );
161
162                Date versionDate;
163                try
164                {
165                    versionDate = timestampParser.parse( tsDate + "." + tsTime );
166                    Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
167                    cal.setTime( versionDate );
168
169                    return cal;
170                }
171                catch ( ParseException e )
172                {
173                    // Invalid Date/Time
174                    return null;
175                }
176            }
177        }
178        return null;
179    }
180
181}