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.audit.AuditEvent; 023 import org.apache.archiva.common.utils.VersionUtil; 024 import org.apache.archiva.metadata.model.ArtifactMetadata; 025 import org.apache.archiva.metadata.model.maven2.MavenArtifactFacet; 026 import org.apache.archiva.metadata.repository.MetadataRepository; 027 import org.apache.archiva.metadata.repository.MetadataRepositoryException; 028 import org.apache.archiva.metadata.repository.MetadataResolutionException; 029 import org.apache.archiva.metadata.repository.RepositorySession; 030 import org.apache.archiva.model.ArtifactReference; 031 import org.apache.archiva.repository.ContentNotFoundException; 032 import org.apache.archiva.repository.ManagedRepositoryContent; 033 import org.apache.archiva.repository.events.RepositoryListener; 034 import org.apache.commons.lang.StringUtils; 035 import org.slf4j.Logger; 036 import org.slf4j.LoggerFactory; 037 038 import java.io.File; 039 import java.io.FilenameFilter; 040 import java.util.Collection; 041 import java.util.List; 042 import java.util.Set; 043 044 /** 045 * Base class for all repository purge tasks. 046 */ 047 public abstract class AbstractRepositoryPurge 048 implements RepositoryPurge 049 { 050 protected Logger log = LoggerFactory.getLogger( getClass() ); 051 052 protected final ManagedRepositoryContent repository; 053 054 protected final RepositorySession repositorySession; 055 056 protected final List<RepositoryListener> listeners; 057 058 private Logger logger = LoggerFactory.getLogger( "org.apache.archiva.AuditLog" ); 059 060 private static final char DELIM = ' '; 061 062 public AbstractRepositoryPurge( ManagedRepositoryContent repository, RepositorySession repositorySession, 063 List<RepositoryListener> listeners ) 064 { 065 this.repository = repository; 066 this.repositorySession = repositorySession; 067 this.listeners = listeners; 068 } 069 070 /** 071 * Purge the repo. Update db and index of removed artifacts. 072 * 073 * @param references 074 */ 075 protected void purge( Set<ArtifactReference> references ) 076 { 077 if ( references != null && !references.isEmpty() ) 078 { 079 MetadataRepository metadataRepository = repositorySession.getRepository(); 080 for ( ArtifactReference reference : references ) 081 { 082 File artifactFile = repository.toFile( reference ); 083 084 for ( RepositoryListener listener : listeners ) 085 { 086 listener.deleteArtifact( metadataRepository, repository.getId(), reference.getGroupId(), 087 reference.getArtifactId(), reference.getVersion(), 088 artifactFile.getName() ); 089 } 090 091 // TODO: this needs to be logged 092 artifactFile.delete(); 093 try 094 { 095 repository.deleteArtifact( reference ); 096 } 097 catch ( ContentNotFoundException e ) 098 { 099 log.warn( "skip error deleting artifact {}: {}", reference, e.getMessage() ); 100 } 101 102 try 103 { 104 metadataRepository.removeProjectVersion( repository.getId(), reference.getGroupId(), 105 reference.getArtifactId(), reference.getVersion() ); 106 } 107 catch ( MetadataRepositoryException e ) 108 { 109 log.warn( "skip error removeProjectVersion artifact {}: {}", reference, e.getMessage() ); 110 } 111 112 boolean snapshotVersion = VersionUtil.isSnapshot( reference.getVersion() ); 113 114 try 115 { 116 if ( snapshotVersion ) 117 { 118 String baseVersion = VersionUtil.getBaseVersion( reference.getVersion() ); 119 Collection<ArtifactMetadata> artifacts = 120 metadataRepository.getArtifacts( repository.getId(), reference.getGroupId(), 121 reference.getArtifactId(), baseVersion ); 122 if ( artifacts != null ) 123 { 124 // cleanup snapshots metadata 125 for ( ArtifactMetadata artifactMetadata : artifacts ) 126 { 127 128 // TODO: mismatch between artifact (snapshot) version and project (base) version here 129 if ( artifactMetadata.getVersion().equals( reference.getVersion() ) ) 130 { 131 if ( StringUtils.isNotBlank( reference.getClassifier() ) ) 132 { 133 134 // cleanup facet which contains classifier information 135 MavenArtifactFacet mavenArtifactFacet = 136 (MavenArtifactFacet) artifactMetadata.getFacet( 137 MavenArtifactFacet.FACET_ID ); 138 139 if ( StringUtils.equals( reference.getClassifier(), 140 mavenArtifactFacet.getClassifier() ) ) 141 { 142 artifactMetadata.removeFacet( MavenArtifactFacet.FACET_ID ); 143 String groupId = reference.getGroupId(), artifactId = 144 reference.getArtifactId(), 145 version = reference.getVersion(); 146 MavenArtifactFacet mavenArtifactFacetToCompare = new MavenArtifactFacet(); 147 mavenArtifactFacetToCompare.setClassifier( reference.getClassifier() ); 148 metadataRepository.removeArtifact( repository.getId(), groupId, artifactId, 149 version, mavenArtifactFacetToCompare ); 150 metadataRepository.save(); 151 } 152 153 } 154 else 155 { 156 metadataRepository.removeArtifact( artifactMetadata, VersionUtil.getBaseVersion( 157 reference.getVersion() ) ); 158 } 159 160 } 161 } 162 } 163 } 164 } 165 catch ( MetadataResolutionException e ) 166 { 167 log.warn( "skip error deleting metadata {}: {}", reference, e.getMessage() ); 168 } 169 catch ( MetadataRepositoryException e ) 170 { 171 log.warn( "skip error deleting metadata {}: {}", reference, e.getMessage() ); 172 } 173 174 repositorySession.save(); 175 176 triggerAuditEvent( repository.getRepository().getId(), ArtifactReference.toKey( reference ), 177 AuditEvent.PURGE_ARTIFACT ); 178 purgeSupportFiles( artifactFile ); 179 } 180 } 181 } 182 183 /** 184 * <p> 185 * This find support files for the artifactFile and deletes them. 186 * </p> 187 * <p> 188 * Support Files are things like ".sha1", ".md5", ".asc", etc. 189 * </p> 190 * 191 * @param artifactFile the file to base off of. 192 */ 193 private void purgeSupportFiles( File artifactFile ) 194 { 195 File parentDir = artifactFile.getParentFile(); 196 197 if ( !parentDir.exists() ) 198 { 199 return; 200 } 201 202 FilenameFilter filter = new ArtifactFilenameFilter( artifactFile.getName() ); 203 204 File[] files = parentDir.listFiles( filter ); 205 206 for ( File file : files ) 207 { 208 if ( file.exists() && file.isFile() ) 209 { 210 String fileName = file.getName(); 211 file.delete(); 212 // TODO: log that it was deleted 213 triggerAuditEvent( repository.getRepository().getId(), fileName, AuditEvent.PURGE_FILE ); 214 } 215 } 216 } 217 218 private void triggerAuditEvent( String repoId, String resource, String action ) 219 { 220 String msg = 221 repoId + DELIM + "<system-purge>" + DELIM + "<system>" + DELIM + '\"' + resource + '\"' + DELIM + '\"' + 222 action + '\"'; 223 224 logger.info( msg ); 225 } 226 }