/*----- PROTECTED REGION ID(SupervisedID.cpp) ENABLED START -----*/

//=============================================================================
//
// file :        SupervisedID.cpp
//
// description : C++ source for the SupervisedID and its commands.
//               The class is derived from Device. It represents the
//               CORBA servant object which will be accessed from the
//               network. All commands which can be executed on the
//               SupervisedID are implemented in this file.
//
// project :     Supervised ID: common interface for supervised insertion devices.
//
// $Author: claudio $
//
// $Revision: 1.2 $
// $Date: 2014-04-14 14:51:54 $
//
// SVN only:
// $HeadURL:  $
//
// CVS only:
// $Source: /home/cvsadm/cvsroot/AbstractClasses7/SupervisedID/SupervisedID.cpp,v $
// $Log: SupervisedID.cpp,v $
// Revision 1.2  2014-04-14 14:51:54  claudio
// for 8.1.2.c and pogo-8
//
// Revision 1.1.1.1  2012-03-05 14:01:56  claudio
// frist import
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#include <SupervisedID.h>
#include <SupervisedIDClass.h>

/*----- PROTECTED REGION END -----*/	//	SupervisedID.cpp

/**
 *  SupervisedID class description:
 *    This abstract class incapsulates the common interface for insertion devices used
 *    under ID supervisor. The "supervisor" can inhibi/allow the operations on the insertion device
 *    and impose limits on the permited range.
 */

//================================================================
//  The following table gives the correspondence
//  between command and method names.
//
//  Command name  |  Method name
//================================================================
//  State         |  Inherited (no method)
//  Status        |  Inherited (no method)
//================================================================

//================================================================
//  Attributes managed are:
//================================================================
//  Enabled  |  Tango::DevBoolean	Scalar
//  Ready    |  Tango::DevBoolean	Scalar
//  StatRF   |  Tango::DevBoolean	Spectrum  ( max = 32)
//================================================================

namespace SupervisedID_ns
{
/*----- PROTECTED REGION ID(SupervisedID::namespace_starting) ENABLED START -----*/

	//	static initializations

