Package org.apache.archiva.web.action

Source Code of org.apache.archiva.web.action.DeleteArtifactAction

package org.apache.archiva.web.action;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.Validateable;
import org.apache.archiva.admin.model.RepositoryAdminException;
import org.apache.archiva.admin.model.beans.ManagedRepository;
import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
import org.apache.archiva.audit.AuditEvent;
import org.apache.archiva.audit.Auditable;
import org.apache.archiva.checksum.ChecksumAlgorithm;
import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.metadata.repository.MetadataRepositoryException;
import org.apache.archiva.metadata.repository.MetadataResolutionException;
import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.security.AccessDeniedException;
import org.apache.archiva.security.ArchivaSecurityException;
import org.apache.archiva.security.PrincipalNotFoundException;
import org.apache.archiva.security.UserRepositories;
import org.apache.commons.lang.StringUtils;
import org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.model.ArchivaRepositoryMetadata;
import org.apache.archiva.model.VersionedReference;
import org.apache.archiva.repository.ContentNotFoundException;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.RepositoryContentFactory;
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryNotFoundException;
import org.apache.archiva.repository.metadata.MetadataTools;
import org.apache.archiva.repository.metadata.RepositoryMetadataException;
import org.apache.archiva.repository.metadata.RepositoryMetadataReader;
import org.apache.archiva.repository.metadata.RepositoryMetadataWriter;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

