From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- cpputools/Executable_sp2bv.mk | 26 ++ cpputools/Executable_uno.mk | 33 +++ cpputools/Makefile | 7 + cpputools/Module_cpputools.mk | 20 ++ cpputools/Package_uno_sh.mk | 16 ++ cpputools/README.md | 3 + cpputools/scripts/uno.sh | 47 ++++ cpputools/source/sp2bv/readme.txt | 8 + cpputools/source/sp2bv/sp2bv.cxx | 122 +++++++++ cpputools/source/unoexe/unoexe.cxx | 543 +++++++++++++++++++++++++++++++++++++ 10 files changed, 825 insertions(+) create mode 100644 cpputools/Executable_sp2bv.mk create mode 100644 cpputools/Executable_uno.mk create mode 100644 cpputools/Makefile create mode 100644 cpputools/Module_cpputools.mk create mode 100644 cpputools/Package_uno_sh.mk create mode 100644 cpputools/README.md create mode 100755 cpputools/scripts/uno.sh create mode 100644 cpputools/source/sp2bv/readme.txt create mode 100644 cpputools/source/sp2bv/sp2bv.cxx create mode 100644 cpputools/source/unoexe/unoexe.cxx (limited to 'cpputools') diff --git a/cpputools/Executable_sp2bv.mk b/cpputools/Executable_sp2bv.mk new file mode 100644 index 000000000..9ebbfaf3d --- /dev/null +++ b/cpputools/Executable_sp2bv.mk @@ -0,0 +1,26 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Executable_Executable,sp2bv)) + +$(eval $(call gb_Executable_use_api,sp2bv,\ + udkapi \ +)) + +$(eval $(call gb_Executable_use_libraries,sp2bv,\ + cppu \ + cppuhelper \ + sal \ +)) + +$(eval $(call gb_Executable_add_exception_objects,sp2bv,\ + cpputools/source/sp2bv/sp2bv \ +)) + +# vim:set noet sw=4 ts=4: diff --git a/cpputools/Executable_uno.mk b/cpputools/Executable_uno.mk new file mode 100644 index 000000000..ba3b22fb6 --- /dev/null +++ b/cpputools/Executable_uno.mk @@ -0,0 +1,33 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Executable_Executable,uno)) + +$(eval $(call gb_Executable_use_internal_comprehensive_api,uno,\ + udkapi \ +)) + +$(eval $(call gb_Executable_use_libraries,uno,\ + cppu \ + cppuhelper \ + sal \ + salhelper \ +)) + +$(eval $(call gb_Executable_use_externals,uno,\ + libxml2 \ +)) + +$(eval $(call gb_Executable_add_exception_objects,uno,\ + cpputools/source/unoexe/unoexe \ +)) + +$(eval $(call gb_Executable_add_default_nativeres,uno)) + +# vim:set noet sw=4 ts=4: diff --git a/cpputools/Makefile b/cpputools/Makefile new file mode 100644 index 000000000..ccb1c85a0 --- /dev/null +++ b/cpputools/Makefile @@ -0,0 +1,7 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/cpputools/Module_cpputools.mk b/cpputools/Module_cpputools.mk new file mode 100644 index 000000000..c71b68e44 --- /dev/null +++ b/cpputools/Module_cpputools.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Module_Module,cpputools)) + +$(eval $(call gb_Module_add_targets,cpputools,\ + $(call gb_CondExeSp2bv,Executable_sp2bv) \ + $(call gb_CondExeUno, \ + Executable_uno \ + Package_uno_sh \ + ) \ +)) + +# vim:set noet sw=4 ts=4: diff --git a/cpputools/Package_uno_sh.mk b/cpputools/Package_uno_sh.mk new file mode 100644 index 000000000..4df4d75f5 --- /dev/null +++ b/cpputools/Package_uno_sh.mk @@ -0,0 +1,16 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Package_Package,uno_sh,$(SRCDIR)/cpputools/scripts)) + +ifneq (,$(filter-out MACOSX WNT,$(OS))) +$(eval $(call gb_Package_add_file,uno_sh,$(LIBO_URE_BIN_FOLDER)/uno,uno.sh)) +endif + +# vim:set noet sw=4 ts=4: diff --git a/cpputools/README.md b/cpputools/README.md new file mode 100644 index 000000000..e6ab397cf --- /dev/null +++ b/cpputools/README.md @@ -0,0 +1,3 @@ +# Old Way of Doing Component Registration + +Nowadays replaced by another stand-alone UI and tools called UNO package. diff --git a/cpputools/scripts/uno.sh b/cpputools/scripts/uno.sh new file mode 100755 index 000000000..f5222ba1c --- /dev/null +++ b/cpputools/scripts/uno.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# 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 . +# + +# Pass -env arguments on to javaldx; needs to be fixed: +my_envargs= +for my_arg in "$@" ; do + case ${my_arg} in + -env:*) my_envargs="${my_envargs} ${my_arg}" ;; + esac +done + +# Extend the LD_LIBRARY_PATH for Java: +epath=$(dirname "$0") +if [ -x "${epath}/javaldx" ] ; then + jpath=$("${epath}/javaldx" $my_envargs) + if [ -n "${jpath}" ]; then + sd_platform=$(uname -s) + case $sd_platform in + AIX) + LIBPATH=${jpath}${LIBPATH:+:${LIBPATH}} + export LIBPATH + ;; + *) + LD_LIBRARY_PATH=${jpath}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} + export LD_LIBRARY_PATH + ;; + esac + fi +fi + +exec "$0.bin" "$@" diff --git a/cpputools/source/sp2bv/readme.txt b/cpputools/source/sp2bv/readme.txt new file mode 100644 index 000000000..f83b442c8 --- /dev/null +++ b/cpputools/source/sp2bv/readme.txt @@ -0,0 +1,8 @@ +This tool converts system paths into file urls and escapes it for use as +bootstrap variable. For example + +c:\program files\App$ +-> +file:///c:/program%20files/App$ +-> +file:///c:/program%20files/App\$ diff --git a/cpputools/source/sp2bv/sp2bv.cxx b/cpputools/source/sp2bv/sp2bv.cxx new file mode 100644 index 000000000..9998e7cdb --- /dev/null +++ b/cpputools/source/sp2bv/sp2bv.cxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include +#include +#include +#include +#include + +static bool hasOption(char const * szOption, int argc, char** argv); + + +#define HELP_TEXT \ +"SYNOPSIS \n\n" \ +"\tsp2bv [-h] [-?] string \n\n" \ +"DESCRIPTION\n\n" \ +"\tsp2bv stands for \"system path to bootstrap variable\"." \ +" First the system path is converted into a file URL. Then all " \ +"characters which have a special meaning in bootstrap variables, " \ +"such as \'$\' are escaped. The resulting string is written to " \ +"stdout and can be assigned to a bootstrap variable.\n" \ +"\n\n" \ +"OPTIONS \n\n" \ +"\tThe following options are supported: \n" \ +"-?\n " \ +"--help" \ +" Display help information.\n" + + +int main(int argc, char **argv) +{ + if( hasOption("--help",argc, argv) || hasOption("-h", argc, argv)) + { + fprintf(stdout, HELP_TEXT);// default + return 0; + } + + if (argc != 2) + { + fprintf(stdout, HELP_TEXT); + return -1; + } + + rtl_uString* pPath = nullptr; + rtl_string2UString( &pPath, argv[1], strlen(argv[1]), + osl_getThreadTextEncoding(),OSTRING_TO_OUSTRING_CVTFLAGS ); + + rtl_uString* pUrl = nullptr; + if (osl_getFileURLFromSystemPath(pPath, &pUrl) != osl_File_E_None) + return -1; +//escape the special characters + + sal_Unicode cEscapeChar = 0x5c; + rtl_uString* pBuffer = nullptr; + sal_Int32 nCapacity = 255; + rtl_uString_new_WithLength( &pBuffer, nCapacity ); + + const sal_Unicode* pCur = pUrl->buffer; + for (int i = 0; i != pUrl->length; i++) + { + switch( *pCur) + { + case '$': + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, &cEscapeChar, 1); + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, pCur, 1); + break; + case '{': + case '}': + case '\\': fprintf(stderr, "sp2vb: file URL contains invalid characters!\n"); + return -1; + default: + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, pCur, 1); + } + pCur ++; + } +//convert back to byte string so that we can print it. + rtl_String* pBootVar = nullptr; + rtl_uString2String( &pBootVar, pBuffer->buffer, pBuffer->length, + osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS); + + fprintf(stdout, "%s", pBootVar->buffer); + fflush(stdout); + + rtl_uString_release(pBuffer); + rtl_uString_release(pPath); + rtl_uString_release(pUrl); + rtl_string_release(pBootVar); + return 0; +} + + +static bool hasOption(char const * szOption, int argc, char** argv) +{ + bool retVal = false; + for(int i= 1; i < argc; i++) + { + if( ! strcmp(argv[i], szOption)) + { + retVal = true; + break; + } + } + return retVal; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cpputools/source/unoexe/unoexe.cxx b/cpputools/source/unoexe/unoexe.cxx new file mode 100644 index 000000000..f8e5aa12d --- /dev/null +++ b/cpputools/source/unoexe/unoexe.cxx @@ -0,0 +1,543 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace osl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::loader; +using namespace com::sun::star::registry; +using namespace com::sun::star::connection; +using namespace com::sun::star::bridge; +using namespace com::sun::star::container; + +namespace unoexe +{ + +static bool s_quiet = false; + +static void out( const char * pText ) +{ + if (! s_quiet) + fputs( pText, stderr ); +} + +static void out( std::u16string_view rText ) +{ + if (! s_quiet) + { + OString aText( OUStringToOString( rText, RTL_TEXTENCODING_ASCII_US ) ); + fputs( aText.getStr(), stderr ); + } +} + +const char arUsingText[] = +"\nusing:\n\n" +"uno [-c ComponentImplementationName -l LocationUrl | -s ServiceName]\n" +" [-u uno:(socket[,host=HostName][,port=nnn]|pipe[,name=PipeName]);;Name\n" +" [--singleaccept] [--singleinstance]]\n" +" [--quiet]\n" +" [-- Argument1 Argument2 ...]\n"; + +/// @throws RuntimeException +static bool readOption( OUString * pValue, const char * pOpt, + sal_uInt32 * pnIndex, const OUString & aArg) +{ + static const OUStringLiteral dash(u"-"); + if(!aArg.startsWith(dash)) + return false; + + OUString aOpt = OUString::createFromAscii( pOpt ); + + if (aArg.getLength() < aOpt.getLength()) + return false; + + if (aOpt.equalsIgnoreAsciiCase( aArg.subView(1, aArg.getLength()-1) )) + { + // take next argument + ++(*pnIndex); + + rtl_getAppCommandArg(*pnIndex, &pValue->pData); + if (*pnIndex >= rtl_getAppCommandArgCount() || pValue->subView(1) == dash) + { + throw RuntimeException( "incomplete option \"-" + aOpt + "\" given!" ); + } + SAL_INFO("cpputools.unoexe", "> identified option -" << pOpt << " = " << aArg); + ++(*pnIndex); + return true; + } + else if (aArg.indexOf(aOpt) == 1) + { + *pValue = aArg.copy(1 + aOpt.getLength()); + SAL_INFO("cpputools.unoexe", "> identified option -" << pOpt << " = " << aArg); + ++(*pnIndex); + + return true; + } + return false; +} + +static bool readOption( bool * pbOpt, const char * pOpt, + sal_uInt32 * pnIndex, std::u16string_view aArg) +{ + OUString aOpt = OUString::createFromAscii(pOpt); + + if(o3tl::starts_with(aArg, u"--") && aOpt == aArg.substr(2)) + { + ++(*pnIndex); + *pbOpt = true; + SAL_INFO("cpputools.unoexe", "> identified option --" << pOpt); + return true; + } + return false; +} + +/// @throws Exception +template< class T > +static void createInstance( + Reference< T > & rxOut, + const Reference< XComponentContext > & xContext, + const OUString & rServiceName ) +{ + Reference< XMultiComponentFactory > xMgr( xContext->getServiceManager() ); + Reference< XInterface > x( xMgr->createInstanceWithContext( rServiceName, xContext ) ); + + if (! x.is()) + { + throw RuntimeException( "cannot get service instance \"" + rServiceName + "\"!" ); + } + + rxOut.set( x.get(), UNO_QUERY_THROW ); +} + +/// @throws Exception +static Reference< XInterface > loadComponent( + const Reference< XComponentContext > & xContext, + const OUString & rImplName, const OUString & rLocation ) +{ + // determine loader to be used + sal_Int32 nDot = rLocation.lastIndexOf( '.' ); + if (nDot <= 0 || nDot >= rLocation.getLength()) + { + throw RuntimeException( + "location \"" + rLocation + "\" has no extension! Cannot determine loader to be used!" ); + } + + Reference< XImplementationLoader > xLoader; + + std::u16string_view aExt( rLocation.subView( nDot +1 ) ); + + if (aExt == u"dll" || aExt == u"exe" || aExt == u"dylib" || aExt == u"so") + { + createInstance( + xLoader, xContext, "com.sun.star.loader.SharedLibrary" ); + } + else if (aExt == u"jar" || aExt == u"class") + { + createInstance( + xLoader, xContext, "com.sun.star.loader.Java" ); + } + else + { + throw RuntimeException( + "unknown extension of \"" + rLocation + "\"! No loader available!" ); + } + + Reference< XInterface > xInstance; + + // activate + Reference< XInterface > xFactory( xLoader->activate( + rImplName, OUString(), rLocation, Reference< XRegistryKey >() ) ); + if (xFactory.is()) + { + Reference< XSingleComponentFactory > xCFac( xFactory, UNO_QUERY ); + if (xCFac.is()) + { + xInstance = xCFac->createInstanceWithContext( xContext ); + } + else + { + Reference< XSingleServiceFactory > xSFac( xFactory, UNO_QUERY ); + if (xSFac.is()) + { + out( "\n> warning: ignoring context for implementation \"" ); + out( rImplName ); + out( "\"!" ); + xInstance = xSFac->createInstance(); + } + } + } + + if (! xInstance.is()) + { + throw RuntimeException( + "activating component \"" + rImplName + "\" from location \"" + rLocation + "\" failed!" ); + } + + return xInstance; +} + +namespace { + +class OInstanceProvider + : public WeakImplHelper< XInstanceProvider > +{ + Reference< XComponentContext > _xContext; + + std::mutex _aSingleInstanceMutex; + Reference< XInterface > _xSingleInstance; + bool _bSingleInstance; + + OUString _aImplName; + OUString _aLocation; + OUString _aServiceName; + Sequence< Any > _aInitParams; + + OUString _aInstanceName; + + /// @throws Exception + inline Reference< XInterface > createInstance() const; + +public: + OInstanceProvider( const Reference< XComponentContext > & xContext, + const OUString & rImplName, const OUString & rLocation, + const OUString & rServiceName, const Sequence< Any > & rInitParams, + bool bSingleInstance, const OUString & rInstanceName ) + : _xContext( xContext ) + , _bSingleInstance( bSingleInstance ) + , _aImplName( rImplName ) + , _aLocation( rLocation ) + , _aServiceName( rServiceName ) + , _aInitParams( rInitParams ) + , _aInstanceName( rInstanceName ) + {} + + // XInstanceProvider + virtual Reference< XInterface > SAL_CALL getInstance( const OUString & rName ) override; +}; + +} + +inline Reference< XInterface > OInstanceProvider::createInstance() const +{ + Reference< XInterface > xRet; + if (!_aImplName.isEmpty()) // manually via loader + xRet = loadComponent( _xContext, _aImplName, _aLocation ); + else // via service manager + unoexe::createInstance( xRet, _xContext, _aServiceName ); + + // opt XInit + Reference< XInitialization > xInit( xRet, UNO_QUERY ); + if (xInit.is()) + xInit->initialize( _aInitParams ); + + return xRet; +} + +Reference< XInterface > OInstanceProvider::getInstance( const OUString & rName ) +{ + try + { + if (_aInstanceName == rName) + { + Reference< XInterface > xRet; + + if (_aImplName.isEmpty() && _aServiceName.isEmpty()) + { + OSL_ASSERT( rName == "uno.ComponentContext" ); + xRet = _xContext; + } + else if (_bSingleInstance) + { + if (! _xSingleInstance.is()) + { + std::lock_guard aGuard( _aSingleInstanceMutex ); + if (! _xSingleInstance.is()) + { + _xSingleInstance = createInstance(); + } + } + xRet = _xSingleInstance; + } + else + { + xRet = createInstance(); + } + + return xRet; + } + } + catch (Exception & rExc) + { + out( "\n> error: " ); + out( rExc.Message ); + } + throw NoSuchElementException( + "no such element \"" + rName + "\"!" ); +} + +namespace { + +struct ODisposingListener : public WeakImplHelper< XEventListener > +{ + Condition cDisposed; + + // XEventListener + virtual void SAL_CALL disposing( const EventObject & rEvt ) override; + + static void waitFor( const Reference< XComponent > & xComp ); +}; + +} + +void ODisposingListener::disposing( const EventObject & ) +{ + cDisposed.set(); +} + +void ODisposingListener::waitFor( const Reference< XComponent > & xComp ) +{ + rtl::Reference xListener = new ODisposingListener; + + xComp->addEventListener( xListener ); + xListener->cDisposed.wait(); +} + +} // namespace unoexe + +using namespace unoexe; + +SAL_IMPLEMENT_MAIN() +{ + sal_uInt32 nCount = rtl_getAppCommandArgCount(); + if (nCount == 0) + { + out( arUsingText ); + return 0; + } + + sal_Int32 nRet = 0; + Reference< XComponentContext > xContext; + + + try + { + OUString aImplName, aLocation, aServiceName, aUnoUrl; + Sequence< OUString > aParams; + bool bSingleAccept = false; + bool bSingleInstance = false; + + // read command line arguments + + sal_uInt32 nPos = 0; + // read up to arguments + while (nPos < nCount) + { + OUString arg; + + rtl_getAppCommandArg(nPos, &arg.pData); + + if (arg == "--") + { + ++nPos; + break; + } + + if (!(readOption( &aImplName, "c", &nPos, arg) || + readOption( &aLocation, "l", &nPos, arg) || + readOption( &aServiceName, "s", &nPos, arg) || + readOption( &aUnoUrl, "u", &nPos, arg) || + readOption( &s_quiet, "quiet", &nPos, arg) || + readOption( &bSingleAccept, "singleaccept", &nPos, arg) || + readOption( &bSingleInstance, "singleinstance", &nPos, arg))) + { + throw RuntimeException( + "unexpected argument \"" + arg + "\"" ); + } + } + + if (!(aImplName.isEmpty() || aServiceName.isEmpty())) + throw RuntimeException("give component exOR service name!" ); + if (aImplName.isEmpty() && aServiceName.isEmpty()) + { + if (! aUnoUrl.endsWithIgnoreAsciiCase( ";uno.ComponentContext" )) + throw RuntimeException( + "expected UNO-URL with instance name uno.ComponentContext!" ); + if (bSingleInstance) + throw RuntimeException( + "unexpected option --singleinstance!" ); + } + if (!aImplName.isEmpty() && aLocation.isEmpty()) + throw RuntimeException("give component location!" ); + if (!aServiceName.isEmpty() && !aLocation.isEmpty()) + out( "\n> warning: service name given, will ignore location!" ); + + // read component params + aParams.realloc( nCount - nPos ); + OUString * pParams = aParams.getArray(); + + sal_uInt32 nOffset = nPos; + for ( ; nPos < nCount; ++nPos ) + { + rtl_getAppCommandArg( nPos, &pParams[nPos -nOffset].pData ); + } + + xContext = defaultBootstrap_InitialComponentContext(); + + // accept, instantiate, etc. + + if (!aUnoUrl.isEmpty()) // accepting connections + { + if (aUnoUrl.getLength() < 10 || !aUnoUrl.startsWithIgnoreAsciiCase( "uno:" )) + { + throw RuntimeException("illegal uno url given!" ); + } + + sal_Int32 nIndex = 4; // skip initial "uno:" + bool bTooFewTokens {false}; + const OUString aConnectDescr{ aUnoUrl.getToken( 0, ';', nIndex ) }; // uno:CONNECTDESCR;iiop;InstanceName + if (nIndex<0) bTooFewTokens = true; + const OUString aUnoUrlToken{ aUnoUrl.getToken( 0, ';', nIndex ) }; + if (nIndex<0) bTooFewTokens = true; + const OUString aInstanceName{ aUnoUrl.getToken( 0, ';', nIndex ) }; + + // Exactly 3 tokens are required + if (bTooFewTokens || nIndex>0) + { + throw RuntimeException("illegal uno url given!" ); + } + + Reference< XAcceptor > xAcceptor = Acceptor::create(xContext); + + // init params + Sequence< Any > aInitParams( aParams.getLength() ); + const OUString * p = aParams.getConstArray(); + Any * pInitParams = aInitParams.getArray(); + for ( sal_Int32 i = aParams.getLength(); i--; ) + { + pInitParams[i] <<= p[i]; + } + + // instance provider + Reference< XInstanceProvider > xInstanceProvider( new OInstanceProvider( + xContext, aImplName, aLocation, aServiceName, aInitParams, + bSingleInstance, aInstanceName ) ); + + // coverity[loop_top] - not really an infinite loop, we can be instructed to exit via the connection + for (;;) + { + // accepting + out( "\n> accepting " ); + out( aConnectDescr ); + out( "..." ); + Reference< XConnection > xConnection( xAcceptor->accept( aConnectDescr ) ); + out( "connection established." ); + + Reference< XBridgeFactory > xBridgeFactory; + createInstance( + xBridgeFactory, xContext, + "com.sun.star.bridge.BridgeFactory" ); + + // bridge + Reference< XBridge > xBridge( xBridgeFactory->createBridge( + OUString(), aUnoUrlToken, + xConnection, xInstanceProvider ) ); + + if (bSingleAccept) + { + Reference< XComponent > xComp( xBridge, UNO_QUERY_THROW ); + ODisposingListener::waitFor( xComp ); + xComp->dispose(); + // explicitly dispose the remote bridge so that it joins + // on all spawned threads before process exit (see + // binaryurp/source/bridge.cxx for details) + break; + } + } + } + else // no uno url + { + Reference< XInterface > xInstance; + if (!aImplName.isEmpty()) // manually via loader + xInstance = loadComponent( xContext, aImplName, aLocation ); + else // via service manager + createInstance( xInstance, xContext, aServiceName ); + + // execution + Reference< XMain > xMain( xInstance, UNO_QUERY ); + if (xMain.is()) + { + nRet = xMain->run( aParams ); + } + else + { + Reference< XComponent > xComp( xInstance, UNO_QUERY ); + if (xComp.is()) + xComp->dispose(); + throw RuntimeException( "component does not export interface \"com.sun.star.lang.XMain\"!" ); + } + } + } + catch (Exception & rExc) + { + out( "\n> error: " ); + out( rExc.Message ); + out( "\n> dying..." ); + nRet = 1; + } + + // cleanup + Reference< XComponent > xComp( xContext, UNO_QUERY ); + if (xComp.is()) + xComp->dispose(); + + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3