com.microsoft.alm.plugin.idea.common.utils.IdeaHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.alm.plugin.idea.common.utils.IdeaHelper.java

Source

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root.

package com.microsoft.alm.plugin.idea.common.utils;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.microsoft.alm.plugin.external.tools.TfTool;
import com.microsoft.alm.plugin.idea.common.resources.TfPluginBundle;
import git4idea.GitVcs;
import git4idea.config.GitExecutableValidator;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.Icon;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;

public class IdeaHelper {
    private static final Logger logger = LoggerFactory.getLogger(IdeaHelper.class);

    private static final String CHARSET_UTF8 = "utf-8";
    public static final String TEST_RESOURCES_SUB_PATH = "/externals/platform/";
    private static final String PROD_RESOURCES_SUB_PATH = "platform";

    public IdeaHelper() {
    }

    public static void setProgress(final ProgressIndicator indicator, final double fraction, final String text) {
        setProgress(indicator, fraction, text, false);
    }

    public static void setProgress(final ProgressIndicator indicator, final double fraction, final String text,
            final boolean delay) {
        if (indicator == null) {
            // Tests send null to skip showing progress
            return;
        }

        IdeaHelper.runOnUIThread(new Runnable() {
            @Override
            public void run() {
                indicator.setFraction(fraction);
                indicator.setText(text);
            }
        });

        if (delay) {
            // Give time for the progress to be updated
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                logger.warn("setting progress failed", e);
            }
        }
    }

    /**
     * Verifies if Git exe is configured, show notification and warning message if not
     *
     * @param project Idea project
     * @return true if Git exe is configured, false if Git exe is not correctly configured
     */
    public static boolean isGitExeConfigured(@NotNull final Project project) {
        final GitExecutableValidator validator = GitVcs.getInstance(project).getExecutableValidator();
        if (!validator.checkExecutableAndNotifyIfNeeded()) {
            //Git.exe is not configured, show warning message in addition to notification from Git plugin
            Messages.showWarningDialog(project, TfPluginBundle.message(TfPluginBundle.KEY_GIT_NOT_CONFIGURED),
                    TfPluginBundle.message(TfPluginBundle.KEY_TF_GIT));
            return false;
        }

        return true;
    }

    /**
     * Verifies if TF is configured, show notification and warning message if not
     *
     * @param project Idea project
     * @return true if TF is configured, false if TF is not correctly configured
     */
    public static boolean isTFConfigured(@NotNull final Project project) {
        final String tfLocation = TfTool.getLocation();
        if (StringUtils.isEmpty(tfLocation)) {
            //TF is not configured, show warning message
            Messages.showWarningDialog(project, TfPluginBundle.message(TfPluginBundle.KEY_TFVC_NOT_CONFIGURED),
                    TfPluginBundle.message(TfPluginBundle.KEY_TFVC));
            return false;
        }

        return true;
    }

    public static void runOnUIThread(final Runnable runnable) {
        runOnUIThread(runnable, false);
    }

    public static void runOnUIThread(final Runnable runnable, final boolean wait) {
        runOnUIThread(runnable, wait,
                ApplicationManager.getApplication() != null
                        ? ApplicationManager.getApplication().getAnyModalityState()
                        : null);
    }

    public static void runOnUIThread(final Runnable runnable, final boolean wait,
            final ModalityState modalityState) {
        if (ApplicationManager.getApplication() != null
                && !ApplicationManager.getApplication().isDispatchThread()) {
            if (wait) {
                ApplicationManager.getApplication().invokeAndWait(runnable, modalityState);
            } else {
                ApplicationManager.getApplication().invokeLater(runnable, modalityState);
            }
        } else {
            // If we are already on the dispatch thread then we can run it here
            // If we don't have an application then we are testing, just run the runnable here
            runnable.run();
        }
    }

    /**
     * Shows a dialog with OK and cancel actions to prompt for confirmation from user
     *
     * @return true if user clicks on ok action and false if user clicks on cancel action
     */
    public static boolean showConfirmationDialog(@NotNull final Project project, final String message,
            final String title, final Icon logo, final String okActionMessage, final String cancelActionMessage) {

        final int result = Messages.showYesNoDialog(project, message, title, okActionMessage, cancelActionMessage,
                logo);
        return result == 0 ? true : false;
    }

    /**
     * Shows an error dialog
     *
     * @param project
     * @param throwable
     */
    public static void showErrorDialog(@NotNull final Project project, final Throwable throwable) {
        if (throwable != null) {
            showErrorDialog(project, throwable.getMessage());
        } else {
            showErrorDialog(project,
                    TfPluginBundle.message(TfPluginBundle.KEY_MESSAGE_TEAM_SERVICES_UNEXPECTED_ERROR));
        }
    }

    /**
     * Shows an error dialog
     *
     * @param project
     * @param message
     */
    public static void showErrorDialog(@NotNull final Project project, @NotNull final String message) {
        if (ApplicationManager.getApplication() == null) {
            // No application manager means no IntelliJ, we are probably in a test context
            return;
        }

        Messages.showErrorDialog(project, message,
                TfPluginBundle.message(TfPluginBundle.KEY_TITLE_TEAM_SERVICES_ERROR));
    }

    /**
     * Finds the full path to a resource whether it's installed by the idea or being run inside the idea
     *
     * @param resourceUrl  the URL for the resource
     * @param resourceName name of the resource
     * @param directory    the directory under the idea.plugin/resource directory to for the resource
     * @return the path to the resource
     * @throws UnsupportedEncodingException
     */
    public static String getResourcePath(final URL resourceUrl, final String resourceName, final String directory)
            throws UnsupportedEncodingException {
        // find location of the resource
        String resourcePath = resourceUrl.getPath();
        resourcePath = URLDecoder.decode(resourcePath, CHARSET_UTF8);
        resourcePath = StringUtils.chomp(resourcePath, "/");

        // When running the plugin inside of the idea for test, the path to the app needs to be
        // manipulated to look in a different location than where the resource resides in production.
        // For prod the url is .../../.IdeaIC15/config/plugins/com.microsoft.alm/lib but for test
        // the url is ../.IdeaIC15/system/plugins-sandbox/plugins/com.microsoft.alm.plugin.idea/classes
        if (resourcePath != null && resourcePath.endsWith(PROD_RESOURCES_SUB_PATH)) {
            return resourcePath + "/" + directory + "/" + resourceName;
        } else {
            return resourcePath + TEST_RESOURCES_SUB_PATH + directory + "/" + resourceName;
        }
    }

    /**
     * Check if a file is executable and if not sets it to be executable. When the plugin is unzipped,
     * the permissions of a file is not persisted so that is why a check is needed.
     *
     * @param executable executable file for application
     * @throws FileNotFoundException
     */
    public static void setExecutablePermissions(final File executable) throws FileNotFoundException {
        if (!executable.exists()) {
            throw new FileNotFoundException(executable.getPath() + " not found while trying to set permissions.");
        }

        // set the executable to execute for all users
        if (!executable.canExecute()) {
            executable.setExecutable(true, false);
        }
    }

    /**
     * Find the project that is associated with the current open frame
     * Got this method from how Git gets the current project
     *
     * @return project based on repo
     */
    public static Project getCurrentProject() {
        final IdeFrame frame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame();
        return frame == null || frame.getProject() == null ? ProjectManager.getInstance().getDefaultProject()
                : frame.getProject();
    }

}