//******************************************************************************
//
// Restricted Rights
// WARNING: This is a restricted distribution Zeligsoft file.
//
//******************************************************************************
//
// Copyright (C) 2006 Zeligsoft Inc. - All Rights Reserved
//

//******************************************************************************
//
//     FILE: zceOperatingEnvironment.h
//
//******************************************************************************

#ifndef __ZCEOPERATINGENVIRONMENT_H
#define __ZCEOPERATINGENVIRONMENT_H


#if defined(OS_WIN32)
//use STL without warnings
#pragma warning(disable:4786)
#endif

// General operating environment includes
#include <string>
#include <string.h>
#include <iostream>
#include <set>
#include <map>
#include "zceCorbaExceptionMacros.h"

// Includes for the SCA
#include "CF.h"
#include "PortTypes.h"
#include "CosLwLog.h"

// Includes for thread handling
#include "Mutex.h"

// Includes for Process control
#include <signal.h>

enum zceStatus {ZCE_STATUS_RUNNING = 0, ZCE_STATUS_SHUTTINGDOWN = 1, ZCE_STATUS_FINISHED = 2};


void* Shutdown_Thread(void* data);
#ifdef ZCE_USE_CORBA_EXCEPTIONS 

	#define SHUTDOWN_COMPONENT(orb, component, wait, env) \
			pthread_t tid_; \
			pthread_create(&tid_, NULL, Shutdown_Thread, component);
	

#else 

	#define SHUTDOWN_COMPONENT(orb, component, wait, env) \
			pthread_t tid_; \
			pthread_create(&tid_, NULL, Shutdown_Thread, component);
	
		
#endif

#define ORB_THREADS_DEFAULT 5


#ifdef ZCE_USE_CORBA_EXCEPTIONS 

	#define INIT_ORB(orb, argc, argv, env) \
		if(CORBA::is_nil(OperatingEnvironment::orb_)) \
		{ \
			orb = CORBA::ORB_init(argc, argv); \
			OperatingEnvironment::orb_ = orb; \
		} \
		else \
		{ \
			orb = OperatingEnvironment::orb_; \
		}
	
	
#else 
	
	#define INIT_ORB(orb, argc, argv, env) \
		if(CORBA::is_nil(OperatingEnvironment::orb_)) \
		{ \
			orb = CORBA::ORB_init(argc, argv); \
			OperatingEnvironment::orb_ = orb; \
		} \
		else \
		{ \
			orb = OperatingEnvironment::orb_; \
		}
	
	
#endif


#ifdef ZCE_USE_CORBA_EXCEPTIONS 

	#define CREATE_ORB_THREAD_POOL(orb, numOfThreads, env)

#else 

	#define CREATE_ORB_THREAD_POOL(orb, numOfThreads, env)


#endif



#ifdef ZCE_USE_CORBA_EXCEPTIONS 

	#define ACTIVATE_COMPONENT(orb, rootpoa, manager, tempobj, component, env) \
		tempobj = orb->resolve_initial_references("RootPOA"); \
		if( CORBA::is_nil( tempobj ) ) \
		{ \
			std::cerr << "Failed to resolve the RootPOA."; \
			return 1; \
		} \
		rootpoa = PortableServer::POA::_narrow(tempobj); \
		if( CORBA::is_nil( rootpoa ) ) \
		{ \
			std::cerr << "Failed to narrow the POA."; \
			return 1; \
	} \
		PortableServer::ObjectId_var oid = rootpoa->activate_object( component ); \
		manager = rootpoa->the_POAManager(); \
		manager->activate();
	
	
#else 
	
	#define ACTIVATE_COMPONENT(orb, rootpoa, manager, tempobj, component, env) \
		tempobj = orb->resolve_initial_references("RootPOA"); \
		if( CORBA::is_nil( tempobj ) ) \
		{ \
			std::cerr << "Failed to resolve the RootPOA."; \
			return 1; \
		} \
		rootpoa = PortableServer::POA::_narrow(tempobj); \
		if( CORBA::is_nil( rootpoa ) ) \
		{ \
		std::cerr << "Failed to narrow the POA."; \
		return 1; \
		} \
		PortableServer::ObjectId_var oid = rootpoa->activate_object( component ); \
		manager = rootpoa->the_POAManager(); \
		manager->activate();
	
	
#endif


