/**************************************************************
 * 
 * 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 <string.h>
#include <vector>

#include "rtl/process.h"
#include "rtl/bootstrap.hxx"
#include "rtl/random.h"
#include "rtl/string.hxx"
#include "rtl/ustrbuf.hxx"
#include "rtl/uri.hxx"
#if OSL_DEBUG_LEVEL > 0
#include "rtl/strbuf.hxx"
#endif
#include "osl/diagnose.h"
#include "osl/file.hxx"
#include "osl/module.hxx"
#include "osl/security.hxx"
#include "osl/thread.hxx"

#include "cppuhelper/shlib.hxx"
#include "cppuhelper/bootstrap.hxx"
#include "cppuhelper/component_context.hxx"
#include "cppuhelper/access_control.hxx"
#include "cppuhelper/findsofficepath.h"

#include <cppuhelper/com/sun/star/container/XElementAccess.hpp>

#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XCurrentContext.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/lang/XServiceInfo.hpp"
#include "com/sun/star/registry/XSimpleRegistry.hpp"
#include "com/sun/star/container/XSet.hpp"
#include "com/sun/star/beans/PropertyValue.hpp"
#include "com/sun/star/io/IOException.hpp"
#include "com/sun/star/bridge/UnoUrlResolver.hpp"
#include "com/sun/star/bridge/XUnoUrlResolver.hpp"

#include "macro_expander.hxx"

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
#define ARLEN(x) sizeof (x) / sizeof *(x)

void primeWeakMap( void); // as defined in primeweak.cxx

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace cppu
{

OUString const & get_this_libpath()
{
    static OUString s_path;
    if (0 == s_path.getLength())
    {
        OUString path;
        Module::getUrlFromAddress( reinterpret_cast<oslGenericFunction>(get_this_libpath), path );
        path = path.copy( 0, path.lastIndexOf( '/' ) );
        MutexGuard guard( Mutex::getGlobalMutex() );
        if (0 == s_path.getLength())
            s_path = path;
    }
    return s_path;
}

Bootstrap const & get_unorc() SAL_THROW( () )
{
    static rtlBootstrapHandle s_bstrap = 0;
    if (! s_bstrap)
    {
        OUString iniName(
            get_this_libpath() + OUSTR("/" SAL_CONFIGFILE("uno")) );
        rtlBootstrapHandle bstrap = rtl_bootstrap_args_open( iniName.pData );

        ClearableMutexGuard guard( Mutex::getGlobalMutex() );
        if (s_bstrap)
        {
            guard.clear();
            rtl_bootstrap_args_close( bstrap );
        }
        else
        {
            s_bstrap = bstrap;
        }
    }
    return *(Bootstrap const *)&s_bstrap;
}


void addFactories(
    char const * const * ppNames /* lib, implname, ..., 0 */,
    OUString const & bootstrapPath,
    Reference< lang::XMultiComponentFactory > const & xMgr,
    Reference< registry::XRegistryKey > const & xKey )
    SAL_THROW( (Exception) )
{
    Reference< container::XSet > xSet( xMgr, UNO_QUERY );
    OSL_ASSERT( xSet.is() );
    Reference< lang::XMultiServiceFactory > xSF( xMgr, UNO_QUERY );

    while (*ppNames)
    {
        OUString lib( OUString::createFromAscii( *ppNames++ ) );
        OUString implName( OUString::createFromAscii( *ppNames++ ) );
        
        Any aFac( makeAny( loadSharedLibComponentFactory(
                               lib, bootstrapPath, implName, xSF, xKey ) ) );
        xSet->insert( aFac );
#if OSL_DEBUG_LEVEL > 1
        if (xSet->has( aFac ))
        {
            Reference< lang::XServiceInfo > xInfo;
            if (aFac >>= xInfo)
            {
                ::fprintf(
                    stderr, "> implementation %s supports: ", ppNames[ -1 ] );
                Sequence< OUString > supported(
                    xInfo->getSupportedServiceNames() );
                for ( sal_Int32 nPos = supported.getLength(); nPos--; )
                {
                    OString str( OUStringToOString(
                        supported[ nPos ], RTL_TEXTENCODING_ASCII_US ) );
                    ::fprintf( stderr, nPos ? "%s, " : "%s\n", str.getStr() );
                }
            }
            else
            {
                ::fprintf(
                    stderr,
                    "> implementation %s provides NO lang::XServiceInfo!!!\n",
                    ppNames[ -1 ] );
            }
        }
#endif
#if OSL_DEBUG_LEVEL > 0
        if (! xSet->has( aFac ))
        {
            OStringBuffer buf( 64 );
            buf.append( "### failed inserting shared lib \"" );
            buf.append( ppNames[ -2 ] );
            buf.append( "\"!!!" );
            OString str( buf.makeStringAndClear() );
            OSL_ENSURE( 0, str.getStr() );
        }
#endif
    }
}

