org.eclipse.egit.ui.internal.branch.LaunchFinder.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.egit.ui.internal.branch.LaunchFinder.java

Source

/*******************************************************************************
 * Copyright (c) 2013, 2016 Robin Stocker and others.
 * 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:
 *    Thomas Wolf <thomas.wolf@paranor.ch>
 *******************************************************************************/
package org.eclipse.egit.ui.internal.branch;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.containers.ProjectSourceContainer;
import org.eclipse.egit.core.internal.util.ProjectUtil;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.operation.ModalContext;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.ui.PlatformUI;

/**
 * Utility class for finding launch configurations.
 */
public final class LaunchFinder {

    private LaunchFinder() {
        // Utility class shall not be instantiated
    }

    /**
     * If there is a running launch covering at least one project from the given
     * repositories, return the first such launch configuration.
     *
     * @param repositories
     *            to determine projects to be checked whether they are used in
     *            running launches
     * @param monitor
     *            for progress reporting and cancellation
     * @return the {@link ILaunchConfiguration}, or {@code null} if none found.
     */
    @Nullable
    public static ILaunchConfiguration getRunningLaunchConfiguration(final Collection<Repository> repositories,
            IProgressMonitor monitor) {
        SubMonitor progress = SubMonitor.convert(monitor, 1);
        final ILaunchConfiguration[] result = { null };
        IRunnableWithProgress operation = new IRunnableWithProgress() {

            @Override
            public void run(IProgressMonitor m) throws InvocationTargetException, InterruptedException {
                Set<IProject> projects = new HashSet<>();
                for (Repository repository : repositories) {
                    projects.addAll(Arrays.asList(ProjectUtil.getProjects(repository)));
                }
                result[0] = findLaunch(projects, m);
            }
        };
        try {
            if (ModalContext.isModalContextThread(Thread.currentThread())) {
                operation.run(progress);
            } else {
                ModalContext.run(operation, true, progress, PlatformUI.getWorkbench().getDisplay());
            }
        } catch (InvocationTargetException e) {
            // ignore
        } catch (InterruptedException e) {
            // ignore
        }
        return result[0];
    }

    private static ILaunchConfiguration findLaunch(Set<IProject> projects, IProgressMonitor monitor) {
        ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
        ILaunch[] launches = launchManager.getLaunches();
        SubMonitor progress = SubMonitor.convert(monitor, UIText.LaunchFinder_SearchLaunchConfiguration,
                launches.length);
        for (ILaunch launch : launches) {
            if (progress.isCanceled()) {
                break;
            }
            if (launch.isTerminated()) {
                progress.worked(1);
                continue;
            }
            ISourceLocator locator = launch.getSourceLocator();
            if (locator instanceof ISourceLookupDirector) {
                ISourceLookupDirector director = (ISourceLookupDirector) locator;
                ISourceContainer[] containers = director.getSourceContainers();
                if (isAnyProjectInSourceContainers(containers, projects, progress.newChild(1))) {
                    return launch.getLaunchConfiguration();
                }
            } else {
                progress.worked(1);
            }
        }
        return null;
    }

    private static boolean isAnyProjectInSourceContainers(ISourceContainer[] containers, Set<IProject> projects,
            IProgressMonitor monitor) {
        SubMonitor progress = SubMonitor.convert(monitor, containers.length);
        for (ISourceContainer container : containers) {
            if (progress.isCanceled()) {
                break;
            }
            if (container instanceof ProjectSourceContainer) {
                ProjectSourceContainer projectContainer = (ProjectSourceContainer) container;
                if (projects.contains(projectContainer.getProject())) {
                    progress.worked(1);
                    return true;
                }
            }
            try {
                boolean found = isAnyProjectInSourceContainers(container.getSourceContainers(), projects,
                        progress.newChild(1));
                if (found) {
                    return true;
                }
            } catch (CoreException e) {
                // Ignore the child source containers, continue search
            }
        }
        return false;
    }

    /**
     * Checks whether there are any running launches based on projects belonging
     * to the given repository. If so, asks the user whether to cancel, and
     * returns the user's choice. The user has the possibility to suppress the
     * dialog, in which case this method returns {@code false} without checking
     * for running launches.
     *
     * @param repository
     *            to determine projects to be checked whether they are used in
     *            running launches
     * @param monitor
     *            for progress reporting and cancellation
     * @return {@code true} if the operation should be canceled, {@code false}
     *         otherwise
     */
    public static boolean shouldCancelBecauseOfRunningLaunches(Repository repository, IProgressMonitor monitor) {
        return shouldCancelBecauseOfRunningLaunches(Collections.singleton(repository), monitor);
    }

    /**
     * Checks whether there are any running launches based on projects belonging
     * to the given repositories. If so, asks the user whether to cancel, and
     * returns the user's choice. The user has the possibility to suppress the
     * dialog, in which case this method returns {@code false} without checking
     * for running launches.
     *
     * @param repositories
     *            to determine projects to be checked whether they are used in
     *            running launches
     * @param monitor
     *            for progress reporting and cancellation
     * @return {@code true} if the operation should be canceled, {@code false}
     *         otherwise
     */
    public static boolean shouldCancelBecauseOfRunningLaunches(Collection<Repository> repositories,
            IProgressMonitor monitor) {
        final IPreferenceStore store = Activator.getDefault().getPreferenceStore();
        if (!store.getBoolean(UIPreferences.SHOW_RUNNING_LAUNCH_ON_CHECKOUT_WARNING)) {
            return false;
        }
        SubMonitor progress = SubMonitor.convert(monitor);
        final ILaunchConfiguration launchConfiguration = getRunningLaunchConfiguration(repositories, progress);
        if (launchConfiguration != null) {
            final boolean[] dialogResult = new boolean[1];
            PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
                @Override
                public void run() {
                    dialogResult[0] = showContinueDialogInUI(store, launchConfiguration);
                }
            });
            return dialogResult[0];
        }
        return false;
    }

    private static boolean showContinueDialogInUI(final IPreferenceStore store,
            final ILaunchConfiguration launchConfiguration) {
        String[] buttons = new String[] { UIText.BranchOperationUI_Continue, IDialogConstants.CANCEL_LABEL };
        String message = NLS.bind(UIText.LaunchFinder_RunningLaunchMessage, launchConfiguration.getName()) + ' '
                + UIText.LaunchFinder_ContinueQuestion;
        MessageDialogWithToggle continueDialog = new MessageDialogWithToggle(
                PlatformUI.getWorkbench().getModalDialogShellProvider().getShell(),
                UIText.LaunchFinder_RunningLaunchTitle, null, message, MessageDialog.NONE, buttons, 0,
                UIText.LaunchFinder_RunningLaunchDontShowAgain, false);
        int result = continueDialog.open();
        // cancel
        if (result == IDialogConstants.CANCEL_ID || result == SWT.DEFAULT)
            return true;
        boolean dontWarnAgain = continueDialog.getToggleState();
        if (dontWarnAgain)
            store.setValue(UIPreferences.SHOW_RUNNING_LAUNCH_ON_CHECKOUT_WARNING, false);
        return false;
    }

}