FileDocCategorySizeDatePackage
RMIPeerImpl.javaAPI DocExample6389Tue Oct 06 23:23:44 BST 1998jdc.patterns.peer

RMIPeerImpl.java

package jdc.patterns.peer;

import jdc.util.*;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Properties;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.net.*;

public class RMIPeerImpl extends UnicastRemoteObject implements RMIPeer {

  /**
   * Table of currently connected Peers.
   */
  protected Hashtable mPeers = new Hashtable();
  protected Hashtable mIdentities = new Hashtable();
  
  /**
   * The networked identity of this peer.  Subclasses implementing this
   * abstract class will need to provide a means for initializing this
   * identity, such that the identity is unique in the distributed context.
   */
  protected Identity mIdentity = null;

  /**
   * Static host property name.  The host specifier includes any required
   * port specifier, if the default RMI port is not in use.
   */
  static final public String HOST_PROP = "HOST";

  /**
   * Property for RMI registry name of remote peer.
   */
  static final public String REGNAME_PROP = "REGNAME";

  /**
   * Name under which this peer is registered.
   */
  protected String mRegName = "Peer";
  
  /**
   * Default constructor.  Leave identity uninitialized, to indicate
   * no identity.
   */
  public RMIPeerImpl() throws RemoteException {
    mIdentity = new Identity();
    register();
  }

  public RMIPeerImpl(String name) throws RemoteException {
    super();
    mRegName = name;
    mIdentity = new Identity();
    register();
  }
  
  protected void register() {
    try {
      // Bind this peer to our name in the local registry
      Naming.rebind(mRegName, this);
      // Set our identity properties accordingly
      // The "name" is the name used in the registry.
      getIdentity().setName(mRegName);
      // The "host" property includes the local host name and the port
      // on which the RMI registry is listening on the local host.
      getIdentity().setProperty(HOST_PROP,
				InetAddress.getLocalHost().getHostName() +
				":" + Registry.REGISTRY_PORT);
    }
    catch (Exception e) {
      System.out.println("Error registering peer \"" + mRegName + "\":");
      e.printStackTrace();
    }
  }
  
  //
  // Remotely exported interface implementation
  //

  public Identity getIdentity() throws RemoteException {
    return mIdentity;
  }

  // Non-remote 
  public void setIdentity(Identity i) {
    mIdentity = i;
  }

  /**
   * Handle an incoming message.
   */
  public void handle(Message m, RMIPeer p) throws RemoteException {
    System.out.println("Got message: \"" + m.getId() + "\", body: \"" +
		       m.getBody() + "\" from " + p.getIdentity().getName());
  }
  
  /**
   * Add a peer to our list.
   */
  public void addPeer(RMIPeer p) throws RemoteException {
    // Store peer by id in one table, and store id by peer in another
    Identity id = p.getIdentity();
    mPeers.put(id, p);
    mIdentities.put(p, id);
  }
  
  /**
   * Get the peer identified by the given identity.
   */
  public RMIPeer getPeer(Identity i) throws RemoteException {
    Enumeration e = mPeers.keys();
    RMIPeer p = null;
    while (e.hasMoreElements()) {
      Object o = e.nextElement();
      if (i.equals(o)) {
	p = (RMIPeer)mPeers.get(o);
	break;
      }
    }
    
    return p;
  }

  /**
   * Get list of Peers
   */
  public Enumeration getPeers() throws RemoteException {
    return mPeers.elements();
  }

  /**
   * Remove a peer from our list.
   */
  public void removePeer(RMIPeer p) throws RemoteException {
    Identity id = (Identity)mIdentities.get(p);
    mPeers.remove(id);
    mIdentities.remove(p);
  }
  
  //
  // Local Peer interface implementation
  //
  
  /**
   * Connect to a peer given the connection properties.  This RMI-based peer
   * requires the host and registry name of the remote peer object.
   */
  public boolean connect(Properties connProps) {
    Identity id = new Identity();
    id.setName((String)connProps.getProperty(REGNAME_PROP));
    id.setProperty(HOST_PROP, (String)connProps.getProperty(HOST_PROP));
    return connect(id);
  }

  /**
   * Connect to a peer given the connection properties and identity of the
   * peer.  Subclasses can choose to implement this using both arguments, or
   * ignoring one in favor of the other (connection properties vs. properties
   * pulled from the remote peer identifier).
   */
  public boolean connect(Identity peerID) {
    boolean success = false;
    String host = (String)peerID.getProperty(HOST_PROP);
    String regName = peerID.getName();
    // If no host specified, assume a local peer
    if (host == null) {
      host = "localhost";
    }

    // If no registry name, then fail right here
    if (regName == null || regName.trim().length() == 0) {
      System.out.println("RMIPeerImpl.connect: No registry name in identity.");
      return false;
    }

    String rmiURL = "rmi://" + host + "/" + regName;
    try {
      RMIPeer p = (RMIPeer)Naming.lookup(rmiURL);
      addPeer(p);
      p.addPeer(this);
      success = true;
    }
    catch (Exception re) {
      re.printStackTrace();
    }

    return success;
  }
  
  /**
   * Broadcast the message to all currently connected peers.
   */
  public boolean broadcast(Message msg) {
    boolean success = true;
    try {
      Enumeration pEnum = getPeers();
      while (pEnum.hasMoreElements()) {
	RMIPeer p = (RMIPeer)pEnum.nextElement();
	
	try {
	  if (!send(msg, p.getIdentity())) {
	    success = false;
	  }
	}
	catch (java.rmi.RemoteException ce) {
	  System.out.println("Lost connection to peer");
	  try { removePeer(p); } catch (Exception e) { e.printStackTrace(); }
	}
      }
    }
    catch (RemoteException re) {
      System.out.println("broadcast failed: ");
      re.printStackTrace();
    }
    return success;
  }
  
  /**
   * Send the message to the identified peer.
   */
  public boolean send(Message msg, Identity peer) {
    boolean success = false;
    RMIPeer p = null;
    try {
      p = (RMIPeer)getPeer(peer);
      p.handle(msg, this);
      success = true;
    }
    catch (java.rmi.ConnectException ce) {
      System.out.println("Lost connection to peer.");
      try { removePeer(p); } catch (Exception e) { e.printStackTrace(); }
    }
    catch (Exception e) {
      System.out.println("Error sending message:" );
      e.printStackTrace();
    }

    return success;
  }
}