📄 startitprocess.java
字号:
/**
* The contents of this file are subject to the OAA Community Research
* License Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License
* at http://www.ai.sri.com/~oaa/. Software distributed under the License
* is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific language governing
* rights and limitations under the License. Portions of the software are
* Copyright (c) SRI International, 1999-2003. All rights reserved.
* "OAA" is a registered trademark, and "Open Agent Architecture" is a
* trademark, of SRI International, a California nonprofit public benefit
* corporation.
*/
package com.sri.oaa2.agt.startit;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.lang.String;
import java.awt.Color; // to report status light colors
// NOTE: even if there's no gui, this module needs to be able to report
// info about what color a light should be, in case another agent
// wishes to show its own version of startit lights (the old ptt
// agent did this)
public class StartitProcess {
// AppStates
public static final int NOT_RUNNING = 401;
public static final int INITIALIZING = 402;
public static final int READY = 403;
public static final int KILLING = 404;
public static final int DIED = 405;
public static final int WAITING_TO_START = 406;
public static final int WAITING_ON_READY_TO_KILL = 407;
public static final int WAITING_TO_KILL = 408;
public static final int NONAGENT_RUNNING = 421;
public static final int NONAGENT_KILLING = 422;
public static final int NONAGENT_DIED = 423;
public static final int NONAGENT_WAITING = 424;
public static final int NONAGENT_WAITING_TO_KILL = 425;
private AppInfo appinfo;
private String oaaID;
private OaaConnection oaa; // will stay NULL if my AppInfo is NOT an agent
private final Hashtable/*OutputFlag, Boolean*/ outputSeen = new Hashtable();
private ThreadForExec mExec = null;
private int mState = NOT_RUNNING; // ALWAYS use changeState() to change this field!
private LoginInfo mLoginInfo;
private Vector/*String*/ mEnvironment;
private String mDirectory;
private String mCommand;
private Vector/*StatusChangeListener*/ listeners = new Vector();
private static javax.swing.Timer startDelayTimer;
private static int timerDelay = 0;
public StartitProcess(AppInfo a) {
appinfo = a;
}
public static void setStartTimerDelay(int ms) {
timerDelay = ms;
}
protected void setOaaConnection(OaaConnection o) {
if (oaa != null) return; // only can set it once
oaa = o;
oaa.addStatusListener(new OaaConnection.StatusListener() {
public void agentStatusChanged(String agentName, String status, String oaaID) {
setReady(oaaID);
}
}, appinfo.oaaname);
}
public OaaConnection getOaaConnection() {
return oaa;
}
public void setLoginInfo(LoginInfo l) {
if (!isStarted()) mLoginInfo = l;
}
public void setEnvironment(Vector/*String*/ v) {
if (!isStarted()) mEnvironment = v;
}
public void setDirectory(String d) {
if (!isStarted()) mDirectory = d;
}
public void setCommand(String c) {
if (!isStarted()) mCommand = c;
}
/** Gives information about the state of the monitored process
@return one of the AppState ints, e.g. StartitProcess.READY
*/
public int getState() {
return mState;
}
private void setReady(String id) {
oaaID = id;
if (mState == INITIALIZING) {
changeState(READY);
}
else if (mState == WAITING_ON_READY_TO_KILL) {
mState = READY; // NOTE: change state WITHOUT informing anyone!
kill();
}
else {
System.err.println("WARNING: agent reported ready, but wasn't initializing");
}
}
/** Groups the many getState() outputs into a boolean: busy or not.
@return True if it's running, waiting, dying, etc. False if it's dead or otherwise not running.
*/
public boolean isBusy() {
return isBusy(mState);
}
public boolean isStarted() {
return isStarted(mState);
}
public boolean isWaiting() {
return (mState == WAITING_TO_START || mState == NONAGENT_WAITING);
}
public boolean isWaitingToBeKilled() {
// This method is only for apps waiting for the death of other apps
// (so do *NOT* return true for WAITING_ON_READY_TO_KILL!)
return (mState == WAITING_TO_KILL || mState == NONAGENT_WAITING_TO_KILL);
}
public static boolean isBusy(int state) {
switch (state) {
case NOT_RUNNING:
case DIED:
case NONAGENT_DIED:
return false;
default:
return true;
}
}
public static boolean isStarted(int state) {
switch (state) {
case INITIALIZING:
case READY:
case KILLING:
case WAITING_ON_READY_TO_KILL:
case WAITING_TO_KILL:
case NONAGENT_RUNNING:
case NONAGENT_KILLING:
case NONAGENT_WAITING_TO_KILL:
return true;
default:
return false;
}
}
public boolean isAgentProcess() {
// return appinfo.isAgent() && (oaa != null);
return appinfo.isAgent();
}
public boolean needToWait() {
// if we have a running startDelayTimer, then we needToWait
if (startDelayTimer != null && startDelayTimer.isRunning()) {
return true;
}
// if there are agentsToWaitFor and any of them are not READY, we needToWait
for(Iterator i = appinfo.agentsToWaitFor.iterator(); i.hasNext(); ) {
AppInfo app = (AppInfo) i.next();
if (app.getProcess().getState() != READY) {
StartitInfo.debugPrint(appinfo, "waiting for " + app.appid);
return true;
}
}
// if there is output we're waiting for from some app, which hasn't
// been seen yet, we needToWait
for(Iterator i = appinfo.waitforoutput.iterator(); i.hasNext(); ) {
AppInfo.OutputFlag flag = (AppInfo.OutputFlag) i.next();
if (!flag.hasSeenOutput()) {
StartitInfo.debugPrint(appinfo, "waiting for output from " + flag.appname);
return true;
}
}
// otherwise, no needToWait!
return false;
}
public boolean needToWaitToKill() {
for(Iterator i = appinfo.appsWaitingForMe.iterator(); i.hasNext(); ) {
AppInfo app = (AppInfo) i.next();
if (app.getProcess().isBusy()) {
StartitInfo.debugPrint(appinfo, "waiting for " + app.appid + " to kill");
return true;
}
}
return false;
}
protected void start() { start(false); }
/** Starts the process to monitor.
Call getState() after requesting a start to find out if it was started, is waiting, etc.
*/
protected void start(boolean forceNoWait) {
if (isStarted()) {return;}
if (!forceNoWait && needToWait()) {
changeState(isAgentProcess() ? WAITING_TO_START : NONAGENT_WAITING);
return;
}
// if we've made it here we're ready to start
// first reset and start the delay timer
if (timerDelay > 0) {
startDelayTimer = new javax.swing.Timer(timerDelay,
new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
startDelayTimer.stop();
appinfo.sinfo.startWaitingApps();
}
});
startDelayTimer.start();
}
// then start
appinfo.updateToStart();
mExec = new ThreadForExec();
try {
//System.out.println("Before mExec.start");
changeState(isAgentProcess() ? INITIALIZING : NONAGENT_RUNNING);
if (appinfo.isFacilitator() && !oaa.isConnected()) {
oaa.pollToConnect(appinfo.getHost(), appinfo.port,
new OaaConnection.ConnectListener() {
public void oaaConnected() {
oaaID = "root";
changeState(READY);
}
});
}
mExec.start();
}
catch (IllegalThreadStateException startException) {
changeState(isAgentProcess() ? DIED : NONAGENT_DIED);
System.out.println("Start exception " + startException);
}
}
/** Stops the process to monitor
Call getState() after requesting a stop to find out if it was killed.
*/
public void kill() {
switch(mState) {
case READY:
case WAITING_TO_KILL:
if (needToWaitToKill()) {
changeState(WAITING_TO_KILL);
return;
}
changeState(KILLING);
oaa.sendHalt(oaaID);
return;
case INITIALIZING:
// if windows, we can't kill a process, so wait til it connects
// then tell it to die
/*
if (isWindows()) {
changeState(WAITING_ON_READY_TO_KILL);
return;
}
*/
// otherwise, fall through to here to kill it:
case NONAGENT_WAITING_TO_KILL:
case NONAGENT_RUNNING:
if (needToWaitToKill()) {
changeState(isAgentProcess() ? WAITING_TO_KILL : NONAGENT_WAITING_TO_KILL);
return;
}
changeState(isAgentProcess() ? KILLING : NONAGENT_KILLING);
killProcess();
return;
case WAITING_TO_START:
case NONAGENT_WAITING:
reportDeath();
case DIED:
case NONAGENT_DIED:
changeState(NOT_RUNNING);
return;
}
}
private void killProcess() {
try {
if ((mExec != null) && (mExec.mProcessToWatch != null)) {
mExec.mProcessToWatch.destroy();
}
mExec = null;
}
catch (IllegalThreadStateException stopException) {
System.out.println("Stop exception " + stopException);
}
}
public void addStatusChangeListener(StatusChangeListener l) {
listeners.add(l);
}
public void removeStatusChangeListener(StatusChangeListener l) {
listeners.remove(l);
}
private synchronized void reportDeath() {
if (mState == KILLING || mState == NONAGENT_KILLING ||
mState == WAITING_TO_KILL || mState == NONAGENT_WAITING_TO_KILL ||
mState == WAITING_ON_READY_TO_KILL) {
changeState(NOT_RUNNING);
}
else {
changeState(isAgentProcess() ? DIED : NONAGENT_DIED);
}
// reset hasSeenOutput for all flags to false
for (Iterator i = outputSeen.keySet().iterator(); i.hasNext(); ) {
outputSeen.put(i.next(), Boolean.FALSE);
}
if (appinfo.isFacilitator()) {
// in case we were polling, it was initializing, and it died
oaa.stopPolling();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -