org.jboss.tools.browsersim.eclipse.launcher.ExternalProcessLauncher.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.browsersim.eclipse.launcher.ExternalProcessLauncher.java

Source

/*******************************************************************************
 * Copyright (c) 2007-2015 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is 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
 *
 * Contributor:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.browsersim.eclipse.launcher;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.jboss.tools.browsersim.browser.PlatformUtil;
import org.jboss.tools.browsersim.eclipse.Activator;
import org.jboss.tools.browsersim.eclipse.Messages;
import org.jboss.tools.browsersim.eclipse.dialog.BrowserSimErrorDialog;
import org.jboss.tools.browsersim.eclipse.preferences.BrowserSimPreferencesPage;
import org.jboss.tools.browsersim.eclipse.preferences.PreferencesUtil;
import org.jboss.tools.browsersim.ui.BrowserSimLogger;
import org.osgi.framework.Bundle;

/**
 * @author Yahor Radtsevich (yradtsevich)
 * @author Ilya Buziuk (ibuziuk)
 */
public class ExternalProcessLauncher {
    private static String PATH_SEPARATOR = System.getProperty("path.separator"); //$NON-NLS-1$
    private static final String CONFIGURATION = "-configuration"; //$NON-NLS-1$
    private static final String SWT_GTK3 = "SWT_GTK3"; //$NON-NLS-1$
    private static final String OFF = "0"; //$NON-NLS-1$
    private static final String ON = "1"; //$NON-NLS-1$

    public static void launchAsExternalProcess(List<String> bundles, List<String> resourcesBundles,
            List<String> jettyBundles, final List<ExternalProcessCallback> callbacks, String className,
            List<String> parameters, final String programName, IVMInstall jvm) {
        try {
            String classPath = getClassPathString(bundles, resourcesBundles, jettyBundles);
            String jreContainerPath = JavaRuntime.newJREContainerPath(jvm).toPortableString();
            if (jreContainerPath != null) {
                List<String> commandElements = new ArrayList<String>();

                // RT-35868 and JBIDE-18404 - need to handle CORS headers correctly
                commandElements.add("-Dsun.net.http.allowRestrictedHeaders=true"); //$NON-NLS-1$

                if (Platform.OS_MACOSX.equals(Platform.getOS())) {
                    commandElements.add("-XstartOnFirstThread"); //$NON-NLS-1$
                }

                addConfigurationFolderParameter(parameters);

                ILaunch launch = launch(programName, classPath, className, parameters, jreContainerPath,
                        commandElements);
                ProcessCallBacks(launch, callbacks);
            } else {
                showErrorDialog(programName);
            }
        } catch (IOException e) {
            Activator.logError(e.getMessage(), e);
        } catch (CoreException e) {
            Activator.logError(e.getMessage(), e);
        } catch (URISyntaxException e) {
            Activator.logError(e.getMessage(), e);
        }
    }

    // JBIDE-17718 Need to save preferences in the folder with configuration info 
    private static List<String> addConfigurationFolderParameter(List<String> parameters)
            throws URISyntaxException, IOException {
        parameters.add(CONFIGURATION);
        parameters.add(PreferencesUtil.getBrowserSimConfigFolderPath());
        return parameters;
    }

    private static void ProcessCallBacks(ILaunch launch, final List<ExternalProcessCallback> callbacks) {
        IProcess[] processes = launch.getProcesses();
        if (processes.length > 0) {
            IProcess process = processes[0];
            IStreamMonitor outputStreamMonitor = process.getStreamsProxy().getOutputStreamMonitor();
            outputStreamMonitor.addListener(new IStreamListener() {

                @Override
                public void streamAppended(String message, IStreamMonitor monitor) {
                    for (ExternalProcessCallback callback : callbacks) {
                        if (message.startsWith(callback.getCallbackId())) {
                            try {
                                callback.call(message, null);
                            } catch (IOException e) {
                                Activator.logError(e.getMessage(), e);
                            }
                        }
                    }

                }
            });
        } else {
            Activator.logError("Unable to get launch process", new Throwable()); //$NON-NLS-1$
        }
    }

    public static boolean isGTK2() {
        IPreferenceStore store = Activator.getDefault().getPreferenceStore();
        if (IPreferenceStore.TRUE.equals(store.getString(BrowserSimPreferencesPage.BROWSERSIM_GTK_2))) {
            return true;
        }
        return false;
    }

    private static void setUpGtkEnvironmentalVariable(ILaunchConfigurationWorkingCopy workingCopy) {
        Map<String, String> environment = new HashMap<String, String>();
        if (isGTK2()) {
            environment.put(SWT_GTK3, OFF);
        } else {
            environment.put(SWT_GTK3, ON);
        }
        workingCopy.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, environment);
    }

    public static void showErrorDialog(final String programName) {
        Display.getDefault().asyncExec(new Runnable() {

            @Override
            public void run() {
                Shell shell = Display.getDefault().getActiveShell();
                if (shell == null) {
                    shell = Display.getDefault().getShells()[0]; // Hot fix for gtk3 
                }
                BrowserSimErrorDialog e = new BrowserSimErrorDialog(shell, Messages.ExternalProcessLauncher_ERROR,
                        shell.getDisplay().getSystemImage(SWT.ICON_ERROR), programName, MessageDialog.ERROR,
                        new String[] { IDialogConstants.OK_LABEL }, 0);
                e.open();
            }
        });
    }

    private static String getClassPathString(List<String> bundles, List<String> resourcesBundles,
            List<String> jettyBundles) throws IOException {
        List<Bundle> classPathBundles = new ArrayList<Bundle>();
        for (String bundleName : bundles) {
            Bundle bundle = Platform.getBundle(bundleName);
            if (bundle != null) {
                classPathBundles.add(bundle);
            }
        }

        for (String bundleName : jettyBundles) {
            Bundle bundle = Platform.getBundle(bundleName); // Highest jetty version from TP
            classPathBundles.add(bundle);
        }

        StringBuilder classPath = new StringBuilder();
        if (classPathBundles.size() > 0) {
            for (int i = 0; i < classPathBundles.size() - 1; i++) {
                classPath.append(getBundleLocation(classPathBundles.get(i)));
                classPath.append(PATH_SEPARATOR);
            }
            classPath.append(getBundleLocation(classPathBundles.get(classPathBundles.size() - 1)));
        }

        for (String bundleName : resourcesBundles) {
            Bundle bundle = Platform.getBundle(bundleName);
            if (bundle != null) {
                classPath.append(getResource(bundle));
            }
        }

        return classPath.toString();
    }

    public static List<String> getClassPathMementos(String classPathString) {
        String[] classPathArray = classPathString.split(PATH_SEPARATOR);
        List<String> classpathMementos = new ArrayList<String>();
        for (int i = 0; i < classPathArray.length; i++) {
            IRuntimeClasspathEntry cpEntry = JavaRuntime
                    .newArchiveRuntimeClasspathEntry(new Path(classPathArray[i]));
            cpEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);
            try {
                classpathMementos.add(cpEntry.getMemento());
            } catch (CoreException e) {
                BrowserSimLogger.logError(e.getMessage(), e);
            }
        }
        return classpathMementos;
    }

    public static String getBundleLocation(Bundle bundle) throws IOException {
        try {
            File bundleLocation = FileLocator.getBundleFile(bundle);

            if (bundleLocation.isDirectory()) {
                File binDirectory = new File(bundleLocation, "bin"); //$NON-NLS-1$
                if (binDirectory.isDirectory()) {
                    bundleLocation = binDirectory;
                }
            }

            return bundleLocation.getCanonicalPath();
        } catch (IOException e) {
            throw new IOException(Messages.ExternalProcessLauncher_NO_BUNDLE + bundle.getSymbolicName(), e);
        }
    }

    private static String getResource(Bundle bundle) throws IOException {
        StringBuilder result = new StringBuilder();

        //URL[] res = FileLocator.findEntries(bundle, new Path("plugins"));
        String location = FileLocator.getBundleFile(bundle).getCanonicalPath();
        File resources = new File(location + "/plugins"); //$NON-NLS-1$
        if (resources.exists()) {
            for (File resource : resources.listFiles()) {
                result.append(PATH_SEPARATOR);
                result.append(resource.getCanonicalPath());
            }
        }
        return result.toString();
    }

    private static ILaunch launch(String programmName, String classPath, String className, List<String> parameters,
            String jvmPath, List<String> commandElements) throws CoreException {
        ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
        ILaunchConfigurationType type = manager
                .getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
        ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null, programmName);
        setWorkingCopyAttributes(workingCopy, classPath, className, parameters, jvmPath, commandElements);
        return workingCopy.launch(ILaunchManager.RUN_MODE, null);
    }

    private static void setWorkingCopyAttributes(ILaunchConfigurationWorkingCopy workingCopy, String classPath,
            String className, List<String> parameters, String jreContainerPath, List<String> commandElements) {
        workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, getClassPathMementos(classPath));
        workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false);
        workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, jreContainerPath);
        workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
                PreferencesUtil.argumentsListToString(commandElements));
        workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
                PreferencesUtil.argumentsListToString(parameters));
        workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, className);

        if (PlatformUtil.OS_LINUX.equals(PlatformUtil.getOs())) {
            setUpGtkEnvironmentalVariable(workingCopy);
        }
    }
}