// private forward decl
Reference< lang::XMultiComponentFactory > bootstrapInitialSF(
    OUString const & rBootstrapPath )
    SAL_THROW( (Exception) );

Reference< XComponentContext > bootstrapInitialContext(
    Reference< lang::XMultiComponentFactory > const & xSF,
    Reference< registry::XSimpleRegistry > const & types_xRegistry,
    Reference< registry::XSimpleRegistry > const & services_xRegistry,
    OUString const & rBootstrapPath, Bootstrap const & bootstrap )
    SAL_THROW( (Exception) );

Reference< XComponentContext > SAL_CALL createInitialCfgComponentContext(
    ContextEntry_Init const * pEntries, sal_Int32 nEntries,
    Reference< XComponentContext > const & xDelegate )
    SAL_THROW( () );

Reference< registry::XSimpleRegistry > SAL_CALL createRegistryWrapper(
    const Reference< XComponentContext >& xContext );

namespace {

template< class T >
inline beans::PropertyValue createPropertyValue(
    OUString const & name, T const & value )
    SAL_THROW( () )
{
    return beans::PropertyValue(
        name, -1, makeAny( value ), beans::PropertyState_DIRECT_VALUE );
}

OUString findBoostrapArgument(
    const Bootstrap & bootstrap,
    const OUString & arg_name,
    sal_Bool * pFallenBack )
    SAL_THROW(())
{
    OUString result;

    OUString prefixed_arg_name = OUSTR("UNO_");
    prefixed_arg_name += arg_name.toAsciiUpperCase();

    // environment not set -> try relative to executable
    if(!bootstrap.getFrom(prefixed_arg_name, result))
    {
        if(pFallenBack)
            *pFallenBack = sal_True;

        OUString fileName;
        bootstrap.getIniName(fileName);

        // cut the rc extension
        OUStringBuffer result_buf( 64 );
        result_buf.append(
            fileName.copy(
                0, fileName.getLength() - strlen(SAL_CONFIGFILE(""))) );
        result_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("_") );
        result_buf.append( arg_name.toAsciiLowerCase() );
        result_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(".rdb") );
        result = result_buf.makeStringAndClear();
        
#if OSL_DEBUG_LEVEL > 1
        OString result_dbg =
            OUStringToOString(result, RTL_TEXTENCODING_ASCII_US);
        OString arg_name_dbg =
            OUStringToOString(arg_name, RTL_TEXTENCODING_ASCII_US);
        OSL_TRACE(
            "cppuhelper::findBoostrapArgument - "
            "setting %s relative to executable: %s\n",
            arg_name_dbg.getStr(),
            result_dbg.getStr() );
#endif
    }
    else
    {
        if(pFallenBack)
            *pFallenBack = sal_False;

#if OSL_DEBUG_LEVEL > 1
        OString prefixed_arg_name_dbg = OUStringToOString(
            prefixed_arg_name, RTL_TEXTENCODING_ASCII_US );
        OString result_dbg = OUStringToOString(
            result, RTL_TEXTENCODING_ASCII_US );
        OSL_TRACE(
            "cppuhelper::findBoostrapArgument - found %s in env: %s",
            prefixed_arg_name_dbg.getStr(),
            result_dbg.getStr() );
#endif
    }

    return result;
}