	/*----- PROTECTED REGION END -----*/	//	SupervisedID::namespace_starting

//--------------------------------------------------------
/**
 *	Method      : SupervisedID::SupervisedID()
 *	Description : Constructors for a Tango device
 *                implementing the classSupervisedID
 */
//--------------------------------------------------------
SupervisedID::SupervisedID(Tango::DeviceClass *cl, string &s)
 : TANGO_BASE_CLASS(cl, s.c_str())
{
	/*----- PROTECTED REGION ID(SupervisedID::constructor_1) ENABLED START -----*/

	init_device();

	/*----- PROTECTED REGION END -----*/	//	SupervisedID::constructor_1
}
//--------------------------------------------------------
SupervisedID::SupervisedID(Tango::DeviceClass *cl, const char *s)
 : TANGO_BASE_CLASS(cl, s)
{
	/*----- PROTECTED REGION ID(SupervisedID::constructor_2) ENABLED START -----*/

	init_device();

	/*----- PROTECTED REGION END -----*/	//	SupervisedID::constructor_2
}
//--------------------------------------------------------
SupervisedID::SupervisedID(Tango::DeviceClass *cl, const char *s, const char *d)
 : TANGO_BASE_CLASS(cl, s, d)
{
	/*----- PROTECTED REGION ID(SupervisedID::constructor_3) ENABLED START -----*/

	init_device();

	/*----- PROTECTED REGION END -----*/	//	SupervisedID::constructor_3
}

//--------------------------------------------------------
/**
 *	Method      : SupervisedID::delete_device()
 *	Description : will be called at device destruction or at init command
 */
//--------------------------------------------------------
void SupervisedID::delete_device()
{
	DEBUG_STREAM << "SupervisedID::delete_device() " << device_name << endl;
	/*----- PROTECTED REGION ID(SupervisedID::delete_device) ENABLED START -----*/

	//	Delete device allocated objects

	/*----- PROTECTED REGION END -----*/	//	SupervisedID::delete_device
}

//--------------------------------------------------------
/**
 *	Method      : SupervisedID::init_device()
 *	Description : will be called at device initialization.
 */
//--------------------------------------------------------
void SupervisedID::init_device()
{
	DEBUG_STREAM << "SupervisedID::init_device() create device " << device_name << endl;
	/*----- PROTECTED REGION ID(SupervisedID::init_device_before) ENABLED START -----*/
	
	//	Initialization before get_device_property() call
	
	/*----- PROTECTED REGION END -----*/	//	SupervisedID::init_device_before
	

	//	Get the device properties from database
	get_device_property();
	
	/*----- PROTECTED REGION ID(SupervisedID::init_device) ENABLED START -----*/

	//	Initialize device
	//init hostMap from hostPriviliges
	{
		vector<string>::const_iterator i;
		for (i = hostPrivileges.begin(); i != hostPrivileges.end(); i++) {
			int pos = (*i).find(':');
			if (pos <= 0) {
				ERROR_STREAM
				<< "SupervisedID::init()  hostPrivileges syntax error "
				<< (*i) << endl;
			} else {
				string h = (*i).substr(0, pos);
				string val = (*i).substr(pos + 1);
				int valint = atoi(val.c_str());
				DEBUG_STREAM << "host: " << h << " privilege: " << valint
						<< endl;
				pair<string, int> mypair(h, valint);
				hostMap.insert(mypair);
			}
		}
	}
	/*----- PROTECTED REGION END -----*/	//	SupervisedID::init_device
}

//--------------------------------------------------------
/**
 *	Method      : SupervisedID::get_device_property()
 *	Description : Read database to initialize property data members.
 */
//--------------------------------------------------------
void SupervisedID::get_device_property()
{
	/*----- PROTECTED REGION ID(SupervisedID::get_device_property_before) ENABLED START -----*/
	
	//	Initialize property data members
	
	/*----- PROTECTED REGION END -----*/	//	SupervisedID::get_device_property_before


	//	Read device properties from database.
	Tango::DbData	dev_prop;
	dev_prop.push_back(Tango::DbDatum("HostPrivileges"));

	//	is there at least one property to be read ?
	if (dev_prop.size()>0)
	{
		//	Call database and extract values
		if (Tango::Util::instance()->_UseDb==true)
			get_db_device()->get_property(dev_prop);
	
		//	get instance on SupervisedIDClass to get class property
		Tango::DbDatum	def_prop, cl_prop;
		SupervisedIDClass	*ds_class =
			(static_cast<SupervisedIDClass *>(get_device_class()));
		int	i = -1;

		//	Try to initialize HostPrivileges from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  hostPrivileges;
		else {
			//	Try to initialize HostPrivileges from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  hostPrivileges;
		}
		//	And try to extract HostPrivileges value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  hostPrivileges;

	}

	/*----- PROTECTED REGION ID(SupervisedID::get_device_property_after) ENABLED START -----*/
	
	//	Check device property data members init
	
	/*----- PROTECTED REGION END -----*/	//	SupervisedID::get_device_property_after
}

//--------------------------------------------------------
/**
 *	Method      : SupervisedID::always_executed_hook()
 *	Description : method always executed before any command is executed
 */
//--------------------------------------------------------
void SupervisedID::always_executed_hook()
{
	DEBUG_STREAM << "SupervisedID::always_executed_hook()  " << device_name << endl;
	/*----- PROTECTED REGION ID(SupervisedID::always_executed_hook) ENABLED START -----*/

	//	code always executed before all requests

	/*----- PROTECTED REGION END -----*/	//	SupervisedID::always_executed_hook
}

//--------------------------------------------------------
/**
 *	Method      : SupervisedID::read_attr_hardware()
 *	Description : Hardware acquisition for attributes
 */
//--------------------------------------------------------
void SupervisedID::read_attr_hardware(TANGO_UNUSED(vector<long> &attr_list))
{
	DEBUG_STREAM << "SupervisedID::read_attr_hardware(vector<long> &attr_list) entering... " << endl;
	/*----- PROTECTED REGION ID(SupervisedID::read_attr_hardware) ENABLED START -----*/

	//	Add your own code

	/*----- PROTECTED REGION END -----*/	//	SupervisedID::read_attr_hardware
}
//--------------------------------------------------------
/**
 *	Method      : SupervisedID::write_attr_hardware()
 *	Description : Hardware writing for attributes
 */
//--------------------------------------------------------
void SupervisedID::write_attr_hardware(TANGO_UNUSED(vector<long> &attr_list))
{
	DEBUG_STREAM << "SupervisedID::write_attr_hardware(vector<long> &attr_list) entering... " << endl;
	/*----- PROTECTED REGION ID(SupervisedID::write_attr_hardware) ENABLED START -----*/
	
	//	Add your own code
	
	/*----- PROTECTED REGION END -----*/	//	SupervisedID::write_attr_hardware
}


//--------------------------------------------------------
/**
 *	Method      : SupervisedID::add_dynamic_attributes()
 *	Description : Create the dynamic attributes if any
 *                for specified device.
 */
//--------------------------------------------------------
void SupervisedID::add_dynamic_attributes()
{
	/*----- PROTECTED REGION ID(SupervisedID::add_dynamic_attributes) ENABLED START -----*/
	
	//	Add your own code to create and add dynamic attributes if any
	
	/*----- PROTECTED REGION END -----*/	//	SupervisedID::add_dynamic_attributes
}

//--------------------------------------------------------
/**
 *	Method      : SupervisedID::add_dynamic_commands()
 *	Description : Create the dynamic commands if any
 *                for specified device.
 */
//--------------------------------------------------------
void SupervisedID::add_dynamic_commands()
{
	/*----- PROTECTED REGION ID(SupervisedID::add_dynamic_commands) ENABLED START -----*/
	
	//	Add your own code to create and add dynamic commands if any
	
	/*----- PROTECTED REGION END -----*/	//	SupervisedID::add_dynamic_commands
}

/*----- PROTECTED REGION ID(SupervisedID::namespace_ending) ENABLED START -----*/

