Package com.salesforce.ide.ui.refactoring

Source Code of com.salesforce.ide.ui.refactoring.DeleteRefactorController

/*******************************************************************************
* Copyright (c) 2014 Salesforce.com, inc..
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Salesforce.com, inc. - initial API and implementation
******************************************************************************/
package com.salesforce.ide.ui.refactoring;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import com.salesforce.ide.core.ForceIdeCorePlugin;
import com.salesforce.ide.core.internal.context.ContainerDelegate;
import com.salesforce.ide.core.internal.utils.Constants;
import com.salesforce.ide.core.internal.utils.PackageManifestDocumentUtils;
import com.salesforce.ide.core.internal.utils.Utils;
import com.salesforce.ide.core.model.Component;
import com.salesforce.ide.core.model.ComponentList;
import com.salesforce.ide.core.model.ProjectPackage;
import com.salesforce.ide.core.model.ProjectPackageList;
import com.salesforce.ide.core.project.ProjectController;
import com.salesforce.ide.core.remote.ForceConnectionException;
import com.salesforce.ide.core.remote.ForceRemoteException;
import com.salesforce.ide.core.remote.metadata.DeployMessageExt;
import com.salesforce.ide.core.remote.metadata.DeployResultExt;
import com.salesforce.ide.core.services.ServiceException;
import com.salesforce.ide.core.services.ServiceTimeoutException;
import com.sforce.soap.metadata.DeployMessage;

/**
* Service methods for refactoring functionality.
*
* @author cwall
*/
public class DeleteRefactorController extends BaseRefactorController {

    private static final Logger logger = Logger.getLogger(DeleteRefactorController.class);

    public DeleteRefactorController(){
        super();
        refactorModel = new RefactorModel();
    }

    /**
     * Validate delete candidates
     *
     * @param changeElements
     * @param monitor
     * @return
     * @throws OperationCanceledException
     * @throws InterruptedException
     */
    public RefactoringStatus validateDelete(IProgressMonitor monitor) throws OperationCanceledException,
            InterruptedException {
        // REVIEWME: what to do w/ ResourceChangeChecker and/or ValidateEditChecker
        monitorCheck(monitor);

        RefactoringStatus refactoringStatus = new RefactoringStatus();
        ProjectPackageList projectPackageList = refactorModel.getProjectPackageList();
        if (projectPackageList == null) {
            logger.error("Project package list not prepared for delete candidates");
            refactoringStatus.addEntry(createFatalRefactoringStatusEntry(Constants.PLUGIN_NAME
                    + " does not support deleting resource(s)"));
            return refactoringStatus;
        }

        Set<IResource> deleteCandidates = refactorModel.getChangeResources();
        if (Utils.isEmpty(deleteCandidates)) {
            refactoringStatus.addEntry(createInfoRefactoringStatusEntry("No resource(s) found to delete"));
            return refactoringStatus;
        }

        // for now, we assume there is only one delete candidate
        for (IResource deleteCandidate : deleteCandidates) {
            monitorCheck(monitor);
            if (Constants.PACKAGE_MANIFEST_FILE_NAME.equals(deleteCandidate.getName())) {
                logger.error(Constants.PLUGIN_NAME + " does not support deleting resource '"
                        + deleteCandidate.getFullPath().toPortableString());
                refactoringStatus.addEntry(createFatalRefactoringStatusEntry(Constants.PLUGIN_NAME
                        + " does not support deleting resource '" + deleteCandidate.getFullPath().toPortableString()));
                continue;
            }

            monitorCheck(monitor);
            boolean forceManaged = ContainerDelegate.getInstance().getServiceLocator().getProjectService().isManagedResource(deleteCandidate);
            if (!forceManaged) {
                if (logger.isInfoEnabled()) {
                    logger.info("Delete resource '" + deleteCandidate.getFullPath().toPortableString() + " is not "
                            + Constants.PLUGIN_NAME + " managed; therefore, we don't care!");
                }
                continue;
            }

            // evaluate based on resource type
            if (deleteCandidate.getType() == IResource.FILE) {
                if (logger.isInfoEnabled()) {
                    logger.info("Delete request for resource '" + deleteCandidate.getFullPath().toPortableString());
                }

                // restrict deleting of force and package essential files
                if (Constants.SCHEMA_FILENAME.equals(deleteCandidate.getName())
                        || Constants.PACKAGE_MANIFEST_FILE_NAME.equals(deleteCandidate.getName())
                        || Constants.DESTRUCTIVE_MANIFEST_FILE_NAME.equals(deleteCandidate.getName())) {
                    logger.error(Constants.PLUGIN_NAME + " does not support deleting '" + deleteCandidate.getName()
                            + "'");
                    refactoringStatus.addEntry(createFatalRefactoringStatusEntry(Constants.PLUGIN_NAME
                            + " does not support deleting '" + deleteCandidate.getName() + "'"));
                }

                continue;
            } else if (deleteCandidate.getType() == IResource.FOLDER) {
                if (logger.isInfoEnabled()) {
                    logger.info("Delete request for resource '" + deleteCandidate.getFullPath().toPortableString());
                }

                // cannot delete package or "referenced packages" folders
                if (ContainerDelegate.getInstance().getServiceLocator().getProjectService().isReferencedPackageResource(deleteCandidate)
                        || ContainerDelegate.getInstance().getServiceLocator().getProjectService().isReferencedPackagesFolder(deleteCandidate)) {
                    logger.error(Constants.PLUGIN_NAME + " does not support deleting 'Referenced Package' resource '"
                            + deleteCandidate.getName() + "'");
                    refactoringStatus.addEntry(createFatalRefactoringStatusEntry(Constants.PLUGIN_NAME
                            + " does not support deleting 'Referenced Package' resource '" + deleteCandidate.getName()
                            + "'"));
                }

                // cannot delete src folder
                if (ContainerDelegate.getInstance().getServiceLocator().getProjectService().isSourceFolder(deleteCandidate)) {
                    logger.error(Constants.PLUGIN_NAME + " does not support deleting package source folder '"
                            + deleteCandidate.getName() + "'");
                    refactoringStatus.addEntry(createFatalRefactoringStatusEntry(Constants.PLUGIN_NAME
                            + " does not support deleting package source folder '" + deleteCandidate.getName() + "'"));
                }

                continue;
            } else if (deleteCandidate.getType() == IResource.PROJECT) {
                if (logger.isInfoEnabled()) {
                    logger.info("Delete request for resource '" + deleteCandidate.getFullPath().toPortableString());
                }
                continue;
            }
        }

        return refactoringStatus;
    }