/**
* Delete an artifact. Metadata will be updated if one exists, otherwise it would be created.
*/
@Controller( "deleteArtifactAction" )
@Scope( "prototype" )
public class DeleteArtifactAction
    extends AbstractActionSupport
    implements Validateable, Preparable, Auditable
{
    /**
     * The groupId of the artifact to be deleted.
     */
    private String groupId;

    /**
     * The artifactId of the artifact to be deleted.
     */
    private String artifactId;

    /**
     * The version of the artifact to be deleted.
     */
    private String version;

    /**
     * The repository where the artifact is to be deleted.
     */
    private String repositoryId;

    /**
     * List of managed repositories to delete from.
     */
    private List<String> managedRepos;

    @Inject
    private UserRepositories userRepositories;

    @Inject
    private RepositoryContentFactory repositoryFactory;

    @Inject
    private List<RepositoryListener> listeners;

    @Inject
    private ManagedRepositoryAdmin managedRepositoryAdmin;

    private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };

    @PostConstruct
    public void initialize()
    {
        super.initialize();
    }

    public String getGroupId()
    {
        return groupId;
    }

    public void setGroupId( String groupId )
    {
        this.groupId = groupId;
    }

    public String getArtifactId()
    {
        return artifactId;
    }

    public void setArtifactId( String artifactId )
    {
        this.artifactId = artifactId;
    }

    public String getVersion()
    {
        return version;
    }

    public void setVersion( String version )
    {
        this.version = version;
    }

    public String getRepositoryId()
    {
        return repositoryId;
    }

    public void setRepositoryId( String repositoryId )
    {
        this.repositoryId = repositoryId;
    }

    public List<String> getManagedRepos()
    {
        return managedRepos;
    }

    public void setManagedRepos( List<String> managedRepos )
    {
        this.managedRepos = managedRepos;
    }

    public void prepare()
    {
        managedRepos = getManagableRepos();
    }

    public String input()
    {
        return INPUT;
    }

    private void reset()
    {
        // reset the fields so the form is clear when
        // the action returns to the jsp page
        groupId = "";
        artifactId = "";
        version = "";
        repositoryId = "";
    }

    public String doDelete()
    {

        RepositorySession repositorySession = repositorySessionFactory.createSession();
        try
        {
            Date lastUpdatedTimestamp = Calendar.getInstance().getTime();

            TimeZone timezone = TimeZone.getTimeZone( "UTC" );
            DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
            fmt.setTimeZone( timezone );
            ManagedRepository repoConfig = getManagedRepositoryAdmin().getManagedRepository( repositoryId );

            VersionedReference ref = new VersionedReference();
            ref.setArtifactId( artifactId );
            ref.setGroupId( groupId );
            ref.setVersion( version );
            ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );

            String path = repository.toMetadataPath( ref );
            int index = path.lastIndexOf( '/' );
            path = path.substring( 0, index );
            File targetPath = new File( repoConfig.getLocation(), path );

            if ( !targetPath.exists() )
            {
                throw new ContentNotFoundException( groupId + ":" + artifactId + ":" + version );
            }

            // TODO: this should be in the storage mechanism so that it is all tied together
            // delete from file system
            repository.deleteVersion( ref );

            File metadataFile = getMetadata( targetPath.getAbsolutePath() );
            ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );

            updateMetadata( metadata, metadataFile, lastUpdatedTimestamp );

            MetadataRepository metadataRepository = repositorySession.getRepository();
            Collection<ArtifactMetadata> artifacts =
                metadataRepository.getArtifacts( repositoryId, groupId, artifactId, version );

            for ( ArtifactMetadata artifact : artifacts )
            {
                // TODO: mismatch between artifact (snapshot) version and project (base) version here
                if ( artifact.getVersion().equals( version ) )
                {
                    metadataRepository.removeArtifact( artifact.getRepositoryId(), artifact.getNamespace(),
                                                       artifact.getProject(), artifact.getVersion(), artifact.getId() );

                    // TODO: move into the metadata repository proper - need to differentiate attachment of
                    //       repository metadata to an artifact
                    for ( RepositoryListener listener : listeners )
                    {
                        listener.deleteArtifact( metadataRepository, repository.getId(), artifact.getNamespace(),
                                                 artifact.getProject(), artifact.getVersion(), artifact.getId() );
                    }

                    triggerAuditEvent( repositoryId, path, AuditEvent.REMOVE_FILE );
                }
            }
            repositorySession.save();
        }
        catch ( ContentNotFoundException e )
        {
            addActionError( "Artifact does not exist: " + e.getMessage() );
            return ERROR;
        }
        catch ( RepositoryNotFoundException e )
        {
            addActionError( "Target repository cannot be found: " + e.getMessage() );
            return ERROR;
        }
        catch ( RepositoryException e )
        {
            addActionError( "Repository exception: " + e.getMessage() );
            return ERROR;
        }
        catch ( MetadataResolutionException e )
        {
            addActionError( "Repository exception: " + e.getMessage() );
            return ERROR;
        }
        catch ( MetadataRepositoryException e )
        {
            addActionError( "Repository exception: " + e.getMessage() );
            return ERROR;
        }
        catch ( RepositoryAdminException e )
        {
            addActionError( "RepositoryAdmin exception: " + e.getMessage() );
            return ERROR;
        }
        finally
        {
            repositorySession.close();
        }

        String msg = "Artifact \'" + groupId + ":" + artifactId + ":" + version
            + "\' was successfully deleted from repository \'" + repositoryId + "\'";

        addActionMessage( msg );

        reset();
        return SUCCESS;
    }

    private File getMetadata( String targetPath )
    {
        String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( File.separatorChar ) );

        return new File( artifactPath, MetadataTools.MAVEN_METADATA );
    }

    private ArchivaRepositoryMetadata getMetadata( File metadataFile )
        throws RepositoryMetadataException
    {
        ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
        if ( metadataFile.exists() )
        {
            metadata = RepositoryMetadataReader.read( metadataFile );
        }
        return metadata;
    }

    /**
     * Update artifact level metadata. Creates one if metadata does not exist after artifact deletion.
     *
     * @param metadata
     */
    private void updateMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, Date lastUpdatedTimestamp )
        throws RepositoryMetadataException
    {
        List<String> availableVersions = new ArrayList<String>();
        String latestVersion = "";

        if ( metadataFile.exists() )
        {
            if ( metadata.getAvailableVersions() != null )
            {
                availableVersions = metadata.getAvailableVersions();

                if ( availableVersions.size() > 0 )
                {
                    Collections.sort( availableVersions, VersionComparator.getInstance() );

                    if ( availableVersions.contains( version ) )
                    {
                        availableVersions.remove( availableVersions.indexOf( version ) );
                    }
                    if ( availableVersions.size() > 0 )
                    {
                        latestVersion = availableVersions.get( availableVersions.size() - 1 );
                    }
                }
            }
        }

        if ( metadata.getGroupId() == null )
        {
            metadata.setGroupId( groupId );
        }
        if ( metadata.getArtifactId() == null )
        {
            metadata.setArtifactId( artifactId );
        }

        if ( !VersionUtil.isSnapshot( version ) )
        {
            if ( metadata.getReleasedVersion() != null && metadata.getReleasedVersion().equals( version ) )
            {
                metadata.setReleasedVersion( latestVersion );
            }
        }

        metadata.setLatestVersion( latestVersion );
        metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
        metadata.setAvailableVersions( availableVersions );

        RepositoryMetadataWriter.write( metadata, metadataFile );
        ChecksummedFile checksum = new ChecksummedFile( metadataFile );
        checksum.fixChecksums( algorithms );
    }

    public void validate()
    {
        try
        {
            if ( !userRepositories.isAuthorizedToDeleteArtifacts( getPrincipal(), repositoryId ) )
            {
                addActionError( "User is not authorized to delete artifacts in repository '" + repositoryId + "'." );
            }

            if ( ( version.length() > 0 ) && ( !VersionUtil.isVersion( version ) ) )
            {
                addActionError( "Invalid version." );
            }
        }
        catch ( AccessDeniedException e )
        {
            addActionError( e.getMessage() );
        }
        catch ( ArchivaSecurityException e )
        {
            addActionError( e.getMessage() );
        }

        // trims all request parameter values, since the trailing/leading white-spaces are ignored during validation.
        trimAllRequestParameterValues();
    }

    private List<String> getManagableRepos()
    {
        try
        {
            return userRepositories.getManagableRepositoryIds( getPrincipal() );
        }
        catch ( PrincipalNotFoundException e )
        {
            log.warn( e.getMessage(), e );
        }
        catch ( AccessDeniedException e )
        {
            log.warn( e.getMessage(), e );
            // TODO: pass this onto the screen.
        }
        catch ( ArchivaSecurityException e )
        {
            log.warn( e.getMessage(), e );
        }
        return Collections.emptyList();
    }

    private void trimAllRequestParameterValues()
    {
        if ( StringUtils.isNotEmpty( groupId ) )
        {
            groupId = groupId.trim();
        }

        if ( StringUtils.isNotEmpty( artifactId ) )
        {
            artifactId = artifactId.trim();
        }

        if ( StringUtils.isNotEmpty( version ) )
        {
            version = version.trim();
        }

        if ( StringUtils.isNotEmpty( repositoryId ) )
        {
            repositoryId = repositoryId.trim();
        }
    }

    public List<RepositoryListener> getListeners()
    {
        return listeners;
    }

    public void setRepositoryFactory( RepositoryContentFactory repositoryFactory )
    {
        this.repositoryFactory = repositoryFactory;
    }

    public ManagedRepositoryAdmin getManagedRepositoryAdmin()
    {
        return managedRepositoryAdmin;
    }

    public void setManagedRepositoryAdmin( ManagedRepositoryAdmin managedRepositoryAdmin )
    {
        this.managedRepositoryAdmin = managedRepositoryAdmin;
    }
}
TOP

Related Classes of org.apache.archiva.web.action.DeleteArtifactAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.