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.MetadataRepository;
025import org.apache.archiva.metadata.repository.MetadataRepositoryException;
026import org.apache.archiva.metadata.repository.RepositorySession;
027import org.apache.archiva.model.ArtifactReference;
028import org.apache.archiva.model.ProjectReference;
029import org.apache.archiva.model.VersionedReference;
030import org.apache.archiva.repository.ContentNotFoundException;
031import org.apache.archiva.repository.LayoutException;
032import org.apache.archiva.repository.ManagedRepositoryContent;
033import org.apache.archiva.repository.ReleaseScheme;
034import org.apache.archiva.repository.RepositoryException;
035import org.apache.archiva.repository.RepositoryRegistry;
036import org.apache.archiva.metadata.audit.RepositoryListener;
037import org.apache.archiva.repository.metadata.base.MetadataTools;
038import org.apache.archiva.repository.metadata.RepositoryMetadataException;
039
040import java.io.IOException;
041import java.nio.file.Files;
042import java.nio.file.Path;
043import java.nio.file.Paths;
044import java.util.ArrayList;
045import java.util.Collection;
046import java.util.Collections;
047import java.util.List;
048
049/**
050 * <p>
051 * This will look in a single managed repository, and purge any snapshots that are present
052 * that have a corresponding released version on the same repository.
053 * </p>
054 * <p>
055 * So, if you have the following (presented in the m2/default layout form) ...
056 * <pre>
057 *   /com/foo/foo-tool/1.0-SNAPSHOT/foo-tool-1.0-SNAPSHOT.jar
058 *   /com/foo/foo-tool/1.1-SNAPSHOT/foo-tool-1.1-SNAPSHOT.jar
059 *   /com/foo/foo-tool/1.2.1-SNAPSHOT/foo-tool-1.2.1-SNAPSHOT.jar
060 *   /com/foo/foo-tool/1.2.1/foo-tool-1.2.1.jar
061 *   /com/foo/foo-tool/2.0-SNAPSHOT/foo-tool-2.0-SNAPSHOT.jar
062 *   /com/foo/foo-tool/2.0/foo-tool-2.0.jar
063 *   /com/foo/foo-tool/2.1-SNAPSHOT/foo-tool-2.1-SNAPSHOT.jar
064 * </pre>
065 * then the current highest ranked released (non-snapshot) version is 2.0, which means
066 * the snapshots from 1.0-SNAPSHOT, 1.1-SNAPSHOT, 1.2.1-SNAPSHOT, and 2.0-SNAPSHOT can
067 * be purged.  Leaving 2.1-SNAPSHOT in alone.
068 */
069public class CleanupReleasedSnapshotsRepositoryPurge
070    extends AbstractRepositoryPurge
071{
072    private MetadataTools metadataTools;
073
074    private RepositoryRegistry repositoryRegistry;
075
076    public CleanupReleasedSnapshotsRepositoryPurge( ManagedRepositoryContent repository, MetadataTools metadataTools,
077                                                    RepositoryRegistry repositoryRegistry,
078                                                    RepositorySession repositorySession,
079                                                    List<RepositoryListener> listeners )
080    {
081        super( repository, repositorySession, listeners );
082        this.metadataTools = metadataTools;
083        this.repositoryRegistry = repositoryRegistry;
084    }
085
086    @Override
087    public void process( String path )
088        throws RepositoryPurgeException
089    {
090        try
091        {
092            Path artifactFile = Paths.get( repository.getRepoRoot( ), path );
093
094            if ( !Files.exists(artifactFile) )
095            {
096                // Nothing to do here, file doesn't exist, skip it.
097                return;
098            }
099
100            ArtifactReference artifactRef = repository.toArtifactReference( path );
101
102            if ( !VersionUtil.isSnapshot( artifactRef.getVersion( ) ) )
103            {
104                // Nothing to do here, not a snapshot, skip it.
105                return;
106            }
107
108            ProjectReference reference = new ProjectReference( );
109            reference.setGroupId( artifactRef.getGroupId( ) );
110            reference.setArtifactId( artifactRef.getArtifactId( ) );
111
112            // Gether the released versions
113            List<String> releasedVersions = new ArrayList<>( );
114
115            Collection<org.apache.archiva.repository.ManagedRepository> repos = repositoryRegistry.getManagedRepositories( );
116            for ( org.apache.archiva.repository.ManagedRepository repo : repos )
117            {
118
119                if ( repo.getActiveReleaseSchemes().contains( ReleaseScheme.RELEASE ))
120                {
121                    try
122                    {
123                        ManagedRepositoryContent repoContent = repo.getContent();
124                        for ( String version : repoContent.getVersions( reference ) )
125                        {
126                            if ( !VersionUtil.isSnapshot( version ) )
127                            {
128                                releasedVersions.add( version );
129                            }
130                        }
131                    }
132                    catch ( RepositoryException e )
133                    {
134                        // swallow
135                    }
136                }
137            }
138
139            Collections.sort( releasedVersions, VersionComparator.getInstance( ) );
140
141            // Now clean out any version that is earlier than the highest released version.
142            boolean needsMetadataUpdate = false;
143
144            VersionedReference versionRef = new VersionedReference( );
145            versionRef.setGroupId( artifactRef.getGroupId( ) );
146            versionRef.setArtifactId( artifactRef.getArtifactId( ) );
147
148            MetadataRepository metadataRepository = repositorySession.getRepository( );
149
150            if ( releasedVersions.contains( VersionUtil.getReleaseVersion( artifactRef.getVersion( ) ) ) )
151            {
152                versionRef.setVersion( artifactRef.getVersion( ) );
153                repository.deleteVersion( versionRef );
154
155                for ( RepositoryListener listener : listeners )
156                {
157                    listener.deleteArtifact( metadataRepository, repository.getId( ), artifactRef.getGroupId( ),
158                        artifactRef.getArtifactId( ), artifactRef.getVersion( ),
159                        artifactFile.getFileName().toString() );
160                }
161                metadataRepository.removeProjectVersion( repositorySession, repository.getId( ),
162                    artifactRef.getGroupId( ), artifactRef.getArtifactId( ), artifactRef.getVersion( ) );
163
164                needsMetadataUpdate = true;
165            }
166
167            if ( needsMetadataUpdate )
168            {
169                updateMetadata( artifactRef );
170            }
171        }
172        catch ( LayoutException e )
173        {
174            log.debug( "Not processing file that is not an artifact: {}", e.getMessage( ) );
175        }
176        catch ( ContentNotFoundException e )
177        {
178            throw new RepositoryPurgeException( e.getMessage( ), e );
179        }
180        catch ( MetadataRepositoryException e )
181        {
182            log.error( "Could not remove metadata during cleanup of released snapshots of {}", path, e );
183        }
184    }
185
186
187    /*
188     * TODO: Uses a deprecated API, but if we use the API with location string, it does not work as expected
189     * -> not sure what needs to be changed here.
190     */
191    @SuppressWarnings( "deprecation" )
192    private void updateMetadata( ArtifactReference artifact )
193    {
194        VersionedReference versionRef = new VersionedReference( );
195        versionRef.setGroupId( artifact.getGroupId( ) );
196        versionRef.setArtifactId( artifact.getArtifactId( ) );
197        versionRef.setVersion( artifact.getVersion( ) );
198
199        ProjectReference projectRef = new ProjectReference( );
200        projectRef.setGroupId( artifact.getGroupId( ) );
201        projectRef.setArtifactId( artifact.getArtifactId( ) );
202
203        try
204        {
205            metadataTools.updateMetadata( repository, versionRef );
206        }
207        catch ( ContentNotFoundException e )
208        {
209            // Ignore. (Just means we have no snapshot versions left to reference).
210        }
211        catch ( RepositoryMetadataException e )
212        {
213            // Ignore.
214        }
215        catch ( IOException e )
216        {
217            // Ignore.
218        }
219        catch ( LayoutException e )
220        {
221            // Ignore.
222        }
223
224        try
225        {
226            metadataTools.updateMetadata( repository, projectRef );
227        }
228        catch ( ContentNotFoundException e )
229        {
230            // Ignore. (Just means we have no snapshot versions left to reference).
231        }
232        catch ( RepositoryMetadataException e )
233        {
234            // Ignore.
235        }
236        catch ( IOException e )
237        {
238            // Ignore.
239        }
240        catch ( LayoutException e )
241        {
242            // Ignore.
243        }
244    }
245}