/**
 * Alternative implementation of RemoteMath interface for RMI server.
 * This class implements the interface RemoteMath which is used to
 * support RMI based simple math operations. 
 * Instead of extending the class UnicastRemoteObject we export
 * a RemoteMathImpl object manually using the static export() method of
 * the UnicastRemoteObject class.
 */

import java.net.*;    // need this for MalformedURLException
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

/** RemoteMathImpl defines the object used by the server.
 * Note that this class will be used to
 * generate stub and skeleton files ... (using rmic)
 *
 * In this example we include a main, in general you would probably not
 * include a main() in the remote object class definitions...
 */

public class RemoteMathImpl implements RemoteMath {

  /** We need to create a constructor (even if it does nothing).  The
   * constructor must throw RemoteException - since when a new
   * UnicastRemoteObject is created it requires some communication
   * resources that may not be available!  In this constructor we just
   * call the static exportObject method of UnicastRemoteObject
   * (instead of inheriting from that class)
   */

  public RemoteMathImpl() throws RemoteException {
	UnicastRemoteObject.exportObject(this);
  }

  /**	 For this simple example we include a main here, in general we
   * will define remote objects and create them elsewhere (in general
   * we don't put main inside the implementation of a remote object).
   */

  public static void main(String args[]) { 
	try {
	  // create a RemoteMathImpl object 
	  RemoteMathImpl r = new RemoteMathImpl();

	  // register the object with the rmi registry
	  // (registry mush already be running)
	  Naming.rebind("ReMath",r);
	  System.out.println("Registered RemoteMath object\n"); 

	} catch (RemoteException e) {
	  System.out.println("RemoteException: " + e.getMessage());
	  e.printStackTrace();

	} catch (MalformedURLException m) {
	  System.out.println("URL Problem: " + m.getMessage());
	  m.printStackTrace();
	}
  }

  // Below are the actual remote methods. Although these are
  // simple methods in this example - it's worth noting that aside
  // from the declaration that each can throw RemoteException, there
  // is no difference between the code in these methods and in
  // a local method (the fact that these methods can be called
  // remotely doesn't change the way we write the code.


  /** Add is a remote method that adds 2 integers 
   *
   * @param x,y are the two ints to add
   * @return returns the sum as an int
   */

  public int Add(int x, int y) throws RemoteException {
	LogRequest("ADD: " + x + "+" + y);
	return(x+y);
  }

  /** Sub is a remote method that subtracts 2 integers 
   *
   * @param x,y are the two ints to subtract (x-y)
   * @return returns the difference as an int
   */
  public int Sub(int x, int y) throws RemoteException {
	LogRequest("SUB: " + x + "-" + y);
	return(x-y);
  }

  /** Mult is a remote method that multiplies 2 integers 
   *
   * @param x,y are the two ints to multiplyd
   * @return returns the product as an int
   */

  public int Mult(int x, int y) throws RemoteException {
	LogRequest("MULT: " + x + "*" + y);
	return(x*y);
  }

  /** Div is a remote method that does integer division
   *
   * @param x,y are the two ints (x / y)
   * @return returns the quotient as an int
   */

  public int Div(int x, int y) throws RemoteException {
	LogRequest("DIV: " + x + "/" + y);
	return(x/y);
  }

  /** 
   * LogRequest is just doing some printing here, although in a real
   * service you might want to replace this with code that does
   * something fancy (actually log to a file or to syslog).
   */

  void LogRequest(String s) {
	System.out.println("RemoteMath Request: " + s );
  }

}



