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 org.apache.archiva.checksum.ChecksumAlgorithm;
33 import org.apache.archiva.checksum.ChecksummedFile;
34 import org.apache.maven.archiva.common.utils.VersionComparator;
35 import org.apache.maven.archiva.common.utils.VersionUtil;
36 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
37 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
38 import org.apache.maven.archiva.database.updater.DatabaseConsumers;
39 import org.apache.maven.archiva.database.ArchivaDatabaseException;
40 import org.apache.maven.archiva.database.ArtifactDAO;
41 import org.apache.maven.archiva.database.constraints.ArtifactVersionsConstraint;
42 import org.apache.maven.archiva.model.ArchivaArtifact;
43 import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
44 import org.apache.maven.archiva.model.VersionedReference;
45 import org.apache.maven.archiva.repository.audit.Auditable;
46 import org.apache.maven.archiva.repository.audit.AuditEvent;
47 import org.apache.maven.archiva.repository.audit.AuditListener;
48 import org.apache.maven.archiva.repository.metadata.MetadataTools;
49 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
50 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
51 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataWriter;
52 import org.apache.maven.archiva.repository.ContentNotFoundException;
53 import org.apache.maven.archiva.repository.RepositoryException;
54 import org.apache.maven.archiva.repository.RepositoryNotFoundException;
55 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
56 import org.apache.maven.archiva.repository.RepositoryContentFactory;
57 import org.apache.maven.archiva.security.ArchivaXworkUser;
58 import org.apache.maven.archiva.security.UserRepositories;
59 import org.codehaus.plexus.redback.rbac.RbacManagerException;
61 import org.apache.struts2.ServletActionContext;
62 import com.opensymphony.xwork2.ActionContext;
63 import com.opensymphony.xwork2.Preparable;
64 import com.opensymphony.xwork2.Validateable;
67 * Delete an artifact. Metadata will be updated if one exists, otherwise it would be created.
69 * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="deleteArtifactAction" instantiation-strategy="per-lookup"
71 public class DeleteArtifactAction
72 extends PlexusActionSupport
73 implements Validateable, Preparable, Auditable
78 private ArchivaXworkUser archivaXworkUser;
81 * The groupId of the artifact to be deleted.
83 private String groupId;
86 * The artifactId of the artifact to be deleted.
88 private String artifactId;
91 * The version of the artifact to be deleted.
93 private String version;
96 * The repository where the artifact is to be deleted.
98 private String repositoryId;
101 * List of managed repositories to delete from.
103 private List<String> managedRepos;
106 * @plexus.requirement
108 private UserRepositories userRepositories;
111 * @plexus.requirement role-hint="default"
113 private ArchivaConfiguration configuration;
116 * @plexus.requirement
118 private RepositoryContentFactory repositoryFactory;
121 * @plexus.requirement role-hint="jdo"
123 private ArtifactDAO artifactDAO;
126 * @plexus.requirement
128 private DatabaseConsumers databaseConsumers;
131 * @plexus.requirement role="org.apache.maven.archiva.repository.audit.AuditListener"
133 private List<AuditListener> auditListeners = new ArrayList<AuditListener>();
135 private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[] { ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
137 public String getGroupId()
142 public void setGroupId( String groupId )
144 this.groupId = groupId;
147 public String getArtifactId()
152 public void setArtifactId( String artifactId )
154 this.artifactId = artifactId;
157 public String getVersion()
162 public void setVersion( String version )
164 this.version = version;
167 public String getRepositoryId()
172 public void setRepositoryId( String repositoryId )
174 this.repositoryId = repositoryId;
177 public List<String> getManagedRepos()
182 public void setManagedRepos( List<String> managedRepos )
184 this.managedRepos = managedRepos;
187 public void prepare()
189 managedRepos = new ArrayList<String>( configuration.getConfiguration().getManagedRepositoriesAsMap().keySet() );
192 public String input()
199 // reset the fields so the form is clear when
200 // the action returns to the jsp page
207 public String doDelete()
211 Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
213 TimeZone timezone = TimeZone.getTimeZone( "UTC" );
214 DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
215 fmt.setTimeZone( timezone );
216 ManagedRepositoryConfiguration repoConfig =
217 configuration.getConfiguration().findManagedRepositoryById( repositoryId );
219 VersionedReference ref = new VersionedReference();
220 ref.setArtifactId( artifactId );
221 ref.setGroupId( groupId );
222 ref.setVersion( version );
224 ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
226 String path = repository.toMetadataPath( ref );
227 int index = path.lastIndexOf( '/' );
228 File targetPath = new File( repoConfig.getLocation(), path.substring( 0, index ) );
230 if ( !targetPath.exists() )
232 throw new ContentNotFoundException( groupId + ":" + artifactId + ":" + version );
235 // delete from file system
236 repository.deleteVersion( ref );
238 File metadataFile = getMetadata( targetPath.getAbsolutePath() );
239 ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );
241 updateMetadata( metadata, metadataFile, lastUpdatedTimestamp );
243 ArtifactVersionsConstraint constraint =
244 new ArtifactVersionsConstraint( repositoryId, groupId, artifactId, false );
245 List<ArchivaArtifact> artifacts = null;
249 artifacts = artifactDAO.queryArtifacts( constraint );
251 if ( artifacts != null )
253 for ( ArchivaArtifact artifact : artifacts )
255 if ( artifact.getVersion().equals( version ) )
257 databaseConsumers.executeCleanupConsumer( artifact );
262 catch ( ArchivaDatabaseException e )
264 addActionError( "Error occurred while cleaning up database: " + e.getMessage() );
269 "Artifact \'" + groupId + ":" + artifactId + ":" + version +
270 "\' was successfully deleted from repository \'" + repositoryId + "\'";
272 triggerAuditEvent( getPrincipal(), repositoryId, groupId + ":" + artifactId + ":" + version,
273 AuditEvent.REMOVE_FILE );
275 addActionMessage( msg );
280 catch ( ContentNotFoundException e )
282 addActionError( "Artifact does not exist: " + e.getMessage() );
285 catch ( RepositoryNotFoundException e )
287 addActionError( "Target repository cannot be found: " + e.getMessage() );
290 catch ( RepositoryException e )
292 addActionError( "Repository exception: " + e.getMessage() );
297 @SuppressWarnings("unchecked")
298 private String getPrincipal()
300 return archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() );
303 private File getMetadata( String targetPath )
305 String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( File.separatorChar ) );
307 return new File( artifactPath, MetadataTools.MAVEN_METADATA );
310 private ArchivaRepositoryMetadata getMetadata( File metadataFile )
311 throws RepositoryMetadataException
313 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
314 if ( metadataFile.exists() )
316 metadata = RepositoryMetadataReader.read( metadataFile );
322 * Update artifact level metadata. Creates one if metadata does not exist after artifact deletion.
326 private void updateMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, Date lastUpdatedTimestamp )
327 throws RepositoryMetadataException
329 List<String> availableVersions = new ArrayList<String>();
330 String latestVersion = "";
332 if ( metadataFile.exists() )
334 if ( metadata.getAvailableVersions() != null )
336 availableVersions = metadata.getAvailableVersions();
338 if ( availableVersions.size() > 0 )
340 Collections.sort( availableVersions, VersionComparator.getInstance() );
342 if ( availableVersions.contains( version ) )
344 availableVersions.remove( availableVersions.indexOf( version ) );
346 if ( availableVersions.size() > 0 )
348 latestVersion = availableVersions.get( availableVersions.size() - 1 );
354 if ( metadata.getGroupId() == null )
356 metadata.setGroupId( groupId );
358 if ( metadata.getArtifactId() == null )
360 metadata.setArtifactId( artifactId );
363 if ( !VersionUtil.isSnapshot( version ) )
365 if ( metadata.getReleasedVersion().equals( version ) )
367 metadata.setReleasedVersion( latestVersion );
371 metadata.setLatestVersion( latestVersion );
372 metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
373 metadata.setAvailableVersions( availableVersions );
375 RepositoryMetadataWriter.write( metadata, metadataFile );
376 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
377 checksum.fixChecksums( algorithms );
380 public void validate()
384 if ( !userRepositories.isAuthorizedToDeleteArtifacts( getPrincipal(), repositoryId ) )
386 addActionError( "User is not authorized to delete artifacts in repository '" + repositoryId + "'." );
389 if ( ( version.length() > 0 ) && ( !VersionUtil.isVersion( version ) ) )
391 addActionError( "Invalid version." );
394 catch ( RbacManagerException e )
396 addActionError( e.getMessage() );
400 public void addAuditListener( AuditListener listener )
402 this.auditListeners.add( listener );
405 public void clearAuditListeners()
407 this.auditListeners.clear();
410 public void removeAuditListener( AuditListener listener )
412 this.auditListeners.remove( listener );
415 private void triggerAuditEvent( String user, String repositoryId, String resource, String action )
417 AuditEvent event = new AuditEvent( repositoryId, user, resource, action );
418 event.setRemoteIP( ServletActionContext.getRequest().getRemoteAddr() );
420 for ( AuditListener listener : auditListeners )
422 listener.auditEvent( event );