Reference< registry::XSimpleRegistry > nestRegistries(
    const OUString baseDir,
    const Reference< lang::XSingleServiceFactory > & xSimRegFac,
    const Reference< lang::XSingleServiceFactory > & xNesRegFac,
    OUString csl_rdbs,
    const OUString & write_rdb,
    sal_Bool forceWrite_rdb,
    sal_Bool bFallenBack )
    SAL_THROW((Exception))
{
    sal_Int32 index;
    Reference< registry::XSimpleRegistry > lastRegistry;

    if(write_rdb.getLength()) // is there a write registry given?
    {
        lastRegistry.set(xSimRegFac->createInstance(), UNO_QUERY);

        try
        {
            lastRegistry->open(write_rdb, sal_False, forceWrite_rdb);
        }
        catch (registry::InvalidRegistryException & invalidRegistryException)
        {
            (void) invalidRegistryException;
#if OSL_DEBUG_LEVEL > 1
            OString rdb_name_tmp = OUStringToOString(
                write_rdb, RTL_TEXTENCODING_ASCII_US);
            OString message_dbg = OUStringToOString(
                invalidRegistryException.Message, RTL_TEXTENCODING_ASCII_US);
            OSL_TRACE(
                "warning: couldn't open %s cause of %s",
                rdb_name_tmp.getStr(), message_dbg.getStr() );
#endif
        }

        if(!lastRegistry->isValid())
            lastRegistry.clear();
    }

    do
    {
        index = csl_rdbs.indexOf((sal_Unicode)' ');
        OUString rdb_name = (index == -1) ? csl_rdbs : csl_rdbs.copy(0, index);
        csl_rdbs = (index == -1) ? OUString() : csl_rdbs.copy(index + 1);

        if (! rdb_name.getLength())
            continue;

        bool optional = ('?' == rdb_name[ 0 ]);
        if (optional)
            rdb_name = rdb_name.copy( 1 );
        
        try
        {
            Reference<registry::XSimpleRegistry> simpleRegistry(
                xSimRegFac->createInstance(), UNO_QUERY_THROW );

            osl::FileBase::getAbsoluteFileURL(baseDir, rdb_name, rdb_name);
            simpleRegistry->open(rdb_name, sal_True, sal_False);

            if(lastRegistry.is())
            {
                Reference< registry::XSimpleRegistry > nestedRegistry(
                    xNesRegFac->createInstance(), UNO_QUERY );
                Reference< lang::XInitialization > nestedRegistry_xInit(
                    nestedRegistry, UNO_QUERY );

                Sequence<Any> aArgs(2);
                aArgs[0] <<= lastRegistry;
                aArgs[1] <<= simpleRegistry;

                nestedRegistry_xInit->initialize(aArgs);

                lastRegistry = nestedRegistry;
            }
            else
                lastRegistry = simpleRegistry;
        }
        catch(registry::InvalidRegistryException & invalidRegistryException)
        {
            if (! optional)
            {
                // if a registry was explicitly given, the exception shall fly
                if( ! bFallenBack )
                    throw;
            }

            (void) invalidRegistryException;
#if OSL_DEBUG_LEVEL > 1
            OString rdb_name_tmp = OUStringToOString(
                rdb_name, RTL_TEXTENCODING_ASCII_US );
            OString message_dbg = OUStringToOString(
                invalidRegistryException.Message, RTL_TEXTENCODING_ASCII_US );
            OSL_TRACE(
                "warning: couldn't open %s cause of %s",
                rdb_name_tmp.getStr(), message_dbg.getStr() );
#endif
        }
    }
    while(index != -1 && csl_rdbs.getLength()); // are there more rdbs in list?

    return lastRegistry;
}

