//     $Id: DemonRMI.java,v 3.5 1998/12/09 20:08:00 mk2z Exp $    
 ////////////////////////////////////////////////////////////////////////////
 //
 // File: DemonRMI.java
 //
 // Purpose: This is the main communications module for Demon. Upon 
 //        getting started, it looks up to see whether a Registry exists on
 //        a specified port/IP.
 //        It also implements the DemonRMIIface and the interface agreed upon
 //        with the DemonEngine. 
 //
 // Summary of incoming calls from the ServerRMI:
 //
 //    void ReceiveClientConnectStatus
 //    void ReceiveStats
 //    void ReceiveMap
 //
 // Summary of outgoing calls (incoming from DemonEngine):
 //
 //    boolean RegisterDemon -- RegisterWithServer
 //    boolean SetParameters
 //    boolean ShutDown -- Shutdown
 //
 // Authors:
 //  Orim   Miro Kresonja  mk2z@virginia.edu
 //
 // Modifications:
 //  15-NOV-1998  Orim  Initial modifications for version 3.0
 //  18-NOV-1998  txe   Fixing name
 //  19-NOV-1998  Orim  Final fix of exceptions
 //  05-DEC-1998  Orim  Modifications for release 4.0 (conn., extra methods)
 //
 ////////////////////////////////////////////////////////////////////////////
 import java.net.URL;
 import java.rmi.*;
 import java.rmi.server.*;
 import java.util.*;
 public class DemonRMI
     implements DemonRMIIface, java.io.Serializable
 {
   // Class variable declarations
   private static final String DEFAULT_IP   = "mamba.cs.virginia.edu";
   private static final String DEFAULT_PORT = "1202";
   private static final String DEFAULT_RMI_NAME= "ServerRMI";
   private String server_ip_port;
   private String server_rmi_name;
   private int my_id;
   private int my_password;
   private static final int FAILED = 0;
   private ServerRMItoDemonIface server_iface = null;
   private DemonEngine my_engine = null;
   ///////////////////////////////////////////////////////////////////
   //
   // DemonRMI Constructor - The demon automatically exports itself.
   //   
   ///////////////////////////////////////////////////////////////////
   public DemonRMI (DemonEngine engine)
   throws NullException, Exception {
     my_engine = engine;
     if (engine == null) {
       throw new NullException ("engine");
     }
     // export the RMIDemon as a remote object
     Print("Exporting Object");
     UnicastRemoteObject.exportObject(this);
   }
   ///////////////////////////////////////////////////////////////////
   //
   //   Connect - invoked by DemonEngine. It finds the server
   //   on a specified port, and gets the initial map out of it.
   //
   ///////////////////////////////////////////////////////////////////
   public Map Connect (String ip, String port)
   throws RemoteException, Exception {
       // Get port/host/name information off of the web page
     String temp_ip, temp_port;
     if (ip == null) {
         temp_ip = DEFAULT_IP;
     }
     else {
         temp_ip = ip;
     }
     if (port == null) {
         temp_port = DEFAULT_PORT;
     }
     else {
         temp_port = port;
     }
     server_rmi_name = temp_ip + ":" + temp_port;
       // Look up the server port/service and get the initial map
     String server_name = "//" + server_rmi_name + "/" + DEFAULT_RMI_NAME;
     Print("Server Lookup for '" + server_name + "'");
     server_iface = (ServerRMItoDemonIface)Naming.lookup(server_name);
     return (server_iface.ConnectDemon());
   }
   ///////////////////////////////////////////////////////////////////
   //
   //   RegisterWithServer - invoked by DemonEngine. It tells the server 
   //   it wants to connect. The Server will send back a map, and a 
   //   ClientConnectStatus object.
   //
   ///////////////////////////////////////////////////////////////////
   public boolean RegisterWithServer ()
   throws RemoteException, Exception {
     int result = server_iface.RegisterDemon (this);
     if (result != FAILED) {
         my_password = result;
         return(true);
     }
     else {
         return(false);
     }
   }
   ///////////////////////////////////////////////////////////////////
   //
   //   Quit - invoked by DemonEngine. It is the only notification of
   //   this event to the server.
   // 
   ///////////////////////////////////////////////////////////////////
   public void Quit ()
   throws Exception {
       server_iface.DemonQuit (my_password);
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   ReceiveMap - implementation of DemonRMIIface. It gets the Map
   //   object passed to it, and it simply hands it along to the 
   //   DemonEngine.
   //   
   ///////////////////////////////////////////////////////////////////
   public void ReceiveMap (Map my_map)
   throws RemoteException, Exception {
     try {
     my_engine.ReceiveMap(my_map);
     }
     catch (Exception e) {
     my_engine.Error(e);
     throw (e);
     }
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   ReceiveStats - implementation of DemonRMIIface. It gets the 
   //   Stats object passed to it, and it simply hands it along to the 
   //   DemonEngine.
   //   
   ///////////////////////////////////////////////////////////////////
   public void ReceiveStats (Stats my_stats)
   throws RemoteException, Exception {
     try {
     my_engine.ReceiveStats(my_stats);
     }
     catch (Exception e) {
         my_engine.Error(e);
         throw (e);
     }
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   ReceiveState - implementation of DemonRMIIface. It gets the 
   //   state of the sim passed to it, and hands it along to the engine
   //   which gives it to GUI.
   //   
   ///////////////////////////////////////////////////////////////////
   public void ReceiveState (int state)
   throws RemoteException, Exception {
     try {
     my_engine.ReceiveState(state);
     }
     catch (Exception e) {
         my_engine.Error(e);
         throw (e);
     }
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   ReceiveClientConnectStatus - implementation of DemonRMIIface. 
   //   It gets the ClientConnectStatus object passed to it, and it 
   //   simply hands it along to the DemonEngine.
   //   
   ///////////////////////////////////////////////////////////////////
   public void ReceiveClientConnectStatus (ClientConnectStatus status)
   throws RemoteException, Exception {
     try {
     my_engine.ReceiveClientConnectStatus (status);
     }
     catch (Exception e) {
         my_engine.Error(e);
         throw (e);
     }
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   SubmitMode - invoked by DemonEngine. It gets the mode of 
   //   execution (Auto, Manual), and in case of Auto, a number of 
   //   runs, then passes them to ServerRMI.
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean SubmitMode (int mode, int runs)
   throws RemoteException, Exception {
     return(server_iface.SubmitMode (mode, runs));
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   StartRun - invoked by DemonEngine. It gets the parameters
   //   for the simulation, and passes them to ServerRMI, thus starting 
   //   a Run
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean StartRun (int propagation, long delay)
   throws RemoteException, Exception {
     return(server_iface.StartRun (propagation, delay));
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   Abort - invoked by DemonEngine. It simply tells
   //   the ServerRMI to end the current run.
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean Abort ()
   throws RemoteException, Exception {
     return(server_iface.Abort());
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   ShutDown - invoked by DemonEngine. It simply tells
   //   the ServerRMI we're finishing up.
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean ShutDown ()
   throws RemoteException, Exception {
     return(server_iface.Shutdown());
   }
   ///////////////////////////////////////////////////////////////////
   //   
   //   Print - ClientRMI's own method, receiving a string from within
   //   ClientRMI, and in turn hands it off to ClientEngine for display.
   //   
   ///////////////////////////////////////////////////////////////////
   private void Print(String s) {
     my_engine.PrintMessage("RMI: "+s);
   }
 }
 ////////////////////////////////////////////////////////////////////////////