1 package org.apache.maven.archiva.web.action;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
22 import com.opensymphony.xwork2.Preparable;
23 import com.opensymphony.xwork2.Validateable;
24 import org.apache.archiva.audit.AuditEvent;
25 import org.apache.archiva.audit.Auditable;
26 import org.apache.archiva.checksum.ChecksumAlgorithm;
27 import org.apache.archiva.checksum.ChecksummedFile;
28 import org.apache.archiva.metadata.model.ArtifactMetadata;
29 import org.apache.archiva.metadata.repository.MetadataRepository;
30 import org.apache.archiva.repository.events.RepositoryListener;
31 import org.apache.maven.archiva.common.utils.VersionComparator;
32 import org.apache.maven.archiva.common.utils.VersionUtil;
33 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
34 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
35 import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
36 import org.apache.maven.archiva.model.VersionedReference;
37 import org.apache.maven.archiva.repository.ContentNotFoundException;
38 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
39 import org.apache.maven.archiva.repository.RepositoryContentFactory;
40 import org.apache.maven.archiva.repository.RepositoryException;
41 import org.apache.maven.archiva.repository.RepositoryNotFoundException;
42 import org.apache.maven.archiva.repository.metadata.MetadataTools;
43 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
44 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
45 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataWriter;
46 import org.apache.maven.archiva.security.AccessDeniedException;
47 import org.apache.maven.archiva.security.ArchivaSecurityException;
48 import org.apache.maven.archiva.security.PrincipalNotFoundException;
49 import org.apache.maven.archiva.security.UserRepositories;
52 import java.text.DateFormat;
53 import java.text.SimpleDateFormat;
54 import java.util.ArrayList;
55 import java.util.Calendar;
56 import java.util.Collection;
57 import java.util.Collections;
58 import java.util.Date;
59 import java.util.List;
60 import java.util.TimeZone;
63 * Delete an artifact. Metadata will be updated if one exists, otherwise it would be created.
65 * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="deleteArtifactAction" instantiation-strategy="per-lookup"
67 public class DeleteArtifactAction
68 extends PlexusActionSupport
69 implements Validateable, Preparable, Auditable
72 * The groupId of the artifact to be deleted.
74 private String groupId;
77 * The artifactId of the artifact to be deleted.
79 private String artifactId;
82 * The version of the artifact to be deleted.
84 private String version;
87 * The repository where the artifact is to be deleted.
89 private String repositoryId;
92 * List of managed repositories to delete from.
94 private List<String> managedRepos;
99 private UserRepositories userRepositories;
102 * @plexus.requirement role-hint="default"
104 private ArchivaConfiguration configuration;
107 * @plexus.requirement
109 private RepositoryContentFactory repositoryFactory;
112 * @plexus.requirement role="org.apache.archiva.repository.events.RepositoryListener"
114 private List<RepositoryListener> listeners;
116 private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5};
119 * @plexus.requirement
121 private MetadataRepository metadataRepository;
123 public String getGroupId()
128 public void setGroupId( String groupId )
130 this.groupId = groupId;
133 public String getArtifactId()
138 public void setArtifactId( String artifactId )
140 this.artifactId = artifactId;
143 public String getVersion()
148 public void setVersion( String version )
150 this.version = version;
153 public String getRepositoryId()
158 public void setRepositoryId( String repositoryId )
160 this.repositoryId = repositoryId;
163 public List<String> getManagedRepos()
168 public void setManagedRepos( List<String> managedRepos )
170 this.managedRepos = managedRepos;
173 public void prepare()
175 managedRepos = getManagableRepos();
178 public String input()
185 // reset the fields so the form is clear when
186 // the action returns to the jsp page
193 public String doDelete()
197 Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
199 TimeZone timezone = TimeZone.getTimeZone( "UTC" );
200 DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
201 fmt.setTimeZone( timezone );
202 ManagedRepositoryConfiguration repoConfig =
203 configuration.getConfiguration().findManagedRepositoryById( repositoryId );
205 VersionedReference ref = new VersionedReference();
206 ref.setArtifactId( artifactId );
207 ref.setGroupId( groupId );
208 ref.setVersion( version );
210 ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
212 String path = repository.toMetadataPath( ref );
213 int index = path.lastIndexOf( '/' );
214 path = path.substring( 0, index );
215 File targetPath = new File( repoConfig.getLocation(), path );
217 if ( !targetPath.exists() )
219 throw new ContentNotFoundException( groupId + ":" + artifactId + ":" + version );
222 // TODO: this should be in the storage mechanism so that it is all tied together
223 // delete from file system
224 repository.deleteVersion( ref );
226 File metadataFile = getMetadata( targetPath.getAbsolutePath() );
227 ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );
229 updateMetadata( metadata, metadataFile, lastUpdatedTimestamp );
231 Collection<ArtifactMetadata> artifacts =
232 metadataRepository.getArtifacts( repositoryId, groupId, artifactId, version );
234 for ( ArtifactMetadata artifact : artifacts )
236 // TODO: mismatch between artifact (snapshot) version and project (base) version here
237 if ( artifact.getVersion().equals( version ) )
239 metadataRepository.deleteArtifact( artifact.getRepositoryId(), artifact.getNamespace(),
240 artifact.getProject(), artifact.getVersion(),
243 // TODO: move into the metadata repository proper - need to differentiate attachment of
244 // repository metadata to an artifact
245 for ( RepositoryListener listener : listeners )
247 listener.deleteArtifact( repository.getId(), artifact.getNamespace(), artifact.getProject(),
248 artifact.getVersion(), artifact.getId() );
251 triggerAuditEvent( repositoryId, path, AuditEvent.REMOVE_FILE );
255 String msg = "Artifact \'" + groupId + ":" + artifactId + ":" + version +
256 "\' was successfully deleted from repository \'" + repositoryId + "\'";
258 addActionMessage( msg );
263 catch ( ContentNotFoundException e )
265 addActionError( "Artifact does not exist: " + e.getMessage() );
268 catch ( RepositoryNotFoundException e )
270 addActionError( "Target repository cannot be found: " + e.getMessage() );
273 catch ( RepositoryException e )
275 addActionError( "Repository exception: " + e.getMessage() );
280 private File getMetadata( String targetPath )
282 String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( File.separatorChar ) );
284 return new File( artifactPath, MetadataTools.MAVEN_METADATA );
287 private ArchivaRepositoryMetadata getMetadata( File metadataFile )
288 throws RepositoryMetadataException
290 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
291 if ( metadataFile.exists() )
293 metadata = RepositoryMetadataReader.read( metadataFile );
299 * Update artifact level metadata. Creates one if metadata does not exist after artifact deletion.
303 private void updateMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, Date lastUpdatedTimestamp )
304 throws RepositoryMetadataException
306 List<String> availableVersions = new ArrayList<String>();
307 String latestVersion = "";
309 if ( metadataFile.exists() )
311 if ( metadata.getAvailableVersions() != null )
313 availableVersions = metadata.getAvailableVersions();
315 if ( availableVersions.size() > 0 )
317 Collections.sort( availableVersions, VersionComparator.getInstance() );
319 if ( availableVersions.contains( version ) )
321 availableVersions.remove( availableVersions.indexOf( version ) );
323 if ( availableVersions.size() > 0 )
325 latestVersion = availableVersions.get( availableVersions.size() - 1 );
331 if ( metadata.getGroupId() == null )
333 metadata.setGroupId( groupId );
335 if ( metadata.getArtifactId() == null )
337 metadata.setArtifactId( artifactId );
340 if ( !VersionUtil.isSnapshot( version ) )
342 if ( metadata.getReleasedVersion().equals( version ) )
344 metadata.setReleasedVersion( latestVersion );
348 metadata.setLatestVersion( latestVersion );
349 metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
350 metadata.setAvailableVersions( availableVersions );
352 RepositoryMetadataWriter.write( metadata, metadataFile );
353 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
354 checksum.fixChecksums( algorithms );
357 public void validate()
361 if ( !userRepositories.isAuthorizedToDeleteArtifacts( getPrincipal(), repositoryId ) )
363 addActionError( "User is not authorized to delete artifacts in repository '" + repositoryId + "'." );
366 if ( ( version.length() > 0 ) && ( !VersionUtil.isVersion( version ) ) )
368 addActionError( "Invalid version." );
371 catch ( AccessDeniedException e )
373 addActionError( e.getMessage() );
375 catch ( ArchivaSecurityException e )
377 addActionError( e.getMessage() );
381 private List<String> getManagableRepos()
385 return userRepositories.getManagableRepositoryIds( getPrincipal() );
387 catch ( PrincipalNotFoundException e )
389 log.warn( e.getMessage(), e );
391 catch ( AccessDeniedException e )
393 log.warn( e.getMessage(), e );
394 // TODO: pass this onto the screen.
396 catch ( ArchivaSecurityException e )
398 log.warn( e.getMessage(), e );
400 return Collections.emptyList();
403 public List<RepositoryListener> getListeners()