#ifdef ZCE_USE_CORBA_EXCEPTIONS 
	
	#define REGISTER_WITH_NAMING_SERVICE(orb, IOR, NAME_BINDING, component, obj, env) \
		obj = orb->string_to_object(IOR); \
		if( CORBA::is_nil( obj ) ) \
		{ \
			std::cerr << "Failed to resolve the naming context."; \
			return 1; \
		} \
		CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow(obj); \
		if( CORBA::is_nil( nc ) ) \
		{ \
			std::cerr << "Failed to narrow the naming context."; \
			return 1; \
		} \
		CosNaming::Name name; \
		name.length(1); \
		name[0].id = CORBA::string_dup(NAME_BINDING); \
		nc->rebind(name, component->_this());
	
	
#else 
	
	#define REGISTER_WITH_NAMING_SERVICE(orb, IOR, NAME_BINDING, component, obj, env) \
		obj = orb->string_to_object(IOR); \
		if( CORBA::is_nil( obj ) ) \
		{ \
			std::cerr << "Failed to resolve the naming context."; \
			return 1; \
		} \
		CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow(obj); \
		if( CORBA::is_nil( nc ) ) \
		{ \
			std::cerr << "Failed to narrow the naming context."; \
			return 1; \
		} \
		CosNaming::Name name; \
		name.length(1); \
		name[0].id = CORBA::string_dup(NAME_BINDING); \
		nc->rebind(name, component->_this());
	
	
#endif


#ifdef ZCE_USE_CORBA_EXCEPTIONS 

	#define GET_ORB(env) OperatingEnvironment::orb_;

#else 

	#define GET_ORB(env) OperatingEnvironment::orb_;

#endif


#define DEFAULT_ORB_PROTOCOL	"iiop"

//Set the callback handler that will capture when the process is manually being killed
void CtrlHandler(int iSignal);
#define REGISTER_PROCESS_TERMINATION_CALLBACK struct sigaction sa; \
		sa.sa_handler = CtrlHandler; \
		sigfillset(&(sa.sa_mask)); \
		sa.sa_flags = 0; \
		sigaction(SIGABRT, &sa, NULL); \
		sigaction(SIGHUP, &sa, NULL); \
		sigaction(SIGINT, &sa, NULL); \
		sigaction(SIGQUIT, &sa, NULL); \
		sigaction(SIGTERM, &sa, NULL);

class OperatingEnvironment
{
	public :
		static CORBA::ORB_var orb_;

		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, PortTypes::BooleanSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, PortTypes::CharSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, PortTypes::DoubleSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, PortTypes::FloatSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, PortTypes::ShortSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, PortTypes::LongSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, CF::OctetSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, CF::StringSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, PortTypes::UlongSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, PortTypes::UshortSequence& to);
		static CORBA::Boolean AnyToSequence(const CORBA::Any& any, CosLwLog::LogLevelSequence& to);

		static void AnyFromSequence(CORBA::Any& any, PortTypes::BooleanSequence& to);
		static void AnyFromSequence(CORBA::Any& any, PortTypes::CharSequence& to);
		static void AnyFromSequence(CORBA::Any& any, PortTypes::DoubleSequence& to);
		static void AnyFromSequence(CORBA::Any& any, PortTypes::FloatSequence& to);
		static void AnyFromSequence(CORBA::Any& any, PortTypes::ShortSequence& to);
		static void AnyFromSequence(CORBA::Any& any, PortTypes::LongSequence& to);
		static void AnyFromSequence(CORBA::Any& any, CF::OctetSequence& to);
		static void AnyFromSequence(CORBA::Any& any, CF::StringSequence& to);
		static void AnyFromSequence(CORBA::Any& any, PortTypes::UlongSequence& to);
		static void AnyFromSequence(CORBA::Any& any, PortTypes::UshortSequence& to);
		static void AnyFromSequence(CORBA::Any& any, CosLwLog::LogLevelSequence& to);


	protected :

	private :

};

std::string IfIsDCEUUIDConvertToUpper( std::string candidate); 

void convert_set_to_string(std::set<std::string>::iterator begin, std::set<std::string>::iterator end, std::string& result);

void convert_map_to_string(std::map<std::string, std::string>::iterator begin, std::map<std::string, std::string>::iterator end, std::string& result);

int str_case_cmp(const char* str1, const char* str2);

void get_host_ip_address(char * pszBuffer);

void exception_to_string(const CORBA::Exception& e, std::string& exString);


#endif     // __ZCEOPERATINGENVIRONMENT_H

// End-Of-File
//------------------------------------------------------------------------------
