Package com.salesforce.ide.core.services

Source Code of com.salesforce.ide.core.services.RetrieveResultAdapter

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

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.xml.bind.JAXBException;

import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;

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.DialogUtils;
import com.salesforce.ide.core.internal.utils.ForceExceptionUtils;
import com.salesforce.ide.core.internal.utils.Messages;
import com.salesforce.ide.core.internal.utils.OperationStats;
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.remote.Connection;
import com.salesforce.ide.core.remote.ForceConnectionException;
import com.salesforce.ide.core.remote.ForceRemoteException;
import com.salesforce.ide.core.remote.InsufficientPermissionsException;
import com.salesforce.ide.core.remote.MetadataStubExt;
import com.salesforce.ide.core.remote.metadata.FileMetadataExt;
import com.salesforce.ide.core.remote.metadata.RetrieveMessageExt;
import com.salesforce.ide.core.remote.metadata.RetrieveResultExt;
import com.sforce.soap.metadata.AsyncResult;
import com.sforce.soap.metadata.FileProperties;
import com.sforce.soap.metadata.ListMetadataQuery;
import com.sforce.soap.metadata.RetrieveRequest;
import com.sforce.soap.metadata.RetrieveResult;
import com.sforce.soap.metadata.RetrieveStatus;

/**
* Class encapsulates all retrieve functionality.
*
* @author cwall
*/
public class PackageRetrieveService extends BasePackageService {
    static final Logger logger = Logger.getLogger(PackageRetrieveService.class);

    protected static final String OPERATION = "Retrieve";
    private static OperationStats operationStats = null;

    static {
        if (logger.isDebugEnabled()) {
            operationStats = new OperationStats(OPERATION);
        }
    }

    // C O N S T R U C T O R
    public PackageRetrieveService() {}

    // M E T H O D S
    public static OperationStats getOperationStats() {
        return operationStats;
    }

    public RetrieveRequest getRetrieveRequest() {
        String lastSupportedEndpointVersion = null;
        if (Utils.isNotEmpty(Utils.getDefaultSystemApiVersion())) {
            lastSupportedEndpointVersion = Utils.getDefaultSystemApiVersion();
        } else {
            lastSupportedEndpointVersion = getProjectService().getLastSupportedEndpointVersion();
        }
        if (logger.isInfoEnabled()) {
            logger.info("RetrieveRequest's api version is set to '" + lastSupportedEndpointVersion + "'");
        }
        return getRetrieveRequest(lastSupportedEndpointVersion);
    }

    public RetrieveRequest getRetrieveRequest(String apiVersion) {
        RetrieveRequest retrieveRequest = new RetrieveRequest();
        retrieveRequest.setApiVersion(Double.valueOf(apiVersion));
        retrieveRequest.setSinglePackage(true);
        return retrieveRequest;
    }

