/*************************************************************************
Copyright © 1999-2003 Novell, Inc. All Rights Reserved. 

THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND 
TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE
AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS
THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS
TO DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S
SAMPLE CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION
RIGHTS TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT
OF DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR
DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS CODE.

***************************************************************************/

/*******************************************************************
* Name: CSkeletonDriver.cpp
* Description: Platform independent code for CSkeletonDriver
* DriverShim implementation
* Tabs: 4
*******************************************************************/

#include	"CSkeletonDriver.h"
#include	"SkeletonSubscriber.h"
#include	"SkeletonPublisher.h"
#include	"InterfaceFactory.h"

//string constants: They are defined as arrays because the L" syntax doesn't work on unix, since a wchar_t is
//32-bits rather than 16-bits as on Win32 and Netware
static const unicode	TEXT_DRIVER[]	=	{'d','r','i','v','e','r',0};
static const unicode	TEXT_OPTION_1[]	=	{'o','p','t','i','o','n','-','1',0};
static const unicode	TEXT_OPTION_2[]	=	{'o','p','t','i','o','n','-','2',0};
static const unicode	MSG_NO_AUTH_INFO[]	=	{'N','o',' ','a','u','t','h','e','n','t','i','c','a','t','i','o','n',' ',
												'i','n','f','o','r','m','a','t','i','o','n',0};
static const unicode	MSG_NO_SCHEMA[]		=	{'S','k','e','l','e','t','o','n',' ','d','r','i','v','e','r',' ',
												'd','o','e','s','n','\'','t',' ','s','u','p','p','o','r','t',' ',
												't','h','e',' ','g','e','t','S','c','h','e','m','a',' ',
												'o','p','e','r','a','t','i','o','n',0};

//description of example init values we want to extract from the init document
//passed to init(). See skel_options.xml
const CommonImpl::ShimParamDesc CSkeletonDriver::DRIVER_PARAMS[] = 
{
	{TEXT_OPTION_1,STRING_TYPE,false},
	{TEXT_OPTION_2,INT_TYPE,false},
	{0,0,false}
};

//macro required by DirXML interface definition (see define_interface.h)
DEFINE_IMPL(CSkeletonDriver,DriverShim);

//++
//=========================================================================
// Purpose:
//		Constructor
// Notes:
//=========================================================================
CSkeletonDriver::CSkeletonDriver()
//--
	:	common("CSkeletonDriver"),
		subscriptionShim(0),
		publicationShim(0),
		authParams(0),
		params(0)
{ 
}

//++
//=========================================================================
// Purpose:
//		Destructor
// Notes:
//=========================================================================
CSkeletonDriver::~CSkeletonDriver()
//--
{
	delete	subscriptionShim;
	delete	publicationShim;
	delete	authParams;
	delete	params;
}

//++
//=========================================================================
// Purpose:
//		DriverShim interface method, called by DirXML to allow driver to
//		perform common initialization.
// Notes:
//=========================================================================
XmlDocument * METHOD_CALL			//result document
CSkeletonDriver::init(
	XmlDocument * initParameters)	//document containing any driver initialization parms
//--
{
#ifndef	NO_CPP_EXCEPTIONS
	try
	{
#endif	
		common.tracer->trace("init");
		//NOTE: only trace this here to test the trace facility...The document is already traced
		//by the engine so it will appear twice in the trace screen
		common.tracer->trace(initParameters);
		//create an output document for returning status to DirXML
		Element * output = NdsDtd_newOutputDocument();
		//setup the shared authentication information
		authParams = common.getAuthenticationParams(initParameters->getDocument());
		//if we don't have any authentication parameters, report a warning. This
		//is intended to serve as an example of how to report a warning or an error. A real
		//driver may or may not need to information in the authentication parameters.
		if (authParams->authenticationId == 0 &&
			authParams->authenticationContext == 0 &&
			authParams->applicationPassword == 0)
		{
			//a real driver would probably want to report a fatal error if required
			//parameters are not supplied
			NdsDtd_addStatus(output,STATUS_LEVEL_WARNING,MSG_NO_AUTH_INFO,0);
		}
		//get any non-authentication options from the init document
		params = common.getShimParams(initParameters->getDocument(),TEXT_DRIVER,DRIVER_PARAMS);
		//create the objects that do the real work
		subscriptionShim = new SkeletonSubscriber(authParams);
		publicationShim = new SkeletonPublisher(authParams);
		//if we didn't already add a status element, add a success
		if (common.getFirstElementByTagName(output, common.ndsDtd->TAG_STATUS) == 0)
		{
			NdsDtd_addStatus(output,STATUS_LEVEL_SUCCESS,0,0);
		}
		//return the status document
		return common.setReturnDocument(output->getOwnerDocument());
#ifndef	NO_CPP_EXCEPTIONS
	} catch (ShimException e)
	{
		return	common.setReturnDocument(common.createStatusDocument(STATUS_LEVEL_FATAL,e.getMessage()));
	} catch (...)
	{
		//something bad happened...
		return	common.setReturnDocument(common.createStatusDocument(STATUS_LEVEL_FATAL,MSG_BAD));
	}
#endif
}

