/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cppuhelper.hxx"
#include <osl/diagnose.h>
#include <osl/mutex.hxx>
#include <cppuhelper/weak.hxx>
#include <cppuhelper/component.hxx>
#include <cppuhelper/factory.hxx>
#ifndef _CPPUHELPER_IMPLBASE3_HXX
#include <cppuhelper/implbase3.hxx>
#endif
#include <cppuhelper/typeprovider.hxx>
#include <rtl/unload.h>

#include "cppuhelper/propshlp.hxx"

#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/lang/XSingleComponentFactory.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/loader/XImplementationLoader.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/uno/XUnloadingPreference.hpp>
#include "com/sun/star/beans/PropertyAttribute.hpp"

#include <memory>

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )


using namespace osl;
using namespace rtl;
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::loader;
using namespace com::sun::star::registry;

namespace cppu
{

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class OSingleFactoryHelper
	: public XServiceInfo
	, public XSingleServiceFactory
    , public lang::XSingleComponentFactory
	, public XUnloadingPreference
{
public:
	OSingleFactoryHelper(
		const Reference<XMultiServiceFactory > & rServiceManager,
		const OUString & rImplementationName_,
		ComponentInstantiation pCreateFunction_,
        ComponentFactoryFunc fptr,
		const Sequence< OUString > * pServiceNames_ )
		SAL_THROW( () )
		: xSMgr( rServiceManager )
		, pCreateFunction( pCreateFunction_ )
        , m_fptr( fptr )
		, aImplementationName( rImplementationName_ )
		{
			if( pServiceNames_ )
				aServiceNames = *pServiceNames_;
		}

	// old function, only for backward compatibility
	OSingleFactoryHelper(
		const Reference<XMultiServiceFactory > & rServiceManager,
		const OUString & rImplementationName_ )
		SAL_THROW( () )
		: xSMgr( rServiceManager )
		, pCreateFunction( NULL )
        , m_fptr( 0 )
		, aImplementationName( rImplementationName_ )
		{}

    virtual ~OSingleFactoryHelper();

	// XInterface
	Any SAL_CALL queryInterface( const Type & rType )
		throw(::com::sun::star::uno::RuntimeException);

	// XSingleServiceFactory
    Reference<XInterface > SAL_CALL createInstance()
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const Sequence<Any>& Arguments)
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    // XSingleComponentFactory
    virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
        Reference< XComponentContext > const & xContext )
        throw (Exception, RuntimeException);
    virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
        Sequence< Any > const & rArguments,
        Reference< XComponentContext > const & xContext )
        throw (Exception, RuntimeException);

	// XServiceInfo
	OUString SAL_CALL getImplementationName()
		throw(::com::sun::star::uno::RuntimeException);
    sal_Bool SAL_CALL supportsService(const OUString& ServiceName)
		throw(::com::sun::star::uno::RuntimeException);
    Sequence< OUString > SAL_CALL getSupportedServiceNames(void)
		throw(::com::sun::star::uno::RuntimeException);

protected:
	/**
	 * Create an instance specified by the factory. The one instance logic is implemented
	 * in the createInstance and createInstanceWithArguments methods.
	 * @return the newly created instance. Do not return a previous (one instance) instance.
	 */
	virtual Reference<XInterface >	createInstanceEveryTime(
        Reference< XComponentContext > const & xContext )
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

	Reference<XMultiServiceFactory > xSMgr;
	ComponentInstantiation			 pCreateFunction;
    ComponentFactoryFunc             m_fptr;
	Sequence< OUString >			 aServiceNames;
	OUString						 aImplementationName;
};
OSingleFactoryHelper::~OSingleFactoryHelper()
{
}


//-----------------------------------------------------------------------------
Any OSingleFactoryHelper::queryInterface( const Type & rType )
	throw(::com::sun::star::uno::RuntimeException)
{
    return ::cppu::queryInterface(
        rType,
        static_cast< XSingleComponentFactory * >( this ),
        static_cast< XSingleServiceFactory * >( this ),
        static_cast< XServiceInfo * >( this ) ,
        static_cast< XUnloadingPreference * >( this ));
}

// OSingleFactoryHelper
Reference<XInterface > OSingleFactoryHelper::createInstanceEveryTime(
    Reference< XComponentContext > const & xContext )
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
    if (m_fptr)
    {
        return (*m_fptr)( xContext );
    }
    else if( pCreateFunction )
    {
        if (xContext.is())
        {
            Reference< lang::XMultiServiceFactory > xContextMgr(
                xContext->getServiceManager(), UNO_QUERY );
            if (xContextMgr.is())
                return (*pCreateFunction)( xContextMgr );
        }
        return (*pCreateFunction)( xSMgr );
    }
	else
    {
		return Reference< XInterface >();
    }
}