    /**
     * Retrieve all packages and their contents and unpackaged using manifest in project.
     *
     * @param project
     * @param includeDefaultManifest
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws RemoteException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveAll(IProject project, boolean includeDefaultManifest, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, FactoryException,
            ForceRemoteException, InterruptedException {
        if (project == null) {
            throw new IllegalArgumentException("Project cannot be null");
        }
        Connection connection = getConnectionFactory().getConnection(project);
        Package defaultMainfest = null;
        if (includeDefaultManifest) {
            defaultMainfest = getPackageManifestFactory().getDefaultPackageManifest(project);
        }
        RetrieveResultExt retrieveResultHandler = retrieveAll(connection, defaultMainfest, monitor);
        retrieveResultHandler.getProjectPackageList().setProject(project);
        return retrieveResultHandler;
    }

    /**
     * @param project
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws RemoteException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveAll(IProject project, IProgressMonitor monitor) throws ForceConnectionException,
            ServiceException, ForceRemoteException, ForceRemoteException, InterruptedException {
        if (project == null) {
            throw new IllegalArgumentException("Project cannot be null");
        }
        Connection connection = getConnectionFactory().getConnection(project);
        return retrieveAll(connection, monitor);
    }

    /**
     * Retrieve all packages and their contents for a given connection.
     *
     * @param connection
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws RemoteException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveAll(Connection connection, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, ForceRemoteException,
            InterruptedException {
        return retrieveAll(connection, null, monitor);
    }

    /**
     * Retrieve all packages and their contents for a given connection.
     *
     * @param connection
     * @param defaultMainfest
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws InterruptedException
     * @throws RemoteException
     */
    public RetrieveResultExt retrieveAll(Connection connection, Package defaultMainfest, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, InterruptedException,
            ForceRemoteException {
        if (connection == null) {
            throw new IllegalArgumentException("Connection cannot be null");
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Retrieve all components for:\n" + connection.getLogDisplay());
        }
        ProjectPackageList projectPackageList =
                getProjectPackageFactory().getDevelopmentAndUnmanagedInstalledProjectPackages(connection);

        if (logger.isDebugEnabled()) {
            logger.debug("Packages for " + connection.getLogDisplay() + " " + projectPackageList.toString());
        }

        RetrieveRequest retrieveRequest = getRetrieveRequest();
        retrieveRequest.setPackageNames(projectPackageList.getNamedPackageNames());
        if (defaultMainfest == null) {
            getPackageManifestFactory().setDefaultPackageManifest(connection, retrieveRequest);
        } else {
            retrieveRequest.setUnpackaged(getPackageManifestFactory().convert(defaultMainfest));
        }

        RetrieveResultExt retrieveResultHandler = retrieveWork(connection, retrieveRequest, monitor);
        retrieveResultHandler.setProjectPackageList(projectPackageList);

        return retrieveResultHandler;
    }

    public RetrieveResultExt retrieveManagedInstalledPackages(IProject project, IProgressMonitor monitor)
            throws ForceConnectionException, FactoryException, ServiceException, ForceRemoteException,
            InterruptedException, ForceRemoteException, CoreException {
        if (project == null) {
            throw new IllegalArgumentException("Project cannot be null");
        }
        Connection connection = getConnectionFactory().getConnection(project);
        return retrieveManagedInstalledPackages(connection, monitor);
    }

    public RetrieveResultExt retrieveManagedInstalledPackages(Connection connection, IProgressMonitor monitor)
            throws ForceConnectionException, FactoryException, ServiceException, ForceRemoteException,
            InterruptedException, ForceRemoteException, CoreException {
        if (connection == null) {
            throw new IllegalArgumentException("Connection cannot be null");
        }

        ProjectPackageList projectPackageList =
                getProjectPackageFactory().getManagedInstalledProjectPackages(connection);

        if (Utils.isEmpty(projectPackageList)) {
            if (logger.isInfoEnabled()) {
                logger.info("No installed, managed packages to retrieve");
            }
            return new RetrieveResultExt();
        }

        RetrieveRequest retrieveRequest = getRetrieveRequest();
        // installed, managed packages are saved to the project w/ package level (<package-name>/<comonent-type>/etc)
        retrieveRequest.setSinglePackage(false);

        if (Utils.isNotEmpty(projectPackageList.getNamedPackageNames())) {
            retrieveRequest.setPackageNames(projectPackageList.getNamedPackageNames());
        }

        RetrieveResultExt resultExt = retrieveWork(connection, retrieveRequest, monitor);
        resultExt.setProjectPackageList(projectPackageList);

        return resultExt;
    }

    /**
     * Support retrieve "selected" installed packages
     *
     * @param project
     * @param packageNames
     *            - selected installed package names
     * @param monitor
     *
     */
    public RetrieveResultExt retrieveInstalledPackages(IProject project, String[] packageNames, IProgressMonitor monitor)
            throws ForceConnectionException, FactoryException, ServiceException, ForceRemoteException,
            InterruptedException, ForceRemoteException, CoreException {
        if (project == null) {
            throw new IllegalArgumentException("Project cannot be null");
        }

        if (Utils.isEmpty(packageNames)) {
            if (logger.isInfoEnabled()) {
                logger.info("No installed, managed packages to retrieve");
            }
            return null;
        }

        Connection connection = getConnectionFactory().getConnection(project);

        RetrieveRequest retrieveRequest = getRetrieveRequest();
        // installed, managed packages are saved to the project w/ package level (<package-name>/<comonent-type>/etc)
        retrieveRequest.setSinglePackage(false);
        retrieveRequest.setPackageNames(packageNames);

        RetrieveResultExt resultExt = retrieveWork(connection, retrieveRequest, monitor);
        resultExt.setProjectPackageList(getProjectPackageFactory().getManagedInstalledProjectPackages(connection,
            packageNames));
        return resultExt;
    }

    /**
     * Retrieve non-installed packages and their contents.
     *
     * @param connection
     * @param project
     * @param packageName
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws FactoryException
     * @throws RetrieveException
     * @throws RemoteException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrievePackage(IProject project, String packageName, IProgressMonitor monitor)
            throws ForceConnectionException, FactoryException, ServiceException, ForceRemoteException,
            ForceRemoteException, InterruptedException {
        if (project == null) {
            throw new IllegalArgumentException("Project cannot be null");
        }

        Connection connection = getConnectionFactory().getConnection(project);
        return retrievePackage(connection, project, packageName, monitor);
    }

    public RetrieveResultExt retrievePackage(Connection connection, IProject project, String packageName,
            IProgressMonitor monitor) throws ForceConnectionException, FactoryException, ServiceException,
            ForceRemoteException, ForceRemoteException, InterruptedException {
        if ((project == null && connection == null) || Utils.isEmpty(packageName)) {
            throw new IllegalArgumentException("Package name and/or project and connection cannot be null");
        }

        if (connection == null) {
            connection = getConnectionFactory().getConnection(project);
        }

        String[] packageNames = null;
        Package defaultPackageManifest = null;
        if (Constants.DEFAULT_PACKAGED_NAME.equals(packageName)) {
            if (project != null) {
                defaultPackageManifest = getPackageManifestFactory().getDefaultPackageManifest(project);
            } else if (connection != null) {
                defaultPackageManifest = getPackageManifestFactory().getDefaultPackageManifest(connection);
            } else {
                throw new IllegalArgumentException(
                        "Unable to generate package manifest - project and connection are null");
            }
        } else {
            packageNames = new String[] { packageName };
        }

        return retrieveWork(connection, packageNames, defaultPackageManifest, monitor);
    }

    /**
     * Retrieve retrieve all type-specific components in a package.
     *
     * @param connection
     * @param packageName
     * @param componentTypes
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveComponentsForComponentTypes(Connection connection, String packageName,
            String[] componentTypes, IProgressMonitor monitor) throws ForceConnectionException, ServiceException,
            ForceRemoteException, FactoryException, InterruptedException {
        if (connection == null || Utils.isEmpty(packageName) || Utils.isEmpty(componentTypes)) {
            throw new IllegalArgumentException("Connection, package name, and/or object types cannot be null");
        }

        // TODO: currently the metadata api does not support object level selects for a non-default package
        Package packageManifest = null;
        String[] packageNames = null;
        if (Constants.DEFAULT_PACKAGED_NAME.equals(packageName)) {
            packageManifest =
                    getPackageManifestFactory().createPackageManifestForComponentTypes(packageName, componentTypes);
        } else {
            packageNames = new String[] { packageName };
        }

        return retrieve(connection, packageNames, packageManifest, monitor);
    }

    /**
     * Retrieve individual component.
     *
     * @param component
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveComponent(Component component, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, FactoryException,
            InterruptedException {
        if (component == null || component.getFileResource() == null) {
            throw new IllegalArgumentException("Component and/or file resource cannot be null");
        }
        Connection connection = getConnectionFactory().getConnection(component.getFileResource().getProject());
        return retrieveComponent(connection, component, monitor);
    }

    /**
     * Retrieve individual component.
     *
     * @param project
     * @param component
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveComponent(IProject project, Component component, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, FactoryException,
            InterruptedException {
        if (project == null) {
            throw new IllegalArgumentException("Project cannot be null");
        }
        Connection connection = getConnectionFactory().getConnection(project);
        return retrieveComponent(connection, component, monitor);
    }

    /**
     * Retrieve individual component.
     *
     * @param connection
     * @param component
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveComponent(Connection connection, Component component, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, FactoryException,
            InterruptedException {
        return retrieveComponent(connection, component, true, monitor);
    }

    /**
     * Retrieve individual component. Option to include metadata component to retrieve request.
     *
     * @param connection
     * @param component
     * @param includeMetadata
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveComponent(Connection connection, Component component, boolean includeMetadata,
            IProgressMonitor monitor) throws ForceConnectionException, ServiceException, ForceRemoteException,
            FactoryException, InterruptedException {
        if (connection == null || component == null) {
            throw new IllegalArgumentException("Component and/or connection cannot be null");
        }

        ProjectPackageList projectPackageList = getProjectPackageListInstance();
        // REVIEWME: should this be an arg requirement?
        if (component.getFileResource() != null) {
            projectPackageList.setProject(component.getFileResource().getProject());
        } else {
            logger.warn("Project not provided, and will not be attached to returned project package");
        }

        projectPackageList.addComponent(component, includeMetadata);

        return retrieveSelective(connection, projectPackageList, true, monitor);
    }

    /**
     * Retrieve default package. Method assembles package manifest based on enabled object types.
     *
     * @param connection
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws InterruptedException
     * @throws RemoteException
     */
    public RetrieveResultExt retrieveDefaultPackage(Connection connection, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, InterruptedException,
            ForceRemoteException {

        if (connection == null) {
            throw new IllegalArgumentException("Connection cannot be null");
        }

        Package defaultPackageManifest = getPackageManifestFactory().getDefaultPackageManifest(connection);
        return retrieveWork(connection, null, defaultPackageManifest, monitor);
    }

    /**
     * @param projectPackageList
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveSelective(ProjectPackageList projectPackageList, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, FactoryException,
            InterruptedException {
        return retrieveSelective(projectPackageList, true, monitor);
    }

    /**
     * Retrieve selective packages and their contents for a given project package list.
     *
     * @param projectPackageList
     * @param selective
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveSelective(ProjectPackageList projectPackageList, boolean selective,
            IProgressMonitor monitor) throws ForceConnectionException, ServiceException, ForceRemoteException,
            FactoryException, InterruptedException {
        if (projectPackageList == null || projectPackageList.getProject() == null) {
            throw new IllegalArgumentException("Project package list and/or containing project cannot be null");
        }
        Connection connection = getConnectionFactory().getConnection(projectPackageList.getProject());
        return retrieveSelective(connection, projectPackageList, selective, monitor);
    }

    /**
     * Retrieve selective packages and their contents for a given project package list.
     *
     * @param connection
     * @param projectPackageList
     * @param selective
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieveSelective(Connection connection, ProjectPackageList projectPackageList,
            boolean selective, IProgressMonitor monitor) throws ServiceException, ForceRemoteException,
            FactoryException, InterruptedException {
        return retrieveSelective(connection, projectPackageList, selective, true, monitor);
    }

    public RetrieveResultExt retrieveSelective(Connection connection, String[] filePaths, String packageName,
            IProject project, IProgressMonitor monitor) throws ForceConnectionException, ServiceException,
            ForceRemoteException, FactoryException, InterruptedException {
        if (connection == null) {
            throw new IllegalArgumentException("Connection cannot be null");
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Retrieving selective packages/components from " + connection.getLogDisplay());
        }

        if (Utils.isEmpty(filePaths)) {
            logger.warn("Nothing to retrieve - filename list is empty");
            return null;
        }

        RetrieveRequest retrieveRequest = getRetrieveRequest();

        // specific files
        retrieveRequest.setSpecificFiles(filePaths);

        // set unpackaged manifest or package naming; if the former and the project's package.xml refers to a
        // package (name=<something>), adjust on the fly to retrieve unpacakged content using package.xml definitions
        Package packageManifest = null;
        if (Utils.isEmpty(packageName) || Constants.DEFAULT_PACKAGED_NAME.equals(packageName)) {
            if (project != null) {
                packageManifest = getPackageManifestFactory().getPackageManifest(project);
            } else {
                packageManifest = getPackageManifestFactory().createDefaultPackageManifest();
            }

            packageManifest.setFullName(packageName);
            retrieveRequest.setUnpackaged(getPackageManifestFactory().convert(packageManifest));
        } else {
            retrieveRequest.setPackageNames(new String[] { packageName });
        }

        monitorWork(monitor);
        RetrieveResultExt retrieveResultExt = retrieveWork(connection, retrieveRequest, monitor);
        return retrieveResultExt;
    }

    public RetrieveResultExt retrieveSelective(Connection connection, ProjectPackageList projectPackageList,
            boolean selective, boolean singlePackage, IProgressMonitor monitor) throws ServiceException,
            ForceRemoteException, FactoryException, InterruptedException {
        if (connection == null || projectPackageList == null) {
            throw new IllegalArgumentException("Project package list and/or connection cannot be null");
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Retrieving selective packages/components from " + connection.getLogDisplay());
        }

        if (projectPackageList.isEmpty()) {
            logger.warn("Nothing to retrieve - ProjectPackageList is empty");
            return null;
        }

        RetrieveRequest retrieveRequest = getRetrieveRequest();

        // specific files
        String[] filePaths = projectPackageList.getComponentFilePathArray(true);
        if (selective && Utils.isNotEmpty(filePaths)) {
            retrieveRequest.setSpecificFiles(filePaths);
        }

        // specific packages
        retrieveRequest.setPackageNames(projectPackageList.getNamedPackageNames());

        // default package
        Package defaultPackageManifest = null;
        if (projectPackageList.hasPackage(Constants.DEFAULT_PACKAGED_NAME)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Include retrieval of default package manifest");
            }
            defaultPackageManifest = getPackageManifestFactory().getDefaultPackageManifest(projectPackageList);
            retrieveRequest.setUnpackaged(getPackageManifestFactory().convert(defaultPackageManifest));
        }

        monitorWork(monitor);
        RetrieveResultExt retrieveResultExt = retrieveWork(connection, retrieveRequest, monitor);
        retrieveResultExt.setProjectPackageList(projectPackageList);
        return retrieveResultExt;
    }

    public RetrieveResultExt retrieveSelective(Connection connection, ProjectPackageList projectPackageList,
            boolean selective, Package packageManifest, IProgressMonitor monitor) throws ForceConnectionException,
            ServiceException, ForceRemoteException, FactoryException, InterruptedException {
        if (connection == null || projectPackageList == null) {
            throw new IllegalArgumentException("Project package list and/or connection cannot be null");
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Retrieving selective packages/components from " + connection.getLogDisplay());
        }

        if (projectPackageList.isEmpty()) {
            logger.warn("Nothing to retrieve - ProjectPackageList is empty");
            return null;
        }

        RetrieveRequest retrieveRequest = getRetrieveRequest();

        // specific files
        String[] filePaths = projectPackageList.getComponentFilePathArray(true);
        if (selective && Utils.isNotEmpty(filePaths)) {
            retrieveRequest.setSpecificFiles(filePaths);
        }

        // specific packages
        retrieveRequest.setPackageNames(projectPackageList.getNamedPackageNames());

        // default package
        if (packageManifest == null) {
            packageManifest = getPackageManifestFactory().getDefaultPackageManifest(projectPackageList);
        }

        retrieveRequest.setUnpackaged(getPackageManifestFactory().convert(packageManifest));

        monitorWork(monitor);
        RetrieveResultExt retrieveResultExt = retrieveWork(connection, retrieveRequest, monitor);
        retrieveResultExt.setProjectPackageList(projectPackageList);
        return retrieveResultExt;
    }

    /**
     * Retrieve selective packages and their contents for a given project package list.
     *
     * @param projectPackageList
     * @param componentTypes
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     * @throws RemoteException
     * @throws ForceRemoteException
     * @throws CoreException
     * @throws MetadataServiceException
     *             , InsufficientOrgPermissions
     */
    public RetrieveResultExt retrieveSelective(ProjectPackageList projectPackageList, String[] componentTypes,
            IProgressMonitor monitor) throws ForceConnectionException, ServiceException, ForceRemoteException,
            FactoryException, InterruptedException, ForceRemoteException, RemoteException, CoreException {
        if (projectPackageList == null || projectPackageList.getProject() == null) {
            throw new IllegalArgumentException("Package list and/or project cannot be null");
        }

        Connection connection = getConnectionFactory().getConnection(projectPackageList.getProject());
        return retrieveSelective(connection, projectPackageList, componentTypes, monitor);
    }

    /**
     *
     * @param connection
     * @param projectPackageList
     * @param componentTypes
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     * @throws CoreException
     * @throws RemoteException
     * @throws ForceRemoteException
     * @throws RemoteException
     * @throws ForceRemoteException
     * @throws CoreException
     * @throws MetadataServiceException
     *             , InsufficientOrgPermissions
     */
    public RetrieveResultExt retrieveSelective(Connection connection, ProjectPackageList projectPackageList,
            String[] componentTypes, IProgressMonitor monitor) throws ForceConnectionException, ServiceException,
            ForceRemoteException, FactoryException, InterruptedException, ForceRemoteException, CoreException {
        if (projectPackageList == null || connection == null) {
            throw new IllegalArgumentException("Package list and/or connection cannot be null");
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Retrieving selective component types for given packages from " + connection.getLogDisplay());
        }

        RetrieveRequest retrieveRequest = getRetrieveRequest();
        retrieveRequest.setPackageNames(projectPackageList.getNamedPackageNames());
        IProject project = projectPackageList.getProject();
        Package packageManifest = null;
        // using setSpecificFile machanism to refresh component folder(s) when component type(s) has associated
        // component type. Otherwise, refresh using sub-stanzas of package.xml
        if (projectPackageList.hasPackage(Constants.DEFAULT_PACKAGED_NAME)) {
            if (hasComponentTypeWthAssociatedComponentTypes(componentTypes)) {
                String[] filePaths = getFilePathsByComponentTypes(project, connection, componentTypes);
                if (logger.isDebugEnabled()) {
                    logRefreshFilePaths(filePaths);
                }

                if (Utils.isNotEmpty(filePaths)) {
                    retrieveRequest.setSpecificFiles(filePaths);
                }

                if (projectPackageList.hasPackage(Constants.DEFAULT_PACKAGED_NAME)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Include retrieval of default package manifest");
                    }
                    packageManifest = getPackageManifestFactory().getDefaultPackageManifest(projectPackageList);

                }
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Include retrieval of subset of stanzas from default package manifest");
                }
                packageManifest =
                        getPackageManifestFactory().getPackageManifestForComponentTypes(project,
                            Constants.DEFAULT_PACKAGED_NAME, componentTypes, true);
            }
            retrieveRequest.setUnpackaged(getPackageManifestFactory().convert(packageManifest));
        }

        RetrieveResultExt retrieveResultExt = retrieveWork(connection, retrieveRequest, monitor);
        retrieveResultExt.setProjectPackageList(projectPackageList);
        return retrieveResultExt;
    }