Reference< XComponentContext >
SAL_CALL defaultBootstrap_InitialComponentContext(
    Bootstrap const & bootstrap )
    SAL_THROW( (Exception) )
{
    primeWeakMap();

    OUString bootstrapPath;
    if (!bootstrap.getFrom(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URE_INTERNAL_LIB_DIR")),
            bootstrapPath))
    {
        bootstrapPath = get_this_libpath();
    }

    OUString iniDir;
    osl_getProcessWorkingDir(&iniDir.pData);

    Reference<lang::XMultiComponentFactory> smgr_XMultiComponentFactory(
        bootstrapInitialSF(bootstrapPath) );
    Reference<lang::XMultiServiceFactory> smgr_XMultiServiceFactory(
        smgr_XMultiComponentFactory, UNO_QUERY );

    Reference<registry::XRegistryKey> xEmptyKey;
    Reference<lang::XSingleServiceFactory> xSimRegFac(
        loadSharedLibComponentFactory(
            OUSTR("bootstrap.uno" SAL_DLLEXTENSION), bootstrapPath,
            OUSTR("com.sun.star.comp.stoc.SimpleRegistry"),
            smgr_XMultiServiceFactory,
            xEmptyKey),
        UNO_QUERY);

    Reference<lang::XSingleServiceFactory> xNesRegFac(
        loadSharedLibComponentFactory(
            OUSTR("bootstrap.uno" SAL_DLLEXTENSION), bootstrapPath,
            OUSTR("com.sun.star.comp.stoc.NestedRegistry"),
            smgr_XMultiServiceFactory,
            xEmptyKey),
        UNO_QUERY);

    sal_Bool bFallenback_types;
    OUString cls_uno_types =
        findBoostrapArgument( bootstrap, OUSTR("TYPES"), &bFallenback_types );
    
    Reference<registry::XSimpleRegistry> types_xRegistry =
        nestRegistries(
            iniDir, xSimRegFac, xNesRegFac, cls_uno_types,
            OUString(), sal_False, bFallenback_types );
    
    // ==== bootstrap from services registry ====
    
    sal_Bool bFallenback_services;
    OUString cls_uno_services = findBoostrapArgument(
        bootstrap, OUSTR("SERVICES"), &bFallenback_services );
    
    sal_Bool fallenBackWriteRegistry;
    OUString write_rdb = findBoostrapArgument(
        bootstrap, OUSTR("WRITERDB"), &fallenBackWriteRegistry );
    if (fallenBackWriteRegistry)
    {
        // no standard write rdb anymore
        write_rdb = OUString();
    }
    
    Reference<registry::XSimpleRegistry> services_xRegistry = nestRegistries(
        iniDir, xSimRegFac, xNesRegFac, cls_uno_services, write_rdb,
        !fallenBackWriteRegistry, bFallenback_services );
    
    Reference< XComponentContext > xContext(
        bootstrapInitialContext(
            smgr_XMultiComponentFactory, types_xRegistry, services_xRegistry,
            bootstrapPath, bootstrap ) );
    
    // initialize sf
    Reference< lang::XInitialization > xInit(
        smgr_XMultiComponentFactory, UNO_QUERY );
    OSL_ASSERT( xInit.is() );
    Sequence< Any > aSFInit( 1 );
    aSFInit[ 0 ] <<= services_xRegistry;
    xInit->initialize( aSFInit );
    
    return xContext;
}

}

Reference< XComponentContext >
SAL_CALL defaultBootstrap_InitialComponentContext(
    OUString const & iniFile )
    SAL_THROW( (Exception) )
{
    Bootstrap bootstrap( iniFile );
    if (bootstrap.getHandle() == 0)
        throw io::IOException(OUSTR("Cannot open for reading: ") + iniFile, 0);
    return defaultBootstrap_InitialComponentContext( bootstrap );
}

Reference< XComponentContext >
SAL_CALL defaultBootstrap_InitialComponentContext()
    SAL_THROW( (Exception) )
{
    return defaultBootstrap_InitialComponentContext( get_unorc() );
}

BootstrapException::BootstrapException()
{
}

BootstrapException::BootstrapException( const ::rtl::OUString & rMessage )
    :m_aMessage( rMessage )
{
}

BootstrapException::BootstrapException( const BootstrapException & e )
{
    m_aMessage = e.m_aMessage;
}

BootstrapException::~BootstrapException()
{
}

BootstrapException & BootstrapException::operator=( const BootstrapException & e )
{
    m_aMessage = e.m_aMessage;
    return *this;
}

const ::rtl::OUString & BootstrapException::getMessage() const
{ 
    return m_aMessage; 
}