// XSingleServiceFactory
Reference<XInterface > OSingleFactoryHelper::createInstance()
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
    return createInstanceWithContext( Reference< XComponentContext >() );
}

// XSingleServiceFactory
Reference<XInterface > OSingleFactoryHelper::createInstanceWithArguments(
	const Sequence<Any>& Arguments )
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
    return createInstanceWithArgumentsAndContext(
        Arguments, Reference< XComponentContext >() );
}

// XSingleComponentFactory
//__________________________________________________________________________________________________
Reference< XInterface > OSingleFactoryHelper::createInstanceWithContext(
    Reference< XComponentContext > const & xContext )
    throw (Exception, RuntimeException)
{
    return createInstanceEveryTime( xContext );
}
//__________________________________________________________________________________________________
Reference< XInterface > OSingleFactoryHelper::createInstanceWithArgumentsAndContext(
    Sequence< Any > const & rArguments,
    Reference< XComponentContext > const & xContext )
    throw (Exception, RuntimeException)
{
	Reference< XInterface > xRet( createInstanceWithContext( xContext ) );

	Reference< lang::XInitialization > xInit( xRet, UNO_QUERY );
    // always call initialize, even if there are no arguments.
    // #i63511# / 2006-03-27 / frank.schoenheit@sun.com
	if (xInit.is())
    {
		xInit->initialize( rArguments );
    }
	else
    {
		if ( rArguments.getLength() )
        {
            // dispose the here created UNO object before throwing out exception
            // to avoid risk of memory leaks #i113722#
            Reference<XComponent> xComp( xRet, UNO_QUERY );
            if (xComp.is())
                xComp->dispose();

		    throw lang::IllegalArgumentException(
                OUString( RTL_CONSTASCII_USTRINGPARAM("cannot pass arguments to component => no XInitialization implemented!") ),
                Reference< XInterface >(), 0 );
		}
    }

	return xRet;
}

// XServiceInfo
OUString OSingleFactoryHelper::getImplementationName()
	throw(::com::sun::star::uno::RuntimeException)
{
	return aImplementationName;
}

// XServiceInfo
sal_Bool OSingleFactoryHelper::supportsService(
    const OUString& ServiceName )
	throw(::com::sun::star::uno::RuntimeException)
{
	Sequence< OUString > seqServices = getSupportedServiceNames();
	const OUString * pServices = seqServices.getConstArray();
	for( sal_Int32 i = 0; i < seqServices.getLength(); i++ )
		if( pServices[i] == ServiceName )
			return sal_True;

	return sal_False;
}

// XServiceInfo
Sequence< OUString > OSingleFactoryHelper::getSupportedServiceNames(void)
	throw(::com::sun::star::uno::RuntimeException)
{
	return aServiceNames;
}


//----------------------------------------------------------------------
//----------------------------------------------------------------------
//----------------------------------------------------------------------
struct OFactoryComponentHelper_Mutex
{
	Mutex	aMutex;
};