    private void logRefreshFilePaths(String[] filePaths) {
        for (int i = 0; i < filePaths.length; i++) {
            logger.debug("file path [" + i + "], " + filePaths[i] + " is added to setSpecificFile for retrieve");
        }
    }

    private boolean hasComponentTypeWthAssociatedComponentTypes(String[] componentTypes) throws FactoryException {
        boolean hasAssociatedComponentTypes = false;
        for (String componentType : componentTypes) {
            hasAssociatedComponentTypes =
                    hasAssociatedComponentTypes | getComponentFactory().hasAssociatedComponentTypes(componentType);
        }
        return hasAssociatedComponentTypes;
    }

    private String[] getFilePathsByComponentTypes(IProject project, Connection connection, String[] componentTypes)
            throws FactoryException, ForceConnectionException, ForceRemoteException, CoreException,
            InterruptedException {
        List<String> filePathList = new ArrayList<String>();
        List<ListMetadataQuery> queryList = new ArrayList<ListMetadataQuery>();
        for (String componentType : componentTypes) {
            if (getComponentFactory().isWildCardSupportedComponentType(componentType)
                    && getPackageManifestFactory().isWildCardUsedForComponentType(project, componentType)) {
                // using listMetadata call to simulate wildcard
                Component componentInfo = getComponentFactory().getComponentByComponentType(componentType);
                ListMetadataQuery listMetadataQuery = new ListMetadataQuery();
                listMetadataQuery.setFolder(componentInfo.getDefaultFolder());
                listMetadataQuery.setType(componentInfo.getComponentType());
                queryList.add(listMetadataQuery);

            }
            // separate if statement for this check due to custom object component type could have * and specific member
            // entry for standard obj in package.xml
            if (getPackageManifestFactory().hasExplicitMemberForComponentType(project, componentType)) {
                List<String> filePathListForComponentType =
                        getPackageManifestFactory().getFilePathsForComponentType(project, componentType);
                filePathList.addAll(filePathListForComponentType);
            }

            // take care of case where sub-component type is supported for retrieve independent from parent component type existence.
            // ex. custom field, validation rule can be retrieved independently from custom object.
            if (getComponentFactory().hasSubComponentTypesForComponentType(componentType)) {
                ProjectPackageList projectPackage = getProjectPackageListInstance();
                IFolder componentFolder = getProjectService().getComponentFolderByComponentType(project, componentType);
                projectPackage =
                        getProjectPackageFactory().loadProjectPackageList(componentFolder, projectPackage, false,
                            new NullProgressMonitor());
                List<String> filePaths = projectPackage.getFilePaths(true);
                filePathList.addAll(filePaths);
            }

        }

        // aggregate all listMetadata call into one call - reduce traffic.
        if (queryList.size() > 0) {
            ListMetadataQuery[] queryArray = queryList.toArray(new ListMetadataQuery[queryList.size()]);
            FileMetadataExt fileMetadataExt =
                    getMetadataService().listMetadata(connection, queryArray, true, new NullProgressMonitor());
            if (fileMetadataExt.getFilePropertiesCount() > 0) {
                for (FileProperties fileProperties : fileMetadataExt.getFileProperties()) {
                    filePathList.add(fileProperties.getFileName());
                }
            }

        }
        return filePathList.toArray(new String[filePathList.size()]);
    }

