/*
 * Server.java
 *
 * Author: Jonathan Boldiga
 * Date: JUN 16 2002
 *
 * Description: This is an adapted/extended version of Kartik Pandya's
 *				chat client/server. It has been ported for use on Orbix 2.x
 *				and also now includes a GUI (graphical user interface).
 *
 * Copyright (c) 1993-2001 IONA Technologies PLC.
 *  			All Rights Reserved
 *
*/

package Chat;

import java.io.*;

import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import java.util.Hashtable;
import java.util.Enumeration;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;



//This program illustrates the use of a persistent POA

public class Server{

  public static ORB global_orb;
  public static Hashtable ClientList;
  public static int NumberOfActiveClients;

  public static void main(String args[]){

	ServerGUI serve = new ServerGUI();
	serve.pack();
	serve.setVisible(true);

    try
    {
      // Initialize the ORB

      System.out.println("Initializing ORBChat Server");
      serve.displayResult("Initializing ORBChat Server", "ORBChat");

      global_orb = ORB.init(args, null);

      ClientList = new Hashtable();
      NumberOfActiveClients = 0;

      org.omg.CORBA.Object poa_obj = global_orb.resolve_initial_references("RootPOA");

      org.omg.PortableServer.POA root_poa = org.omg.PortableServer.POAHelper.narrow(poa_obj);

      org.omg.PortableServer.POAManager poa_manager = root_poa.the_POAManager();

      // Create a PERSISTENT POA named 'simple_chat', beneath the root^M

      org.omg.CORBA.Policy[] policies=new org.omg.CORBA.Policy[2];

      policies[0]=root_poa.create_lifespan_policy(org.omg.PortableServer.LifespanPolicyValue.PERSISTENT);
      policies[1]=root_poa.create_id_assignment_policy(org.omg.PortableServer.IdAssignmentPolicyValue.USER_ID);

      org.omg.PortableServer.POA persistent_poa=
        root_poa.create_POA("simple_chat",
                            poa_manager,
                            policies);


      // Create and activate the servants, giving it an id and making
      // them available for use.
      System.out.println("Creating objects");
      serve.displayResult("Creating objects", "ORBChat");

      ChatServerImpl my_servant = new ChatServerImpl();
      byte[] oid="my_chat_object".getBytes();
      persistent_poa.activate_object_with_id(oid, my_servant);

      // If the user specified an objref file, export the servant
      // object reference to this file.
      //
      for (int i = 0 ; i < args.length - 1 ; i++)
      {
        if ("-file".equals(args[i]))
        {
          export_object(persistent_poa,
                        oid,
                        args[i + 1],
                        Chat.ChatRemoteHelper.id());
        }
      }

      // Activate the POA Manager to allow new requests to arrive
      //
      System.out.println("Activating the POA Manager");
      serve.displayResult("Activating the POA Manager", "ORBChat");


      poa_manager.activate();


      // Give control to the ORB to let it process incoming requests
      //

      System.out.println("Giving control to the ORB to process requests");
      serve.displayResult("Giving control to the ORB to process requests", "ORBChat");

      System.out.println("How May I Serve You Master?");
      serve.displayResult("How May I Serve You Master?", "ORBChat");

      global_orb.run();

      System.out.println ("Done");
      serve.displayResult("Done", "ORBChat");


    }
    catch(org.omg.CORBA.ORBPackage.InvalidName ex)
    {
      System.out.println("Failed to obtain root poa " + ex );
      serve.displayResult("Failed to obtain root poa " + ex, "ORBChat");
    }
    catch(org.omg.PortableServer.POAPackage.WrongPolicy ex)
    {
      System.out.println("Invalid POA policy " + ex );
      serve.displayResult("Invalid POA policy " + ex, "ORBChat");
    }
    catch(org.omg.PortableServer.POAPackage.ServantAlreadyActive ex)
    {
      System.out.println("POA servant already active " + ex );
      serve.displayResult("POA servant already active " + ex, "ORBChat");
    }
    catch(org.omg.PortableServer.POAManagerPackage.AdapterInactive ex)
    {
      System.out.println("POAManager activate failed" + ex );
      serve.displayResult("POAManager activate failed " + ex, "ORBChat");
    }
    catch(org.omg.PortableServer.POAPackage.ObjectAlreadyActive ex)
    {
      System.out.println("Object activation failed" + ex);
      serve.displayResult("Object activation failed " + ex, "ORBChat");
    }
    catch(org.omg.PortableServer.POAPackage.AdapterAlreadyExists ex)
    {
      System.out.println("Adapter creation failed" + ex);
      serve.displayResult("Adapter creation failed " + ex, "ORBChat");
    }
    catch(org.omg.PortableServer.POAPackage.InvalidPolicy ex)
    {
      System.out.println("Adapter creation failed" + ex);
      serve.displayResult("Adapter creation failed " + ex, "ORBChat");
    }
  }


  /**
   * This function takes a poa and object id, builds an object
   * reference representing that object, and exports the object
   * reference to a file.
   */

  public static void export_object(POA poa, byte[] oid, String filename, String type_id)
    {
      try
      {
        org.omg.CORBA.Object ref = poa.create_reference_with_id(oid, type_id);

        String stringified_ref = global_orb.object_to_string(ref);

        RandomAccessFile FileStream = null;
        try
        {
          FileStream = new RandomAccessFile(filename,"rw");
          FileStream.writeBytes(stringified_ref);
          FileStream.close();
        }
        catch(Exception ex)
        {
          System.out.println("Failed to write to " + filename );
        }
      }
      catch(org.omg.PortableServer.POAPackage.WrongPolicy ex)
      {
        System.out.println("Invalid POA policy " + ex );
      }
    }

}

/**
 * This is an example of using skeleton inheritance to create
 * a servant.  The implementation class derives directly from
 * the POA skeleton, and implements each of the skeleton methods.
 */
class ChatServerImpl extends ChatRemotePOA{

    public String[] who(){

        String[] ret = null;
        Enumeration en = null;
        try{

            ret = new String[(Server.ClientList).size()];
            en = (Server.ClientList).keys();
            for(int i=0; en.hasMoreElements(); i++){

                ret[i] = (String)en.nextElement();
            }
        }
        catch(Exception e){
            // nothing
        }
        return ret;
    }

    public boolean available(String userID){

        if((Server.ClientList).containsKey(userID))
            return false;
        else
            return true;
    }

    public void enroll(ChatLocal ccObj, String selectedUserID){
		ServerGUI.displayResult("enrolling " + selectedUserID, "ORBChat");
        Server.ClientList.put(selectedUserID, ccObj);
    }

    public void remove(String userID){
        ServerGUI.displayResult("removing " + userID, "ORBChat");
        Server.ClientList.remove(userID);
    }

    public boolean request(String senderID, String receiverID){

        try{
            ServerGUI.displayResult("ReceiveID is : >>" + receiverID + "<<", "ORBChat");// DEBUG
            ChatLocal clocal = (ChatLocal)(Server.ClientList).get(receiverID);
            ServerGUI.displayResult("ChatLocal Object Value : " + clocal.toString(), "ORBChat");// DEBUG
            return clocal.ask(senderID);
        }
        catch(Exception e){
            ServerGUI.displayResult("Exception in REQUEST method : " + e.toString(), "ORBChat"); // DEBUG
            return false;
        }
    }

    public void send(String msg, String senderID, String receiverID){
  		ChatLocal clocal = (ChatLocal)(Server.ClientList).get(receiverID);
        ServerGUI.displayResult(senderID + " -> " + receiverID, "ORBChat");
        clocal.receive(msg, senderID);
	}

	public void callUpdate(String receiverID, ChatRemote cr){
		String [] online = cr.who();
		String user = null;
		for(int i = 0; i < (cr.who()).length; i++){
			user = online[i];
			ChatLocal clocal = (ChatLocal)(Server.ClientList).get(user);
			clocal.update();
		}
	}

}