class OFactoryComponentHelper
	: public OFactoryComponentHelper_Mutex
	, public OComponentHelper
	, public OSingleFactoryHelper
{
public:
	OFactoryComponentHelper(
		const Reference<XMultiServiceFactory > & rServiceManager,
		const OUString & rImplementationName_,
		ComponentInstantiation pCreateFunction_,
        ComponentFactoryFunc fptr,
		const Sequence< OUString > * pServiceNames_,
		sal_Bool bOneInstance_ = sal_False )
		SAL_THROW( () )
		: OComponentHelper( aMutex )
		, OSingleFactoryHelper( rServiceManager, rImplementationName_, pCreateFunction_, fptr, pServiceNames_ )
		, bOneInstance( bOneInstance_ )
		, pModuleCount(0)
		{
		}

	// Used by the createXXXFactory functions. The argument pModCount is used to  prevent the unloading of the module
	// which contains pCreateFunction_
	OFactoryComponentHelper(
		const Reference<XMultiServiceFactory > & rServiceManager,
		const OUString & rImplementationName_,
		ComponentInstantiation pCreateFunction_,
        ComponentFactoryFunc fptr,
		const Sequence< OUString > * pServiceNames_,
		rtl_ModuleCount * pModCount,
		sal_Bool bOneInstance_ = sal_False )
		SAL_THROW( () )
		: OComponentHelper( aMutex )
		, OSingleFactoryHelper( rServiceManager, rImplementationName_, pCreateFunction_, fptr, pServiceNames_ )
		, bOneInstance( bOneInstance_ )
		, pModuleCount(pModCount)
		{
			if(pModuleCount)
				pModuleCount->acquire( pModuleCount);
		}

	// old function, only for backward compatibility
	OFactoryComponentHelper(
		const Reference<XMultiServiceFactory > & rServiceManager,
		const OUString & rImplementationName_,
		sal_Bool bOneInstance_ = sal_False )
		SAL_THROW( () )
		: OComponentHelper( aMutex )
		, OSingleFactoryHelper( rServiceManager, rImplementationName_ )
		, bOneInstance( bOneInstance_ )
		, pModuleCount(0)
		{
		}

	~OFactoryComponentHelper()
	{
		if(pModuleCount)
			pModuleCount->release( pModuleCount);
	}

	// XInterface
	Any SAL_CALL queryInterface( const Type & rType )
		throw(::com::sun::star::uno::RuntimeException);
	void SAL_CALL acquire() throw()
		{ OComponentHelper::acquire(); }
	void SAL_CALL release() throw()
		{ OComponentHelper::release(); }

	// XSingleServiceFactory
    Reference<XInterface > SAL_CALL createInstance()
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
	Reference<XInterface > SAL_CALL createInstanceWithArguments( const Sequence<Any>& Arguments )
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    // XSingleComponentFactory
    virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
        Reference< XComponentContext > const & xContext )
        throw (Exception, RuntimeException);
    virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
        Sequence< Any > const & rArguments,
        Reference< XComponentContext > const & xContext )
        throw (Exception, RuntimeException);

	// XTypeProvider
	virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException);
	virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException);

	// XAggregation
	Any SAL_CALL queryAggregation( const Type & rType )
		throw(::com::sun::star::uno::RuntimeException);

	// XUnloadingPreference
	virtual sal_Bool SAL_CALL releaseOnNotification()
		throw(::com::sun::star::uno::RuntimeException);

	// OComponentHelper
	void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);

private:
	Reference<XInterface >	xTheInstance;
	sal_Bool				bOneInstance;
	rtl_ModuleCount	*		pModuleCount;
protected:
	// needed for implementing XUnloadingPreference in inheriting classes
	sal_Bool isOneInstance() {return bOneInstance;}
	sal_Bool isInstance() {return xTheInstance.is();}
};


Any SAL_CALL OFactoryComponentHelper::queryInterface( const Type & rType )
	throw(::com::sun::star::uno::RuntimeException)
{
	if( rType == ::getCppuType( (Reference<XUnloadingPreference>*)0))
	{
		return makeAny(
            Reference< XUnloadingPreference >(
                static_cast< XUnloadingPreference * >(this) ) );
	}
	return OComponentHelper::queryInterface( rType );
}

// XAggregation
Any OFactoryComponentHelper::queryAggregation( const Type & rType )
	throw(::com::sun::star::uno::RuntimeException)
{
	Any aRet( OComponentHelper::queryAggregation( rType ) );
	return (aRet.hasValue() ? aRet : OSingleFactoryHelper::queryInterface( rType ));
}

// XTypeProvider
Sequence< Type > OFactoryComponentHelper::getTypes()
	throw (::com::sun::star::uno::RuntimeException)
{
    Type ar[ 4 ];
    ar[ 0 ] = ::getCppuType( (const Reference< XSingleServiceFactory > *)0 );
    ar[ 1 ] = ::getCppuType( (const Reference< XServiceInfo > *)0 );
    ar[ 2 ] = ::getCppuType( (const Reference< XUnloadingPreference > *)0 );

    if (m_fptr)
        ar[ 3 ] = ::getCppuType( (const Reference< XSingleComponentFactory > *)0 );

    return Sequence< Type >( ar, m_fptr ? 4 : 3 );
}

Sequence< sal_Int8 > OFactoryComponentHelper::getImplementationId()
	throw (::com::sun::star::uno::RuntimeException)
{
	static OImplementationId * pId = 0;
	if (! pId)
	{
		MutexGuard aGuard( Mutex::getGlobalMutex() );
		if (! pId)
		{
			static OImplementationId aId;
			pId = &aId;
		}
	}
	return pId->getImplementationId();
}

// XSingleServiceFactory
Reference<XInterface > OFactoryComponentHelper::createInstance()
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
	if( bOneInstance )
	{
		if( !xTheInstance.is() )
        {
            MutexGuard aGuard( aMutex );
            if( !xTheInstance.is() )
                xTheInstance = OSingleFactoryHelper::createInstance();
        }
		return xTheInstance;
	}
	return OSingleFactoryHelper::createInstance();
}