Reference< XComponentContext > SAL_CALL bootstrap()
{
    Reference< XComponentContext > xRemoteContext;

    try
    {
        char const * p1 = cppuhelper_detail_findSofficePath();
        if (p1 == NULL) {
            throw BootstrapException(
                OUSTR("no soffice installation found!"));
        }
        rtl::OUString p2;
        if (!rtl_convertStringToUString(
                &p2.pData, p1, strlen(p1), osl_getThreadTextEncoding(),
                (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
                 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
                 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
        {
            throw BootstrapException(
                OUSTR("bad characters in soffice installation path!"));
        }
        OUString path;
        if (osl::FileBase::getFileURLFromSystemPath(p2, path) !=
            osl::FileBase::E_None)
        {
            throw BootstrapException(
                OUSTR("cannot convert soffice installation path to URL!"));
        }
        if (path.getLength() > 0 && path[path.getLength() - 1] != '/') {
            path += OUSTR("/");
        }

        OUString uri;
        if (!Bootstrap::get(OUSTR("URE_BOOTSTRAP"), uri)) {
            Bootstrap::set(
                OUSTR("URE_BOOTSTRAP"),
                Bootstrap::encode(path + OUSTR(SAL_CONFIGFILE("fundamental"))));
        }

        // create default local component context
        Reference< XComponentContext > xLocalContext( 
            defaultBootstrap_InitialComponentContext() );
        if ( !xLocalContext.is() )
            throw BootstrapException( OUSTR( "no local component context!" ) );

        // create a random pipe name
        rtlRandomPool hPool = rtl_random_createPool();
        if ( hPool == 0 )
            throw BootstrapException( OUSTR( "cannot create random pool!" ) );
        sal_uInt8 bytes[ 16 ];
        if ( rtl_random_getBytes( hPool, bytes, ARLEN( bytes ) ) 
            != rtl_Random_E_None )
            throw BootstrapException( OUSTR( "random pool error!" ) );
        rtl_random_destroyPool( hPool );
        ::rtl::OUStringBuffer buf;
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "uno" ) );
        for ( sal_uInt32 i = 0; i < ARLEN( bytes ); ++i )
            buf.append( static_cast< sal_Int32 >( bytes[ i ] ) );
        OUString sPipeName( buf.makeStringAndClear() );

        // accept string
        OSL_ASSERT( buf.getLength() == 0 );
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "-accept=pipe,name=" ) );
        buf.append( sPipeName );
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ";urp;" ) );

        // arguments
        OUString args [] = {
            OUSTR( "-nologo" ),
            OUSTR( "-nodefault" ),
            OUSTR( "-norestore" ),
            OUSTR( "-nocrashreport" ),
            OUSTR( "-nolockcheck" ),
            buf.makeStringAndClear()
        };
        rtl_uString * ar_args [] = {
            args[ 0 ].pData,
            args[ 1 ].pData,
            args[ 2 ].pData,
            args[ 3 ].pData,
            args[ 4 ].pData,
            args[ 5 ].pData
        };
        ::osl::Security sec;

        // start office process
        oslProcess hProcess = 0;
        oslProcessError rc = osl_executeProcess(
            (path + OUSTR("soffice")).pData, ar_args, ARLEN( ar_args ),
            osl_Process_DETACHED,
            sec.getHandle(),
            0, // => current working dir
            0, 0, // => no env vars
            &hProcess );
        switch ( rc )
        {
            case osl_Process_E_None:
                osl_freeProcessHandle( hProcess );
                break;
            case osl_Process_E_NotFound:
                throw BootstrapException( OUSTR( "image not found!" ) );
            case osl_Process_E_TimedOut:
                throw BootstrapException( OUSTR( "timeout occurred!" ) );
            case osl_Process_E_NoPermission:
                throw BootstrapException( OUSTR( "permission denied!" ) );
            case osl_Process_E_Unknown:
                throw BootstrapException( OUSTR( "unknown error!" ) );
            case osl_Process_E_InvalidError:
            default:
                throw BootstrapException( OUSTR( "unmapped error!" ) );
        }

        // create a URL resolver
        Reference< bridge::XUnoUrlResolver > xUrlResolver(
            bridge::UnoUrlResolver::create( xLocalContext ) );

        // connection string
        OSL_ASSERT( buf.getLength() == 0 );
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "uno:pipe,name=" ) );
        buf.append( sPipeName );
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 
            ";urp;StarOffice.ComponentContext" ) );
        OUString sConnectString( buf.makeStringAndClear() );

        // wait until office is started
        for ( ; ; )
        {
            try
            {
                // try to connect to office
                xRemoteContext.set( 
                    xUrlResolver->resolve( sConnectString ), UNO_QUERY_THROW );
                break;
            }
            catch ( connection::NoConnectException & )
            {
                // wait 500 ms, then try to connect again
                TimeValue tv = { 0 /* secs */, 500000000 /* nanosecs */ };
                ::osl::Thread::wait( tv );
            }
        }
    }
    catch ( Exception & e )
    {
        throw BootstrapException( 
            OUSTR( "unexpected UNO exception caught: " ) + e.Message );
    }

    return xRemoteContext;
}

OUString bootstrap_expandUri(OUString const & uri) {
    static char const PREFIX[] = "vnd.sun.star.expand:";
    return uri.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(PREFIX))
        ? cppuhelper::detail::expandMacros(
            rtl::Uri::decode(
                uri.copy(RTL_CONSTASCII_LENGTH(PREFIX)),
                rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8))
        : uri;
}

} // namespace cppu
