/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation 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:
* ??? (DLTK) - initial API and implementation
* Bruno Medeiros - modifications, removed DLTK dependencies
*******************************************************************************/
package melnorme.lang.ide.launching;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import java.io.IOException;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IProcess;
import melnorme.lang.ide.core.EclipseCore;
import melnorme.lang.ide.core.launch.LaunchMessages;
import melnorme.lang.ide.core.operations.build.VariablesResolver;
import melnorme.lang.tooling.commands.CommandInvocation;
import melnorme.utilbox.collections.Indexable;
import melnorme.utilbox.core.CommonException;
import melnorme.utilbox.misc.Location;
import melnorme.utilbox.misc.StringUtil;
/**
* Helper class to launch an Eclipse IProcess.
*/
public class EclipseProcessLauncher {
public final IProject project;
public final Location programFileLocation;
public final IPath workingDir;
public final CommandInvocation unresolvedProgramInvocation;
public String processType;
public EclipseProcessLauncher(
IProject project,
Location programFileLocation,
IPath workingDir,
CommandInvocation unresolvedProgramInvocation,
String processType
) {
this.project = assertNotNull(project);
this.programFileLocation = assertNotNull(programFileLocation);
this.workingDir = workingDir;
this.unresolvedProgramInvocation = assertNotNull(unresolvedProgramInvocation);
this.processType = processType;
}
protected CoreException abort(String message, Throwable exception) throws CoreException {
throw EclipseCore.createCoreException(message, exception);
}
protected CoreException fail(String messagePattern, Object... arguments) throws CoreException {
throw abort(MessageFormat.format(messagePattern, arguments), null);
}
protected IProcess launchProcess(final ILaunch launch) throws CoreException, CommonException {
if(workingDir != null && !workingDir.toFile().exists()) {
fail(LaunchMessages.errWorkingDirectoryDoesntExist, workingDir);
}
if(!programFileLocation.toFile().exists()) {
fail(LaunchMessages.errExecutableFileDoesntExist, programFileLocation);
}
CommandInvocation programInvocation = unresolvedProgramInvocation.getResolvedCommandInvocation(
new VariablesResolver(VariablesPlugin.getDefault().getStringVariableManager()));
Indexable<String> cmdLine = programInvocation.parseCommandLineArguments();
Process sp = newSystemProcess(programInvocation);
return newEclipseProcessWithLabelUpdater(launch, cmdLine, sp);
}
protected Process newSystemProcess(CommandInvocation resolvedProgramInvocation) throws CoreException {
ProcessBuilder processBuilder = resolvedProgramInvocation.getProcessBuilder();
if(workingDir != null) {
processBuilder.directory(workingDir.toFile());
}
Process sp= null;
try {
sp = processBuilder.start();
} catch (IOException e) {
abort(LaunchMessages.errNewJavaProcessFailed, e);
}
return sp;
}
public IProcess newEclipseProcessWithLabelUpdater(ILaunch launch, Indexable<String> cmdLine, Process sp)
throws CoreException {
final String cmdLineLabel = renderCommandLineLabel(cmdLine);
final String processLabel = renderProcessLabel();
IProcess process = newEclipseProcess(launch, sp, processLabel);
process.setAttribute(IProcess.ATTR_CMDLINE, cmdLineLabel);
return process;
}
protected IProcess newEclipseProcess(ILaunch launch, Process sp, String label) throws CoreException {
// We ignore process factories, and create the class ourselves:
return new RuntimeProcessExtension(launch, sp, label, getProcessAttributes());
//return DebugPlugin.newProcess(launch, sp, label, getProcessAttributes());
}
protected Map<String, String> getProcessAttributes() {
Map<String, String> map = new HashMap<String, String>();
if(processType != null) {
map.put(IProcess.ATTR_PROCESS_TYPE, processType);
}
return map;
}
protected static final DateFormat PROCESS_LABEL_DATE_FORMAT =
DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
protected String renderProcessLabel() {
String timestampLabel = PROCESS_LABEL_DATE_FORMAT.format(new Date(System.currentTimeMillis()));
String processFilePath = programFileLocation.toString();
return MessageFormat.format("{0} ({1})", processFilePath, timestampLabel);
}
protected static String renderCommandLineLabel(Indexable<String> commandLine) {
return StringUtil.collToString(commandLine, "\n");
}
}