Reference<XInterface > OFactoryComponentHelper::createInstanceWithArguments(
	const Sequence<Any>& Arguments )
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
	if( bOneInstance )
	{
		if( !xTheInstance.is() )
        {
            MutexGuard aGuard( aMutex );
//          OSL_ENSURE( !xTheInstance.is(), "### arguments will be ignored!" );
            if( !xTheInstance.is() )
                xTheInstance = OSingleFactoryHelper::createInstanceWithArguments( Arguments );
        }
        return xTheInstance;
	}
	return OSingleFactoryHelper::createInstanceWithArguments( Arguments );
}

// XSingleComponentFactory
//__________________________________________________________________________________________________
Reference< XInterface > OFactoryComponentHelper::createInstanceWithContext(
    Reference< XComponentContext > const & xContext )
    throw (Exception, RuntimeException)
{
	if( bOneInstance )
	{
		if( !xTheInstance.is() )
        {
            MutexGuard aGuard( aMutex );
//          OSL_ENSURE( !xTheInstance.is(), "### context will be ignored!" );
            if( !xTheInstance.is() )
                xTheInstance = OSingleFactoryHelper::createInstanceWithContext( xContext );
        }
		return xTheInstance;
	}
	return OSingleFactoryHelper::createInstanceWithContext( xContext );
}
//__________________________________________________________________________________________________
Reference< XInterface > OFactoryComponentHelper::createInstanceWithArgumentsAndContext(
    Sequence< Any > const & rArguments,
    Reference< XComponentContext > const & xContext )
    throw (Exception, RuntimeException)
{
	if( bOneInstance )
	{
		if( !xTheInstance.is() )
        {
            MutexGuard aGuard( aMutex );
//          OSL_ENSURE( !xTheInstance.is(), "### context and arguments will be ignored!" );
            if( !xTheInstance.is() )
                xTheInstance = OSingleFactoryHelper::createInstanceWithArgumentsAndContext( rArguments, xContext );
        }
		return xTheInstance;
	}
	return OSingleFactoryHelper::createInstanceWithArgumentsAndContext( rArguments, xContext );
}


// OComponentHelper
void OFactoryComponentHelper::dispose()
	throw(::com::sun::star::uno::RuntimeException)
{
	OComponentHelper::dispose();

	Reference<XInterface > x;
	{
		// do not delete in the guard section
		MutexGuard aGuard( aMutex );
		x = xTheInstance;
		xTheInstance = Reference<XInterface >();
	}
	// if it is a component call dispose at the component
	Reference<XComponent > xComp( x, UNO_QUERY );
	if( xComp.is() )
		xComp->dispose();
}

// XUnloadingPreference
// This class is used for single factories, component factories and
// one-instance factories. Depending on the usage this function has
// to return different values.
// one-instance factory: sal_False
// single factory: sal_True
// component factory: sal_True
sal_Bool SAL_CALL OFactoryComponentHelper::releaseOnNotification() throw(::com::sun::star::uno::RuntimeException)
{
	if( bOneInstance)
		return sal_False;
	return sal_True;
}


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class ORegistryFactoryHelper : public OFactoryComponentHelper,
                               public OPropertySetHelper
    
{
public:
	ORegistryFactoryHelper(
		const Reference<XMultiServiceFactory > & rServiceManager,
		const OUString & rImplementationName_,
		const Reference<XRegistryKey > & xImplementationKey_,
		sal_Bool bOneInstance_ = sal_False ) SAL_THROW( () )
            : OFactoryComponentHelper(
                rServiceManager, rImplementationName_, 0, 0, 0, bOneInstance_ ),
              OPropertySetHelper( OComponentHelper::rBHelper ),
              xImplementationKey( xImplementationKey_ )
		{}
    
    // XInterface
    virtual Any SAL_CALL queryInterface( Type const & type )
        throw (RuntimeException);
    virtual void SAL_CALL acquire() throw ();
    virtual void SAL_CALL release() throw ();
    // XTypeProvider
    virtual Sequence< Type > SAL_CALL getTypes()
        throw (RuntimeException);
    // XPropertySet
    virtual Reference< beans::XPropertySetInfo > SAL_CALL getPropertySetInfo()
        throw (RuntimeException);

    // OPropertySetHelper
    virtual IPropertyArrayHelper & SAL_CALL getInfoHelper();
    virtual sal_Bool SAL_CALL convertFastPropertyValue(
        Any & rConvertedValue, Any & rOldValue,
        sal_Int32 nHandle, Any const & rValue )
        throw (lang::IllegalArgumentException);
    virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
        sal_Int32 nHandle, Any const & rValue )
        throw (Exception);
    using OPropertySetHelper::getFastPropertyValue;
    virtual void SAL_CALL getFastPropertyValue(
        Any & rValue, sal_Int32 nHandle ) const;
    
	// OSingleFactoryHelper
	Reference<XInterface > createInstanceEveryTime(
        Reference< XComponentContext > const & xContext )
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

	// XSingleServiceFactory
	Reference<XInterface > SAL_CALL createInstanceWithArguments(const Sequence<Any>& Arguments)
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    // XSingleComponentFactory
    Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
        Sequence< Any > const & rArguments,
        Reference< XComponentContext > const & xContext )
        throw (Exception, RuntimeException);

	// XServiceInfo
    Sequence< OUString > SAL_CALL getSupportedServiceNames(void)
		throw(::com::sun::star::uno::RuntimeException);
	// XUnloadingPreference
	sal_Bool SAL_CALL releaseOnNotification()
		throw( RuntimeException);


