summaryrefslogtreecommitdiffstats
path: root/cpputools
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /cpputools
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'cpputools')
-rw-r--r--cpputools/Executable_sp2bv.mk26
-rw-r--r--cpputools/Executable_uno.mk33
-rw-r--r--cpputools/Makefile7
-rw-r--r--cpputools/Module_cpputools.mk20
-rw-r--r--cpputools/Package_uno_sh.mk16
-rw-r--r--cpputools/README.md3
-rwxr-xr-xcpputools/scripts/uno.sh47
-rw-r--r--cpputools/source/sp2bv/readme.txt8
-rw-r--r--cpputools/source/sp2bv/sp2bv.cxx122
-rw-r--r--cpputools/source/unoexe/unoexe.cxx543
10 files changed, 825 insertions, 0 deletions
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 <stdio.h>
+#include <string.h>
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <rtl/ustrbuf.h>
+
+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 <stdio.h>
+#include <mutex>
+#include <string_view>
+
+#include <sal/main.h>
+#include <sal/log.hxx>
+#include <o3tl/string_view.hxx>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <osl/conditn.hxx>
+
+#include <rtl/process.h>
+#include <rtl/ref.hxx>
+
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/lang/XMain.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/loader/XImplementationLoader.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/connection/Acceptor.hpp>
+#include <com/sun/star/connection/XConnection.hpp>
+#include <com/sun/star/bridge/XBridgeFactory.hpp>
+#include <com/sun/star/bridge/XBridge.hpp>
+
+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]);<protocol>;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<ODisposingListener> 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: */