/*************************************************************************
 *
 *  $RCSfile: SServices.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2003/06/30 15:21:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  the BSD license.
 *  
 *  Copyright (c) 2003 by Sun Microsystems, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *     
 *************************************************************************/

#include "SDriver.hxx"
#ifndef _CPPUHELPER_FACTORY_HXX_
#include <cppuhelper/factory.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

using namespace connectivity::skeleton;
using ::rtl::OUString;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::registry::XRegistryKey;
using ::com::sun::star::lang::XSingleServiceFactory;
using ::com::sun::star::lang::XMultiServiceFactory;

typedef Reference< XSingleServiceFactory > (SAL_CALL *createFactoryFunc)
		(
			const Reference< XMultiServiceFactory > & rServiceManager,
			const OUString & rComponentName, 
			::cppu::ComponentInstantiation pCreateFunction,
			const Sequence< OUString > & rServiceNames,
			rtl_ModuleCount* _pTemp
		);

//***************************************************************************************
//
// Die vorgeschriebene C-Api muss erfuellt werden!
// Sie besteht aus drei Funktionen, die von dem Modul exportiert werden muessen.
//

//---------------------------------------------------------------------------------------
void REGISTER_PROVIDER(
		const OUString& aServiceImplName, 
		const Sequence< OUString>& Services, 
		const Reference< ::com::sun::star::registry::XRegistryKey > & xKey)
{
	OUString aMainKeyName;
	aMainKeyName = OUString::createFromAscii("/");
	aMainKeyName += aServiceImplName;
	aMainKeyName += OUString::createFromAscii("/UNO/SERVICES");

	Reference< ::com::sun::star::registry::XRegistryKey >  xNewKey( xKey->createKey(aMainKeyName) );
	OSL_ENSURE(xNewKey.is(), "SKELETON::component_writeInfo : could not create a registry key !");

	for (sal_uInt32 i=0; i<Services.getLength(); ++i)
		xNewKey->createKey(Services[i]);
}


//---------------------------------------------------------------------------------------
struct ProviderRequest
{
	Reference< XSingleServiceFactory > xRet;
	Reference< XMultiServiceFactory > const xServiceManager;
	OUString const sImplementationName;

	ProviderRequest(
		void* pServiceManager,
		sal_Char const* pImplementationName
	)
	: xServiceManager(reinterpret_cast<XMultiServiceFactory*>(pServiceManager))
	, sImplementationName(OUString::createFromAscii(pImplementationName))
	{
	}

	inline
	sal_Bool CREATE_PROVIDER(
				const OUString& Implname, 
				const Sequence< OUString > & Services, 
				::cppu::ComponentInstantiation Factory,
				createFactoryFunc creator
			)
	{
		if (!xRet.is() && (Implname == sImplementationName))
		try																							
		{																								
			xRet = creator( xServiceManager, sImplementationName,Factory, Services,0);	
		}
		catch(...)
		{
		}
		return xRet.is();
	}
	
	void* getProvider() const { return xRet.get(); }
};

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
				const sal_Char	**ppEnvTypeName,
				uno_Environment	**ppEnv
			)
{
	*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//---------------------------------------------------------------------------------------
extern "C" sal_Bool SAL_CALL component_writeInfo(
				void* pServiceManager,
				void* pRegistryKey
			)
{
	if (pRegistryKey) 
	try 
	{
		Reference< ::com::sun::star::registry::XRegistryKey > xKey(reinterpret_cast< ::com::sun::star::registry::XRegistryKey*>(pRegistryKey));

		REGISTER_PROVIDER(
			SkeletonDriver::getImplementationName_Static(), 
			SkeletonDriver::getSupportedServiceNames_Static(), xKey);		

		return sal_True;
	}
	catch (::com::sun::star::registry::InvalidRegistryException& )
	{
		OSL_ENSURE(sal_False, "SKELETON::component_writeInfo : could not create a registry key ! ## InvalidRegistryException !");
	}

	return sal_False;
}

//---------------------------------------------------------------------------------------
extern "C" void* SAL_CALL component_getFactory(
					const sal_Char* pImplementationName,
					void* pServiceManager,
					void* pRegistryKey)
{
	void* pRet = 0;
	if (pServiceManager)
	{
		ProviderRequest aReq(pServiceManager,pImplementationName);

		aReq.CREATE_PROVIDER(
			SkeletonDriver::getImplementationName_Static(), 
			SkeletonDriver::getSupportedServiceNames_Static(),
			SkeletonDriver_CreateInstance, ::cppu::createSingleFactory) 
		;

		if(aReq.xRet.is())
			aReq.xRet->acquire();

		pRet = aReq.getProvider();
	}

	return pRet;
};


