blob: d4226b776ace82273707aa6c157d6c0a4a747aa0 [file] [log] [blame]
// Copyright (c) 2013 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.0s which accompanies this distribution,
// and is available at http://www.eclipse.org/legal/epl-v10.html
package org.eclipse.ptp.rm.ibm.lsf.ui;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ptp.remote.core.IRemoteConnection;
import org.eclipse.ptp.remote.core.IRemoteProcess;
import org.eclipse.ptp.remote.core.IRemoteProcessBuilder;
import org.eclipse.ptp.remote.core.IRemoteServices;
import org.eclipse.ptp.rm.ibm.lsf.ui.widgets.Messages;
/**
* This class implements invocation of LSF commands as a job running on a non-UI thread with the
* ability for the user to cancel the job.
*/
public class LSFCommand implements IRunnableWithProgress {
private String command[];
private String commandDescription;
private IRemoteConnection remoteConnection;
protected Vector<String[]> commandResponse;
protected String columnLabels[];
public static final int OK = 0;
public static final int COMMAND_ERROR = 3;
public static final int CANCELED = 2;
public static final int NO_DATA = 3;
protected IRemoteProcess process;
protected IStatus runStatus;
/**
* Constructor for creating a job to run a LSF command
*
* @param name
* - Name of the job
* @param connection
* The remote connection where the job will be run
* @param cmd
* Array containing command name and command parameters
*/
public LSFCommand(String name, IRemoteConnection connection, String cmd[]) {
commandDescription = name;
remoteConnection = connection;
command = cmd;
commandResponse = new Vector<String[]>();
}
/**
* Run the LSF command specified when this object was created.
*
* @param monitor
* - Progress monitor used to monitor and control job execution
*/
@Override
public void run(IProgressMonitor monitor) {
monitor.beginTask(commandDescription, IProgressMonitor.UNKNOWN);
runStatus = runCommand(monitor);
if (runStatus.isOK() && (process.exitValue() == 0)) {
runStatus = getCommandOutput(monitor);
}
monitor.done();
}
protected IStatus runCommand(IProgressMonitor monitor) {
IRemoteServices remoteServices;
IRemoteProcessBuilder processBuilder;
remoteServices = remoteConnection.getRemoteServices();
processBuilder = remoteServices.getProcessBuilder(remoteConnection, command);
process = null;
try {
process = processBuilder.start();
try {
for (;;) {
if (process.isCompleted()) {
break;
}
if (monitor.isCanceled()) {
process.destroy();
return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, CANCELED, Messages.CommandCancelMessage, null);
}
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// Do nothing
}
} catch (IOException e) {
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, COMMAND_ERROR, Messages.LSFCommandFailed, e);
}
return new Status(IStatus.OK, Activator.PLUGIN_ID, OK, Messages.OkMessage, null);
}
protected IStatus getCommandOutput(IProgressMonitor monitor) {
BufferedReader reader;
String columnData[];
String data;
boolean headerLine;
/*
* Read stderr and check for "No application profiles found."
* as the first line of output. Subsequent lines are ignored.
*/
try {
reader = new BufferedReader(new InputStreamReader(
process.getErrorStream()));
data = reader.readLine();
headerLine = true;
while (data != null) {
if (headerLine) {
if (data.equals("No application profiles found.")) { //$NON-NLS-1$
reader.close();
return new Status(IStatus.INFO, Activator.PLUGIN_ID, NO_DATA, Messages.NoProfileMessage, null);
}
headerLine = false;
}
data = reader.readLine();
if (monitor.isCanceled()) {
reader.close();
return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, CANCELED, Messages.CommandCancelMessage, null);
}
}
reader.close();
/*
* Read stdout and tokenize each line of data into an array of
* blank-delimited strings. The first line of output is the
* column headings. Subsequent lines are reservation data.
*/
reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
data = reader.readLine();
headerLine = true;
commandResponse.clear();
while (data != null) {
if (headerLine) {
if (data.equals("No reservation found")) { //$NON-NLS-1$
reader.close();
return new Status(IStatus.INFO, Activator.PLUGIN_ID, NO_DATA, Messages.NoReservationMessage, null);
} else {
columnLabels = data.split(" +"); //$NON-NLS-1$
headerLine = false;
}
} else {
data = data.replaceAll(" +/ +", "/"); //$NON-NLS-1$ //$NON-NLS-2$
columnData = data.split(" +"); //$NON-NLS-1$
commandResponse.add(columnData);
}
data = reader.readLine();
if (monitor.isCanceled()) {
reader.close();
return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, CANCELED, Messages.CommandCancelMessage, null);
}
}
reader.close();
} catch (IOException e) {
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, COMMAND_ERROR, "Error reading command output", e);
}
return new Status(IStatus.OK, Activator.PLUGIN_ID, OK, Messages.OkMessage, null);
}
/**
* Get the command response
*
* @return Command response
*/
public Vector<String[]> getCommandResponse() {
return commandResponse;
}
/**
* Get the column headings. Column headings are the first line of the command response data
* where each column has a blank-delimited column heading
*
* @return Column heading data
*/
public String[] getColumnLabels() {
return columnLabels;
}
public IStatus getRunStatus() {
return runStatus;
}
}