    /**
     * @param projectPackageList
     * @param componentTypes
     * @param subComponentFolder
     *            - retrieve content for given subComponentFolder
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws FactoryException
     * @throws InterruptedException
     * @throws RemoteException
     * @throws ForceRemoteException
     * @throws CoreException
     * @throws MetadataServiceException
     *             , InsufficientOrgPermissions
     */
    public RetrieveResultExt retrieveSelectiveSubComponentFolder(ProjectPackageList projectPackageList,
            String[] componentTypes, String subComponentFolder, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, FactoryException,
            InterruptedException, ForceRemoteException, RemoteException, CoreException {
        if (projectPackageList == null || projectPackageList.getProject() == null) {
            throw new IllegalArgumentException("Package list and/or project cannot be null");
        }

        Connection connection = getConnectionFactory().getConnection(projectPackageList.getProject());
        return retrieveSelective(connection, projectPackageList, componentTypes, monitor);
    }

    /**
     * @param connection
     * @param projectPackageList
     * @param monitor
     * @return
     * @throws RetrieveException
     * @throws ForceConnectionException
     * @throws FactoryException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieve(Connection connection, ProjectPackageList projectPackageList,
            IProgressMonitor monitor) throws ServiceException, ForceRemoteException, ForceConnectionException,
            FactoryException, InterruptedException {
        return retrieveSelective(connection, projectPackageList, false, monitor);
    }

    /**
     * @param project
     * @param packageNames
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws RemoteException
     * @throws InterruptedException
     * @throws FactoryException
     */
    public RetrieveResultExt retrieve(IProject project, List<String> packageNames, IProgressMonitor monitor)
            throws ForceConnectionException, ServiceException, ForceRemoteException, ForceRemoteException,
            InterruptedException, FactoryException {
        if (Utils.isEmpty(packageNames)) {
            return retrieveAll(project, monitor);
        }

        Package packageManifest = null;
        if (packageNames.contains(Constants.DEFAULT_PACKAGED_NAME)) {
            packageManifest = getPackageManifestFactory().getDefaultPackageManifest(project);
            packageNames.remove(Constants.DEFAULT_PACKAGED_NAME);
        }

        Connection connection = getConnectionFactory().getConnection(project);

        return retrieveWork(connection, packageNames.toArray(new String[packageNames.size()]), packageManifest, monitor);
    }

    /**
     * Retrieve packages and their contents for a given connection and project package list.
     *
     * @param connection
     * @param packageNames
     * @param packageManifest
     * @param monitor
     * @return
     * @throws ForceConnectionException
     * @throws RetrieveException
     * @throws InterruptedException
     */
    public RetrieveResultExt retrieve(Connection connection, String[] packageNames, Package packageManifest,
            IProgressMonitor monitor) throws ForceConnectionException, ServiceException, ForceRemoteException,
            InterruptedException {
        return retrieveWork(connection, packageNames, packageManifest, monitor);
    }

    /**
     * Retrieves asynchronous result from server for a given operation id.
     *
     * @param retrieveResultExt
     * @param asyncResult
     * @param metadataStubExt
     * @param monitor
     *
     * @return retrieveResultExt
     *
     * @throws RemoteException
     * @throws InterruptedException
     * @throws ServiceException
     *             , InsufficientOrgPermissions
     * @throws ServiceException
     *             , InsufficientOrgPermissions
     * @throws ServiceException
     *             , InsufficientOrgPermissions
     */
    public RetrieveResultExt getRetrieveResult(RetrieveResultExt retrieveResultExt, AsyncResult asyncResult,
            MetadataStubExt metadataStubExt, IProgressMonitor monitor) throws ForceRemoteException, ServiceException,
            ForceRemoteException, InterruptedException {
        if (metadataStubExt == null) {
            throw new IllegalArgumentException("MetadataStubExt cannot be null");
        }

        monitorCheckSubTask(monitor, Messages.getString("Retrieve.PreparingResults"));

        RetrieveResult retrieveResult;
        try {
            IFileBasedResultAdapter result =
                    waitForResult(new RetrieveResultAdapter(asyncResult, metadataStubExt), metadataStubExt,
                        operationStats, monitor);
            retrieveResult = ((RetrieveResultAdapter) result).getRetrieveResult();

        } catch (ServiceTimeoutException e) {
            e.setMetadataResultExt(retrieveResultExt);
            throw e;
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Received retrieve() result at " + (new Date()).toString());
        }

        if (retrieveResultExt == null) {
            retrieveResultExt = new RetrieveResultExt();
        }

        retrieveResultExt.setRetrieveResult(retrieveResult);

        // log result
        logResult(retrieveResultExt);

        monitorWork(monitor);

        return retrieveResultExt;
    }

    public RetrieveResultExt handleRetrieveServiceTimeoutException(ServiceTimeoutException ex, String operation,
            IProgressMonitor monitor) throws ForceRemoteException, ServiceException, ForceRemoteException,
            InterruptedException {

        // REVIEWME: ui-stuff (dialog to continue) should be handled outside of services
        boolean proceed = DialogUtils.getInstance().presentCycleLimitExceptionDialog(ex, monitor);
        if (proceed) {
            try {
                return getPackageRetrieveService().getRetrieveResult((RetrieveResultExt) ex.getMetadataResultExt(),
                    ex.getAsyncResult(), ex.getMetadataStubExt(), monitor);
            } catch (ServiceTimeoutException e) {
                return handleRetrieveServiceTimeoutException(e, operation, monitor);
            }
        } else {
            throw new InterruptedException("User canceled " + operation + " due to cycle polling limits reached: "
                    + ex.getMessage());
        }
    }

    // W O R K E R   B E E   R E T R I E V E   M E T H O D S
    private RetrieveResultExt retrieveWork(Connection connection, String[] packageNames, Package packageManifest,
            IProgressMonitor monitor) throws ForceConnectionException, ServiceException, ForceRemoteException,
            InterruptedException {
        if (connection == null) {
            throw new IllegalArgumentException("Connection cannot be null");
        }

        RetrieveRequest retrieveRequest = getRetrieveRequest();

        if (Utils.isNotEmpty(packageNames)) {
            retrieveRequest.setPackageNames(packageNames);
        }

        if (packageManifest != null) {
            retrieveRequest.setUnpackaged(getPackageManifestFactory().convert(packageManifest));
        }

        RetrieveResultExt resultExt = retrieveWork(connection, retrieveRequest, monitor);
        ProjectPackageList projectPackageList = getProjectPackageFactory().getProjectPackageListInstance(packageNames);

        resultExt.setProjectPackageList(projectPackageList);
        return resultExt;
    }

    private RetrieveResultExt retrieveWork(Connection connection, RetrieveRequest retrieveRequest,
            IProgressMonitor monitor) throws ServiceException, ForceRemoteException, InterruptedException {
        if (connection == null || retrieveRequest == null) {
            throw new IllegalArgumentException("Connection and/or RetrieveRequest cannot be null");
        }

        if (logger.isDebugEnabled()) {
            logger.debug("");
            logger.debug("***   R E T R I E V E   C O M P O N E N T S   ***");
        }

        monitorWorkCheck(monitor);

        if (Utils.isNotEmpty(retrieveRequest.getPackageNames())
                && (retrieveRequest.getPackageNames().length > 1 || retrieveRequest.getUnpackaged() != null)) {
            retrieveRequest.setSinglePackage(false);
            if (logger.isDebugEnabled()) {
                logger.debug("Adjusted singlePackage=false after finding request containing > 1 packages");
            }
        }

        // log retrieval details
        logRetrieve(connection, retrieveRequest);

        RetrieveResultExt retrieveResultExt = new RetrieveResultExt();
        try {
            // get metadata stub
            MetadataStubExt metadataStubExt = getMetadataFactory().getMetadataStubExt(connection);

            monitorWorkCheck(monitor);

            // send request and wait for result
            if (logger.isDebugEnabled()) {
                logger.debug("Calling retrieve() at " + (new Date()).toString());
            }

            AsyncResult asyncResult = metadataStubExt.retrieve(retrieveRequest);
            monitorWork(monitor);

            // get async result
            retrieveResultExt = getRetrieveResult(retrieveResultExt, asyncResult, metadataStubExt, monitor);

        } catch (ServiceTimeoutException e) {
            throw e;
        } catch (InterruptedException e) {
            throw e;
        } catch (InsufficientPermissionsException e) {
            throw e;
        } catch (ServiceException e) {
            logger.warn("Unable to retrieve components: " + ForceExceptionUtils.getRootCauseMessage(e));
            throw new RetrieveException(e, connection, retrieveRequest);
        } catch (Exception e) {
            logger.error("Unable to retrieve components: " + ForceExceptionUtils.getRootCauseMessage(e));
            throw new RetrieveException(e, connection, retrieveRequest);
        }

        return retrieveResultExt;
    }

    // L O G G I N G
    private void logRetrieve(Connection connection, RetrieveRequest retrieveRequest) {
        if (logger.isDebugEnabled()) {
            logger.debug("Retrieve request from " + connection.getLogDisplay());
            StringBuffer strBuff = new StringBuffer();
            boolean defaultPackage = (retrieveRequest.getUnpackaged() != null ? true : false);
            String[] packageNames = retrieveRequest.getPackageNames();
            strBuff.append("Retrieval request of the following");
            if (Utils.isNotEmpty(packageNames)) {
                strBuff.append(" [").append(defaultPackage ? packageNames.length + 1 : packageNames.length)
                        .append("] packages: ");
                for (String packageName : packageNames) {
                    strBuff.append("'").append(packageName).append("' ");
                }
            } else {
                strBuff.append(" packages: (no named packages) ");
            }

            if (defaultPackage) {
                strBuff.append("'").append(Constants.DEFAULT_PACKAGED_NAME).append("' ");
            }

            String[] componentNames = retrieveRequest.getSpecificFiles();
            int componentCnt = 0;
            if (Utils.isNotEmpty(componentNames)) {
                strBuff.append("\nRequesting retrieval of the following ").append("[").append(componentNames.length)
                        .append("] components: ");
                for (String componentName : componentNames) {
                    strBuff.append("\n (").append(++componentCnt).append(") ").append(componentName);
                }
            }

            strBuff.append("\nsingle package = " + retrieveRequest.isSinglePackage());

            if (retrieveRequest.getUnpackaged() != null) {
                Package packageManifest = getPackageManifestFactory().convert(retrieveRequest.getUnpackaged());
                try {
                    strBuff.append("\npackage.xml =\n" + packageManifest.getXMLString());
                } catch (JAXBException e) {
                    logger.warn("Unable to get package.xml string: " + e.getMessage());
                }
            }

            logger.debug(strBuff.toString());
        } else {
            if (logger.isInfoEnabled()) {
                String[] packageNames = retrieveRequest.getPackageNames();
                int packageCount = 0;
                if (Utils.isNotEmpty(packageNames)) {
                    packageCount = packageNames.length;
                }
                packageCount = packageCount + (retrieveRequest.getUnpackaged() != null ? 1 : 0);
                logger.info("Retrieving [" + packageCount + "] packages from:\n " + connection.getLogDisplay());
            }
        }
    }

    private void logResult(RetrieveResultExt resultExt) {
        if (logger.isDebugEnabled()) {
            logger.debug("Retrieve result contains zip of size ["
                    + (resultExt.getZipFile() != null ? resultExt.getZipFile().length : 0) + "]");
            StringBuffer strBuff = new StringBuffer("Retrieved the following components in package(s) '");
            if (resultExt != null && resultExt.getProjectPackageList() != null) {
                String[] packageNames = resultExt.getProjectPackageList().getPackageNames();
                for (int i = 0; i < packageNames.length; i++) {
                    strBuff.append(packageNames[i]);
                    if (i < packageNames.length - 1) {
                        strBuff.append(", ");
                    }
                }
            }
            strBuff.append("'");
            logger.debug(getFilePathLog(strBuff.toString(), resultExt.getZipFile()));

            RetrieveMessageExt messageHandler = resultExt.getMessageHandler();
            if (messageHandler != null) {
                messageHandler.logMessage();
            }
        } else if (logger.isInfoEnabled()) {
            int zipFileSize = 0;
            if (Utils.isNotEmpty(resultExt.getZipFile())) {
                zipFileSize = resultExt.getZipFile().length;
            }

            int fileCount = resultExt.getZipFileCount();
            logger.info("Retrieved zip file of size [" + zipFileSize + "] containing [" + fileCount + "] files");

            RetrieveMessageExt messageHandler = resultExt.getMessageHandler();
            if (messageHandler != null) {
                messageHandler.logMessage();
            }
        }
    }

}

class RetrieveResultAdapter implements IFileBasedResultAdapter {

