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
23 import java.text.DateFormat;
24 import java.text.SimpleDateFormat;
25 import java.util.ArrayList;
26 import java.util.Calendar;
27 import java.util.Collections;
28 import java.util.Date;
29 import java.util.List;
30 import java.util.TimeZone;
32 import com.opensymphony.xwork2.Preparable;
33 import com.opensymphony.xwork2.Validateable;
34 import org.apache.archiva.checksum.ChecksumAlgorithm;
35 import org.apache.archiva.checksum.ChecksummedFile;
36 import org.apache.maven.archiva.common.utils.VersionComparator;
37 import org.apache.maven.archiva.common.utils.VersionUtil;
38 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
39 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
40 import org.apache.maven.archiva.database.ArchivaDatabaseException;
41 import org.apache.maven.archiva.database.ArtifactDAO;
42 import org.apache.maven.archiva.database.constraints.ArtifactVersionsConstraint;
43 import org.apache.maven.archiva.database.updater.DatabaseConsumers;
44 import org.apache.maven.archiva.model.ArchivaArtifact;
45 import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
46 import org.apache.maven.archiva.model.VersionedReference;
47 import org.apache.maven.archiva.repository.ContentNotFoundException;
48 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
49 import org.apache.maven.archiva.repository.RepositoryContentFactory;
50 import org.apache.maven.archiva.repository.RepositoryException;
51 import org.apache.maven.archiva.repository.RepositoryNotFoundException;
52 import org.apache.maven.archiva.repository.audit.AuditEvent;
53 import org.apache.maven.archiva.repository.audit.Auditable;
54 import org.apache.maven.archiva.repository.events.RepositoryListener;
55 import org.apache.maven.archiva.repository.metadata.MetadataTools;
56 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
57 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
58 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataWriter;
59 import org.apache.maven.archiva.security.AccessDeniedException;
60 import org.apache.maven.archiva.security.ArchivaSecurityException;
61 import org.apache.maven.archiva.security.PrincipalNotFoundException;
62 import org.apache.maven.archiva.security.UserRepositories;
65 * Delete an artifact. Metadata will be updated if one exists, otherwise it would be created.
67 * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="deleteArtifactAction" instantiation-strategy="per-lookup"
69 public class DeleteArtifactAction
70 extends PlexusActionSupport
71 implements Validateable, Preparable, Auditable
74 * The groupId of the artifact to be deleted.
76 private String groupId;
79 * The artifactId of the artifact to be deleted.
81 private String artifactId;
84 * The version of the artifact to be deleted.
86 private String version;
89 * The repository where the artifact is to be deleted.
91 private String repositoryId;
94 * List of managed repositories to delete from.
96 private List<String> managedRepos;
101 private UserRepositories userRepositories;
104 * @plexus.requirement role-hint="default"
106 private ArchivaConfiguration configuration;
109 * @plexus.requirement
111 private RepositoryContentFactory repositoryFactory;
114 * @plexus.requirement role-hint="jdo"
116 private ArtifactDAO artifactDAO;
119 * @plexus.requirement
121 private DatabaseConsumers databaseConsumers;
123 /** @plexus.requirement */
124 private List<RepositoryListener> listeners;
126 private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[] { ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
128 public String getGroupId()
133 public void setGroupId( String groupId )
135 this.groupId = groupId;
138 public String getArtifactId()
143 public void setArtifactId( String artifactId )
145 this.artifactId = artifactId;
148 public String getVersion()
153 public void setVersion( String version )
155 this.version = version;
158 public String getRepositoryId()
163 public void setRepositoryId( String repositoryId )
165 this.repositoryId = repositoryId;
168 public List<String> getManagedRepos()
173 public void setManagedRepos( List<String> managedRepos )
175 this.managedRepos = managedRepos;
178 public void prepare()
180 managedRepos = getManagableRepos();
183 public String input()
190 // reset the fields so the form is clear when
191 // the action returns to the jsp page
198 public String doDelete()
202 Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
204 TimeZone timezone = TimeZone.getTimeZone( "UTC" );
205 DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
206 fmt.setTimeZone( timezone );
207 ManagedRepositoryConfiguration repoConfig =
208 configuration.getConfiguration().findManagedRepositoryById( repositoryId );
210 VersionedReference ref = new VersionedReference();
211 ref.setArtifactId( artifactId );
212 ref.setGroupId( groupId );
213 ref.setVersion( version );
215 ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
217 String path = repository.toMetadataPath( ref );
218 int index = path.lastIndexOf( '/' );
219 File targetPath = new File( repoConfig.getLocation(), path.substring( 0, index ) );
221 if ( !targetPath.exists() )
223 throw new ContentNotFoundException( groupId + ":" + artifactId + ":" + version );
226 // delete from file system
227 repository.deleteVersion( ref );
229 File metadataFile = getMetadata( targetPath.getAbsolutePath() );
230 ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );
232 updateMetadata( metadata, metadataFile, lastUpdatedTimestamp );
234 ArtifactVersionsConstraint constraint =
235 new ArtifactVersionsConstraint( repositoryId, groupId, artifactId, false );
236 List<ArchivaArtifact> artifacts = null;
240 artifacts = artifactDAO.queryArtifacts( constraint );
242 if ( artifacts != null )
244 for ( ArchivaArtifact artifact : artifacts )
246 if ( artifact.getVersion().equals( version ) )
248 for ( RepositoryListener listener : listeners )
250 listener.deleteArtifact( repository, artifact );
256 catch ( ArchivaDatabaseException e )
258 addActionError( "Error occurred while cleaning up database: " + e.getMessage() );
263 "Artifact \'" + groupId + ":" + artifactId + ":" + version +
264 "\' was successfully deleted from repository \'" + repositoryId + "\'";
266 triggerAuditEvent( repositoryId, groupId + ":" + artifactId + ":" + version,
267 AuditEvent.REMOVE_FILE );
269 addActionMessage( msg );
274 catch ( ContentNotFoundException e )
276 addActionError( "Artifact does not exist: " + e.getMessage() );
279 catch ( RepositoryNotFoundException e )
281 addActionError( "Target repository cannot be found: " + e.getMessage() );
284 catch ( RepositoryException e )
286 addActionError( "Repository exception: " + e.getMessage() );
291 private File getMetadata( String targetPath )
293 String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( File.separatorChar ) );
295 return new File( artifactPath, MetadataTools.MAVEN_METADATA );
298 private ArchivaRepositoryMetadata getMetadata( File metadataFile )
299 throws RepositoryMetadataException
301 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
302 if ( metadataFile.exists() )
304 metadata = RepositoryMetadataReader.read( metadataFile );
310 * Update artifact level metadata. Creates one if metadata does not exist after artifact deletion.
314 private void updateMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, Date lastUpdatedTimestamp )
315 throws RepositoryMetadataException
317 List<String> availableVersions = new ArrayList<String>();
318 String latestVersion = "";
320 if ( metadataFile.exists() )
322 if ( metadata.getAvailableVersions() != null )
324 availableVersions = metadata.getAvailableVersions();
326 if ( availableVersions.size() > 0 )
328 Collections.sort( availableVersions, VersionComparator.getInstance() );
330 if ( availableVersions.contains( version ) )
332 availableVersions.remove( availableVersions.indexOf( version ) );
334 if ( availableVersions.size() > 0 )
336 latestVersion = availableVersions.get( availableVersions.size() - 1 );
342 if ( metadata.getGroupId() == null )
344 metadata.setGroupId( groupId );
346 if ( metadata.getArtifactId() == null )
348 metadata.setArtifactId( artifactId );
351 if ( !VersionUtil.isSnapshot( version ) )
353 if ( metadata.getReleasedVersion().equals( version ) )
355 metadata.setReleasedVersion( latestVersion );
359 metadata.setLatestVersion( latestVersion );
360 metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
361 metadata.setAvailableVersions( availableVersions );
363 RepositoryMetadataWriter.write( metadata, metadataFile );
364 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
365 checksum.fixChecksums( algorithms );
368 public void validate()
372 if ( !userRepositories.isAuthorizedToDeleteArtifacts( getPrincipal(), repositoryId ) )
374 addActionError( "User is not authorized to delete artifacts in repository '" + repositoryId + "'." );
377 if ( ( version.length() > 0 ) && ( !VersionUtil.isVersion( version ) ) )
379 addActionError( "Invalid version." );
382 catch ( AccessDeniedException e )
384 addActionError( e.getMessage() );
386 catch ( ArchivaSecurityException e )
388 addActionError( e.getMessage() );
392 private List<String> getManagableRepos()
396 return userRepositories.getManagableRepositoryIds( getPrincipal() );
398 catch ( PrincipalNotFoundException e )
400 log.warn( e.getMessage(), e );
402 catch ( AccessDeniedException e )
404 log.warn( e.getMessage(), e );
405 // TODO: pass this onto the screen.
407 catch ( ArchivaSecurityException e )
409 log.warn( e.getMessage(), e );
411 return Collections.emptyList();