/*
  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.

  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
  try {
    CORBA::Object_var poaObj = orb->resolve_initial_references("RootPOA");
    if (CORBA::is_nil(poaObj)){
      cerr << "error resolving RootPOA, exiting" << endl;
      return EXIT_FAILURE;
    }
    PortableServer::POA_var 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 servant. This is the simplest way to
    // do this: the root POA is used, creation and activation of the CORBA object
    // takes place automatically
    Hallo_impl* halloImpl = new Hallo_impl(orb, "*Ingo*");
    Hallo_var servant = halloImpl->_this();

    // 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;
}

