/**************************************************************
 * 
 * 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_filter.hxx"

#include <stdio.h>

#include <cppuhelper/factory.hxx>
#include <cppuhelper/servicefactory.hxx>
#include <cppuhelper/implbase4.hxx>
#include <cppuhelper/implbase.hxx>

#include <osl/time.h>
#include <osl/conditn.h>
#include <tools/urlobj.hxx>
#include <osl/module.h>
#include <osl/file.hxx>
#include <osl/process.h>

#include <com/sun/star/lang/XComponent.hpp>

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Type.hxx>

#include <com/sun/star/beans/PropertyValue.hpp>

#include <com/sun/star/xml/sax/XParser.hpp>
#include <com/sun/star/xml/sax/InputSource.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#include <com/sun/star/xml/sax/SAXException.hpp>
#include <com/sun/star/xml/XImportFilter.hpp>
#include <com/sun/star/xml/XExportFilter.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/util/XMacroExpander.hpp>

#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/io/XActiveDataSource.hpp>
#include <com/sun/star/io/XActiveDataSink.hpp>
#include <com/sun/star/io/XActiveDataControl.hpp>
#include <com/sun/star/io/XStreamListener.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/lang/EventObject.hpp>
#include <com/sun/star/util/XStringSubstitution.hpp>
#include <com/sun/star/beans/NamedValue.hpp>


#include "uof2splitter.hxx"
#include "uof2storage.hxx"
#include "uof2merge.hxx"

using namespace ::rtl;
using namespace ::cppu;
using namespace ::osl;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::xml;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::util;

namespace XSLT {


class XSLTFilter : public WeakImplHelper4< XImportFilter, XExportFilter, XDocumentHandler, XStreamListener>
{
public:

    // ctor...
    XSLTFilter( const Reference< XMultiServiceFactory > &r );

    // XStreamListener
    virtual void SAL_CALL error(const Any& a) throw (RuntimeException);
    virtual void SAL_CALL closed() throw (RuntimeException);
    virtual void SAL_CALL terminated() throw (RuntimeException);
    virtual void SAL_CALL started() throw (RuntimeException);
    virtual void SAL_CALL disposing(const EventObject& e) throw (RuntimeException);


    // XImportFilter
    virtual sal_Bool SAL_CALL importer(
            const Sequence<PropertyValue>& aSourceData,
            const Reference<XDocumentHandler>& xHandler,
            const Sequence<OUString>& msUserData)
        throw(RuntimeException);

    // XExportFilter
    virtual sal_Bool SAL_CALL exporter(
            const Sequence<PropertyValue>& aSourceData,
            const Sequence<OUString>& msUserData)
        throw(RuntimeException);

    // XDocumentHandler
    virtual void SAL_CALL startDocument()
        throw (SAXException,RuntimeException);
    virtual void SAL_CALL endDocument()
        throw (SAXException, RuntimeException);
    virtual void SAL_CALL startElement(const OUString& str, const Reference<XAttributeList>& attriblist)
        throw (SAXException,RuntimeException);
    virtual void SAL_CALL endElement(const OUString& str)
        throw (SAXException, RuntimeException);
    virtual void SAL_CALL characters(const OUString& str)
        throw (SAXException, RuntimeException);
    virtual void SAL_CALL ignorableWhitespace(const OUString& str)
        throw (SAXException, RuntimeException);
    virtual void SAL_CALL processingInstruction(const OUString& str, const OUString& str2)
        throw (com::sun::star::xml::sax::SAXException,RuntimeException);
    virtual void SAL_CALL setDocumentLocator(const Reference<XLocator>& doclocator)
        throw (SAXException,RuntimeException);

private:
    // the UNO ServiceFactory
    Reference< XMultiServiceFactory > m_rServiceFactory;

    // DocumentHandler interface of the css::xml::sax::Writer service
    Reference < XExtendedDocumentHandler > m_rDocumentHandler;
    Reference < XOutputStream > m_rOutputStream;

    // controls pretty-printing
    sal_Bool m_bPrettyPrint;

    Reference< XActiveDataControl > m_tcontrol;
    oslCondition m_cTransformed;

    sal_Bool m_bTerminated;
    sal_Bool m_bError;

    OUString m_aExportBaseUrl;
    OUString m_aOldBaseUrl;

    OUString rel2abs(const OUString&);
    OUString expandUrl(const OUString&);

    // for support of UOF v2.0
    Reference< XActiveDataControl > m_splitControl;
    Reference< XStream > m_rStream;

    bool isUOF2ExportStyleSheet( const OUString& rExportStyleSheet );

};

XSLTFilter::XSLTFilter( const Reference< XMultiServiceFactory > &r )
    : m_rServiceFactory( r )
    , m_rDocumentHandler()
    , m_rOutputStream()
    , m_bPrettyPrint( sal_True )
    , m_tcontrol()
    , m_cTransformed()
    , m_bTerminated( sal_False )
    , m_bError( sal_False )
    , m_aExportBaseUrl()
    , m_aOldBaseUrl()
    , m_splitControl()
    , m_rStream()
{
    m_cTransformed = osl_createCondition();
}

void XSLTFilter::disposing(const EventObject& ) throw (RuntimeException)
{
}

::rtl::OUString XSLTFilter::expandUrl( const ::rtl::OUString& sUrl )
{
    ::rtl::OUString sExpandedUrl;
    try
    {
        Reference< XComponentContext > xContext;
        Reference< XPropertySet > xProps( m_rServiceFactory, UNO_QUERY_THROW );
        xContext.set( xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "DefaultContext" ) ), UNO_QUERY_THROW );
        Reference< XMacroExpander > xMacroExpander( xContext->getValueByName( ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ), UNO_QUERY_THROW );
        sExpandedUrl = xMacroExpander->expandMacros(sUrl);
        sal_Int32 nPos = sExpandedUrl.indexOf(::rtl::OUString::createFromAscii("vnd.sun.star.expand:"));
        if ( nPos != -1 )
            sExpandedUrl = sExpandedUrl.copy(nPos+20);
    }
    catch (Exception&) {}
    return sExpandedUrl;
}

void XSLTFilter::started() throw (RuntimeException)
{
    osl_resetCondition(m_cTransformed);
}
void XSLTFilter::error(const Any& a) throw (RuntimeException)
{
    Exception e;
    if ( a >>= e)
    {
        OString aMessage("XSLTFilter::error was called: ");
        aMessage += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
        OSL_ENSURE(sal_False, aMessage);
    }
    m_bError = sal_True;
    osl_setCondition(m_cTransformed);
}
void XSLTFilter::closed() throw (RuntimeException)
{
    osl_setCondition(m_cTransformed);
}
void XSLTFilter::terminated() throw (RuntimeException)
{
    m_bTerminated = sal_True;
    osl_setCondition(m_cTransformed);
}

OUString XSLTFilter::rel2abs(const OUString& s)
{

	Reference< XStringSubstitution > subs(m_rServiceFactory->createInstance(
        OUString::createFromAscii("com.sun.star.util.PathSubstitution")), UNO_QUERY);
    OUString aWorkingDir = subs->getSubstituteVariableValue(OUString::createFromAscii("$(progurl)"));
    INetURLObject aObj( aWorkingDir );
    aObj.setFinalSlash();
    bool bWasAbsolute;
    INetURLObject aURL = aObj.smartRel2Abs(
        s, bWasAbsolute, false, INetURLObject::WAS_ENCODED, RTL_TEXTENCODING_UTF8, true );
    return aURL.GetMainURL(INetURLObject::NO_DECODE);
}



sal_Bool XSLTFilter::importer(
        const Sequence<PropertyValue>& aSourceData,
        const Reference<XDocumentHandler>& xHandler,
        const Sequence<OUString>& msUserData)
    throw (RuntimeException)
{
    if ( msUserData.getLength() < 5 )
        return sal_False;

    const OUString udStyleSheet = rel2abs( msUserData[4] );

    // get information from media descriptor
    // the imput stream that represents the imported file
    // is most important here since we need to supply it to
    // the sax parser that drives the supplied document handler
    const sal_Int32 nLength = aSourceData.getLength();
    OUString aFileName;
    OUString aURL;
    Reference< XInputStream > xInputStream;
    for ( sal_Int32 i = 0 ; i < nLength; i++)
    {
        const OUString aName = aSourceData[i].Name;
        if ( aName.equalsAscii( "InputStream" ) )
            aSourceData[i].Value >>= xInputStream;
        else if ( aName.equalsAscii( "FileName" ) )
            aSourceData[i].Value >>= aFileName;
        else if ( aName.equalsAscii( "URL" ) )
            aSourceData[i].Value >>= aURL;
    }
    OSL_ASSERT(xInputStream.is());
    if ( !xInputStream.is() )
        return sal_False;

    // create SAX parser that will read the document file
    // and provide events to xHandler passed to this call
	Reference < XParser > xSaxParser( m_rServiceFactory->createInstance(
        OUString::createFromAscii("com.sun.star.xml.sax.Parser")), UNO_QUERY );
    OSL_ASSERT(xSaxParser.is());
	if( !xSaxParser.is() )
	    return sal_False;

    // create transformer
    Sequence< Any > args(3);
    NamedValue nv;

    nv.Name = OUString::createFromAscii("StylesheetURL");
    nv.Value <<= expandUrl(udStyleSheet); args[0] <<= nv;
    nv.Name = OUString::createFromAscii("SourceURL");
    nv.Value <<= aURL; args[1] <<= nv;
    nv.Name = OUString::createFromAscii("SourceBaseURL");
    nv.Value <<= OUString(INetURLObject(aURL).getBase());
    args[2] <<= nv;

    m_tcontrol = Reference< XActiveDataControl >(m_rServiceFactory->createInstanceWithArguments(
        OUString::createFromAscii("com.sun.star.comp.JAXTHelper"), args), UNO_QUERY);

    OSL_ASSERT(xHandler.is());
    OSL_ASSERT(xInputStream.is());
    OSL_ASSERT(m_tcontrol.is());
    if (xHandler.is() && xInputStream.is() && m_tcontrol.is())
    {
        try
    	{
            // we want to be notified when the processing is done...
            m_tcontrol->addListener(Reference< XStreamListener >(this));

            // connect input to transformer
            Reference< XActiveDataSink > tsink(m_tcontrol, UNO_QUERY);
            //UOF v2 import
            UOF2Storage aUOF2Storage( m_rServiceFactory, xInputStream );
            if ( aUOF2Storage.isValidUOF2Doc() )
            {
                UOF2Merge aUOF2Merge( aUOF2Storage, m_rServiceFactory );
                aUOF2Merge.merge();
                tsink->setInputStream( aUOF2Merge.getMergedInStream() );
            }
            else
            {
                tsink->setInputStream( xInputStream );
            }

            // create pipe
            Reference< XOutputStream > pipeout(m_rServiceFactory->createInstance(
                OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY);
            Reference< XInputStream > pipein(pipeout, UNO_QUERY);

            //connect transformer to pipe
            Reference< XActiveDataSource > tsource(m_tcontrol, UNO_QUERY);
            tsource->setOutputStream(pipeout);

            // connect pipe to sax parser
	        InputSource aInput;
	        aInput.sSystemId = aURL;
            aInput.sPublicId = aURL;
	        aInput.aInputStream = pipein;

            // set doc handler
            xSaxParser->setDocumentHandler(xHandler);

            // transform
            m_tcontrol->start();
            // osl_waitCondition(m_cTransformed, 0);
            if (!m_bError && !m_bTerminated)
            {
                // parse the transformed XML buffered in the pipe
                xSaxParser->parseStream(aInput);
                osl_waitCondition(m_cTransformed, 0);
                return sal_True;
            } else {
                return sal_False;
            }
	    }
#if OSL_DEBUG_LEVEL > 0
	    catch( Exception& exc)
#else
	    catch( Exception& )
#endif
	    {
            // something went wrong
            OSL_ENSURE(0, OUStringToOString(exc.Message, RTL_TEXTENCODING_ASCII_US).getStr());
            return sal_False;
	    }
    } else
    {
        return sal_False;
    }
}

bool XSLTFilter::isUOF2ExportStyleSheet( const OUString& rExportStyleSheet )
{
    bool bIsUOFDocumentType = false;

    if ( rExportStyleSheet.endsWithAsciiL( "uof.xsl", 7 ) )
    {
        bIsUOFDocumentType = true;
    }

    return bIsUOFDocumentType;
}

sal_Bool XSLTFilter::exporter(
        const Sequence<PropertyValue>& aSourceData,
        const Sequence<OUString>& msUserData)
    throw (RuntimeException)
{
    if ( msUserData.getLength() < 6 )
        return sal_False;

    // get interesting values from user data
    const OUString udStyleSheet = rel2abs( msUserData[5] );

    // read source data
    // we are especially interested in the output stream
    // since that is where our xml-writer will push the data
    // from it's data-source interface
    OUString sURL;
    sal_Bool bIndent = sal_False;
    OUString aDoctypePublic;
    OUString aDoctypeSystem;
    {
        const sal_Int32 nLength = aSourceData.getLength();
        for ( sal_Int32 i = 0; i < nLength; i++ )
        {
            const OUString aName = aSourceData[i].Name;
            if ( aName.equalsAscii( "Indent" ) )
                aSourceData[i].Value >>= bIndent;
            if ( aName.equalsAscii( "DocType_Public" ) )
                aSourceData[i].Value >>= aDoctypePublic;
            if ( aName.equalsAscii( "DocType_System" ) )
                aSourceData[i].Value >>= aDoctypeSystem;
            if ( aName.equalsAscii( "OutputStream" ) )
                aSourceData[i].Value >>= m_rOutputStream;
            else if ( aName.equalsAscii( "URL" ) )
                aSourceData[i].Value >>= sURL;
            //UOF v2.0 export, get Stream for constructing UOF2Storage
            if ( aName.equalsAscii( "StreamForOutput" ) )
                aSourceData[i].Value >>= m_rStream;
        }
    }

    if (!m_rDocumentHandler.is())
    {
        // get the document writer
        m_rDocumentHandler = Reference<XExtendedDocumentHandler>(
            m_rServiceFactory->createInstance(
                OUString::createFromAscii("com.sun.star.xml.sax.Writer") ),
            UNO_QUERY);
    }

    // create transformer
    Sequence< Any > args(4);
    NamedValue nv;
    nv.Name = OUString::createFromAscii("StylesheetURL");
    nv.Value <<= expandUrl(udStyleSheet); args[0] <<= nv;
    nv.Name = OUString::createFromAscii("TargetURL");
    nv.Value <<= sURL; args[1] <<= nv;
    nv.Name = OUString::createFromAscii("DoctypeSystem");
    nv.Value <<= aDoctypeSystem; args[2] <<= nv;
    nv.Name = OUString::createFromAscii("DoctypePublic");
    nv.Value <<= aDoctypePublic; args[3] <<= nv;
    nv.Name = OUString::createFromAscii("TargetBaseURL");
    INetURLObject ineturl(sURL);
    ineturl.removeSegment();
    m_aExportBaseUrl = ineturl.GetMainURL(INetURLObject::NO_DECODE);
    nv.Value <<= m_aExportBaseUrl;
    args[3] <<= nv;

    m_tcontrol = Reference< XActiveDataControl >(m_rServiceFactory->createInstanceWithArguments(
        OUString::createFromAscii("com.sun.star.comp.JAXTHelper"), args), UNO_QUERY);

    OSL_ASSERT(m_rDocumentHandler.is());
    OSL_ASSERT(m_rOutputStream.is());
    OSL_ASSERT(m_tcontrol.is());
    if (m_tcontrol.is() && m_rOutputStream.is() && m_rDocumentHandler.is())
    {
        // we want to be notified when the processing is done...
        m_tcontrol->addListener(Reference< XStreamListener >(this));

        // create pipe
        Reference< XOutputStream > pipeout(m_rServiceFactory->createInstance(
            OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY);
        Reference< XInputStream > pipein(pipeout, UNO_QUERY);

        // connect sax writer to pipe
        Reference< XActiveDataSource > xmlsource(m_rDocumentHandler, UNO_QUERY);
        xmlsource->setOutputStream(pipeout);

        // connect pipe to transformer
        Reference< XActiveDataSink > tsink(m_tcontrol, UNO_QUERY);
        tsink->setInputStream(pipein);

        // connect transformer to output
        Reference< XActiveDataSource > tsource( m_tcontrol, UNO_QUERY );
        if ( isUOF2ExportStyleSheet( udStyleSheet ) )
        {
            // special handling for UOF 2

            if ( !m_rStream.is() )
            {
                return sal_False;
            }

            //creating pipe2
            Reference< XOutputStream > x_Pipeout(
                m_rServiceFactory->createInstance(
                    OUString::createFromAscii( "com.sun.star.io.Pipe" ) ), UNO_QUERY );
            Reference< XInputStream > x_Pipein( x_Pipeout, UNO_QUERY );

            // connect transformer to pipe2
            tsource->setOutputStream( x_Pipeout );

            UOF2Splitter* pSplitter = new UOF2Splitter( m_rServiceFactory, sURL );
            m_splitControl =
                Reference< XActiveDataControl >(
                    static_cast< cppu::OWeakObject* >( pSplitter ), UNO_QUERY );
            // connect pipe2 to splitter
            Reference< XActiveDataSink > splitsink( m_splitControl, UNO_QUERY );
            splitsink->setInputStream( x_Pipein );
            // connect splitter to output
            Reference< XActiveDataStreamer > splitout( m_splitControl, UNO_QUERY );
            splitout->setStream( m_rStream );
            m_rOutputStream = m_rStream->getOutputStream();
        }
        else
        {
            tsource->setOutputStream( m_rOutputStream );
        }

        // we will start receiving events after returning 'true'.
        // we will start the transformation as soon as we receive the startDocument event.
        return sal_True;
    }
    else
    {
        return sal_False;
    }
}

// for the DocumentHandler implementation, we just proxy the the
// events to the XML writer that we created upon the output stream
// that was provided by the XMLFilterAdapter
void XSLTFilter::startDocument() throw (SAXException,RuntimeException){
    OSL_ASSERT(m_rDocumentHandler.is());
    m_rDocumentHandler->startDocument();
    m_tcontrol->start();
}

void XSLTFilter::endDocument() throw (SAXException, RuntimeException){
    OSL_ASSERT(m_rDocumentHandler.is());
    m_rDocumentHandler->endDocument();

    // m_splitControl only set for UOF 2
    if ( m_splitControl.is() )
    {
        //when the inputStream(outputStream of filter) was closed, start to parse it.
        m_splitControl->start();
    }

    // wait for the transformer to finish
    osl_waitCondition(m_cTransformed, 0);
    if (!m_bError && !m_bTerminated)
    {
        return;
    } else {        
        throw RuntimeException();
    }

}

void XSLTFilter::startElement(const OUString& str, const Reference<XAttributeList>& attriblist)
    throw (SAXException, RuntimeException)
{
    OSL_ASSERT(m_rDocumentHandler.is());
//	SvXMLAttributeList* _attriblist=SvXMLAttributeList::getImplementation(attriblist);
    m_rDocumentHandler->startElement(str, attriblist);
}

void XSLTFilter::endElement(const OUString& str)
    throw (SAXException, RuntimeException)
{
    OSL_ASSERT(m_rDocumentHandler.is());
    m_rDocumentHandler->endElement(str);
}

void XSLTFilter::characters(const OUString& str)
    throw (SAXException, RuntimeException)
{
    OSL_ASSERT(m_rDocumentHandler.is());
    m_rDocumentHandler->characters(str);
}

void XSLTFilter::ignorableWhitespace(const OUString& str)
    throw (SAXException, RuntimeException)
{
    OSL_ASSERT(m_rDocumentHandler.is());
    if (!m_bPrettyPrint) return;
    m_rDocumentHandler->ignorableWhitespace(str);
}

void  XSLTFilter::processingInstruction(const OUString& str, const OUString& str2)
    throw (SAXException, RuntimeException)
{
    OSL_ASSERT(m_rDocumentHandler.is());
    m_rDocumentHandler->processingInstruction(str, str2);
}

void XSLTFilter::setDocumentLocator(const Reference<XLocator>& doclocator)
    throw (SAXException, RuntimeException)
{
    OSL_ASSERT(m_rDocumentHandler.is());
    m_rDocumentHandler->setDocumentLocator(doclocator);
}

// --------------------------------------
// Component management
// --------------------------------------
#define SERVICE_NAME "com.sun.star.documentconversion.XSLTFilter"
#define IMPLEMENTATION_NAME "com.sun.star.comp.documentconversion.XSLTFilter"

static Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r)
{
    return Reference< XInterface >(( OWeakObject *)new XSLTFilter(r));
}

static Sequence< OUString > getSupportedServiceNames()
{
	static Sequence < OUString > *pNames = 0;
	if( ! pNames )
	{
		MutexGuard guard( Mutex::getGlobalMutex() );
		if( !pNames )
		{
			static Sequence< OUString > seqNames(1);
			    seqNames.getArray()[0] = OUString::createFromAscii(SERVICE_NAME);
			pNames = &seqNames;
		}
	}
	return *pNames;
}

}

using namespace XSLT;

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

sal_Bool SAL_CALL component_writeInfo(void * /* pServiceManager */, void * pRegistryKey )
{
    if (pRegistryKey)
	{
        try
        {
            Reference< XRegistryKey > xNewKey(
                reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
                    OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) );

            const Sequence< OUString > & rSNL = getSupportedServiceNames();
            const OUString * pArray = rSNL.getConstArray();
            for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
                xNewKey->createKey( pArray[nPos] );

            return sal_True;
        }
        catch (InvalidRegistryException &)
        {
            OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
        }
    }
    return sal_False;
}

void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ )
{
    void * pRet = 0;

    if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0)
    {
        Reference< XSingleServiceFactory > xFactory( createSingleFactory(
            reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
            OUString::createFromAscii( pImplName ),
            CreateInstance, getSupportedServiceNames() ) );

        if (xFactory.is())
        {
            xFactory->acquire();
            pRet = xFactory.get();
        }
    }
    return pRet;
}

} // extern "C"