    private AsyncResult asyncResult;
    private RetrieveResult retrieveResult;
    private MetadataStubExt metadataStubExt;

    public RetrieveResultAdapter(AsyncResult asyncResult, MetadataStubExt metadataStubExt) {
        this.asyncResult = asyncResult;
        this.metadataStubExt = metadataStubExt;
    }

    @Override
    public AsyncResult getAsyncResult() {
        return asyncResult;
    }

    @Override
    public IFileBasedResultAdapter checkStatus() throws ForceRemoteException {
        retrieveResult = metadataStubExt.checkRetrieveStatus(asyncResult.getId());
        return this;
    }

    @Override
    public boolean isDone() {
        return retrieveResult.isDone();
    }

    @Override
    public boolean isFailure() {
        return retrieveResult.getStatus() == RetrieveStatus.Failed;
    }

    @Override
    public String logStatus(Logger logger) {
        String status =
                "Retrieve result state is '" + retrieveResult.getStatus().toString() + "' for operation id '"
                        + asyncResult.getId() + "'";
        logger.debug(status);
        return status;
    }

    @Override
    public String logFailure(Logger logger) {
        StringBuffer strBuff =
                new StringBuffer().append(retrieveResult.getErrorMessage()).append(" (")
                        .append(retrieveResult.getStatus()).append(")");
        logger.warn("Retrieve operation from '" + metadataStubExt.getServerName() + "' failed: " + strBuff.toString());
        return strBuff.toString();
    }

    @Override
    public String logResult(Logger logger, OperationStats operationStats) {
        StringBuffer errorMessageBuffer = new StringBuffer();

        errorMessageBuffer.append("\nOperation : ").append(operationStats.getOperationName()).append("\nMessage : ")
                .append(retrieveResult.getMessages().toString()).append("\nState Detail : ")
                .append(retrieveResult.getStatus()).append("\nStatus Code : ").append(retrieveResult.getStatus());

        logger.debug(errorMessageBuffer.toString());
        return errorMessageBuffer.toString();
    }

    @Override
    public String retrieveRealTimeStatusUpdatesIfAny() {
        if (retrieveResult != null && retrieveResult.getStatus() != null) {
            return Messages.getString("Retrieve.ReportingStatus",
                new Object[] { retrieveResult.getStatus(), new Date() });
        }
        return Messages.getString("PackageService.Polling", new Object[] { metadataStubExt.getServerName() });
    }

    public RetrieveResult getRetrieveResult() {
        return retrieveResult;
    }
}
TOP

Related Classes of com.salesforce.ide.core.services.RetrieveResultAdapter

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.