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"
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 String timestamp = fmt.format( lastUpdatedTimestamp );
218 ManagedRepositoryConfiguration repoConfig =
219 configuration.getConfiguration().findManagedRepositoryById( repositoryId );
221 VersionedReference ref = new VersionedReference();
222 ref.setArtifactId( artifactId );
223 ref.setGroupId( groupId );
224 ref.setVersion( version );
226 ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
228 String path = repository.toMetadataPath( ref );
229 int index = path.lastIndexOf( '/' );
230 File targetPath = new File( repoConfig.getLocation(), path.substring( 0, index ) );
232 if ( !targetPath.exists() )
234 throw new ContentNotFoundException( groupId + ":" + artifactId + ":" + version );
237 // delete from file system
238 repository.deleteVersion( ref );
240 File metadataFile = getMetadata( targetPath.getAbsolutePath() );
241 ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );
243 updateMetadata( metadata, metadataFile, lastUpdatedTimestamp );
245 ArtifactVersionsConstraint constraint =
246 new ArtifactVersionsConstraint( repositoryId, groupId, artifactId, false );
247 List<ArchivaArtifact> artifacts = null;
251 artifacts = artifactDAO.queryArtifacts( constraint );
253 if ( artifacts != null )
255 for ( ArchivaArtifact artifact : artifacts )
257 if ( artifact.getVersion().equals( version ) )
259 databaseConsumers.executeCleanupConsumer( artifact );
264 catch ( ArchivaDatabaseException e )
266 addActionError( "Error occurred while cleaning up database: " + e.getMessage() );
271 "Artifact \'" + groupId + ":" + artifactId + ":" + version +
272 "\' was successfully deleted from repository \'" + repositoryId + "\'";
274 triggerAuditEvent( getPrincipal(), repositoryId, groupId + ":" + artifactId + ":" + version,
275 AuditEvent.REMOVE_FILE );
277 addActionMessage( msg );
282 catch ( ContentNotFoundException e )
284 addActionError( "Artifact does not exist: " + e.getMessage() );
287 catch ( RepositoryNotFoundException e )
289 addActionError( "Target repository cannot be found: " + e.getMessage() );
292 catch ( RepositoryException e )
294 addActionError( "Repository exception: " + e.getMessage() );
299 private String getPrincipal()
301 return archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() );
304 private File getMetadata( String targetPath )
306 String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( File.separatorChar ) );
308 return new File( artifactPath, MetadataTools.MAVEN_METADATA );
311 private ArchivaRepositoryMetadata getMetadata( File metadataFile )
312 throws RepositoryMetadataException
314 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
315 if ( metadataFile.exists() )
317 metadata = RepositoryMetadataReader.read( metadataFile );
323 * Update artifact level metadata. Creates one if metadata does not exist after artifact deletion.
327 private void updateMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, Date lastUpdatedTimestamp )
328 throws RepositoryMetadataException
330 List<String> availableVersions = new ArrayList<String>();
331 String latestVersion = "";
333 if ( metadataFile.exists() )
335 if ( metadata.getAvailableVersions() != null )
337 availableVersions = metadata.getAvailableVersions();
339 if ( availableVersions.size() > 0 )
341 Collections.sort( availableVersions, VersionComparator.getInstance() );
343 if ( availableVersions.contains( version ) )
345 availableVersions.remove( availableVersions.indexOf( version ) );
347 if ( availableVersions.size() > 0 )
349 latestVersion = availableVersions.get( availableVersions.size() - 1 );
355 if ( metadata.getGroupId() == null )
357 metadata.setGroupId( groupId );
359 if ( metadata.getArtifactId() == null )
361 metadata.setArtifactId( artifactId );
364 if ( !VersionUtil.isSnapshot( version ) )
366 if ( metadata.getReleasedVersion().equals( version ) )
368 metadata.setReleasedVersion( latestVersion );
372 metadata.setLatestVersion( latestVersion );
373 metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
374 metadata.setAvailableVersions( availableVersions );
376 RepositoryMetadataWriter.write( metadata, metadataFile );
377 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
378 checksum.fixChecksums( algorithms );
381 public void validate()
385 if ( !userRepositories.isAuthorizedToDeleteArtifacts( getPrincipal(), repositoryId ) )
387 addActionError( "User is not authorized to delete artifacts in repository '" + repositoryId + "'." );
390 if ( ( version.length() > 0 ) && ( !VersionUtil.isVersion( version ) ) )
392 addActionError( "Invalid version." );
395 catch ( RbacManagerException e )
397 addActionError( e.getMessage() );
401 public void addAuditListener( AuditListener listener )
403 this.auditListeners.add( listener );
406 public void clearAuditListeners()
408 this.auditListeners.clear();
411 public void removeAuditListener( AuditListener listener )
413 this.auditListeners.remove( listener );
416 private void triggerAuditEvent( String user, String repositoryId, String resource, String action )
418 AuditEvent event = new AuditEvent( repositoryId, user, resource, action );
419 event.setRemoteIP( ServletActionContext.getRequest().getRemoteAddr() );
421 for ( AuditListener listener : auditListeners )
423 listener.auditEvent( event );