    @Override
    public void finish(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException, IOException {
        try {
            performRemoteDelete(monitor);
        } catch (OperationCanceledException e) {
            throw new InterruptedException(e.getMessage());
        } catch (ForceConnectionException e) {
            throw new InterruptedException(e.getMessage());
        } catch (ServiceException e) {
            throw new InterruptedException(e.getMessage());
        } catch (ForceRemoteException e) {
            throw new InterruptedException(e.getMessage());
        }
    }

    public List<RefactoringStatusEntry> performRemoteDelete(IProgressMonitor monitor)
            throws OperationCanceledException, InterruptedException, ForceConnectionException, ServiceException,
            ForceRemoteException, InvocationTargetException {
        if (refactorModel.isChangeResourcesEmpty()) {
            logger.warn("Unable to perform delete - delete resources is empty");
            return null;
        }

        List<RefactoringStatusEntry> entries = new ArrayList<RefactoringStatusEntry>();

        // abort if online nature is not applied
        if (!ContainerDelegate.getInstance().getServiceLocator().getProjectService().isManagedOnlineProject(refactorModel.getProject())) {
            logger.warn("Unable to delete deploy for project '" + refactorModel.getProject().getName()
                    + "' - project is not online enabled");
            entries.add(createWarningRefactoringStatusEntry("Unable to test deploy for project '"
                    + refactorModel.getProject().getName() + "' - project is not online enabled"));
            return entries;
        }

        ProjectPackageList projectPackageList = refactorModel.getProjectPackageList();
        if (Utils.isEmpty(projectPackageList)) {
            logger.error("Unable to perform server delete - project package list is null");
            entries.add(createFatalRefactoringStatusEntry("Cannot perform delete - project package list is null"));
            return entries;
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Deleting the following from server (excluding package.xml(s)):\n"
                    + projectPackageList.getAllComponents().toStringLite());
        }

        monitorCheck(monitor);

        // ensure that each project package has a delete manifest
        for (ProjectPackage projectPackage : projectPackageList) {
            if (projectPackage.getDeleteManifest() == null) {
                try {
                    ContainerDelegate.getInstance().getServiceLocator().getProjectService().getPackageManifestFactory().attachDeleteManifest(projectPackage, true);
                } catch (Exception e) {
                    logger.error("Unable to perform delete - destructive manifest is missing or cannot be "
                            + "generated for package '" + projectPackage.getName() + "'", e);
                    entries
                            .add(createFatalRefactoringStatusEntry("Unable to perform delete - destructive manifest is missing or cannot be "
                                    + "generated for package '" + projectPackage.getName() + "': " + e.getMessage()));
                    return entries;
                }

                // and if it's STILL null, abort
                if (projectPackage.getDeleteManifest() == null) {
                    logger.error("Unable to perform delete - destructive manifest is missing or cannot be "
                            + "generated for package '" + projectPackage.getName() + "'");
                    entries
                            .add(createFatalRefactoringStatusEntry("Unable to perform delete - destructive manifest is missing or cannot be "
                                    + "generated for package '" + projectPackage.getName() + "'"));
                    return entries;
                }
            }
        }

        // test delete, if we have any issues deleting, prompt the user to see if she wants to continue with only deleting locally
        testDeploy(monitor);

        boolean continueDelete = projectPackageList.hasComponents(false);
        if (!continueDelete) {
            logger.warn("No delete components found.- discontinuing remote delete");
            return entries;
        }

        // perform sdelete!!
        monitorCheck(monitor);
        DeployResultExt deployResultExt = null;
        try {
            deployResultExt = ContainerDelegate.getInstance().getServiceLocator().getPackageDeployService().deployDelete(projectPackageList, false, monitor);
            // as part of delete deploy, ide request with auto update package and retrieve for getting updated package.xml
            ContainerDelegate.getInstance().getServiceLocator().getProjectService().handleRetrieveResult(projectPackageList, deployResultExt.getRetrieveResultHandler(), true, monitor);

        } catch (ServiceTimeoutException ex) {
            deployResultExt =
                    ContainerDelegate.getInstance().getServiceLocator().getPackageDeployService().handleDeployServiceTimeoutException(ex, "remote delete", monitor);
        } catch (CoreException e) {
            logger.error("Unable to handle retrieve result from delete deploy ", e);
            throw new InvocationTargetException(e);
        } catch (IOException e) {
            logger.error("Unable to handle retrieve result from delete deploy ", e);
            throw new InvocationTargetException(e);
        }

        if (!deployResultExt.isSuccess()) {
            deployResultExt.getMessageHandler().sort(DeployMessageExt.SORT_RESULT);
            DeployMessage[] messages = deployResultExt.getMessageHandler().getMessages();
            StringBuffer strBuff = new StringBuffer();
            strBuff.append("Remote delete failed with the following message. Will only delete locally.");
            for (DeployMessage deployMessage : messages) {
                strBuff.append("\n  ").append(deployMessage.getFullName()).append(": ").append(
                    deployMessage.getProblem());
            }
            logger.error(strBuff.toString());
            entries.add(createWarningRefactoringStatusEntry(strBuff.toString()));
        } else {
            entries.add(createInfoRefactoringStatusEntry("Resources successfully deleted on server"));

            try {
                postDeleteProcess(projectPackageList, monitor);
            } catch (InvocationTargetException e) {
                logger.warn("Unable to update cache with with deleted component(s)", e);
            }

            clearCaches(projectPackageList);
        }

        // set to skip builder since new component is validated/compiled during deploy()
        try {
            ContainerDelegate.getInstance().getServiceLocator().getProjectService().flagSkipBuilder(projectPackageList.getProject());
        } catch (CoreException e) {
            String logMessage = Utils.generateCoreExceptionLog(e);
            logger.warn("Unable to set builder skip flag: " + logMessage, e);
        }

        return entries;
    }

