001 package 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 022 import org.apache.archiva.admin.model.RepositoryAdminException; 023 import org.apache.archiva.admin.model.beans.ManagedRepository; 024 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; 025 import org.apache.archiva.metadata.repository.MetadataRepository; 026 import org.apache.archiva.metadata.repository.RepositorySession; 027 import org.apache.archiva.repository.events.RepositoryListener; 028 import org.apache.archiva.common.utils.VersionComparator; 029 import org.apache.archiva.common.utils.VersionUtil; 030 import org.apache.archiva.model.ArtifactReference; 031 import org.apache.archiva.model.ProjectReference; 032 import org.apache.archiva.model.VersionedReference; 033 import org.apache.archiva.repository.ContentNotFoundException; 034 import org.apache.archiva.repository.ManagedRepositoryContent; 035 import org.apache.archiva.repository.RepositoryContentFactory; 036 import org.apache.archiva.repository.RepositoryException; 037 import org.apache.archiva.repository.RepositoryNotFoundException; 038 import org.apache.archiva.repository.layout.LayoutException; 039 import org.apache.archiva.repository.metadata.MetadataTools; 040 import org.apache.archiva.repository.metadata.RepositoryMetadataException; 041 042 import java.io.File; 043 import java.io.IOException; 044 import java.util.ArrayList; 045 import java.util.Collections; 046 import java.util.List; 047 048 /** 049 * <p> 050 * This will look in a single managed repository, and purge any snapshots that are present 051 * that have a corresponding released version on the same repository. 052 * </p> 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 * </p> 069 * 070 * 071 */ 072 public class CleanupReleasedSnapshotsRepositoryPurge 073 extends AbstractRepositoryPurge 074 { 075 private MetadataTools metadataTools; 076 077 private ManagedRepositoryAdmin managedRepositoryAdmin; 078 079 private RepositoryContentFactory repoContentFactory; 080 081 public CleanupReleasedSnapshotsRepositoryPurge( ManagedRepositoryContent repository, MetadataTools metadataTools, 082 ManagedRepositoryAdmin managedRepositoryAdmin, 083 RepositoryContentFactory repoContentFactory, 084 RepositorySession repositorySession, 085 List<RepositoryListener> listeners ) 086 { 087 super( repository, repositorySession, listeners ); 088 this.metadataTools = metadataTools; 089 this.managedRepositoryAdmin = managedRepositoryAdmin; 090 this.repoContentFactory = repoContentFactory; 091 } 092 093 public void process( String path ) 094 throws RepositoryPurgeException 095 { 096 try 097 { 098 File artifactFile = new File( repository.getRepoRoot(), path ); 099 100 if ( !artifactFile.exists() ) 101 { 102 // Nothing to do here, file doesn't exist, skip it. 103 return; 104 } 105 106 ArtifactReference artifactRef = repository.toArtifactReference( path ); 107 108 if ( !VersionUtil.isSnapshot( artifactRef.getVersion() ) ) 109 { 110 // Nothing to do here, not a snapshot, skip it. 111 return; 112 } 113 114 ProjectReference reference = new ProjectReference(); 115 reference.setGroupId( artifactRef.getGroupId() ); 116 reference.setArtifactId( artifactRef.getArtifactId() ); 117 118 // Gether the released versions 119 List<String> releasedVersions = new ArrayList<String>(); 120 121 List<ManagedRepository> repos = managedRepositoryAdmin.getManagedRepositories(); 122 for ( ManagedRepository repo : repos ) 123 { 124 if ( repo.isReleases() ) 125 { 126 try 127 { 128 ManagedRepositoryContent repoContent = 129 repoContentFactory.getManagedRepositoryContent( repo.getId() ); 130 for ( String version : repoContent.getVersions( reference ) ) 131 { 132 if ( !VersionUtil.isSnapshot( version ) ) 133 { 134 releasedVersions.add( version ); 135 } 136 } 137 } 138 catch ( RepositoryNotFoundException e ) 139 { 140 // swallow 141 } 142 catch ( RepositoryException e ) 143 { 144 // swallow 145 } 146 } 147 } 148 149 Collections.sort( releasedVersions, VersionComparator.getInstance() ); 150 151 // Now clean out any version that is earlier than the highest released version. 152 boolean needsMetadataUpdate = false; 153 154 VersionedReference versionRef = new VersionedReference(); 155 versionRef.setGroupId( artifactRef.getGroupId() ); 156 versionRef.setArtifactId( artifactRef.getArtifactId() ); 157 158 MetadataRepository metadataRepository = repositorySession.getRepository(); 159 160 if ( releasedVersions.contains( VersionUtil.getReleaseVersion( artifactRef.getVersion() ) ) ) 161 { 162 versionRef.setVersion( artifactRef.getVersion() ); 163 repository.deleteVersion( versionRef ); 164 165 // FIXME: looks incomplete, might not delete related metadata? 166 for ( RepositoryListener listener : listeners ) 167 { 168 listener.deleteArtifact( metadataRepository, repository.getId(), artifactRef.getGroupId(), 169 artifactRef.getArtifactId(), artifactRef.getVersion(), 170 artifactFile.getName() ); 171 } 172 173 needsMetadataUpdate = true; 174 } 175 176 if ( needsMetadataUpdate ) 177 { 178 updateMetadata( artifactRef ); 179 } 180 } catch ( RepositoryAdminException e ) 181 { 182 throw new RepositoryPurgeException( e.getMessage(), e ); 183 } 184 catch ( LayoutException e ) 185 { 186 log.debug( "Not processing file that is not an artifact: {}", e.getMessage() ); 187 } 188 catch ( ContentNotFoundException e ) 189 { 190 throw new RepositoryPurgeException( e.getMessage(), e ); 191 } 192 } 193 194 private void updateMetadata( ArtifactReference artifact ) 195 { 196 VersionedReference versionRef = new VersionedReference(); 197 versionRef.setGroupId( artifact.getGroupId() ); 198 versionRef.setArtifactId( artifact.getArtifactId() ); 199 versionRef.setVersion( artifact.getVersion() ); 200 201 ProjectReference projectRef = new ProjectReference(); 202 projectRef.setGroupId( artifact.getGroupId() ); 203 projectRef.setArtifactId( artifact.getArtifactId() ); 204 205 try 206 { 207 metadataTools.updateMetadata( repository, versionRef ); 208 } 209 catch ( ContentNotFoundException e ) 210 { 211 // Ignore. (Just means we have no snapshot versions left to reference). 212 } 213 catch ( RepositoryMetadataException e ) 214 { 215 // Ignore. 216 } 217 catch ( IOException e ) 218 { 219 // Ignore. 220 } 221 catch ( LayoutException e ) 222 { 223 // Ignore. 224 } 225 226 try 227 { 228 metadataTools.updateMetadata( repository, projectRef ); 229 } 230 catch ( ContentNotFoundException e ) 231 { 232 // Ignore. (Just means we have no snapshot versions left to reference). 233 } 234 catch ( RepositoryMetadataException e ) 235 { 236 // Ignore. 237 } 238 catch ( IOException e ) 239 { 240 // Ignore. 241 } 242 catch ( LayoutException e ) 243 { 244 // Ignore. 245 } 246 } 247 }