📄 libcom.java
字号:
/*
* @(#)LibCom.java 08/1999
*
* 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. All rights reserved.
* "OAA" is a registered trademark, and "Open Agent Architecture" is a
* trademark, of SRI International, a California nonprofit public benefit
* corporation.
*/
/*
* file: LibCom.java
* purpose: Connection functions for OAA V2.0
*
* Copyright (C) 1998, SRI International. All rights reserved.
*/
package com.sri.oaa2.com;
import java.util.*;
import java.lang.String;
import com.sri.oaa2.icl.*;
import com.sri.oaa2.lib.LibOaa;
import com.sri.oaa2.simplefac.ConnectionId;
import edu.emory.mathcs.backport.java.util.concurrent.ArrayBlockingQueue;
import org.apache.log4j.Logger;
/**
* Provides communications methods for the agentlib
*/
public class LibCom implements LibComClient, LibComServerListener, LibComListener {
// Number of incoming terms that we allow to accumulate before refusing
// to accept any more.
public static final int MAXBACKLOG = 64;
// DEBUG : Should be private
public IclDb commdb;
// Used for the synchronization between the application
// and the socket server.
// By checking this variable, the application
// (through a LibOaa object) knows if it
// was set free from a Wait call because the TimeOut
// occured or the nofify() was called by the server.
// See waitForIncomingMessage method.
boolean timeOutFlag;
// Contains the latest term received as a string.
String latestMessage[] = new String[2];
// Stores connections using their names as keys.
Hashtable connectionsTable = new Hashtable();
// Buffers accumulate the IclTerm objects received for each connection.
HashMap connectionsBuffersTable = new HashMap();
// Lock table for connections buffers
HashMap connectionsBuffersLocks = new HashMap();
// Stores the protocols using their names as keys.
Hashtable mProtocolTable = new Hashtable();
private LibComInterface mListener;
protected String[] mCmdLine;
// Initialize the library
static {LibOaa.libInit();}
/**
* Constructor
*/
public LibCom(LibComProtocol inProtocol, String[] inCmdLine) {
commdb= new IclDb();
mCmdLine = inCmdLine;
mProtocolTable.put(inProtocol.getProtocolName(), inProtocol);
}
public void comAddProtocol(LibComProtocol inProtocol) {
mProtocolTable.put(inProtocol.getProtocolName(), inProtocol);
}
/**
* Connect a client agent to the Facilitator found at Address. Assign the value
* of ConnectionId as the name for this connection which is used to reference
* it in subsequent operations such as oaaDisconnect and comGetInfo.
* <p>
* For successful connections, comConnect() adds a new entry to a database
* maintained by LibCom, also called the InfoList. LibCom uses this database for
* managing the the set of connections, and for Java, a corresponding set of execution
* threads (one per connection). The database contains a key which identifies the
* connection (ConnectionId), a list of ICL Terms that describe the connection
* (e.g., status(connected), connection(8)), and a pointer to a buffer which
* is used for storing data received from the Facilitator for the client.
* <p>
* A client agent may connect to only one Facilitator. The value for connectionId must
* be 'parent' or "parent" for the Prolog and Java implementations respectively.
* Future releases will support connections to multiple facilitators by a single client.
* <p>
* @param connectionId a Prolog ICL atom or Java String that specifies the name of
* the Facilitator connection.
* @param params a list of IclTerms. THe only param used is "other_address". If
* "other_address" is defined, it is used as "other_address" in the
* connection_info.
* @param address may be either an explicit connection address for a Facilitator
* or an uninitialized variable. The latter is most commonly used.
* Examples include tcp("test.ai.sri.com", "7576") and tcp(Host, Port).
* @return returns true if the connection attempt was successful and false otherwise.
* <pre>
* Use of an uninitialized variable for Address cues comConnect to determine the host
* and port according to the following order of priority:
*
* Highest: retrieve host and port from command line arguments
* -oaa_connect tcp(Host,Port)
* Example:
* -oaa_connect "tcp('test.ai.sri.com', 7576)"
* Next: retrieve this information from the environment variables OAA_CONNECT.
* Lowest: use information found in the configuration file setup.pl. Entries must be of the form
* default_facilitator(tcp(Host,PortNumber)).
* For example
* default_facilitator(tcp('test.ai.sri.com', 7576)).
*
* comConnect() locates setup.pl by first looking in the local directory, then if not found,
* looks in the user's home directory.
*
* Example:
* // First, connect to the facilitator
* if (!oaa.getComLib().comConnect("parent", IclTerm.fromString(true, "tcp(Host,Port)"))){
* printError("Could not connect");
* return;
* }
* </pre>
* @see com.sri.oaa2.lib.LibOaa#oaaRegister
* @see com.sri.oaa2.lib.LibOaa#oaaRegisterCallback
* @see com.sri.oaa2.lib.LibOaa#oaaMainLoop
* @see com.sri.oaa2.lib.LibOaa#oaaDisconnect
* @see #comDisconnect
*/
public boolean comConnect(String connectionId, IclTerm address, IclList params) {
// Creates a generic address term for unification, tcp(Host,Port)
LibComProtocol newProtocol = (LibComProtocol)mProtocolTable.get(address.toIdentifyingString());
if (newProtocol == null)
return false;
LibComConnection newConnection = newProtocol.prot_getConnection(this, connectionId, mCmdLine);
if (newConnection.cnx_Connect(address, params)) {
newConnection.setLibComListener(this);
return comSetConnectData(newConnection, connectionId, address, params);
}
return false;
}
public void notifyConnectionEstablished(LibComConnection newConnection, String connectionId,
IclTerm address, IclList params) {
comSetConnectData(newConnection, connectionId, address, params);
}
boolean comSetConnectData(LibComConnection newConnection, String connectionId,
IclTerm address, IclList params) {
connectionsTable.put(connectionId, newConnection);
synchronized(this) {
connectionsBuffersTable.put(connectionId, new ArrayBlockingQueue(MAXBACKLOG));
connectionsBuffersLocks.put(connectionId, new ComSem(1));
this.connectionIds = (String[])connectionsBuffersTable.keySet().toArray(this.connectionIds);
}
IclTerm info;
// DEBUG
// System.out.println("address --> " + address);
IclTerm canonicalAddress = newConnection.cnx_CanonicalAddress(address);
IclTerm primary = IclUtils.getParamValue("other_address", null, params);
IclTerm formalActualAddress = newConnection.getClientAddress();
if (primary == null) {
primary = formalActualAddress;
}
// DEBUG
// System.out.println("canonicalAddress --> " + canonicalAddress);
//ComPrintInfo("Connection ok");
StringBuffer infoString = new StringBuffer();
infoString.append("com_connection_info('");
infoString.append(connectionId);
infoString.append("',");
infoString.append(address.toIdentifyingString());
infoString.append(", client, [other_address(");
infoString.append(canonicalAddress);
infoString.append("), other_address(");
infoString.append(primary);
infoString.append("), connect_address(");
infoString.append(formalActualAddress);
infoString.append("), connection(0)], connected)");
info = IclTerm.fromString(true, infoString.toString());
if (info != null) {
commdb.db_Assert(info, new IclList());
//ComPrintDB("On Connect");
}
else
ComPrintError("Comm info could not be constructed");
return true;
}
/**
* Shut down the connection between client agent and Facilitator as named by ConnectionId.
* <p>
* comDisconnect() immediatly disconnects the client-Facilitator connection with no delays
* (e.g., remaining data on the connection is discarded) and removes the entry corresponding
* to ConnectionId from the LibCom database. For the Java implementation, comDisconnect()
* also kills the thread of execution associated with this connection.
* <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 a Java String that specifies the name of the Facilitator connection.
* At present, the value must "parent" for the Java implementation.
* @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 returns true if the disconnection attempt was successful and false otherwise.
* @see #comConnect
* @see com.sri.oaa2.lib.LibOaa#oaaDisconnect
*/
public boolean comDisconnect(String connectionId, IclList params) {
synchronized(this) {
this.connectionsBuffersTable.remove(connectionId);
this.connectionsBuffersLocks.remove(connectionId);
this.connectionIds = (String[])this.connectionsBuffersTable.keySet().toArray(this.connectionIds);
notify();
}
IclUtils.debugPrint("*** DISCONNECT");
// Gets the socket from the table
LibComConnection currentConnection = (LibComConnection)(connectionsTable.remove(connectionId));
if (currentConnection==null)
IclUtils.debugPrint("CONNECTION NULL !!!");
if ((connectionId != null) && (currentConnection != null)) {
String retractInfo = "com_connection_info('" + connectionId +
"',_,client,_Info,connected)";
currentConnection.setLibComListener(null);
currentConnection.cnx_Disconnect();
IclTerm t = null;
t = IclTerm.fromString(true, retractInfo);
commdb.db_Retract(t,
new IclList());
return true;
}
return false;
}
/**
* Given a connection ID and an address, initiate a server connection.
* remarks:
* - if Address is a variable, instantiates the Address by using
* oaa_ResolveVariables, which looks in a setup file, command line, and
* environment variables for the required info.
* - stores the connection info for connection ID in com_connection_info/5.
* - fails if connection can't be made
*/
public boolean comListenAt(String connectionId, IclTerm params, IclTerm address) {
boolean ret = false;
LibComProtocol newProtocol = (LibComProtocol)mProtocolTable.get(
address.toIdentifyingString());
if (newProtocol != null) {
LibComConnection newConnection = newProtocol.prot_getConnection(this,
connectionId, mCmdLine);
newConnection.setLibComServerListener(this);
if (newConnection.cnx_ListenAt(address, params)) {
connectionsTable.put(connectionId, newConnection);
IclTerm listenAddress = newConnection.getListenAddress();
IclTerm server = listenAddress.getTerm(0);
IclTerm port = listenAddress.getTerm(1);
StringBuffer infoString = new StringBuffer();
infoString.append("com_connection_info('");
infoString.append(connectionId);
infoString.append("', ");
infoString.append(address.toIdentifyingString());
infoString.append(", server, [oaa_address(addr(tcp('");
infoString.append(server.toIdentifyingString());
infoString.append("',");
infoString.append(port.toIdentifyingString());
infoString.append(")))], connected)");
IclTerm info = IclTerm.fromString(true, infoString.toString());
if (info != null) {
ret = commdb.db_Assert(info, new IclList());
} else {
ComPrintError("Comm info could not be constructed");
}
}
}
return ret;
}
public boolean comSendData(String connectionId, IclTerm t)
{
LibComConnection currentConnection = (LibComConnection)(connectionsTable.get(connectionId));
if (currentConnection==null) {
IclUtils.debugPrint("CONNECTION NULL !!!");
return false;
}
if((connectionId != null) && (currentConnection != null)) {
return currentConnection.cnx_sendMsgFormatWriter(t);
}
return false;
}
/**
* Find and return information associated with Info stored in the client database for the
* connection named ConnectionId.
* <p>
* @param ConnectionId a Java String that specifies the name of the Facilitator connection.
* @param Info a Java String which contains one or more elements to look-up in the list of
* data for the client. Possible values of Info to search for include status(S),
* type(T), protocol(P), or others defined by the client. Placeholder values such
* 'S,' 'T,' and 'P' are ignored and real values are returned in an ICL Term.
* @return null if connectionId is invalid or if Info is not found in the dataset.
* Otherwise, it returns an IclTerm instance containing the result(s).
* @see #comAddInfo
*/
public IclTerm comGetInfo(String connectionId, IclTerm infoIn) {
IclTerm result = null;
IclList resultFromDb = new IclList();
IclTerm info = null;
// DEBUG
// ComPrintDB("On Get info");
// Make sure there's a valid connection id
if (connectionId == null)
return null;
StringBuffer cmdBuf = new StringBuffer("com_connection_info('");
cmdBuf.append(connectionId.toString());
cmdBuf.append("',Protocol,Type,InfoList,Status)");
info = IclTermCache.getNoAnon(cmdBuf.toString());
// DEBUG
//System.out.println("info " + info);
if (commdb.db_Solve(info, new IclList(), resultFromDb)) {
IclTerm item;
// DEBUG
//System.out.println("result " + resultFromDb);
item = resultFromDb.getTerm(0);
if (Unifier.getInstance().unify(new IclStruct("protocol", new IclVar("_")),
infoIn)!=null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -