/*
  server.cpp

  This program is the mainline of a Corba server which acts as a StockFactory,
  returning (Corba) Stock objects by request. It instantiates the Corba
  object and controls its service.
  Therefore, we need a reference to an ORB and a POA which we have to start
  (activate) for the server to be really available from outside.

  This version of the server uses explicit activation of the server object
  via the POA. the implicit version is coded as server_implicit.cpp.

  Author: Ingo Kloeckl
 */

#include <OB/CORBA.h>
#include <Stock_Factory_impl.h> // header of the server implementation class

#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 {
    // get ORB - first thing to do!
    orb = CORBA::ORB_init(argc, argv);
  } catch (const CORBA::SystemException& e){
    cerr << "error initializing ORB: " << e << endl;
    return EXIT_FAILURE;
  }

  PortableServer::POA_var rootPOA;
  PortableServer::POAManager_var manager;
  try {
    // get explicit references to the POA and its corresponding POA manager
    CORBA::Object_var poaObj = orb->resolve_initial_references("RootPOA");
    if (CORBA::is_nil(poaObj)){
      cerr << "cannot get reference to RootPOA, exiting" << endl;
      return EXIT_FAILURE;
    }
    rootPOA = PortableServer::POA::_narrow(poaObj);
    if (CORBA::is_nil(rootPOA)){
      cerr << "reference is not a RootPOA, exiting" << endl;
      return EXIT_FAILURE;
    }
    manager = rootPOA->the_POAManager();
    cout << "got POA and POAManager" << 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
    Quote_Stock_Factory_impl* QSFImpl = new Quote_Stock_Factory_impl(orb);
    rootPOA->activate_object(QSFImpl);
    cout << "got and activated stock factory " << endl;

    // save reference to server by poor man's means (writing the IOR of the
    // server to a file).
    // The call to _this() only return the reference without implicit activation
    // of the servant because we already activated it explicitly by POA means.
    Quote::Stock_Factory_var stockFactory = QSFImpl->_this();
    CORBA::String_var str = orb->object_to_string(stockFactory);
    cout << "save IOR " << str << " to file QSF.ref" << endl;
    const char* refFile = "QSF.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();

    // activate the POA and thereby run the implementation of the server
    // without this call, we only have some references to ORBs, POAs and servants
    // doing little or nothing ...
    manager->activate();
  } catch (const CORBA::SystemException& e){
    cerr << "SystemException: " << e << endl;
    return EXIT_FAILURE;
  }

  try {
    // start ORB in a loop which can be terminated via shutdown() by the client
    // (in real life, not the stock client should control this server, but for
    // simplicity we assume that behind the stock ticker control application
    // is a really superuser, maybe a Unix admin who has accidantly studied BWL
    orb->run();
  } catch (const CORBA::SystemException& e){
    cerr << "SystemException: " << e << endl;
    status = EXIT_FAILURE;
  }

  // if the superuser intervention of the client program has not really shutdowned
  // the ORB, we do it here by simply destroying it
  if (!CORBA::is_nil(orb)){
    try {
      orb->destroy();
    } catch (const CORBA::Exception& e){
      cerr << e << endl;
      status = EXIT_FAILURE;
    }
  }

  return status;
}

