Package com.salesforce.ide.ui.actions

Source Code of com.salesforce.ide.ui.actions.RefreshResourceActionController

/*******************************************************************************
* 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.actions;

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

import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

import com.salesforce.ide.api.metadata.types.Package;
import com.salesforce.ide.core.factories.FactoryException;
import com.salesforce.ide.core.internal.utils.Constants;
import com.salesforce.ide.core.internal.utils.MessageDialogRunnable;
import com.salesforce.ide.core.internal.utils.Messages;
import com.salesforce.ide.core.internal.utils.Utils;
import com.salesforce.ide.core.model.Component;
import com.salesforce.ide.core.model.ProjectPackageList;
import com.salesforce.ide.core.project.ForceProjectException;
import com.salesforce.ide.core.remote.Connection;
import com.salesforce.ide.core.remote.ForceConnectionException;
import com.salesforce.ide.core.remote.ForceRemoteException;
import com.salesforce.ide.core.remote.metadata.RetrieveResultExt;
import com.salesforce.ide.core.services.ServiceException;
import com.salesforce.ide.core.services.ServiceTimeoutException;

public class RefreshResourceActionController extends ActionController {
    private static final Logger logger = Logger.getLogger(RefreshResourceActionController.class);

    private static final String OPERATION = "refresh resource(s)";
    private boolean refreshResult = true;

    //   C O N S T R U C T O R S
    public RefreshResourceActionController() throws ForceProjectException {
        super();
    }

    //   M E T H O D S
    @Override
    public WizardDialog getWizardDialog() {
        return null;
    }

    @Override
    public boolean preRun(IAction action) {
        if (Utils.isEmpty(selectedResources)) {
            logger.info("Operation cancelled.  Resources not provided.");
            return false;
        }

        // skip if not a force managed resource
        if (!getProjectService().isManagedResources(selectedResources)) {
            Utils.openError("Not Managed Resource", "Unable to refresh resource '" + getSelectedResource().getName()
                    + "'.  Resource is not a " + Constants.PRODUCT_NAME + " resource.");
            return false;
        }

        for (IResource selectedResource : selectedResources) {
            // if dirty, ask user what he/she wants to do
            if (checkForDirtyResource(selectedResource)) {
                StringBuffer strBuffer = new StringBuffer("One or more of the resources or their child resources ");
                strBuffer.append("you are trying to refresh is open, unsaved, and/or dirty.\n\n").append(
                    "Continue to refresh this resource replacing it with the latest from Salesforce?");
                boolean result = Utils.openQuestion("Confirm Refresh Open File", strBuffer.toString());
                if (!result) {
                    if (logger.isInfoEnabled()) {
                        logger.info("User cancelled.  File is open for edit or dirty.");
                    }
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Refresh given resources fetching latest instance(s) from org and saving to project
     *
     * @param monitor
     * @return
     * @throws InterruptedException
     * @throws ForceConnectionException
     * @throws FactoryException
     * @throws CoreException
     * @throws IOException
     * @throws ForceRemoteException
     * @throws InvocationTargetException
     * @throws ServiceException
     * @throws MetadataServiceException
     */
    public boolean refreshResources(IProgressMonitor monitor) throws InterruptedException, ForceConnectionException,
            FactoryException, CoreException, IOException, ForceRemoteException, InvocationTargetException,
            ServiceException, Exception {

        if (Utils.isEmpty(selectedResources)) {
            logger.warn("Unable to refresh resources - resources is null or empty");
            return false;
        }

        if (logger.isDebugEnabled()) {
            StringBuffer strBuffer =
                    new StringBuffer("Refreshing the following resource roots [" + selectedResources.size() + "]:");
            int resourceCnt = 0;
            for (IResource resource : selectedResources) {
                strBuffer.append("\n (").append(++resourceCnt).append(") ").append(
                    resource.getProjectRelativePath().toPortableString());
            }
            logger.debug(strBuffer.toString());
        }

        monitorCheck(monitor);
        monitorSubTask(monitor, "Retrieving remote components...");

        monitorCheck(monitor);
        // refresh at project root - fetch and save everything and be done w/ it
        if (Utils.isNotEmpty(getProjectService().getResourcesByType(selectedResources, IResource.PROJECT))) {
            IFolder folder = getProjectService().getSourceFolder(project);
            if (!refreshSourceFolder(folder, monitor)) {
                failRefreshResult();
            }

            // must fetch separately due to returned package structure - referenced packages
            // maintains the package-prefixed hierarchy
            if (!retrieveInstalledPackages(project, monitor)) {
                failRefreshResult();
            }

            // project level refresh takes care of everything
            return refreshResult;
        }

        // handle if source root was selected
        handleSourceRefresh(monitor);

        // if only source root was selected was selected, let's end here
        if (selectedResources.size() == 1
                && Utils.isNotEmpty(getProjectService().getFolder(selectedResources, Constants.SOURCE_FOLDER_NAME))) {
            return refreshResult;
        }

        // handle source component folders
        handleSourceComponentFolderRefresh(monitor);

        // handle source component files
        handleSourceComponentFileRefresh(monitor);

        // handle if referenced packages dir was selected
        handleReferencePackagesRefresh(monitor);

        // handle if individual/multiple reference package folder was selected
        handleReferencePackageFolderRefresh(monitor);

        if (logger.isDebugEnabled()) {
            logger.debug("Overall refresh process was" + (refreshResult ? " " : " NOT") + " successful");
        }

        return refreshResult;
    }

    protected void handleSourceRefresh(IProgressMonitor monitor) throws InterruptedException, ForceConnectionException,
            ForceRemoteException, FactoryException, CoreException, IOException, InvocationTargetException,
            ServiceException, Exception {
        monitorCheck(monitor);
        if (Utils.isNotEmpty(getProjectService().getFolder(selectedResources, Constants.SOURCE_FOLDER_NAME))) {
            IFolder sourceFolder = getProjectService().getSourceFolder(project);
            if (!refreshSourceFolder(sourceFolder, monitor)) {
                logger.warn("Unable to refresh source root");
                failRefreshResult();
            }
        }
    }

    // refresh folder
    private boolean refreshSourceFolder(IFolder folder, IProgressMonitor monitor) throws FactoryException,
            ForceConnectionException, CoreException, InterruptedException, IOException, ForceRemoteException,
            InvocationTargetException, ServiceException, Exception {
        if (folder == null || !folder.exists()) {
            return false;
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Refreshing folder '" + folder.getProjectRelativePath().toPortableString() + "' resource");
        }

        String packageName = getProjectService().getPackageName(project);

        // perform retrieve
        RetrieveResultExt retrieveResultHandler = null;
        try {
            retrieveResultHandler =
                    getServiceLocator().getPackageRetrieveService().retrievePackage(project, packageName, monitor);
        } catch (ServiceTimeoutException ex) {
            retrieveResultHandler =
                getServiceLocator().getPackageRetrieveService().handleRetrieveServiceTimeoutException(ex, OPERATION,
                        monitor);
        }

        if (retrieveResultHandler == null) {
            logger.warn("Unable to refresh folder '" + folder.getName() + "' - retrieve result is null");
            return false;
        }

        monitorWork(monitor);

        ProjectPackageList projectPackageList =
                getProjectPackageFactory().getProjectPackageListInstance(new String[] { packageName });
        projectPackageList.setProject(project);

        // handle result including messages and saving resources
        return getProjectService().handleRetrieveResult(projectPackageList, retrieveResultHandler, true, null, monitor);
    }

    protected void handleReferencePackagesRefresh(IProgressMonitor monitor) throws InterruptedException,
            ForceConnectionException, ForceRemoteException, FactoryException, CoreException, IOException,
            InvocationTargetException, ServiceException, Exception {
        monitorCheck(monitor);

        IFolder referencePkgFolder =
                getProjectService().getFolder(selectedResources, Constants.REFERENCED_PACKAGE_FOLDER_NAME);
        if (referencePkgFolder != null) {
            if (!retrieveInstalledPackages(project, monitor)) {
                logger.warn("Unable to refresh installed packages");
                failRefreshResult();
            }
        }
    }

    protected void handleReferencePackageFolderRefresh(IProgressMonitor monitor) throws InterruptedException,
            ForceConnectionException, ForceRemoteException, FactoryException, CoreException, ServiceException,
            IOException, InvocationTargetException, Exception {
        monitorCheck(monitor);
        List<IResource> folders = getProjectService().getResourcesByType(selectedResources, IResource.FOLDER);
        List<String> pkgNames = new ArrayList<String>();
        if (Utils.isNotEmpty(folders)) {
            for (IResource folder : folders) {
                if (getProjectService().isReferencedPackageFolder(folder)) {
                    // set reference pkg folder contents to readonly=false so save of retrieve content
                    // doesn't prompt with 'unable to write'
                    Utils.adjustResourceReadOnly(folder, false, true);

                    pkgNames.add(folder.getName());
                }
            }

            if (Utils.isNotEmpty(pkgNames)) {
                RetrieveResultExt retrieveResultHandler = null;
                try {
                    retrieveResultHandler =
                        getServiceLocator().getPackageRetrieveService().retrieveInstalledPackages(project,
                                pkgNames.toArray(new String[pkgNames.size()]), monitor);
                    retrieveResultHandler.getProjectPackageList().setProject(project);
                } catch (ServiceTimeoutException ex) {
                    retrieveResultHandler =
                        getServiceLocator().getPackageRetrieveService().handleRetrieveServiceTimeoutException(ex,
                                OPERATION, monitor);
                    if (retrieveResultHandler != null) {
                        ProjectPackageList projectPackageList =
                                getProjectPackageFactory().getProjectPackageListInstance(
                                    pkgNames.toArray(new String[pkgNames.size()]));
                        if (projectPackageList != null) {
                            projectPackageList.setProject(project);
                        }
                        retrieveResultHandler.setProjectPackageList(projectPackageList);
                    }
                }

                if (retrieveResultHandler == null
                        || !getProjectService().handleRetrieveResult(retrieveResultHandler, true, monitor)) {
                    logger.warn("Unable to refresh component folders");
                    failRefreshResult();
                }
            }
        }
    }

    protected boolean retrieveInstalledPackages(IProject project, IProgressMonitor monitor)
            throws InterruptedException, ForceConnectionException, ForceRemoteException, FactoryException,
            CoreException, InvocationTargetException, IOException, ServiceException, Exception {
        if (project == null) {
            throw new IllegalArgumentException("Project cannot be null");
        }

        if (logger.isInfoEnabled()) {
            logger.info("Fetching and saving all installed, managed components for '" + project.getName() + "'");
        }

        // set reference pkg folder contents to readonly=false so save of retrieve content
        // doesn't prompt with 'unable to write'
        IFolder referencePkgFolder = getProjectService().getReferencedPackagesFolder(project);
        Utils.adjustResourceReadOnly(referencePkgFolder, false, true);

        monitorCheck(monitor);
        RetrieveResultExt retrieveResultHandler = null;
        try {
            retrieveResultHandler =
                getServiceLocator().getPackageRetrieveService().retrieveManagedInstalledPackages(project, monitor);
        } catch (ServiceTimeoutException ex) {
            retrieveResultHandler =
                getServiceLocator().getPackageRetrieveService().handleRetrieveServiceTimeoutException(ex, OPERATION,
                        monitor);
            if (retrieveResultHandler != null) {
                Connection connection = getConnectionFactory().getConnection(project);
                ProjectPackageList projectPackageList =
                        getProjectPackageFactory().getManagedInstalledProjectPackages(connection);
                if (projectPackageList != null) {
                    projectPackageList.setProject(project);
                }
                retrieveResultHandler.setProjectPackageList(projectPackageList);
            }
        }

        if (retrieveResultHandler == null) {
            logger.warn("Unable to refresh installed packages - retrieve result is null");
            return false;
        }

        if (retrieveResultHandler.getZipFileCount() == 0) {
            return true;
        }

        if (Utils.isNotEmpty(retrieveResultHandler.getProjectPackageList())) {
            retrieveResultHandler.getProjectPackageList().setProject(project);
        }

        monitorCheck(monitor);
        return getProjectService().handleRetrieveResult(retrieveResultHandler.getProjectPackageList(),
            retrieveResultHandler, true, null, monitor);
    }

    protected void handleSourceComponentFolderRefresh(IProgressMonitor monitor) throws InterruptedException,
            ForceConnectionException, ForceRemoteException, FactoryException, CoreException, IOException,
            InvocationTargetException, ServiceException, Exception {
        monitorCheck(monitor);
        List<IResource> folders = getProjectService().getResourcesByType(selectedResources, IResource.FOLDER);
        List<String> componentTypes = new ArrayList<String>();
        if (Utils.isNotEmpty(folders)) {
            for (IResource folder : folders) {
                if (getProjectService().isComponentFolder(folder)) {
                    Component component = getComponentFactory().getComponentByFolderName(folder.getName());
                    componentTypes.add(component.getComponentType());
                } else if (getProjectService().isSubComponentFolder(folder)) {
                    Component component = getComponentFactory().getComponentFromSubFolder((IFolder) folder, false);
                    componentTypes.add(component.getSecondaryComponentType());
                }
                // reference package folders is handled in methods specific for reference packages.
            }

            if (Utils.isNotEmpty(componentTypes)) {
                // Bug #206315: In package project, prompt user that refresh on component folder is not support, and
                // either cancel or refresh from src.
                Package packageManifest = getPackageManifestFactory().getPackageManifest(getProject());
                if (Utils.isEmpty(packageManifest)) {
                    throw new FactoryException(Messages.getString(
                        "Retrieve.PackageProject.RefreshComponentFolder.MissPackageManifest.Exception.message",
                        new String[] { getProject().getName() }));
                }
                if (Utils.isNotEmpty(packageManifest.getFullName())) {
                    String dialogMsg =
                            Messages.getString("Retrieve.PackageProject.RefreshComponentFolder.Dialog.message");
                    MessageDialogRunnable messageDialogRunnable =
                            new MessageDialogRunnable("Refresh from server", null, dialogMsg,
                                    MessageDialog.INFORMATION, new String[] { IDialogConstants.OK_LABEL,
                                            IDialogConstants.CANCEL_LABEL }, 0);
                    Display.getDefault().syncExec(messageDialogRunnable);

                    if (messageDialogRunnable.getAction() == Window.CANCEL) {
                        String cancelMsg =
                                Messages.getString("Retrieve.PackageProject.RefreshComponentFolder.Cancel.message");
                        logger.info(cancelMsg);
                        throw new InterruptedException(cancelMsg);
                    }
                }

                // refresh component dirs
                ProjectPackageList projectPackageList =
                        getProjectPackageFactory().getProjectPackageListInstance(project);

                // only save these types
                String[] saveComponentTypes = componentTypes.toArray(new String[componentTypes.size()]);

                // perform retrieve
                RetrieveResultExt retrieveResultHandler = null;
                try {
                    retrieveResultHandler =
                        getServiceLocator().getPackageRetrieveService().retrieveSelective(projectPackageList,
                                saveComponentTypes, monitor);
                } catch (ServiceTimeoutException ex) {
                    retrieveResultHandler =
                        getServiceLocator().getPackageRetrieveService().handleRetrieveServiceTimeoutException(ex,
                                OPERATION, monitor);
                }

                if (retrieveResultHandler == null
                        || !getProjectService().handleRetrieveResult(projectPackageList, retrieveResultHandler, true,
                            saveComponentTypes, monitor)) {
                    logger.warn("Unable to refresh component folders");
                    failRefreshResult();
                }
            }
        }
    }

    protected void handleSourceComponentFileRefresh(IProgressMonitor monitor) throws InterruptedException,
            ForceConnectionException, ForceRemoteException, FactoryException, CoreException, IOException,
            InvocationTargetException, ServiceException, Exception {
        monitorCheck(monitor);
        List<IResource> files = getProjectService().getResourcesByType(selectedResources, IResource.FILE);
        if (Utils.isNotEmpty(files)) {
            List<IResource> sourceResources = new ArrayList<IResource>(files.size());
            for (IResource file : files) {
                if (getProjectService().isSourceResource(file)) {
                    sourceResources.add(file);
                }
            }

            ProjectPackageList projectPackageList = getProjectService().getProjectContents(sourceResources, monitor);
            projectPackageList.setProject(project);
            monitorCheck(monitor);
            RetrieveResultExt retrieveResultHandler = null;
            try {
                retrieveResultHandler =
                    getServiceLocator().getPackageRetrieveService().retrieveSelective(projectPackageList, true, monitor);
            } catch (ServiceTimeoutException ex) {
                retrieveResultHandler =
                    getServiceLocator().getPackageRetrieveService().handleRetrieveServiceTimeoutException(ex, OPERATION,
                            monitor);
            }

            if (retrieveResultHandler == null
                    || !getProjectService().handleRetrieveResult(retrieveResultHandler, true, monitor)) {
                logger.warn("Unable to refresh component files");
                failRefreshResult();
            }
        }
    }

    @Override
    public void postRun(IAction action) {}

    private boolean checkForDirtyResource(IResource resource) {
        try {
            if (checkForMarkers(resource)) {
                return true;
            }

            if (resource.getType() == IResource.FILE && checkForOpenFileWork((IFile) resource)) {
                return true;
            } else if (resource.getType() == IResource.FOLDER) {
                return checkForOpenFile((IFolder) resource);
            } else if (resource.getType() == IResource.PROJECT) {
                IFolder srcFolder = getProjectService().getSourceFolder(project);
                return checkForOpenFile(srcFolder);
            }
        } catch (CoreException e) {
            String logMessage = Utils.generateCoreExceptionLog(e);
            logger.warn("Unable to test for markers on " + resource.getProjectRelativePath().toPortableString() + ": "
                    + logMessage, e);
        }

        return false;
    }

    private boolean checkForMarkers(IResource resource) throws CoreException {
        if (resource == null || !resource.exists()) {
            return false;
        }

        IMarker[] markers = resource.findMarkers("com.salesforce.ide.core.problem", true, IResource.DEPTH_INFINITE);

        // no markers, let's go
        if (Utils.isEmpty(markers)) {
            return false;
        }

        // ignore package.xml markers - typically general warnings are applied to package.xml and the probably
        // will not overwrite it anyway
        if (markers.length == 1 && getProjectService().isPackageManifestFile(markers[0].getResource())) {
            return false;
        }

        // markers were found, let's warn
        return true;
    }

    private boolean checkForOpenFile(IFolder folder) throws CoreException {
        if (folder == null || Utils.isEmpty(folder.members())) {
            return false;
        }

        IResource[] members = folder.members();
        for (IResource resource : members) {
            if (resource.getType() == IResource.FILE && checkForOpenFileWork((IFile) resource)) {
                return true;
            } else if (resource.getType() == IResource.FOLDER) {
                return checkForOpenFile((IFolder) resource);
            }
        }

        return false;
    }

    private boolean checkForOpenFileWork(IFile file) {
        IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
        if (Utils.isNotEmpty(windows)) {
            // loop thru open windows to check if file is open if open, check w/ user
            for (IWorkbenchWindow window : windows) {
                IWorkbenchPage page = window.getActivePage();
                IEditorPart editor = page.getActiveEditor();

                if (editor != null && editor instanceof IFileEditorInput) {
                    IFileEditorInput fei = (IFileEditorInput) editor.getEditorInput();
                    IFile editFile = fei.getFile();
                    if (file.equals(editFile)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private void failRefreshResult() {
        if (refreshResult) {
            refreshResult = false;
        }
    }
}
TOP

Related Classes of com.salesforce.ide.ui.actions.RefreshResourceActionController

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.