/*
  server.cpp

  This is the mainline of a Corba server which only can say "Hallo". It is the
  simplest server, using no naming services, but a file-based IOR for presenting
  the reference to the server object to everybody.

  As a simple server application, we only need an ORB and the root POA. The latter
  is only needed for activating which is done explicitly, but without specifying
  object IDs.

  Author: Ingo Kloeckl
 */

#include <OB/CORBA.h>
#include <Hallo_impl.h>   // header of famous server object

#include <stdlib.h>
#include <errno.h>
#include <fstream.h>

using namespace std;


int main(int argc, char* argv[], char*[]){
  int status = EXIT_SUCCESS;
  CORBA::ORB_var orb;

  try {
    // No.1 task - get an ORB
    orb = CORBA::ORB_init(argc, argv);
  } catch (const CORBA::SystemException& e){
    cerr << "Error initializing ORB: " << e << endl;
    return EXIT_FAILURE;
  }

  // get the root POA - this is only necessary because we have to activate at
  // least this root POA
  PortableServer::POA_var rootPOA;
  try {
    CORBA::Object_var poaObj = orb->resolve_initial_references("RootPOA");
    if (CORBA::is_nil(poaObj)){
      cerr << "error resolving RootPOA, exiting" << endl;
      return EXIT_FAILURE;
    }
    rootPOA = PortableServer::POA::_narrow(poaObj);
    if (CORBA::is_nil(rootPOA)){
      cerr << "RootPOA is not a POA reference, exiting" << endl;
      return EXIT_FAILURE;
    }
    // get the POAs manager to activate. If the POA is not activated, the ORB
    // try to dispatch requests to it, but no one processes them :-(
    PortableServer::POAManager_var manager = rootPOA->the_POAManager();
    manager->activate();
    cout << "got POA and POAManager and activated" << endl;
  } catch (const CORBA::ORB::InvalidName& e){
    cerr << "Invalid name passed: " << e << endl;
    return EXIT_FAILURE;
  } catch (const CORBA::SystemException& e){
    cerr << "Error handling POA: " << e << endl;
    return EXIT_FAILURE;
  }

  try {
    // create implementation object and activate it explicitly with a special
    // POA, in this case the root POA (but this could be another, newly
    // created POA).
    Hallo_impl* halloImpl = new Hallo_impl(orb, "*Ingo*");
    // activation call
    PortableServer::ObjectId_var oid;
    oid = rootPOA->activate_object(halloImpl);
    cout << "implementation activated" << endl;

    // The activation of the implementataion does not return a reference to the
    // implementation, so we get it here via the object ID.
    CORBA::Object_var obj = rootPOA->id_to_reference(oid);
    Hallo_var servant = Hallo::_narrow(obj);
    if (CORBA::is_nil(servant)){
      cerr << "returned reference is not a Hallo object, exiting" << endl;
      return EXIT_FAILURE;
    }

    // save reference to server by poor man's means (writing the IOR of the
    // server to a file).
    CORBA::String_var str = orb->object_to_string(servant);
    cout << "save IOR " << str << " to file HAL.ref" << endl;
    const char* refFile = "HAL.ref";
    ofstream out(refFile);
    if (out.fail()){
      cerr << argv[0] << ": can not open " << refFile << ": " << strerror(errno) << endl;
      return EXIT_FAILURE;
    }
    out << str << endl;
    out.close();
  } catch (const CORBA::SystemException& e){
    cerr << "Error activating servant: " << e << endl;
    return EXIT_FAILURE;
  } catch (...){
    cerr << "Something was wrong" << endl;
    return EXIT_FAILURE;
  }

  try {
    orb->run();
  } catch (const CORBA::SystemException& e){
    cerr << e << endl;
    status = EXIT_FAILURE;
  }

  // if the ORB is not fully shutdowned by the superuser, we just destroy it here
  if (!CORBA::is_nil(orb)){
    try {
      orb->destroy();
    } catch (const CORBA::Exception& e){
      cerr << e << endl;
      status = EXIT_FAILURE;
    }
  }

  return status;
}