private:
	Reference< XInterface > createModuleFactory()
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

	/** The registry key of the implementation section */
	Reference<XRegistryKey >	xImplementationKey;
	/** The factory created with the loader. */
	Reference<XSingleComponentFactory >	xModuleFactory;
	Reference<XSingleServiceFactory >	xModuleFactoryDepr;
    Reference< beans::XPropertySetInfo > m_xInfo;
    ::std::auto_ptr< IPropertyArrayHelper > m_property_array_helper;
protected:
    using OPropertySetHelper::getTypes;
};

// XInterface
//______________________________________________________________________________
Any SAL_CALL ORegistryFactoryHelper::queryInterface(
    Type const & type ) throw (RuntimeException)
{
    Any ret( OFactoryComponentHelper::queryInterface( type ) );
    if (ret.hasValue())
        return ret;
    else
        return OPropertySetHelper::queryInterface( type );
}

//______________________________________________________________________________
void ORegistryFactoryHelper::acquire() throw ()
{
    OFactoryComponentHelper::acquire();
}

//______________________________________________________________________________
void ORegistryFactoryHelper::release() throw ()
{
    OFactoryComponentHelper::release();
}

// XTypeProvider
//______________________________________________________________________________
Sequence< Type > ORegistryFactoryHelper::getTypes() throw (RuntimeException)
{
    Sequence< Type > types( OFactoryComponentHelper::getTypes() );
    sal_Int32 pos = types.getLength();
    types.realloc( pos + 3 );
    Type * p = types.getArray();
    p[ pos++ ] = ::getCppuType(
        reinterpret_cast< Reference< beans::XMultiPropertySet > const * >(0) );
    p[ pos++ ] = ::getCppuType(
        reinterpret_cast< Reference< beans::XFastPropertySet > const * >(0) );
    p[ pos++ ] = ::getCppuType(
        reinterpret_cast< Reference< beans::XPropertySet > const * >(0) );
    return types;
}

// XPropertySet
//______________________________________________________________________________
Reference< beans::XPropertySetInfo >
ORegistryFactoryHelper::getPropertySetInfo() throw (RuntimeException)
{
    ::osl::MutexGuard guard( aMutex );
    if (! m_xInfo.is())
        m_xInfo = createPropertySetInfo( getInfoHelper() );
    return m_xInfo;
}

// OPropertySetHelper
//______________________________________________________________________________
IPropertyArrayHelper & ORegistryFactoryHelper::getInfoHelper()
{
    ::osl::MutexGuard guard( aMutex );
    if (m_property_array_helper.get() == 0)
    {
        beans::Property prop(
            OUSTR("ImplementationKey") /* name */,
            0 /* handle */,
            ::getCppuType( &xImplementationKey ),
            beans::PropertyAttribute::READONLY |
            beans::PropertyAttribute::OPTIONAL );
        m_property_array_helper.reset(
            new ::cppu::OPropertyArrayHelper( &prop, 1 ) );
    }
    return *m_property_array_helper.get();
}

//______________________________________________________________________________
sal_Bool ORegistryFactoryHelper::convertFastPropertyValue(
    Any &, Any &, sal_Int32, Any const & )
    throw (lang::IllegalArgumentException)
{
    OSL_ENSURE( 0, "unexpected!" );
    return false;
}

//______________________________________________________________________________
void ORegistryFactoryHelper::setFastPropertyValue_NoBroadcast(
    sal_Int32, Any const & )
    throw (Exception)
{
    throw beans::PropertyVetoException(
        OUSTR("unexpected: only readonly properties!"),
        static_cast< OWeakObject * >(this) );
}

//______________________________________________________________________________
void ORegistryFactoryHelper::getFastPropertyValue(
    Any & rValue, sal_Int32 nHandle ) const
{
    if (nHandle == 0)
    {
        rValue <<= xImplementationKey;
    }
    else
    {
        rValue.clear();
        throw beans::UnknownPropertyException(
            OUSTR("unknown property!"), static_cast< OWeakObject * >(
                const_cast< ORegistryFactoryHelper * >(this) ) );
    }
}