    protected void postDeleteProcess(final ProjectPackageList projectPackageList, final IProgressMonitor monitor)
            throws InvocationTargetException, InterruptedException {
        // manually update cache inserting new component in appropriate stanza
        Job updateCacheJob = new Job("Update list metadata cache") {
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                if (Utils.isEmpty(projectPackageList)) {
                    return Status.OK_STATUS;
                }

                // set cache, may not exists
                URL cacheUrl = Utils.getCacheUrl(projectPackageList.getProject());
                Document packageManifestCache = Utils.loadDocument(cacheUrl);
                if (packageManifestCache != null) {
                    ComponentList deleteComponents = projectPackageList.getAllComponents();
                    for (Component deleteComponent : deleteComponents) {
                        Node componentTypeNode =
                                PackageManifestDocumentUtils.getComponentNode(packageManifestCache, deleteComponent
                                        .getComponentType());
                        if (componentTypeNode != null && componentTypeNode.hasChildNodes()) {
                            PackageManifestDocumentUtils.removeMemberNode(componentTypeNode, deleteComponent.getName());
                        }

                        if (componentTypeNode != null && !componentTypeNode.hasChildNodes()) {
                            PackageManifestDocumentUtils.removeComponentTypeNode(packageManifestCache, deleteComponent
                                    .getComponentType());
                        }
                    }

                    try {
                        Utils.saveDocument(packageManifestCache, cacheUrl.getPath());



                    } catch (Exception e) {
                        logger.warn("Unable to update cache with deleted component(s)", e);
                        return new Status(Status.INFO, ForceIdeCorePlugin.PLUGIN_ID, Status.INFO,
                                "Unable to update cache with with deleted component(s)", e);
                    }

                    if (logger.isDebugEnabled()) {
                        logger.debug("Deleted component(s) from cache");
                        logger.debug("Updated cache...");
                        PackageManifestDocumentUtils.log(packageManifestCache);
                    }
                } else {
                    logger.warn("Unable to update cache with with deleted component(s)  - cache is not found");
                    return new Status(Status.INFO, ForceIdeCorePlugin.PLUGIN_ID, Status.INFO,
                            "Unable to update cache with with deleted component(s)  - cache is not found", null);
                }

                return Status.OK_STATUS;
            }

        };

        // perform now
        updateCacheJob.setSystem(true);
        updateCacheJob.schedule();
    }

    private ProjectController projectController = null;
    protected ProjectController getProjectController() {
        // lazy init
        if (projectController == null) {
            projectController = new ProjectController(getProject());
        }
        return projectController;
    }
}
TOP

Related Classes of com.salesforce.ide.ui.refactoring.DeleteRefactorController

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.