/***************************************************************************** * Copyright (c) 2006-2013, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text of * such license is available at www.eclipse.org. *****************************************************************************/ package org.eclipse.buckminster.core.internal.actor; import static org.eclipse.buckminster.runtime.Trivial.trim; import java.io.PrintStream; import org.eclipse.buckminster.core.CorePlugin; import org.eclipse.buckminster.core.Messages; import org.eclipse.buckminster.core.actor.AbstractActor; import org.eclipse.buckminster.core.actor.IActionContext; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; 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.debug.core.model.IStreamsProxy; import org.eclipse.osgi.util.NLS; /** * An actor that triggers a launch configuration */ public class LaunchActor extends AbstractActor { static class StreamDispatcher implements IStreamListener { private final PrintStream stream; StreamDispatcher(PrintStream stream) { this.stream = stream; } @Override public void streamAppended(String text, IStreamMonitor monitor) { stream.print(text); } } public static final String ID = "launch"; //$NON-NLS-1$ private static final String LAUNCHER_PATH = "path"; //$NON-NLS-1$ private static final String LAUNCHER_MODE = "mode"; //$NON-NLS-1$ /** * Returns the component (project) relative path to the launch * configuration. This is a required attribute. * * @return The component relative path to the launch configuration. * @throws CoreException * if the attribute is missing */ private IPath getLaunchConfigurationPath() throws CoreException { String path = trim(getActorProperty(LAUNCHER_PATH)); if (path == null) throw BuckminsterException.fromMessage(Messages.Launch_No_launch_config); return Path.fromPortableString(path); } /** * Returns the launch mode that is used for launching. Defaults to * {@link ILaunchManager#RUN_MODE}. * * @return The launch mode to use. Never null. */ protected String getLaunchMode() { String mode = trim(getActorProperty(LAUNCHER_MODE)); return mode == null ? ILaunchManager.RUN_MODE : mode; } @Override protected IStatus internalPerform(IActionContext ctx, IProgressMonitor monitor) throws CoreException { IProject project = ctx.getProject(); IFile launchFile = null; IPath launchConfigPath = getLaunchConfigurationPath(); if (project != null && project.isAccessible()) launchFile = project.getFile(launchConfigPath); if (launchFile == null || !launchFile.exists()) throw BuckminsterException.fromMessage(NLS.bind(Messages.Launch_Cannot_open_launch_config, launchConfigPath.toPortableString())); ILaunch launch = DebugPlugin.getDefault().getLaunchManager().getLaunchConfiguration(launchFile).launch(getLaunchMode(), monitor); IProcess[] processes = launch.getProcesses(); StreamDispatcher out = new StreamDispatcher(ctx.getOutputStream()); StreamDispatcher err = new StreamDispatcher(ctx.getErrorStream()); for (IProcess p : processes) { IStreamsProxy streamsProxy = p.getStreamsProxy(); if (streamsProxy != null) { IStreamMonitor outMon = streamsProxy.getOutputStreamMonitor(); if (outMon != null) outMon.addListener(out); IStreamMonitor errMon = streamsProxy.getErrorStreamMonitor(); if (errMon != null) errMon.addListener(err); } } try { while (!launch.isTerminated()) { if (monitor.isCanceled() && launch.canTerminate()) launch.terminate(); Thread.sleep(500); } } catch (InterruptedException e) { throw new OperationCanceledException(); } MultiStatus result = new MultiStatus(CorePlugin.getID(), 0, "launch problem", null); //$NON-NLS-1$ for (IProcess p : processes) if (p.getExitValue() != 0) result.add(new Status(IStatus.ERROR, CorePlugin.getID(), NLS.bind(Messages.Launch_Terminated_with_exit_status, p.getLabel(), Integer.valueOf(p.getExitValue())))); project.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); return result; } }