📄 startitprocess.java
字号:
// in case we were connected
oaa.disconnect();
}
mExec = null;
StartitInfo.debugPrint(appinfo, "---Died---");
// app died on its own
if (appinfo.restart &&
getState() != NOT_RUNNING) { // only restart if it died by itself
StartitInfo.debugPrint(appinfo, "--Auto-restart: Restarting--");
start(); // (not when user killed it)
}
// app died after a "kill"
else {
appinfo.sinfo.appKilled(); // inform StartitInfo whenever an app
// is successfully killed
}
}
public Color getColor() {
return getColor(mState);
}
public String getLabel() {
return getLabel(mState);
}
private synchronized void changeState(int state) {
if (mState == state) return;
mState = state;
for(Iterator i = listeners.iterator(); i.hasNext(); ) {
StatusChangeListener l = (StatusChangeListener) i.next();
l.statusChanged(appinfo, mState);
}
if (state == READY)
appinfo.sinfo.startWaitingApps();
}
public void addOutputFlag(AppInfo.OutputFlag flag) {
outputSeen.put(flag, Boolean.FALSE);
}
public boolean hasSeenOutput(AppInfo.OutputFlag flag) {
Boolean tf = (Boolean) outputSeen.get(flag);
if (tf == null) return true;
else return tf.booleanValue();
}
///////////////////////////////////////////
// STATIC METHODS
///////////////////////////////////////////
public static Color getColor(int state) {
switch(state) {
case INITIALIZING:
case WAITING_TO_START:
return Color.yellow;
case READY:
return new Color(0,150,0); // medium green
case KILLING:
case DIED:
return Color.red;
case NONAGENT_RUNNING:
case NONAGENT_WAITING:
return Color.white;
case NONAGENT_DIED:
case NONAGENT_KILLING:
case NONAGENT_WAITING_TO_KILL:
return Color.black;
case WAITING_ON_READY_TO_KILL:
case WAITING_TO_KILL:
return Color.red;
//return new Color(200,150,0); // medium orange
}
// NOT_RUNNING, or anything else (though there shouldn't be)
return StartitColors.gray2;
}
public static String getLabel(int state) {
switch(state) {
case KILLING:
case NONAGENT_KILLING:
return "k";
case WAITING_TO_START:
case NONAGENT_WAITING:
case WAITING_ON_READY_TO_KILL:
case WAITING_TO_KILL:
case NONAGENT_WAITING_TO_KILL:
return "w";
}
// default:
return "";
}
public static String[] getEnvironmentArray() {
return getMergedEnvironmentArray(null);
}
public static String[] getMergedEnvironmentArray(Collection c) {
HashSet keys = new HashSet();
Vector envs = new Vector();
String key, value;
Iterator i;
// first add user's specified environment
if (c != null) {
for (i = c.iterator(); i.hasNext(); ) {
String env = (String) i.next();
String[] keyval = env.split("=", 2);
keys.add(keyval[0]);
envs.add(env);
}
}
// then add the system environment, for each key that wasn't in
// the user's environment
for (i = Environment.get().keySet().iterator(); i.hasNext(); ) {
key = (String) i.next();
value = (String) Environment.get(key);
if(!keys.contains(key)) envs.add(key + "=" + value);
}
// finally, return the Vector as an array of Strings, suitable for
// use in Runtime.exec()
String[] out = new String[envs.size()];
for (int j = 0; j < envs.size(); j++) {
out[j] = (String) envs.get(j);
}
return out;
}
public Vector/*String*/ getStartCommands() {
Vector out = new Vector();
out.add(mLoginInfo.getRemoteCdCommand(mDirectory));
if (appinfo.isFacilitator()) { // facilitator must UN-set OAA_CONNECT
out.add(mLoginInfo.getRemoteSetenvCommand("OAA_CONNECT", ""));
}
else if (isAgentProcess() && oaa.isConnected()) { // other agents must set it
out.add(mLoginInfo.getRemoteSetenvCommand("OAA_CONNECT", getOAAConnectString()));
}
out.add(mLoginInfo.getRemoteLaunchCommand(mCommand));
//out.add(mLoginInfo.getRemoteExitCommand()); // needed for windows 9x
return out;
}
public String getOAAConnectString() {
return oaa.getOAAConnectString(
// if I'm not a fac, and I'm remote, then resolve "localhost" to
// a real name
!appinfo.isFacilitator() && appinfo.shell != LoginInfo.LOCAL
);
}
///////////////////////////////////////////
// NESTED CLASSES
///////////////////////////////////////////
// Private nested class that implements a thread waiting for the started process to die.
class ThreadForExec extends Thread {
Runtime mRt = Runtime.getRuntime();
public Process mProcessToWatch = null;
public ReadOutputProcess mReadOutProcess = null;
public ReadOutputProcess mReadErrorProcess = null;
BufferedWriter mBufferWriter = null;
public ThreadForExec() {}
public synchronized boolean sendCommand(String inCommand) {
if (mProcessToWatch == null || inCommand == null) return false;
try {
StartitInfo.debugPrint(appinfo, "Sending command " + inCommand);
mBufferWriter.write(inCommand+"\n");
mBufferWriter.flush();
return true;
} catch (IOException e1) {
return false;
}
}
public void run() {
// 1: start the shell (local or remote) that will launch the process
// (e.g. "rsh HOST exec sh", or "sh" if local, or "cmd.exe" if windows, etc.)
boolean local = mLoginInfo.getRemoteShellCommand() == mLoginInfo.LOCAL;
boolean hadLocalFailure = false;
// String[] ar = getMergedEnvironmentArray(mEnvironment);
// for(int i=0;i<ar.length;i++) StartitInfo.debugPrint(appinfo, i+") "+ar[i]);
try {
if (local) {
StartitInfo.debugPrint(appinfo, "Local execution");
mProcessToWatch = mRt.exec(mCommand,
getMergedEnvironmentArray(mEnvironment),
new File(mDirectory));
}
else {
StartitInfo.debugPrint(appinfo, "Exec: " + mLoginInfo.getLocalShellCommand());
mProcessToWatch = mRt.exec(mLoginInfo.getLocalShellCommand());
}
}
catch (IOException e) {
if (local) hadLocalFailure = true;
else {
StartitInfo.errorPrint(appinfo, "Couldn't execute command: " + e);
StartitInfo.errorPrint(appinfo, "(This probably means the ssh command (\"ssh\" or \"plink\") is not in your path)");
reportDeath();
}
}
catch (NullPointerException e) {
// can happen if mLoginInfo returns null, in which case it
// should have already printed the error
reportDeath();
}
if (hadLocalFailure) {
try /* try again! */ {
StartitInfo.debugPrint(appinfo, "Local execute failed; prepending appdir and retrying...");
// Bug fix, mDirectory may be a relative path, make it absolute before running.
String absDirectory = (new File(mDirectory)).getAbsolutePath();
mProcessToWatch = mRt.exec(absDirectory + "/" + mCommand,
getMergedEnvironmentArray(mEnvironment),
new File(mDirectory));
}
catch (IOException e) {
StartitInfo.debugPrint(appinfo, "...failed.");
StartitInfo.errorPrint(appinfo, "Couldn't execute command: " + e);
reportDeath();
}
}
if (mProcessToWatch == null) {
StartitInfo.errorPrint(appinfo, "Could not start process");
return;
}
if (hadLocalFailure) StartitInfo.debugPrint(appinfo, "...succeeded.");
// 2: capture the new process' in/out/err streams
try {
// Launch the threads that listen to the output
mBufferWriter = new BufferedWriter(new OutputStreamWriter(mProcessToWatch.getOutputStream()));
mReadOutProcess = new ReadOutputProcess(mProcessToWatch.getInputStream(), false, appinfo.logfile);
mReadErrorProcess = new ReadOutputProcess(mProcessToWatch.getErrorStream(), true, appinfo.logfile);
mReadOutProcess.start();
mReadErrorProcess.start();
// 3: if non-local, send the commands to the shell (cd, env
// vars, and mCommand)
if (!local) {
Vector cmds = getStartCommands();
for(Iterator i = cmds.iterator(); i.hasNext(); ) {
sendCommand((String) i.next());
}
}
// 4: wait for it do die
mProcessToWatch.waitFor();
mReadOutProcess.setDone();
mReadErrorProcess.setDone();
}
catch (InterruptedException e) {
System.out.println("Exception raised during waitFor");
e.printStackTrace();
}
// Invokes parent's callback (Parent has to implement MonListener interface)
reportDeath();
mProcessToWatch = null;
}
}
class ReadOutputProcess extends Thread {
BufferedReader mReader;
boolean mDone;
boolean mIsErr;
PrintStream output;
public ReadOutputProcess(InputStream inStream, boolean isErr) {
mReader = new BufferedReader(new InputStreamReader(inStream));
mDone = false;
mIsErr = isErr;
}
public ReadOutputProcess(InputStream inStream, boolean isErr, String logfile) {
this(inStream, isErr);
if (logfile != null) {
if (logfile.equals("-")) {
output = isErr ? System.err : System.out;
}
else {
try {
output = new PrintStream(new FileOutputStream(new File(logfile), true));
}
catch (FileNotFoundException e) {
appinfo.sinfo.getOutputter().outputLine(appinfo,
"WARNING: can't create logfile: " + logfile,
Outputter.WARNING);
}
}
}
}
public synchronized void setDone() {
mDone = true;
}
public void run() {
String line;
try {
do {
line = mReader.readLine();
if (line != null) {
for (Iterator i = outputSeen.keySet().iterator(); i.hasNext(); ) {
AppInfo.OutputFlag flag = (AppInfo.OutputFlag) i.next();
if (!flag.hasSeenOutput()) {
Matcher m = flag.regexp.matcher(line);
if (m.find()) {
outputSeen.put(flag, Boolean.TRUE);
appinfo.sinfo.startWaitingApps(); // probably shouldn't do that from this thread
}
}
}
if (output != null) {
output.println(line);
output.flush();
}
appinfo.sinfo.getOutputter().outputLine(appinfo, line,
mIsErr ? Outputter.ERROR
: Outputter.INFO);
}
}
while (line != null);
}
catch(IOException e) {
System.err.println("ERROR reading process output: " + e);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -