public class CommPeer {
public static boolean DEBUG = false;
/** Accessor to the communicator */
public Communicator getCommunicator () {return comm;}
//---------------------------------------------------------------------------
// Call this to turn off Communicator and KQMLMessage specific debug
// messages.
//---------------------------------------------------------------------------
public void setDebugFlags () {
//---------------------------------------------------------------------------
// Detects the hostname for the program, sets HOST to it, and returns it to
// the caller.
//---------------------------------------------------------------------------
public static String detectHost () {
//---------------------------------------------------------------------------
// Instantiate Instance ID
//
// Make an instance of the ID string which will uniquely identify this to the
// the ANS.
// Note:
// 1. Do not use colons as delimiters since "Connection.sendMsg" uses them
// to identify a field name.
// 2. Do not use periods (".") in agent names, as the ANS parses that which
// is to the right as a domain name.
// Hostname precedence:
// First, use what was specified with the "-Dhost=" argument to "java".
// Example: java -Dhost=pleiades AirResourceMgr &
// Example: java -Dhost=$HOST AirResourceMgr &
// Second, try to determine the hostname automatically. Rumor has it that
// for some systems this will return "localhost" instead of the real
// internet hostname, but that has yet to be verified.
// Third, if unable to determine hostname from InetAddress, use the
// default, which should be "localhost".
//
// This version allows the caller to reuse the same "creation_time" so as to
// identify thread descendants.
//
// instance_count: A short number which identifies the application thread.
// If this class is single-threaded, this value should remain 0.
//---------------------------------------------------------------------------
public static String makeInstanceID (String appl_prefix, long creation_time,
short instance_count) {
//---------------------------------------------------------------------------
// A version of makeInstanceID that generates a unique timestamp for every
// call.
//---------------------------------------------------------------------------
public static String makeInstanceID (String appl_prefix, short inst_count) {
//---------------------------------------------------------------------------
// The Main CommPeer Constructor Method
//
// This method should be modified to throw an exception. For now just return
// "null" instead.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID, int preferred_port,
String agentInfo, MsgLogInterface logFacilityList[],
String ANShost, Integer ANSport) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that lets the caller specify its host,
// caller_ID, and port. It does not allow for the specification of
// ANS information.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID, int preferred_port,
String agentInfo, MsgLogInterface logFacilityList[]) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that lets the caller specify its host,
// caller_ID, and port. It does not allow for the specification of a message
// log facility.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID, int preferred_port,
String ANShost, Integer ANSport) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that lets the caller specify its host,
// caller_ID, and port. It does not allow for the specification of a message
// log facility.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID, int preferred_port,
String ANShost, Integer ANSport) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that lets the caller specify its host,
// caller_ID, and port. It does not allow for the specification of a message
// log facility, or ANS information.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID, int preferred_port) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that lets the Communicator assign the
// port by default. It does not allow for the specification of a message log
// facility.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID,
String ANShost, Integer ANSport) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that lets the Communicator assign the
// port by default. It does not allow for the specification of a message log
// facility or ANS information.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that lets the Communicator assign the
// caller_host and the port by default. It does not allow for the
// specification of a message log facility.
//---------------------------------------------------------------------------
public CommPeer (String caller_ID, String ANShost, Integer ANSport) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that lets the Communicator assign the
// caller_host and the port by default. It does not allow for the
// specification of a message log facility, or ANS information.
//---------------------------------------------------------------------------
public CommPeer (String caller_ID) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that assigns a port by default and
// permits the caller to specify a message log facility.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID, String agentInfo,
MsgLogInterface logFacilityList[],
String ANShost, Integer ANSport) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that assigns a port by default and
// permits the caller to specify a message log facility, or ANS information.
//---------------------------------------------------------------------------
public CommPeer (String caller_host, String caller_ID, String agentInfo,
MsgLogInterface logFacilityList[]) {
this (caller_host, caller_ID, DEFAULT_PORT, agentInfo, logFacilityList,
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that assigns the caller_host and the
// port by default, and permits the caller to specify a message log facility.
//---------------------------------------------------------------------------
public CommPeer (String caller_ID, String agentInfo,
MsgLogInterface logFacilityList[],
String ANShost, Integer ANSport) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that assigns the caller_host and the
// port by default, and permits the caller to specify a message log facility,
// or ANS information.
//---------------------------------------------------------------------------
public CommPeer (String caller_ID, String agentInfo,
MsgLogInterface logFacilityList[]) {
//---------------------------------------------------------------------------
// CommPeer Constructor
//
// A variant of the main constructor that is used when the communicator
// is available. For instance, the communicator is available to the
// code of the actions of retsina agents. This constructor allows
// CommPeer to be used by those actions.
//---------------------------------------------------------------------------
public CommPeer (Communicator comm) {
//---------------------------------------------------------------------------
// Attempt to return the ConnectionDescriptor identified by "agentName".
// Will return 'null' if the ConnectionDescriptor cannot be found.
//---------------------------------------------------------------------------
public ConnectionDescriptor getCD (String agentName) {
//==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==.
// Message Passing Methods
//==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==.
//---------------------------------------------------------------------------
// Send Message To (, )
//
// Example: CommPeer.Send_Msg_To ("caps", capsMsg);
// agent:
// The same name specified by ":AgentName" in the agent's ".config" file.
// message:
// The message to be sent to the agent, in string format, similar to the
// examples declared in the ".ob.gin" file for that agent.
// N.B.: it may be advantageous to prepare this string with
// "makeKQMLMsgContentString()".
//
//---------------------------------------------------------------------------
public void Send_Msg_To (String agentName, String message) {
/** send message to the agent named agentName, on a specific connection
* @param agentName the name of the receiver
* @param message the message sent
* @param tempCD the connection descriptor that specifies the connection to use
*/
public void Send_Msg_To (String agentName, String message,
ConnectionDescriptor tempCD) {
//---------------------------------------------------------------------------
// Send Message To (, , , ,
// , , )
//
// Example: CommPeer.Send_Msg_To ("caps", capsMsg, KQMLmessage.REPLY_KEY);
//
// Note, we use misc.KQMLParser.UtilMsgMethods.createInternKQMLMsg
// to build the message to send. Thus is some args are null, they
// will be filled in by that method with appropriate defaults.
//
// agent:
// The same name specified by ":AgentName" in the agent's ".config" file.
// message:
// The message to be sent to the agent, in string format, similar to the
// examples declared in the ".ob.gin" file for that agent.
// N.B.: it may be advantageous to prepare this string with
// "makeKQMLMsgContentString()".
// performative:
// Any legal performative. For best and safe results, use those defined
// by "KQMLmessage". (4/13/2000 SRO - I couldn't find any KQMLmessage class
// that listed performatives. Perhaps meant the performatives listed in
// softagents.misc.KQMLParser.UtilMsgMethods.)
// ontology:
// Ontology of the message, i.e. default-ontology, matchmaker, etc.
// language:
// language of the message, i.e. gin_v0.01, simple-query, etc.
// replyTo:
// the reply-with field of the message we are replying to, if any.
// replyWith:
// the tag we wish the receiver to use in 'replyTo' to respond to this
// message.
//
//---------------------------------------------------------------------------
public void Send_Msg_To (String agentName, String message, String perf, String ontology, String language, String replyTo, String replyWith) {
//---------------------------------------------------------------------------
// Send Message To (, , )
//
// Example: CommPeer.Send_Msg_To ("caps", capsMsg, KQMLmessage.REPLY_KEY);
//
// agent:
// The same name specified by ":AgentName" in the agent's ".config" file.
// message:
// The message to be sent to the agent, in string format, similar to the
// examples declared in the ".ob.gin" file for that agent.
// N.B.: it may be advantageous to prepare this string with
// "makeKQMLMsgContentString()".
// performative:
// Any legal performative. For best and safe results, use those defined
// by "KQMLmessage".
//---------------------------------------------------------------------------
public void Send_Msg_To (String agentName, String message, String perf) {
//---------------------------------------------------------------------------
// Use this method if you already prepared your own instance of
// InternalKQMLmessage.
//---------------------------------------------------------------------------
public void Send_Msg_To (String agentName, InternalKQMLmessage ikm) {
//---------------------------------------------------------------------------
// Get_Reply_From (agentName, ikm_p)
//
// agentName:
// The name of the agent from which you would like to receive a reply.
//
// ikm_p:
// A dummy argument used to work-around the Java compiler restriction that
// you cannot have same-name methods with the same number of arguments
// return different data types. If they have a different number of
// arguments, then they may return different data types.
//
// Use this method ONLY if you have already initiated a connection to
// "agentName" via "Send_Msg_To()".
//---------------------------------------------------------------------------
public InternalKQMLmessage Get_Reply_From (String agentName, boolean ikm_p) {
//---------------------------------------------------------------------------
// Get_Reply_From (agentName)
//
// agentName:
// The same name specified by ":AgentName" in the agent's ".config" file.
//
// Use this method ONLY if you have already initiated a connection to
// "agentName" via "Send_Msg_To()".
//---------------------------------------------------------------------------
public String Get_Reply_From (String agentName) {
//==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==.
// Server Mode Methods
//
// The the application using CommPeer sits and waits for somebody to send a
// message to it, then it is using CommPeer in "Server Mode".
//
// In this section there are four Server Mode methods. Two of them,
// "blockUntilActivated()", were implemented for the side-effect of having an
// application block until somebody sends a message to it. See their
// comments for more details.
// The other two ... were implemented for having an outside application
// initiate the communication and for the communication between the two peers
// to continue.
//==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==.
//---------------------------------------------------------------------------
// Motivation: Marios Savvid's MoDSAFMapRecognizer would like to block its
// load action until he receives a message from an enabling program. He does
// not care what the message it, all he is concerned about is the blocking
// behavior as a means of remotely controlling thread execution.
// This method implements such behavior.
// There is no need to establish a connection with a remote agent. This
// method will unblock for any message sent to this client.
//---------------------------------------------------------------------------
public void blockUntilActivated () {
//---------------------------------------------------------------------------
// A version of "blockUntilActivated()" that returns "msg" to its caller as a
// confirmation.
//---------------------------------------------------------------------------
public void blockUntilActivated (String msg) {
//---------------------------------------------------------------------------
// Block and wait for a connection. Once received, discover who initiated
// it, add the ConnectionDescriptor to the CD_Table, and return the string
// identifying the remote client. "closeConnection()" may be called on this
// new ConnectionDescriptor, but that connection will not be closed since
// the CommPeer in Server Mode does not own it.
//
// If the remote entity initiates multiple connections on different ports (as
// KQMLMessageSenderGUI does), there are two possible actions:
// 1. Update the CD_Table entry for "Entity" by overwriting its descriptor.
// This action is effected by setting "ignore_multiple_CDs" to `false'.
// or
// 2. Ignore the new ConnectionDescriptor and continue to use the old one.
// This action is effected by setting "ignore_multiple_CDs" to `true'.
//---------------------------------------------------------------------------
public String waitForConnection (boolean ignore_multiple_CDs) {
//---------------------------------------------------------------------------
// A client should be able to send messages to the connection owner
// regardless of "ignore_multiple_CDs". Use this method if you do not care.
// This method calls its sibling method with "ignore_multiple_CDs" set to
// `true'.
//---------------------------------------------------------------------------
public String waitForConnection () {
//---------------------------------------------------------------------------
// waitForIMConnection()
//
// A server-mode method which waits for an incoming message and returns it in
// InternalMsg format. Motivated by the Retsina/OAA Interoperator.
//
// 1. Block and wait for a connection.
// 2. Once a connection is received, discover who initiated it, add the
// ConnectionDescriptor to the "CD_Table", and return the "InternalMsg" of
// the connecting request.
// 3. Since the ConnectionDescriptor is registered with the "CD_Table" the
// caller need only worry about the string representation of the
// destination peer.
// 4. The return value is an InternalMsg object so that the caller can decide
// how to process the message.
// 5. The ConnectionDescriptor is still registered with the CD_Table so that
// the caller need only worry about the string representation of the
// destination peer.
//---------------------------------------------------------------------------
public InternalKQMLmessage waitForIKMConnection (boolean ignore_multiple_CDs)
//---------------------------------------------------------------------------
// A client should be able to send messages to the connection owner
// regardless of "ignore_multiple_CDs". Use this method if you do not care.
// This method calls its sibling method with "ignore_multiple_CDs" set to
// `false'.
//---------------------------------------------------------------------------
public InternalKQMLmessage waitForIKMConnection () {
/** locks on a connection and waits until a message is sent
* @param conn the connection on which to wait on
*/
public InternalKQMLmessage waitOnConnection (ConnectionDescriptor conn) {
// block on the connection
//---------------------------------------------------------------------------
// pollConnections()
//
// 1. This method does not block and wait for a connection to be established.
// If there is no message on the input queue, this method returns
// immediately.
// 2. This method will poll connections that it both owns and does not own.
// 3. This method ignores the possibility that there may be multiple CDs
// 4. The return value is an InternalMsg object so that the caller can decide
// how to process the message.
// 5. The ConnectionDescriptor is still registered with the CD_Table so that
// the caller need only worry about the string representation of the
// destination peer.
//
// Implementation Note: getNextInputMsg() can starve other threads of CPU
// time. When using it, precede its invocation with a "yield()". Other
// techniques might be necessary, such as sleeping.
//---------------------------------------------------------------------------
public InternalMsg pollConnections () {
//==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==.
// Diconnect and Shutdown Methods
//==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==..==.
//---------------------------------------------------------------------------
// Iterates all members of the CD_Table and closes any open connections.
//---------------------------------------------------------------------------
private void Close_CD_Connections () {
//---------------------------------------------------------------------------
// Close the connection descriptor for the agent identified by "agentID".
//---------------------------------------------------------------------------
public void closeConnection (String agentID) {
//---------------------------------------------------------------------------
// A Mandatory ANS Unregister Method
//
// This method must be called to free the ANS entry maintained for the
// calling application. Otherwise, an error similar to the following might
// occur: "Communicator.registerWithANS: Cannot register with ANS: "
//
// N.B.: This method was not explicitly designed to support multithreading,
// although it might do so accidentally. Review your multithread model to be
// sure.
//---------------------------------------------------------------------------
public void ANS_Unregister () {