📄 liboaa.java
字号:
setName(this.oaaThreadName);
mLibCom = inLibCom;
mAwaitedEvents = new CAwaitedEventsVector(this);
// Starts the main thread that listens to incoming messages.
// This is poor style--shouldn't call non-private methods from
// the constructor--possible breakage for subclasses
this.start();
}
/**
* Returns the communications library defined at startup in the constructor.
* <p>
* @return the communications library defined at startup in the constructor
*/
public final LibCom getComLib() {
return mLibCom;
}
/**
* Establishes default communications connections for a client agent.
*
* <p>
* Remarks:
* <ul>
* <li>If oaa_listen argument is given, opens a listener socket, so the client
* can handle requests by direct connection.</li>
* <li>IAttempts to connect to facilitator at address indicated by oaa_connect
* or default_facilitator parameter in command line, environment
* variable, or setup file (see com_Connect, in com_tcp.pl).</li>
* <li>Icom_Connect (which see) provides some retry options.</li>
* <li>IFAILS if connection to the facilitator cannot be established, and
* prints a simple error message.</li>
* <li>IAfter performing local initializations, and calling this procedure,
* the default client agent should also call oaa_MainLoop(true).</li>
* </ul>
* </p>
*
* @param initialAgentName the agent name
* @return <code>true</code> if successful, <code>false</code> otherwise
*/
public boolean oaaSetupCommunication(String initialAgentName) {
IclTerm oaaListen = LibComUtils.oaaResolveVariable("oaa_listen",
mLibCom.getCmdLine());
boolean ret = false;
boolean listening = false;
if (oaaListen != null) {
// Set up listen connection
if (mLibCom.comListenAt("client_listener",
new IclList(resolveFalseTerm), oaaListen)) {
logger.info("Listening at " + oaaListen);
listening = true;
} else {
logger.error("Unable to open a listener connection for " +
oaaListen + "; continuing without it.");
}
}
// Connect to the OAA facilitator
if (oaaConnect("parent", _Address, initialAgentName, new IclList())) {
ret = true;
} else {
logger.error("Unable to connect to facilitator");
if (listening) {
logger.error("Closing listener at " + oaaListen);
oaaDisconnect("client_listener", new IclList());
}
}
return ret;
}
private static Object oaaConnectLock = new Object();
/**
* Connect and handshake with the agent listening on Address,
* or, if Address is a var, allow com_Connect to find
* the address.
*
* @param connectionID the connection id to use
* @param address the address in icl to connect to
* @param initialAgentName the name of the agent
* @param params parameters to use when connecting
* @return <code>true</code> if the connection was successful and
* <code>false</code> if an error occurred.
*/
public boolean oaaConnect(String connectionID, IclTerm address,
String initialAgentName, IclList params) {
synchronized(oaaConnectLock) {
boolean ret = mLibCom.comConnect(connectionID, address, params);
if (ret) {
logger.info("Connected to " + address);
ret = oaaHandshake(connectionID, initialAgentName, params);
}
return ret;
}
}
/**
* Disconnect the connection between client agent and Facilitator at ConnectionId.
* <p>
* It is strongly suggested that oaaDisconnect be called directly rather than
* comDisconnect as the former performs other client clean-up activities necessary
* for proper shutdown of a connection.
* <p>
* @param connectionId the Java String that specifies the name of the Facilitator connection.
* @param params a list of IclTerms which indicate options for performing the disconnection.
* At present, only one parameter is recognized, TBD. It signals to the
* Facilitator that the client is temporarily disconnecting (e.g., robot
* out of range, or PDA temporarily off line). Future service requests received
* by the Facilitator for the disconnected client will be queued by the
* Facilitator and delivered upon reconnection.
* @return true if the connection exists and was disconnected, and false otherwise.
* @see LibCom#comDisconnect
* @see LibCom#comConnect
*/
public final boolean oaaDisconnect(String connectionId, IclList params) {
disconnect = true;
boolean ret = mLibCom.comDisconnect( connectionId, params);
return ret;
}
/**
* Disconnect all connections between client agent and Facilitator. All
* direct_connect connections are also disconnected.
* <p>
* It is strongly suggested that oaaDisconnect be called directly rather than
* comDisconnect as the former performs other client clean-up activities necessary
* for proper shutdown of a connection.
* <p>
* @param params a list of IclTerms which indicate options for performing the disconnection.
* At present, only one parameter is recognized, TBD. It signals to the
* Facilitator that the client is temporarily disconnecting (e.g., robot
* out of range, or PDA temporarily off line). Future service requests received
* by the Facilitator for the disconnected client will be queued by the
* Facilitator and delivered upon reconnection.
* @return true if any connections were disconnected, and false if
* no connections were disconnected or an error occurred.
* @see LibCom#comDisconnect
* @see LibCom#comConnect
*/
public final boolean oaaDisconnect(IclList params) {
disconnect = true;
boolean success = true;
IclList connections = mLibCom.getAllValidConnections();
for (int i = 0; i < connections.size(); i++) {
String connectionId = connections.getTerm(i).toIdentifyingString();
boolean shutDown = mLibCom.comDisconnect(connectionId, params);
if (!shutDown) {
logger.error("Failed to shut down connection " + connectionId);
}
success = success && shutDown;
}
return success;
}
/**
* Consistent handshaking code for oaaConnect and oaaRegister.
*/
final boolean oaaHandshake(String connectionId, String agentName,
IclList params) {
IclTerm tempTerm = null;
boolean isClient = true;
int myId = -1;
// Make sure there's a valid connection
if ((connectionId == null) ||
(mLibCom.comGetInfo(connectionId,
IclTermCache.getNoAnon("status(connected)")) == null)) {
return false;
}
// Determine whether connection is server or client type
tempTerm =
mLibCom.comGetInfo(connectionId, IclTermCache.getNoAnon("type(T)"));
if (tempTerm != null) {
isClient = ((tempTerm.toIdentifyingString()).equals("client"));
} else {
return false;
}
/* Uses the command line info to figure out wether the
agent's name should be changed
*/
try
{
IclTerm agent_name_cmdline = LibComUtils.oaaResolveVariable("oaa_name", mLibCom.getCmdLine());
if (agent_name_cmdline != null) {
agentName = agent_name_cmdline.toString();
}
}
catch(SecurityException e)
{
logger.info("The security manager does not allow setting the agent's name. Agent's name remains "+agentName+".");
}
tempTerm = new IclStruct("oaa_name", new IclStr(agentName));
mLibCom.comAddInfo(connectionId, tempTerm);
// DEBUG
// mLibCom.ComPrintDB("First addInfo");
if (isClient) { // CLIENT AGENT
// handshaking with Facilitator -- exchange information...
// note: for this first communication, no format is defined for the
// connection, so it will be sent using default (ascii) format.
// Information coming back from Facilitator will update the
// format() field for the connection, possibly improving future
// communication (if the comm library support it -- libcom_tcp doesn't.
// (c), (pure_text)
// list elements are written as other_*, because they will be
// installed on the fac's end of the connection
boolean usingPassword = false;
IclTerm usePassword = LibComUtils.oaaResolveVariable("use_password", mLibCom.getCmdLine());
if(usePassword != null) {
usingPassword = ((IclStr)usePassword).equals(new IclStr("true"));
}
String tempString;
if(usingPassword) {
String password = "X";
IclTerm clientPassword = LibComUtils.oaaResolveVariable("client_password", mLibCom.getCmdLine());
if(clientPassword != null) {
password = clientPassword.toString();
if(password.trim().equals("")) {
password = "X";
}
}
tempString =
"ev_connect([other_name('" + agentName + "')," +
"other_language(" + oaa_library_language + ")," +
"other_type(client)," +
"other_version(" + oaa_library_version + ")," +
"password(" + password + ")" +
"])";
}
else {
tempString =
"ev_connect([other_name('" + agentName + "')," +
"other_language(" + oaa_library_language + ")," +
"other_type(client)," +
"other_version(" + oaa_library_version + ")])";
}
IclTerm connectionRequest = IclTerm.fromString(true, tempString);
IclTerm firstMessageFromFac;
firstMessageFromFac = IclTermCache.getNoAnon("ev_connected(FacInfoList)");
IclList waitParams = new IclList(new IclStruct("connection_id", new IclStr(connectionId)));
IclTerm results = post_and_poll_until_event(connectionRequest,
firstMessageFromFac, waitParams);
if((results != null) &&
results.getTerm(0).isStruct()) {
IclStruct resStruct = (IclStruct)results.getTerm(0);
if(resStruct.getFunctor().toString().equals("exception")) {
logger.error("Exception in connection: " + resStruct.getTerm(0).toString());
return false;
}
}
/*XXXXXXXXXX */
if (results != null) {
IclTerm newParams = results.getTerm(0);
mLibCom.comAddInfo(connectionId, newParams);
// DEBUG
// mLibCom.ComPrintDB("Second addInfo");
oaa_call_callback("app_init", null, null, null);
this.runLatch.countDown();
} else {
/* XXXXXXX */
return false;
}
} else { //server, Facilitator
// Add the agent's name and ID to the connection info
// For a client agent, this is done through handshaking with the
// facilitator.
tempTerm = new IclStruct("oaa_name", new IclStr(agentName));
mLibCom.comAddInfo(connectionId, tempTerm);
// A Facilitator's ID is always 0
myId = 0;
tempTerm = new IclStruct("oaa_id", new IclInt(myId));
mLibCom.comAddInfo(connectionId, tempTerm);
// I didn't do anything about the following comment. If we ever
// have a Facilitator written in Java, this might cause a problem
// and should be looked into...
// The fac. records its own agent_data in the same way as its clients'.
// Note that we can't call oaa_add_data_local until after the solvables
// have been declared, and we can't declare solvables until we're
// open - so we have to bootstrap this assertion:
// oaa_assertz(agent_data(AgentId, open, [], AgentName), AgentId)
}
return true;
}
/**
* Registers a client's name and capabilities declarations (solvables) with the Facilitator
* found at ConnectionId. This step is to be performed after a client agent successfully
* connects to a Facilitator agent using comConnect().
* <p>
* The actions described below provide a view of how oaaRegister() is implemented;
* these are NOT actions for a client agent to perform separately.
* <p>
* The registration process involves handshaking (i.e., an exchange of messages) between
* the client and Facilitator. The client sends a message containing its name, OAA library
* version, and implementation language. The Facilitator returns information about itself including:
* <pre>
*
* Facilitator name: symbolic name of the Facilitator
* OAA version: version number of the agent library used to construct the facilitator
* Language: facilitator's implementation language
* Client local id: a numeric identifier for this client assigned by the Facilitator
* Facilitator local id: a numerid identifier for the Facilitator to be used by this client
* </pre>
* The client agent then provides its hostname (as retrieved from environment variable 'HOST')
* to the Facilitator using oaaAddData(). As the last step in the registration process, the
* client declares its solvables to the Facilitator using oaaDeclare().
* <p>
* @param connectionId a Java String that specifies the name of the Facilitator connection
* ('parent' for the Prolog implementation and "parent" for Java implementation).
* @param agentName a symbolic name representing the agent, e.g., 'email'.
* @param solvables a list of capabilities or data definitions (solvables ) for this client.
* For example, [send(email,ToWhom,Params)].
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -