com.google.dart.tools.debug.core.configs.DartServerLaunchConfigurationDelegate.java Source code

Java tutorial

Introduction

Here is the source code for com.google.dart.tools.debug.core.configs.DartServerLaunchConfigurationDelegate.java

Source

/*
 * Copyright (c) 2012, the Dart project authors.
 * 
 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.dart.tools.debug.core.configs;

import com.google.dart.engine.utilities.instrumentation.InstrumentationBuilder;
import com.google.dart.tools.core.DartCore;
import com.google.dart.tools.core.DartCoreDebug;
import com.google.dart.tools.core.model.DartSdkManager;
import com.google.dart.tools.core.pub.IPackageRootProvider;
import com.google.dart.tools.core.utilities.net.NetUtils;
import com.google.dart.tools.debug.core.DartDebugCorePlugin;
import com.google.dart.tools.debug.core.DartLaunchConfigWrapper;
import com.google.dart.tools.debug.core.DartLaunchConfigurationDelegate;
import com.google.dart.tools.debug.core.coverage.CoverageManager;
import com.google.dart.tools.debug.core.server.ServerDebugTarget;
import com.google.dart.tools.debug.core.server.ServerRemoteProcess;
import com.google.dart.tools.debug.core.source.UriToFileResolver;
import com.google.dart.tools.debug.core.util.CoreLaunchUtils;
import com.google.dart.tools.debug.core.util.IRemoteConnectionDelegate;

import org.apache.commons.lang3.ObjectUtils;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
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.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The Dart Server Application launch configuration.
 */
public class DartServerLaunchConfigurationDelegate extends DartLaunchConfigurationDelegate
        implements IRemoteConnectionDelegate {
    private static final int DEFAULT_PORT_NUMBER = 5858;

    //  private IPackageRootProvider packageRootProvider;

    private int observatoryPort = -1;

    /**
     * Create a new DartServerLaunchConfigurationDelegate.
     */
    public DartServerLaunchConfigurationDelegate() {
        this(IPackageRootProvider.DEFAULT);
    }

    public DartServerLaunchConfigurationDelegate(IPackageRootProvider packageRootProvider) {
        //    this.packageRootProvider = packageRootProvider;
    }

    @Override
    public void doLaunch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor,
            InstrumentationBuilder instrumentation) throws CoreException {

        DartLaunchConfigWrapper launchConfig = new DartLaunchConfigWrapper(configuration.getWorkingCopy());

        launchConfig.markAsLaunched();

        boolean enableDebugging = ILaunchManager.DEBUG_MODE.equals(mode) && !DartCoreDebug.DISABLE_CLI_DEBUGGER;

        terminateSameLaunches(launch);

        launchVM(launch, launchConfig, enableDebugging, monitor);
    }

    @Override
    public IDebugTarget performRemoteConnection(String host, int port, IContainer container,
            IProgressMonitor monitor, boolean usePubServe) throws CoreException {
        if (monitor == null) {
            monitor = new NullProgressMonitor();
        }

        ILaunch launch = CoreLaunchUtils.createTemporaryLaunch(DartDebugCorePlugin.SERVER_LAUNCH_CONFIG_ID,
                host + "[" + port + "]");

        monitor.beginTask("Opening Connection...", 1);

        try {
            if (container != null) {
                ILaunchConfiguration launchConfiguration = launch.getLaunchConfiguration();
                DartLaunchConfigWrapper wrapper = new DartLaunchConfigWrapper(launchConfiguration);
                wrapper.setSourceDirectoryName(container.getFullPath().toPortableString());
            }

            CoreLaunchUtils.addLaunch(launch);

            ServerRemoteProcess process = new ServerRemoteProcess(launch);

            ServerDebugTarget debugTarget = new ServerDebugTarget(launch, process, host, port);

            process.setTarget(debugTarget);

            process.fireCreateEvent();

            debugTarget.connect();

            monitor.worked(1);

            launch.addDebugTarget(debugTarget);

            return debugTarget;
        } catch (CoreException ce) {
            CoreLaunchUtils.removeLaunch(launch);

            throw ce;
        } finally {
            monitor.done();
        }
    }

    protected void launchVM(ILaunch launch, DartLaunchConfigWrapper launchConfig, boolean enableDebugging,
            IProgressMonitor monitor) throws CoreException {
        // Usage: dart [options] script.dart [arguments]

        File currentWorkingDirectory = getCurrentWorkingDirectory(launchConfig);

        String scriptPath = launchConfig.getApplicationName();

        scriptPath = translateToFilePath(currentWorkingDirectory, scriptPath);

        String vmExecPath = "";

        if (DartSdkManager.getManager().hasSdk()) {
            File vmExec = DartSdkManager.getManager().getSdk().getVmExecutable();

            if (vmExec != null) {
                vmExecPath = vmExec.getAbsolutePath().toString();
            }
        } else {
            vmExecPath = DartDebugCorePlugin.getPlugin().getDartVmExecutablePath();
        }

        if (vmExecPath.length() == 0) {
            throw new CoreException(
                    DartDebugCorePlugin.createErrorStatus("The executable path for the Dart VM has not been set."));
        }

        List<String> commandsList = new ArrayList<String>();

        int connectionPort = NetUtils.findUnusedPort(DEFAULT_PORT_NUMBER);

        commandsList.add(vmExecPath);
        commandsList.addAll(Arrays.asList(launchConfig.getVmArgumentsAsArray()));

        if (enableDebugging) {
            commandsList.add("--debug:" + connectionPort);
        }

        observatoryPort = NetUtils.findUnusedPort(0);

        launchConfig.setObservatoryPort(observatoryPort);
        launchConfig.save();

        commandsList.add("--enable-vm-service:" + observatoryPort);
        commandsList.add("--trace_service_pause_events");

        if (launchConfig.getPauseIsolateOnExit()) {
            commandsList.add("--pause-isolates-on-exit");
        }

        if (launchConfig.getPauseIsolateOnStart()) {
            commandsList.add("--pause-isolates-on-start");
        }

        // This lets us debug isolates.
        if (enableDebugging) {
            commandsList.add("--break-at-isolate-spawn");
        }

        String coverageTempDir = null;
        if (DartCoreDebug.ENABLE_COVERAGE) {
            coverageTempDir = CoverageManager.createTempDir();
            commandsList.add("--coverage_dir=" + coverageTempDir);
        }

        String packageRoot = DartCore.getPlugin().getVmPackageRoot(launchConfig.getProject());
        if (packageRoot != null) {
            String fileSeparator = System.getProperty("file.separator");
            if (!packageRoot.endsWith(fileSeparator)) {
                packageRoot += fileSeparator;
            }
            commandsList.add("--package-root=" + packageRoot);
        }

        commandsList.add(scriptPath);
        commandsList.addAll(Arrays.asList(launchConfig.getArgumentsAsArray()));
        String[] commands = commandsList.toArray(new String[commandsList.size()]);
        ProcessBuilder processBuilder = new ProcessBuilder(commands);

        if (currentWorkingDirectory != null) {
            processBuilder.directory(currentWorkingDirectory);
        }

        Process runtimeProcess = null;

        try {
            runtimeProcess = processBuilder.start();
            if (coverageTempDir != null) {
                UriToFileResolver uriToFileResolver = new UriToFileResolver(launch);
                CoverageManager.registerProcess(uriToFileResolver, coverageTempDir,
                        launchConfig.getApplicationName(), runtimeProcess);
            }
        } catch (IOException ioe) {
            throw new CoreException(
                    new Status(IStatus.ERROR, DartDebugCorePlugin.PLUGIN_ID, ioe.getMessage(), ioe));
        }

        IProcess eclipseProcess = null;

        Map<String, String> processAttributes = new HashMap<String, String>();

        String programName = "dart";
        processAttributes.put(IProcess.ATTR_PROCESS_TYPE, programName);
        processAttributes.put(IProcess.ATTR_CMDLINE, describe(processBuilder));

        if (runtimeProcess != null) {
            monitor.beginTask("Dart", IProgressMonitor.UNKNOWN);

            eclipseProcess = DebugPlugin.newProcess(launch, runtimeProcess,
                    launchConfig.getApplicationName() + " (" + new Date() + ")", processAttributes);
        }

        if (runtimeProcess == null || eclipseProcess == null) {
            if (runtimeProcess != null) {
                runtimeProcess.destroy();
            }

            throw new CoreException(DartDebugCorePlugin.createErrorStatus("Error starting Dart VM process"));
        }

        eclipseProcess.setAttribute(IProcess.ATTR_CMDLINE, describe(processBuilder));

        if (enableDebugging) {
            ServerDebugTarget debugTarget = new ServerDebugTarget(launch, eclipseProcess, connectionPort);

            try {
                debugTarget.connect();

                launch.addDebugTarget(debugTarget);
            } catch (DebugException ex) {
                // We don't throw an exception if the process died before we could connect.
                if (!isProcessDead(runtimeProcess)) {
                    throw ex;
                }
            }
        }

        monitor.done();
    }

    private String describe(ProcessBuilder processBuilder) {
        StringBuilder builder = new StringBuilder();

        for (String arg : processBuilder.command()) {
            builder.append(arg);
            builder.append(" ");
        }

        return builder.toString().trim();
    }

    private File getCurrentWorkingDirectory(DartLaunchConfigWrapper launchConfig) {
        if (launchConfig.getWorkingDirectory().length() > 0) {
            String cwd = launchConfig.getWorkingDirectory();

            return new File(cwd);
        } else {
            IResource resource = launchConfig.getApplicationResource();

            if (resource == null) {
                if (launchConfig.getProject() != null) {
                    return launchConfig.getProject().getLocation().toFile();
                } else {
                    return null;
                }
            } else {
                // Set the cwd to the project root.
                return resource.getProject().getLocation().toFile();
            }
        }
    }

    private boolean isProcessDead(Process process) {
        try {
            process.exitValue();

            return true;
        } catch (IllegalThreadStateException ex) {
            return false;
        }
    }

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {

        }
    }

    @SuppressWarnings("deprecation")
    private void terminateSameLaunches(ILaunch currentLaunch) {
        ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();

        boolean launchTerminated = false;

        for (ILaunch launch : manager.getLaunches()) {
            if (ObjectUtils.equals(launch.getLaunchConfiguration(), currentLaunch.getLaunchConfiguration())) {
                try {
                    launchTerminated = true;
                    launch.terminate();
                } catch (DebugException e) {
                    DartDebugCorePlugin.logError(e);
                }
            }
        }

        if (launchTerminated) {
            // Wait a while for processes to shutdown.
            sleep(100);
        }
    }

    /**
     * Return either a path relative to the cwd, if possible, or an absolute path to the given script.
     * 
     * @param cwd the current working directory for the launch
     * @param scriptPath the path to the script (a workspace path)
     * @return either a cwd relative path or an absolute path
     */
    private String translateToFilePath(File cwd, String scriptPath) {
        IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(scriptPath);

        if (resource != null) {
            String path = resource.getLocation().toFile().getAbsolutePath();

            if (cwd != null) {
                String cwdPath = cwd.getAbsolutePath();

                if (!cwdPath.endsWith(File.separator)) {
                    cwdPath = cwdPath + File.separator;
                }

                if (path.startsWith(cwdPath)) {
                    path = path.substring(cwdPath.length());
                }
            }

            return path;
        } else {
            return scriptPath;
        }
    }

}