View Javadoc
1   package org.apache.archiva.consumers.core.repository;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.archiva.metadata.model.facets.AuditEvent;
23  import org.apache.archiva.common.utils.VersionUtil;
24  import org.apache.archiva.metadata.model.ArtifactMetadata;
25  import org.apache.archiva.metadata.model.maven2.MavenArtifactFacet;
26  import org.apache.archiva.metadata.repository.MetadataRepository;
27  import org.apache.archiva.metadata.repository.MetadataRepositoryException;
28  import org.apache.archiva.metadata.repository.MetadataResolutionException;
29  import org.apache.archiva.metadata.repository.RepositorySession;
30  import org.apache.archiva.model.ArtifactReference;
31  import org.apache.archiva.repository.ContentNotFoundException;
32  import org.apache.archiva.repository.ManagedRepositoryContent;
33  import org.apache.archiva.repository.events.RepositoryListener;
34  import org.apache.commons.lang.StringUtils;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  import java.io.File;
39  import java.io.FilenameFilter;
40  import java.util.Collection;
41  import java.util.List;
42  import java.util.Set;
43  
44  /**
45   * Base class for all repository purge tasks.
46   */
47  public abstract class AbstractRepositoryPurge
48      implements RepositoryPurge
49  {
50      protected Logger log = LoggerFactory.getLogger( getClass() );
51  
52      protected final ManagedRepositoryContent repository;
53  
54      protected final RepositorySession repositorySession;
55  
56      protected final List<RepositoryListener> listeners;
57  
58      private Logger logger = LoggerFactory.getLogger( "org.apache.archiva.AuditLog" );
59  
60      private static final char DELIM = ' ';
61  
62      public AbstractRepositoryPurge( ManagedRepositoryContent repository, RepositorySession repositorySession,
63                                      List<RepositoryListener> listeners )
64      {
65          this.repository = repository;
66          this.repositorySession = repositorySession;
67          this.listeners = listeners;
68      }
69  
70      /**
71       * Purge the repo. Update db and index of removed artifacts.
72       *
73       * @param references
74       */
75      protected void purge( Set<ArtifactReference> references )
76      {
77          if ( references != null && !references.isEmpty() )
78          {
79              MetadataRepository metadataRepository = repositorySession.getRepository();
80              for ( ArtifactReference reference : references )
81              {
82                  File artifactFile = repository.toFile( reference );
83  
84                  for ( RepositoryListener listener : listeners )
85                  {
86                      listener.deleteArtifact( metadataRepository, repository.getId(), reference.getGroupId(),
87                                               reference.getArtifactId(), reference.getVersion(),
88                                               artifactFile.getName() );
89                  }
90  
91                  // TODO: this needs to be logged
92                  artifactFile.delete();
93                  try
94                  {
95                      repository.deleteArtifact( reference );
96                  }
97                  catch ( ContentNotFoundException e )
98                  {
99                      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 }