
package jmxserv;

import java.io.*;
import java.util.Properties;
import java.util.Enumeration;

import java.net.InetAddress;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import common.TestParamsRMISSL;
import common.RMISSLClientSocketFactory;
import common.RMISSLServerSocketFactory;

public class TestParamsRMISSLImpl extends UnicastRemoteObject implements TestParamsRMISSL {
  static boolean TRACE = false;
  static void out (String msg) { System.out.println("-- TestParamsRMISSLImpl: " + msg); }

  public TestParamsRMISSLImpl(int PORT, RMISSLClientSocketFactory cf, RMISSLServerSocketFactory sf)
    throws Exception 
  {
    super(PORT, cf, sf);
  }

  public TestParamsRMISSLImpl(int PORT)
    throws Exception 
  {
    super(PORT);
  }

  public String retString () {
    return "small string of text";
  }

  public int retInt()  {
    return 125;
  }

  public double retDouble() {
    return 125.6;
  }

  public double retMathSqrt(double arg) {
    return Math.sqrt(arg);
  }
  
  public Properties retProperties() {
    Properties props = new Properties();
    String[] arr = mkStrings();
    for (int i = 0; i < arr.length; i+=2) {
      props.put(arr[i], arr[i+1]);
    }
    return props;
  }

  static String filler = "________________________________________________________";

  String[]  mkStrings() {
    String[] res = new String[10000];
    for (int i = 0; i < 10000;) {
      String key = "key" + i + filler;
      String val = "val" + i + filler;
      res[i++] = key;
      res[i++] = val;
    }
    return res;
  }

  String[] strings = null;
  public String[]  retStrings() {
    // this will require a permission
    if (strings == null) strings = mkStrings();
    return strings;
  }

  public void shutDown () {
    if (TRACE) out("shutting RMI down...");
    // ugly way of doing it: System.exit(0);

    // better way:
    final TestParamsRMISSLImpl obj_to_unregister = this;
    new Thread(new Runnable() { public void run() {
      try {
        // System.out.println("--unregistering  obj_to_unregister: " + obj_to_unregister);
        registry.unbind("TestParamServer");
        TestParamsRMISSLImpl.unexportObject(obj_to_unregister, true); // inherited from UnicastRemoteObject
      } catch (Exception e) {
        out(" on shutDown got " + e + " when unexporting TestParamsRMISSLImpl");
        System.exit(0);      
      }
    }}).run();
    
  }

  static int PORT = 2019;
  static String keyManager = "default";

  public static void main(String args[]) {
    if (args.length > 3 && args[3].toLowerCase().equals("trace")) {
      TRACE = true;
      RMISSLServerSocketFactory.TRACE = true;
      RMISSLClientSocketFactory.TRACE = true;
    }
    if (args.length > 2) {
      try {
        PORT = Integer.parseInt(args[2]);
      } catch (Exception e) {
        if (TRACE) out("bad port argument (not an integer). Use default " + PORT);
      }
    }
    if (args.length > 1) {
      keyManager  = args[1].toLowerCase();
    }
    if (args.length > 0 && args[0].toLowerCase().equals("ssl")) {
      do_RMI_SSL();
    }
    else 
      do_RMI();
  }
  
  static void do_RMI_SSL() {
    boolean isDefault = keyManager.equals("default");
    
    if (TRACE) out("starting do_RMI_SSL ...");

    try {

      // Create and install a security manager
      if (System.getSecurityManager() == null) {
        if (TRACE) out("Creating RMISecurityManager...");
        RMISecurityManager rmism = new RMISecurityManager(); 
        System.setSecurityManager(rmism);
        if (TRACE) out("Created and installed RMISecurityManager " + rmism);
      }

      // create factories a-new. todo: cache?
      RMISSLServerSocketFactory ssf = null; 
      RMISSLClientSocketFactory csf = null; 

      // we attempt up to connect_count times; often this helps if the port appears bound
      int connect_count = 30;
      while(connect_count > 0) {
        try {
          // this is for the server's own use
          ssf = new RMISSLServerSocketFactory(isDefault);
          // the state of this will be passed to the client,
          // controlling its mode
          csf = new RMISSLClientSocketFactory(isDefault);      

          // Create SSL-based registry
          if (TRACE) out("Create SSL-based registry...");
          registry = LocateRegistry.createRegistry(PORT, csf, ssf);
          obj = new TestParamsRMISSLImpl(PORT, csf, ssf);

          break; // while(connect_count)
        }
        catch (Exception port_e) {
          connect_count--;
          if (connect_count <= 0) throw port_e;
          else {
            System.out.println("-- got " + port_e + " retying..." );
            Thread.sleep(2000);
          }
        }
      }

      // Bind this object instance to the name "TestParamServer"
      if (TRACE) out("Binding TestParamServer...");
      registry.bind("TestParamServer", obj);
      if (TRACE) out("TestParamServer bound in registry");
    } catch (Exception e) {
      out("Error: " + e.getMessage());
      e.printStackTrace();
      System.exit(1);
    }
  }

  static Registry registry;
  static TestParamsRMISSLImpl obj;

  static void do_RMI() {

    // Create and install a security manager
    // if (System.getSecurityManager() == null) {
    //   System.setSecurityManager(new RMISecurityManager());
    // }

    try {
      registry = LocateRegistry.createRegistry(PORT);
      obj = new TestParamsRMISSLImpl(PORT);

      // Bind this object instance to the name "TestParamServer"
      registry.bind("TestParamServer", obj);

      if (TRACE) out("TestParamServer bound in registry");
    } catch (Exception e) {
      out("Error: " + e.getMessage());
      e.printStackTrace();
    }
  }


}