Reference<XInterface > ORegistryFactoryHelper::createInstanceEveryTime(
    Reference< XComponentContext > const & xContext )
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
	if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
	{
        Reference< XInterface > x( createModuleFactory() );
        if (x.is())
        {
            MutexGuard aGuard( aMutex );
            if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
            {
                xModuleFactory.set( x, UNO_QUERY );
                xModuleFactoryDepr.set( x, UNO_QUERY );
            }
        }
	}
	if( xModuleFactory.is() )
    {
		return xModuleFactory->createInstanceWithContext( xContext );
    }
    else if( xModuleFactoryDepr.is() )
    {
		return xModuleFactoryDepr->createInstance();
    }

	return Reference<XInterface >();
}

Reference<XInterface > SAL_CALL ORegistryFactoryHelper::createInstanceWithArguments(
    const Sequence<Any>& Arguments )
    throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
	if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
	{
        Reference< XInterface > x( createModuleFactory() );
        if (x.is())
        {
            MutexGuard aGuard( aMutex );
            if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
            {
                xModuleFactory.set( x, UNO_QUERY );
                xModuleFactoryDepr.set( x, UNO_QUERY );
            }
        }
	}
    if( xModuleFactoryDepr.is() )
    {
		return xModuleFactoryDepr->createInstanceWithArguments( Arguments );
    }
	else if( xModuleFactory.is() )
    {
#if OSL_DEBUG_LEVEL > 1
        OSL_TRACE( "### no context ORegistryFactoryHelper::createInstanceWithArgumentsAndContext()!\n" );
#endif
		return xModuleFactory->createInstanceWithArgumentsAndContext( Arguments, Reference< XComponentContext >() );
    }

	return Reference<XInterface >();
}

Reference< XInterface > ORegistryFactoryHelper::createInstanceWithArgumentsAndContext(
    Sequence< Any > const & rArguments,
    Reference< XComponentContext > const & xContext )
    throw (Exception, RuntimeException)
{
	if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
	{
        Reference< XInterface > x( createModuleFactory() );
        if (x.is())
        {
            MutexGuard aGuard( aMutex );
            if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
            {
                xModuleFactory.set( x, UNO_QUERY );
                xModuleFactoryDepr.set( x, UNO_QUERY );
            }
        }
	}
	if( xModuleFactory.is() )
    {
		return xModuleFactory->createInstanceWithArgumentsAndContext( rArguments, xContext );
    }
    else if( xModuleFactoryDepr.is() )
    {
#if OSL_DEBUG_LEVEL > 1
        if (xContext.is())
        {
            OSL_TRACE( "### ignoring context calling ORegistryFactoryHelper::createInstanceWithArgumentsAndContext()!\n" );
        }
#endif
		return xModuleFactoryDepr->createInstanceWithArguments( rArguments );
    }

	return Reference<XInterface >();
}


// OSingleFactoryHelper
Reference< XInterface > ORegistryFactoryHelper::createModuleFactory()
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
    OUString aActivatorUrl;
    OUString aActivatorName;
    OUString aLocation;

    Reference<XRegistryKey > xActivatorKey = xImplementationKey->openKey(
        OUString( RTL_CONSTASCII_USTRINGPARAM("/UNO/ACTIVATOR") ) );
    if( xActivatorKey.is() && xActivatorKey->getValueType() == RegistryValueType_ASCII )
    {
        aActivatorUrl = xActivatorKey->getAsciiValue();

        OUString tmpActivator(aActivatorUrl.getStr());
        sal_Int32 nIndex = 0;
        aActivatorName = tmpActivator.getToken(0, ':', nIndex );

        Reference<XRegistryKey > xLocationKey = xImplementationKey->openKey(
            OUString( RTL_CONSTASCII_USTRINGPARAM("/UNO/LOCATION") ) );
        if( xLocationKey.is() && xLocationKey->getValueType() == RegistryValueType_ASCII )
            aLocation = xLocationKey->getAsciiValue();
    }
    else
    {
        // old style"url"
        // the location of the program code of the implementation
        Reference<XRegistryKey > xLocationKey = xImplementationKey->openKey(
            OUString( RTL_CONSTASCII_USTRINGPARAM("/UNO/URL") ) );
        // is the the key of the right type ?
        if( xLocationKey.is() && xLocationKey->getValueType() == RegistryValueType_ASCII )
        {
            // one implementation found -> try to activate
            aLocation = xLocationKey->getAsciiValue();

            // search protocol delemitter
            sal_Int32 nPos = aLocation.indexOf(
                OUString( RTL_CONSTASCII_USTRINGPARAM("://") ) );
            if( nPos != -1 )
            {
                aActivatorName = aLocation.copy( 0, nPos );
                if( aActivatorName.compareToAscii( "java" ) == 0 )
                    aActivatorName = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.Java") );
                else if( aActivatorName.compareToAscii( "module" ) == 0 )
                    aActivatorName = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.SharedLibrary") );
                aLocation = aLocation.copy( nPos + 3 );
            }
        }
    }

	Reference< XInterface >	xFactory;
    if( aActivatorName.getLength() != 0 )
    {
        Reference<XInterface > x = xSMgr->createInstance( aActivatorName );
        Reference<XImplementationLoader > xLoader( x, UNO_QUERY );
        Reference<XInterface > xMF;
        if (xLoader.is())
        {
            xFactory = xLoader->activate( aImplementationName, aActivatorUrl, aLocation, xImplementationKey );
        }
    }
	return xFactory;
}

