blob: df509bd06eb22ec05d949742330e1ec4865dd2db [file] [log] [blame]
package org.eclipse.ptp.internal.debug.sdm.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ptp.core.jobs.IJobControl;
import org.eclipse.ptp.debug.core.launch.IPLaunch;
import org.eclipse.ptp.internal.debug.core.PDebugOptions;
import org.eclipse.ptp.internal.debug.core.PTPDebugCorePlugin;
import org.eclipse.ptp.internal.debug.sdm.core.messages.Messages;
import org.eclipse.remote.core.IRemoteConnection;
import org.eclipse.remote.core.IRemoteFileService;
import org.eclipse.remote.core.IRemoteProcess;
import org.eclipse.remote.core.IRemoteProcessBuilder;
import org.eclipse.remote.core.IRemoteProcessService;
public class SDMRunner extends Job {
public enum SDMMasterState {
UNKNOWN, STARTING, RUNNING, FINISHED, ERROR
};
private List<String> command;
private String workDir = null;
private SDMMasterState sdmState = SDMMasterState.STARTING;
private IRemoteConnection connection = null;
private IRemoteProcess sdmProcess;
private IPLaunch launch;
/**
* @since 6.0
*/
public SDMRunner(IRemoteConnection conn) {
super(Messages.SDMRunner_0);
this.setPriority(Job.LONG);
this.setSystem(true);
this.connection = conn;
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER_MORE, Messages.SDMRunner_4);
}
public void setCommand(List<String> command) {
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER_MORE, Messages.SDMRunner_5, command.toString());
this.command = command;
}
public void setWorkDir(String workDir) {
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER_MORE, Messages.SDMRunner_6, workDir);
this.workDir = workDir;
}
public synchronized SDMMasterState getSdmState() {
return sdmState;
}
protected synchronized void setSdmState(SDMMasterState sdmState) {
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER_MORE, Messages.SDMRunner_7, sdmState.toString());
this.sdmState = sdmState;
this.notifyAll();
}
/**
* @since 6.0
*/
public void setLaunch(IPLaunch launch) {
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER_MORE, Messages.SDMRunner_8, launch.getJobId());
this.launch = launch;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
assert command != null;
assert sdmProcess == null;
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_9);
if (!connection.hasService(IRemoteFileService.class) || !connection.hasService(IRemoteProcessService.class)) {
return new Status(IStatus.ERROR, SDMDebugCorePlugin.getUniqueIdentifier(),
"Failed to start: connection does not provide requisite services");
}
/*
* Catch all try...catch
*/
try {
if (monitor.isCanceled()) {
throw new InterruptedException();
}
/*
* Prepare remote connection.
*/
IRemoteFileService fileService = connection.getService(IRemoteFileService.class);
IRemoteProcessService processService = connection.getService(IRemoteProcessService.class);
IRemoteProcessBuilder sdmProcessBuilder = processService.getProcessBuilder(command);
if (workDir != null) {
sdmProcessBuilder.directory(fileService.getResource(workDir));
}
/*
* Wait some time to assure that SDM servers and front end have started.
*/
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_10);
if (monitor.isCanceled()) {
throw new InterruptedException();
}
synchronized (this) {
wait(3000);
}
/*
* Create process.
*/
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_11);
if (monitor.isCanceled()) {
throw new InterruptedException();
}
synchronized (this) {
sdmProcess = sdmProcessBuilder.start();
}
final BufferedReader err_reader = new BufferedReader(new InputStreamReader(sdmProcess.getErrorStream()));
final BufferedReader out_reader = new BufferedReader(new InputStreamReader(sdmProcess.getInputStream()));
if (PDebugOptions.isDebugging(PDebugOptions.DEBUG_MASTER_OUTPUT)) {
new Thread(new Runnable() {
public void run() {
try {
String output;
while ((output = out_reader.readLine()) != null) {
System.out.println(Messages.SDMRunner_12 + output);
}
} catch (IOException e) {
// Ignore
}
try {
out_reader.close();
} catch (IOException e) {
// Ignore
}
}
}, Messages.SDMRunner_13).start();
}
if (PDebugOptions.isDebugging(PDebugOptions.DEBUG_MASTER_OUTPUT)) {
new Thread(new Runnable() {
public void run() {
try {
String line;
while ((line = err_reader.readLine()) != null) {
System.err.println(Messages.SDMRunner_14 + line);
}
} catch (IOException e) {
// Ignore
}
try {
err_reader.close();
} catch (IOException e) {
// Ignore
}
}
}, Messages.SDMRunner_15).start();
}
/*
* Wait while running but not canceled.
*/
setSdmState(SDMMasterState.RUNNING);
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER_MORE, Messages.SDMRunner_16);
while (!sdmProcess.isCompleted()) {
synchronized (this) {
wait(500);
}
if (monitor.isCanceled()) {
out_reader.close();
err_reader.close();
throw new InterruptedException();
}
}
/*
* Check if process terminated successfully (if not canceled).
*/
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_17, Integer.toString(sdmProcess.exitValue()));
if (sdmProcess.exitValue() != 0) {
if (!monitor.isCanceled()) {
throw new CoreException(new Status(IStatus.ERROR, SDMDebugCorePlugin.getUniqueIdentifier(), NLS.bind(
Messages.SDMRunner_2, sdmProcess.exitValue())));
} else {
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_18);
}
}
setSdmState(SDMMasterState.FINISHED);
return Status.OK_STATUS;
} catch (Exception e) {
/*
* Terminate the job, handling the error.
*/
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_19, e.toString());
synchronized (this) {
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_20, e.toString());
sdmProcess.destroy();
}
try {
if (launch != null) {
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_21, launch.getJobId());
launch.getJobControl().control(launch.getJobId(), IJobControl.TERMINATE_OPERATION, null);
}
} catch (CoreException e1) {
PTPDebugCorePlugin.log(e1);
}
if (e instanceof InterruptedException) {
setSdmState(SDMMasterState.FINISHED);
return Status.CANCEL_STATUS;
} else if (e instanceof CoreException) {
setSdmState(SDMMasterState.ERROR);
return ((CoreException) e).getStatus();
} else {
setSdmState(SDMMasterState.ERROR);
return new Status(IStatus.ERROR, SDMDebugCorePlugin.getUniqueIdentifier(), Messages.SDMRunner_3, e);
}
} finally {
PDebugOptions.trace(PDebugOptions.DEBUG_MASTER, Messages.SDMRunner_22);
synchronized (this) {
sdmProcess = null;
}
}
}
@Override
protected void canceling() {
synchronized (this) {
if (sdmProcess != null) {
sdmProcess.destroy();
}
}
}
}