//++
//=========================================================================
// Purpose:
//		DriverShim interface method, called by DirXML to instruct driver
//		to shutdown.
// Notes:
//		Cleanup may be performed here, but any returned
//		document must be cleaned up either in destroy() or the destructor.
//
//		In addition, the publisher must obviously not be destroyed until
//		it returns from start(). Once it has returned from start() it is
//		save to destroy the publisher since DirXML will not call any
//		publisher methods again. Generally, it is safest to destroy the
//		publisher in destroy() or the driver destructor since destroy()
//		will not be called until and unless the publisher returns from 
//		start().
//=========================================================================
XmlDocument * METHOD_CALL			//result document
CSkeletonDriver::shutdown(
	XmlDocument * reason)			//document containing reason for shutdown
//--
{
#ifndef	NO_CPP_EXCEPTIONS
	try
	{
#endif	
		common.tracer->trace("shutdown");
		common.tracer->trace(reason);
			//create an output document so the subscriber can write its state info
		Element * output = NdsDtd_newOutputDocument();
		subscriptionShim->setState(output);
		// shutdown whatever needs shutting down
		// which will always include telling the publication shim to return control
		// back to the caller
		publicationShim->stop();
		//add a successful status
		NdsDtd_addStatus(output,STATUS_LEVEL_SUCCESS,0,0);
		//return the status and state to DirXML
		return common.setReturnDocument(output->getOwnerDocument());
#ifndef	NO_CPP_EXCEPTIONS
	} catch (...)
	{
		//something bad happened...
		return	common.setReturnDocument(common.createStatusDocument(STATUS_LEVEL_FATAL,MSG_BAD));
	}
#endif	
}

//++
//=========================================================================
// Purpose:
//		DriverShim interface method, called by DirXML to obtain an interface
//		to a SubscriptionShim implementation.
// Notes:
//=========================================================================
SubscriptionShim * METHOD_CALL			//pointer to SubscriptionShim implementation
CSkeletonDriver::getSubscriptionShim(void)
//--
{
	common.tracer->trace("getSubscriptionShim");
	return subscriptionShim;
}

//++
//=========================================================================
// Purpose:
//		DriverShim interface method, called by DirXML to obtain an interface
//		to a PublicationShim implementation.
// Notes:
//=========================================================================
PublicationShim * METHOD_CALL			//pointer to PublicationShim implementation
CSkeletonDriver::getPublicationShim(void)
//--
{
	common.tracer->trace("getPublicationShim");
	return publicationShim;
}

//++
//=========================================================================
// Purpose:
//			Get an XML representation of the application schema from the
//			driver. This will not be called if init()/shutdown() are called
//			for a driver instance, and vice-versa.
// Notes:	
//=========================================================================
XmlDocument * METHOD_CALL			//document containing schema description, or error return
CSkeletonDriver::getSchema(
	XmlDocument * initParameters)	//XDS initialization parameters
//--
{
#ifndef	NO_CPP_EXCEPTIONS
	try
	{
#endif	
		common.tracer->trace("getSchema");
		//setup the shared authentication information
		authParams = common.getAuthenticationParams(initParameters->getDocument());
		//a driver that supports a real application would do whatever is necessary to
		//create an XDS schema description document and return it. For example, it might
		//create an instance of the Subscriber object and query the application schema.
		//If the application has an invariant schema, the driver might just have an embedded XML document
		//describing the schema in XDS terms. This embedded document could then be returned to DirXML
		//wrapped by an XmlDocument object.
		//
		//However, since we are just a skeleton...
		//
		//Create a return document that says we can't do it. Note that this will
		//cause DirXML to display a warning in DSTrace that it is unable to read the application schema
		return common.setReturnDocument(common.createStatusDocument(STATUS_LEVEL_ERROR,MSG_NO_SCHEMA));
#ifndef	NO_CPP_EXCEPTIONS
	} catch (ShimException e)
	{
		return	common.setReturnDocument(common.createStatusDocument(STATUS_LEVEL_FATAL,e.getMessage()));
	} catch (...)
	{
		//something bad happened...
		return	common.setReturnDocument(common.createStatusDocument(STATUS_LEVEL_FATAL,MSG_BAD));
	}
#endif	
}

//++
//=========================================================================
// Purpose:
//		DriverShim interface method, called by DirXML to allow driver to
//		cleanup all resources connected with the driver, including the
//		driver object.
// Notes:
//=========================================================================
void METHOD_CALL
CSkeletonDriver::destroy(void)
//--
{
	common.tracer->trace("destroy");
	delete	this;
}