// XServiceInfo
Sequence< OUString > ORegistryFactoryHelper::getSupportedServiceNames(void)
	throw(::com::sun::star::uno::RuntimeException)
{
	MutexGuard aGuard( aMutex );
	if( aServiceNames.getLength() == 0 )
	{
		// not yet loaded
		try
		{
			Reference<XRegistryKey > xKey = xImplementationKey->openKey(
				OUString( RTL_CONSTASCII_USTRINGPARAM("UNO/SERVICES") ) );

			if (xKey.is())
			{
				// length of prefix. +1 for the '/' at the end
				sal_Int32 nPrefixLen = xKey->getKeyName().getLength() + 1;

				// Full qualified names like "IMPLEMENTATIONS/TEST/UNO/SERVICES/com.sun.star..."
				Sequence<OUString> seqKeys = xKey->getKeyNames();
				OUString* pKeys = seqKeys.getArray();
				for( sal_Int32 i = 0; i < seqKeys.getLength(); i++ )
					pKeys[i] = pKeys[i].copy(nPrefixLen);

				aServiceNames = seqKeys;
			}
		}
		catch (InvalidRegistryException &)
		{
		}
	}
	return aServiceNames;
}

sal_Bool SAL_CALL ORegistryFactoryHelper::releaseOnNotification() throw(::com::sun::star::uno::RuntimeException)
{
	sal_Bool retVal= sal_True;
	if( isOneInstance() && isInstance())
	{
		retVal= sal_False;
	}
	else if( ! isOneInstance())
	{
		// try to delegate
		if( xModuleFactory.is())
		{
			Reference<XUnloadingPreference> xunloading( xModuleFactory, UNO_QUERY);
			if( xunloading.is())
				retVal= xunloading->releaseOnNotification();
		}
		else if( xModuleFactoryDepr.is())
		{
			Reference<XUnloadingPreference> xunloading( xModuleFactoryDepr, UNO_QUERY);
			if( xunloading.is())
				retVal= xunloading->releaseOnNotification();
		}
	}
	return retVal;
}

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

class OFactoryProxyHelper : public WeakImplHelper3< XServiceInfo, XSingleServiceFactory,
													XUnloadingPreference >
{
	Reference<XSingleServiceFactory >	xFactory;

public:

	OFactoryProxyHelper(
		const Reference<XMultiServiceFactory > & /*rServiceManager*/,
		const Reference<XSingleServiceFactory > & rFactory )
		SAL_THROW( () )
		: xFactory( rFactory )
		{}

	// XSingleServiceFactory
    Reference<XInterface > SAL_CALL createInstance()
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    Reference<XInterface > SAL_CALL createInstanceWithArguments(const Sequence<Any>& Arguments)
		throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

	// XServiceInfo
	OUString SAL_CALL getImplementationName()
		throw(::com::sun::star::uno::RuntimeException);
    sal_Bool SAL_CALL supportsService(const OUString& ServiceName)
		throw(::com::sun::star::uno::RuntimeException);
    Sequence< OUString > SAL_CALL getSupportedServiceNames(void)
		throw(::com::sun::star::uno::RuntimeException);
	//XUnloadingPreference
	sal_Bool SAL_CALL releaseOnNotification()
		throw(::com::sun::star::uno::RuntimeException);

};

// XSingleServiceFactory
Reference<XInterface > OFactoryProxyHelper::createInstance()
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
	return xFactory->createInstance();
}

// XSingleServiceFactory
Reference<XInterface > OFactoryProxyHelper::createInstanceWithArguments
(
	const Sequence<Any>& Arguments
)
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
	return xFactory->createInstanceWithArguments( Arguments );
}

// XServiceInfo
OUString OFactoryProxyHelper::getImplementationName()
	throw(::com::sun::star::uno::RuntimeException)
{
	Reference<XServiceInfo > xInfo( xFactory, UNO_QUERY  );
	if( xInfo.is() )
		return xInfo->getImplementationName();
	return OUString();
}

// XServiceInfo
sal_Bool OFactoryProxyHelper::supportsService(const OUString& ServiceName)
	throw(::com::sun::star::uno::RuntimeException)
{
	Reference<XServiceInfo > xInfo( xFactory, UNO_QUERY  );
	if( xInfo.is() )
		return xInfo->supportsService( ServiceName );
	return sal_False;
}

// XServiceInfo
Sequence< OUString > OFactoryProxyHelper::getSupportedServiceNames(void)
	throw(::com::sun::star::uno::RuntimeException)
{
	Reference<XServiceInfo > xInfo( xFactory, UNO_QUERY  );
	if( xInfo.is() )
		return xInfo->getSupportedServiceNames();
	return Sequence< OUString >();
}

sal_Bool SAL_CALL OFactoryProxyHelper::releaseOnNotification() throw(::com::sun::star::uno::RuntimeException)
{

	Reference<XUnloadingPreference> pref( xFactory, UNO_QUERY);
	if( pref.is())
		return pref->releaseOnNotification();
	return sal_True;
}


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// global function
Reference<XSingleServiceFactory > SAL_CALL createSingleFactory(
	const Reference<XMultiServiceFactory > & rServiceManager,
	const OUString & rImplementationName,
	ComponentInstantiation pCreateFunction,
	const Sequence< OUString > & rServiceNames,
	rtl_ModuleCount *pModCount )
	SAL_THROW( () )
{
	return new OFactoryComponentHelper(
        rServiceManager, rImplementationName, pCreateFunction, 0, &rServiceNames, pModCount, sal_False );
}

// global function
Reference<XSingleServiceFactory > SAL_CALL createFactoryProxy(
	const Reference<XMultiServiceFactory > & rServiceManager,
	const Reference<XSingleServiceFactory > & rFactory )
	SAL_THROW( () )
{
	return new OFactoryProxyHelper(
        rServiceManager, rFactory );
}

// global function
Reference<XSingleServiceFactory > SAL_CALL createOneInstanceFactory(
	const Reference<XMultiServiceFactory > & rServiceManager,
	const OUString & rImplementationName,
	ComponentInstantiation pCreateFunction,
	const Sequence< OUString > & rServiceNames,
	rtl_ModuleCount *pModCount )
	SAL_THROW( () )
{
	return new OFactoryComponentHelper(
        rServiceManager, rImplementationName, pCreateFunction, 0, &rServiceNames, pModCount, sal_True );
//	return new OFactoryUnloadableComponentHelper(
//		rServiceManager, rImplementationName, pCreateFunction, 0, &rServiceNames, pModCount, sal_True );
}

// global function
Reference<XSingleServiceFactory > SAL_CALL createSingleRegistryFactory(
	const Reference<XMultiServiceFactory > & rServiceManager,
	const OUString & rImplementationName,
	const Reference<XRegistryKey > & rImplementationKey )
	SAL_THROW( () )
{
	return new ORegistryFactoryHelper(
        rServiceManager, rImplementationName, rImplementationKey, sal_False );
}

// global function
Reference<XSingleServiceFactory > SAL_CALL createOneInstanceRegistryFactory(
	const Reference<XMultiServiceFactory > & rServiceManager,
	const OUString & rImplementationName,
	const Reference<XRegistryKey > & rImplementationKey )
	SAL_THROW( () )
{
	return new ORegistryFactoryHelper(
        rServiceManager, rImplementationName, rImplementationKey, sal_True );
}

//##################################################################################################
Reference< lang::XSingleComponentFactory > SAL_CALL createSingleComponentFactory(
	ComponentFactoryFunc fptr,
    OUString const & rImplementationName,
    Sequence< OUString > const & rServiceNames,
	rtl_ModuleCount * pModCount)
	SAL_THROW( () )
{
	return new OFactoryComponentHelper(
        Reference< XMultiServiceFactory >(), rImplementationName, 0, fptr, &rServiceNames, pModCount, sal_False );
}

Reference< lang::XSingleComponentFactory > SAL_CALL createOneInstanceComponentFactory(
	ComponentFactoryFunc fptr,
    OUString const & rImplementationName,
    Sequence< OUString > const & rServiceNames,
	rtl_ModuleCount * pModCount)
	SAL_THROW( () )
{
	return new OFactoryComponentHelper(
        Reference< XMultiServiceFactory >(), rImplementationName, 0, fptr, &rServiceNames, pModCount, sal_True );
}

}