	//	Additional Methods
//-------------------------------------------------------------------------------
    /**
	 * assign privileges elevel based on host name from which the call is generated
	 * PRIVILEGED : can change the enable bit and set gap/tapering
	 * AUTHORIZED : can set gap/tapering when enabled
	 * NORMAL     : can only read;
	 */
privilege SupervisedID::caller_privileges(void)
{
	//if no privileges are configured, run unimpeded
	if(hostMap.size() == 0)return PRIVILEGED;

	Tango::DevVarStringArray blackbox = black_box(1)[0];
	string last_msg(blackbox[0].in());
	string::size_type loc = last_msg.find( " requested from ", 0 );
	if( loc != string::npos )
	{
		clientAddress = last_msg.substr(loc + strlen(" requested from "));
		loc=clientAddress.find(" ",0);
		clientAddress =clientAddress.substr(0,loc);
		INFO_STREAM<<"checking call from "<<clientAddress<<endl;
		map<string,int>::iterator it;
		it=hostMap.find(clientAddress);
		if (it == hostMap.end()) {
			INFO_STREAM << clientAddress<< " host not foud" << endl;
			return NORMAL;
		}
		else {
			INFO_STREAM << "host: " << clientAddress << " privilges="
					<< it->second << endl;
			switch (it->second) {
			case 0:
				return NORMAL;
			case 1:
				return AUTHORIZED;
			case 2:
				return PRIVILEGED;
			default:
				return NORMAL;

			}

		}

	}
	else
	{
		WARN_STREAM << "Cannot extract client IP or hostname from tango blackbox, denying access.";
		clientAddress="";
		return NORMAL; //do not grant special privileges
	}
	return NORMAL; //do not grant special privilege - but we should NOT arrive at this line
}
//--------------------------------------------------------------------
/**
	 * check privileges level based on host name from which the call is generated
	 * formats warning/  error messages and throw exception in case of vilotaions
	 * privilege levels:
	 * PRIVILEGED : can change the enable bit and set gap/tapering
	 * AUTHORIZED : can set gap/tapering when enabled
	 * NORMAL     : can only read;
	 */

privilege SupervisedID::check_privileges(privilege level, string msg)
{
	privilege priv=caller_privileges();
	if (priv < level){
		INFO_STREAM << msg << " from "<< clientAddress <<" REJECTED"<<endl;
		TangoSys_OMemStream o;
		o << msg << " from "<< clientAddress <<" REJECTED"<<ends;
		Tango::Except::throw_exception((const char *)"Host not allowed",o.str(),msg);
	}
	return priv;
}
	/*----- PROTECTED REGION END -----*/	//	SupervisedID::namespace_ending
} //	namespace