⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libcom.java

📁 SRI international 发布的OAA框架软件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * @(#)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 + -