summaryrefslogtreecommitdiff
path: root/bridges/source/cpp_uno/shared
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/source/cpp_uno/shared')
-rw-r--r--bridges/source/cpp_uno/shared/bridge.cxx226
-rw-r--r--bridges/source/cpp_uno/shared/component.cxx272
-rw-r--r--bridges/source/cpp_uno/shared/component.hxx39
-rw-r--r--bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx205
-rw-r--r--bridges/source/cpp_uno/shared/guardedarray.hxx52
-rw-r--r--bridges/source/cpp_uno/shared/makefile.mk53
-rw-r--r--bridges/source/cpp_uno/shared/types.cxx126
-rw-r--r--bridges/source/cpp_uno/shared/unointerfaceproxy.cxx142
-rw-r--r--bridges/source/cpp_uno/shared/vtablefactory.cxx382
-rw-r--r--bridges/source/cpp_uno/shared/vtables.cxx154
10 files changed, 1651 insertions, 0 deletions
diff --git a/bridges/source/cpp_uno/shared/bridge.cxx b/bridges/source/cpp_uno/shared/bridge.cxx
new file mode 100644
index 000000000000..731eab39cc7c
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/bridge.cxx
@@ -0,0 +1,226 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include "bridges/cpp_uno/shared/bridge.hxx"
+
+#include "component.hxx"
+
+#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
+#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
+
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "osl/interlck.h"
+#include "rtl/ustring.h"
+#include "sal/types.h"
+#include "typelib/typedescription.h"
+#include "uno/dispatcher.h"
+#include "uno/environment.h"
+#include "uno/mapping.h"
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+void freeMapping(uno_Mapping * pMapping)
+{
+ delete static_cast< Bridge::Mapping * >( pMapping )->pBridge;
+}
+
+void acquireMapping(uno_Mapping * pMapping)
+{
+ static_cast< Bridge::Mapping * >( pMapping )->pBridge->acquire();
+}
+
+void releaseMapping(uno_Mapping * pMapping)
+{
+ static_cast< Bridge::Mapping * >( pMapping )->pBridge->release();
+}
+
+void cpp2unoMapping(
+ uno_Mapping * pMapping, void ** ppUnoI, void * pCppI,
+ typelib_InterfaceTypeDescription * pTypeDescr)
+{
+ OSL_ENSURE( ppUnoI && pTypeDescr, "### null ptr!" );
+ if (*ppUnoI)
+ {
+ (*reinterpret_cast< uno_Interface * >( *ppUnoI )->release)(
+ reinterpret_cast< uno_Interface * >( *ppUnoI ) );
+ *ppUnoI = 0;
+ }
+ if (pCppI)
+ {
+ Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge;
+
+ // get object id of interface to be wrapped
+ rtl_uString * pOId = 0;
+ (*pBridge->pCppEnv->getObjectIdentifier)(
+ pBridge->pCppEnv, &pOId, pCppI );
+ OSL_ASSERT( pOId );
+
+ // try to get any known interface from target environment
+ (*pBridge->pUnoEnv->getRegisteredInterface)(
+ pBridge->pUnoEnv, ppUnoI, pOId, pTypeDescr );
+
+ if (! *ppUnoI) // no existing interface, register new proxy interface
+ {
+ // try to publish a new proxy (refcount initially 1)
+ uno_Interface * pSurrogate
+ = bridges::cpp_uno::shared::UnoInterfaceProxy::create(
+ pBridge,
+ static_cast< ::com::sun::star::uno::XInterface * >( pCppI ),
+ pTypeDescr, pOId );
+
+ // proxy may be exchanged during registration
+ (*pBridge->pUnoEnv->registerProxyInterface)(
+ pBridge->pUnoEnv, reinterpret_cast< void ** >( &pSurrogate ),
+ freeUnoInterfaceProxy, pOId,
+ pTypeDescr );
+
+ *ppUnoI = pSurrogate;
+ }
+ ::rtl_uString_release( pOId );
+ }
+}
+
+void uno2cppMapping(
+ uno_Mapping * pMapping, void ** ppCppI, void * pUnoI,
+ typelib_InterfaceTypeDescription * pTypeDescr)
+{
+ OSL_ASSERT( ppCppI && pTypeDescr );
+ if (*ppCppI)
+ {
+ static_cast< ::com::sun::star::uno::XInterface * >( *ppCppI )->
+ release();
+ *ppCppI = 0;
+ }
+ if (pUnoI)
+ {
+ Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge;
+
+ // get object id of uno interface to be wrapped
+ rtl_uString * pOId = 0;
+ (*pBridge->pUnoEnv->getObjectIdentifier)(
+ pBridge->pUnoEnv, &pOId, pUnoI );
+ OSL_ASSERT( pOId );
+
+ // try to get any known interface from target environment
+ (*pBridge->pCppEnv->getRegisteredInterface)(
+ pBridge->pCppEnv, ppCppI, pOId, pTypeDescr );
+
+ if (! *ppCppI) // no existing interface, register new proxy interface
+ {
+ // try to publish a new proxy (ref count initially 1)
+ com::sun::star::uno::XInterface * pProxy
+ = bridges::cpp_uno::shared::CppInterfaceProxy::create(
+ pBridge, static_cast< uno_Interface * >( pUnoI ),
+ pTypeDescr, pOId );
+
+ // proxy may be exchanged during registration
+ (*pBridge->pCppEnv->registerProxyInterface)(
+ pBridge->pCppEnv, reinterpret_cast< void ** >( &pProxy ),
+ freeCppInterfaceProxy, pOId,
+ pTypeDescr );
+
+ *ppCppI = pProxy;
+ }
+ ::rtl_uString_release( pOId );
+ }
+}
+
+uno_Mapping * Bridge::createMapping(
+ uno_ExtEnvironment * pCppEnv, uno_ExtEnvironment * pUnoEnv,
+ bool bExportCpp2Uno) SAL_THROW(())
+{
+ Bridge * bridge = new Bridge(pCppEnv, pUnoEnv, bExportCpp2Uno);
+ return bExportCpp2Uno ? &bridge->aCpp2Uno : &bridge->aUno2Cpp;
+}
+
+void Bridge::acquire() SAL_THROW(())
+{
+ if (1 == osl_incrementInterlockedCount( &nRef ))
+ {
+ if (bExportCpp2Uno)
+ {
+ uno_Mapping * pMapping = &aCpp2Uno;
+ ::uno_registerMapping(
+ &pMapping, freeMapping, (uno_Environment *)pCppEnv,
+ (uno_Environment *)pUnoEnv, 0 );
+ }
+ else
+ {
+ uno_Mapping * pMapping = &aUno2Cpp;
+ ::uno_registerMapping(
+ &pMapping, freeMapping, (uno_Environment *)pUnoEnv,
+ (uno_Environment *)pCppEnv, 0 );
+ }
+ }
+}
+
+void Bridge::release() SAL_THROW(())
+{
+ if (! osl_decrementInterlockedCount( &nRef ))
+ {
+ ::uno_revokeMapping( bExportCpp2Uno ? &aCpp2Uno : &aUno2Cpp );
+ }
+}
+
+Bridge::Bridge(
+ uno_ExtEnvironment * pCppEnv_, uno_ExtEnvironment * pUnoEnv_,
+ bool bExportCpp2Uno_) SAL_THROW(())
+ : nRef( 1 )
+ , pCppEnv( pCppEnv_ )
+ , pUnoEnv( pUnoEnv_ )
+ , bExportCpp2Uno( bExportCpp2Uno_ )
+{
+ bridges::cpp_uno::shared::g_moduleCount.modCnt.acquire(
+ &bridges::cpp_uno::shared::g_moduleCount.modCnt );
+
+ aCpp2Uno.pBridge = this;
+ aCpp2Uno.acquire = acquireMapping;
+ aCpp2Uno.release = releaseMapping;
+ aCpp2Uno.mapInterface = cpp2unoMapping;
+
+ aUno2Cpp.pBridge = this;
+ aUno2Cpp.acquire = acquireMapping;
+ aUno2Cpp.release = releaseMapping;
+ aUno2Cpp.mapInterface = uno2cppMapping;
+
+ (*((uno_Environment *)pCppEnv)->acquire)( (uno_Environment *)pCppEnv );
+ (*((uno_Environment *)pUnoEnv)->acquire)( (uno_Environment *)pUnoEnv );
+}
+
+Bridge::~Bridge() SAL_THROW(())
+{
+ (*((uno_Environment *)pUnoEnv)->release)( (uno_Environment *)pUnoEnv );
+ (*((uno_Environment *)pCppEnv)->release)( (uno_Environment *)pCppEnv );
+ bridges::cpp_uno::shared::g_moduleCount.modCnt.release(
+ &bridges::cpp_uno::shared::g_moduleCount.modCnt );
+}
+
+} } }
diff --git a/bridges/source/cpp_uno/shared/component.cxx b/bridges/source/cpp_uno/shared/component.cxx
new file mode 100644
index 000000000000..1f8a6eccb41f
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/component.cxx
@@ -0,0 +1,272 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include "component.hxx"
+
+#include "bridges/cpp_uno/shared/bridge.hxx"
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+#include "osl/time.h"
+#include "rtl/process.h"
+#include "rtl/unload.h"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "uno/environment.h"
+#include "uno/lbnames.h"
+#include "uno/mapping.h"
+#include "cppu/EnvDcp.hxx"
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
+
+} } }
+
+namespace {
+
+#if (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) \
+ || (defined(__GNUC__) && defined(__APPLE__))
+static ::rtl::OUString * s_pStaticOidPart = 0;
+#endif
+
+const ::rtl::OUString & SAL_CALL cppu_cppenv_getStaticOIdPart() SAL_THROW( () )
+{
+#if ! ((defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) \
+ || (defined(__GNUC__) && defined(__APPLE__)))
+ static ::rtl::OUString * s_pStaticOidPart = 0;
+#endif
+ if (! s_pStaticOidPart)
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if (! s_pStaticOidPart)
+ {
+ ::rtl::OUStringBuffer aRet( 64 );
+ aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
+ // good guid
+ sal_uInt8 ar[16];
+ ::rtl_getGlobalProcessId( ar );
+ for ( sal_Int32 i = 0; i < 16; ++i )
+ {
+ aRet.append( (sal_Int32)ar[i], 16 );
+ }
+#if (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) \
+ || (defined(__GNUC__) && defined(__APPLE__))
+ s_pStaticOidPart = new ::rtl::OUString( aRet.makeStringAndClear() );
+#else
+ static ::rtl::OUString s_aStaticOidPart(
+ aRet.makeStringAndClear() );
+ s_pStaticOidPart = &s_aStaticOidPart;
+#endif
+ }
+ }
+ return *s_pStaticOidPart;
+}
+
+}
+
+extern "C" {
+
+static void s_stub_computeObjectIdentifier(va_list * pParam)
+ SAL_THROW( () )
+{
+ uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ rtl_uString ** ppOId = va_arg(*pParam, rtl_uString **);
+ void * pInterface = va_arg(*pParam, void *);
+
+
+ OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
+ if (pEnv && ppOId && pInterface)
+ {
+ if (*ppOId)
+ {
+ rtl_uString_release( *ppOId );
+ *ppOId = 0;
+ }
+
+ try
+ {
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface > xHome(
+ reinterpret_cast< ::com::sun::star::uno::XInterface * >(
+ pInterface ),
+ ::com::sun::star::uno::UNO_QUERY );
+ OSL_ENSURE( xHome.is(), "### query to XInterface failed!" );
+ if (xHome.is())
+ {
+ // interface
+ ::rtl::OUStringBuffer oid( 64 );
+ oid.append( reinterpret_cast< sal_Int64 >(xHome.get()), 16 );
+ oid.append( (sal_Unicode)';' );
+ // ;environment[context]
+ oid.append(
+ *reinterpret_cast< ::rtl::OUString const * >(
+ &((uno_Environment *) pEnv)->pTypeName ) );
+ oid.append( (sal_Unicode)'[' );
+ oid.append(
+ reinterpret_cast< sal_Int64 >(
+ ((uno_Environment *)pEnv)->pContext),
+ 16 );
+ // ];good guid
+ oid.append( cppu_cppenv_getStaticOIdPart() );
+ ::rtl::OUString aRet( oid.makeStringAndClear() );
+ ::rtl_uString_acquire( *ppOId = aRet.pData );
+ }
+ }
+ catch (::com::sun::star::uno::RuntimeException &)
+ {
+ OSL_ENSURE(
+ 0, "### RuntimeException occured udring queryInterface()!" );
+ }
+ }
+}
+
+static void SAL_CALL computeObjectIdentifier(
+ uno_ExtEnvironment * pExtEnv, rtl_uString ** ppOId, void * pInterface )
+ SAL_THROW( () )
+{
+ uno_Environment_invoke(&pExtEnv->aBase, s_stub_computeObjectIdentifier, pExtEnv, ppOId, pInterface);
+}
+
+static void s_stub_acquireInterface(va_list * pParam)
+ SAL_THROW( () )
+{
+ /*uno_ExtEnvironment * pExtEnv = */va_arg(*pParam, uno_ExtEnvironment *);
+ void * pCppI = va_arg(*pParam, void *);
+
+ reinterpret_cast< ::com::sun::star::uno::XInterface * >( pCppI )->acquire();
+}
+
+static void SAL_CALL acquireInterface( uno_ExtEnvironment * pExtEnv, void * pCppI )
+ SAL_THROW( () )
+{
+ uno_Environment_invoke(&pExtEnv->aBase, s_stub_acquireInterface, pExtEnv, pCppI);
+}
+
+static void s_stub_releaseInterface(va_list * pParam)
+ SAL_THROW( () )
+{
+ /*uno_ExtEnvironment * pExtEnv = */va_arg(*pParam, uno_ExtEnvironment *);
+ void * pCppI = va_arg(*pParam, void *);
+
+ reinterpret_cast< ::com::sun::star::uno::XInterface * >( pCppI )->release();
+}
+
+static void SAL_CALL releaseInterface( uno_ExtEnvironment * pExtEnv, void * pCppI )
+ SAL_THROW( () )
+{
+ uno_Environment_invoke(&pExtEnv->aBase, s_stub_releaseInterface, pExtEnv, pCppI);
+}
+
+static void SAL_CALL environmentDisposing( uno_Environment * ) SAL_THROW( () )
+{
+ bridges::cpp_uno::shared::g_moduleCount.modCnt.release(
+ &bridges::cpp_uno::shared::g_moduleCount.modCnt );
+}
+
+sal_Bool SAL_CALL component_canUnload(TimeValue * pTime) SAL_THROW_EXTERN_C() {
+ return bridges::cpp_uno::shared::g_moduleCount.canUnload(
+ &bridges::cpp_uno::shared::g_moduleCount, pTime);
+}
+
+void SAL_CALL uno_initEnvironment(uno_Environment * pCppEnv)
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( pCppEnv->pExtEnv, "### expected extended environment!" );
+ OSL_ENSURE(
+ ::rtl_ustr_ascii_compare_WithLength(
+ pCppEnv->pTypeName->buffer, rtl_str_getLength(CPPU_CURRENT_LANGUAGE_BINDING_NAME), CPPU_CURRENT_LANGUAGE_BINDING_NAME )
+ == 0,
+ "### wrong environment type!" );
+ bridges::cpp_uno::shared::g_moduleCount.modCnt.acquire(
+ &bridges::cpp_uno::shared::g_moduleCount.modCnt );
+ ((uno_ExtEnvironment *)pCppEnv)->computeObjectIdentifier
+ = computeObjectIdentifier;
+ ((uno_ExtEnvironment *)pCppEnv)->acquireInterface = acquireInterface;
+ ((uno_ExtEnvironment *)pCppEnv)->releaseInterface = releaseInterface;
+ pCppEnv->environmentDisposing = environmentDisposing;
+}
+
+void SAL_CALL uno_ext_getMapping(
+ uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo)
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ASSERT( ppMapping && pFrom && pTo );
+ if (ppMapping && pFrom && pTo && pFrom->pExtEnv && pTo->pExtEnv)
+ {
+ uno_Mapping * pMapping = 0;
+
+ rtl::OUString from_envTypeName(cppu::EnvDcp::getTypeName(pFrom->pTypeName));
+ rtl::OUString to_envTypeName(cppu::EnvDcp::getTypeName(pTo->pTypeName));
+
+ if (0 == rtl_ustr_ascii_compare(
+ from_envTypeName.pData->buffer,
+ CPPU_CURRENT_LANGUAGE_BINDING_NAME ) &&
+ 0 == rtl_ustr_ascii_compare(
+ to_envTypeName.pData->buffer, UNO_LB_UNO ))
+ {
+ // ref count initially 1
+ pMapping = bridges::cpp_uno::shared::Bridge::createMapping(
+ pFrom->pExtEnv, pTo->pExtEnv, sal_True );
+ ::uno_registerMapping(
+ &pMapping, bridges::cpp_uno::shared::freeMapping,
+ (uno_Environment *)pFrom->pExtEnv,
+ (uno_Environment *)pTo->pExtEnv, 0 );
+ }
+ else if (0 == rtl_ustr_ascii_compare(
+ to_envTypeName.pData->buffer,
+ CPPU_CURRENT_LANGUAGE_BINDING_NAME ) &&
+ 0 == rtl_ustr_ascii_compare(
+ from_envTypeName.pData->buffer, UNO_LB_UNO ))
+ {
+ // ref count initially 1
+ pMapping = bridges::cpp_uno::shared::Bridge::createMapping(
+ pTo->pExtEnv, pFrom->pExtEnv, sal_False );
+ ::uno_registerMapping(
+ &pMapping, bridges::cpp_uno::shared::freeMapping,
+ (uno_Environment *)pFrom->pExtEnv,
+ (uno_Environment *)pTo->pExtEnv, 0 );
+ }
+
+ if (*ppMapping)
+ {
+ (*(*ppMapping)->release)( *ppMapping );
+ }
+ if (pMapping)
+ *ppMapping = pMapping;
+ }
+}
+
+}
diff --git a/bridges/source/cpp_uno/shared/component.hxx b/bridges/source/cpp_uno/shared/component.hxx
new file mode 100644
index 000000000000..31622f312304
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/component.hxx
@@ -0,0 +1,39 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_SHARED_COMPONENT_HXX
+#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_SHARED_COMPONENT_HXX
+
+#include "rtl/unload.h"
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+extern rtl_StandardModuleCount g_moduleCount;
+
+} } }
+
+#endif
diff --git a/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx b/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx
new file mode 100644
index 000000000000..90c53d258d10
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/cppinterfaceproxy.cxx
@@ -0,0 +1,205 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
+
+#include "guardedarray.hxx"
+
+#include "bridges/cpp_uno/shared/bridge.hxx"
+#include "bridges/cpp_uno/shared/vtablefactory.hxx"
+
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "osl/getglobalmutex.hxx"
+#include "osl/interlck.h"
+#include "osl/mutex.hxx"
+#include "rtl/instance.hxx"
+#include "typelib/typedescription.h"
+
+#include <cstddef>
+#include <new>
+
+
+static bridges::cpp_uno::shared::VtableFactory * pInstance;
+
+#if defined(__GNUG__) && !defined(__MINGW32__)
+void dso_init(void) __attribute__((constructor));
+void dso_exit(void) __attribute__((destructor));
+#endif
+
+void dso_init(void) {
+ if (!pInstance)
+ pInstance = new bridges::cpp_uno::shared::VtableFactory();
+}
+
+void dso_exit(void) {
+ if (pInstance)
+ {
+ delete pInstance;
+ pInstance = NULL;
+ }
+}
+
+#ifdef __SUNPRO_CC
+# pragma init(dso_init)
+# pragma fini(dso_exit)
+#endif
+
+
+
+namespace {
+
+struct InitVtableFactory {
+ bridges::cpp_uno::shared::VtableFactory * operator()() {
+ return pInstance;
+ }
+};
+
+bridges::cpp_uno::shared::VtableFactory * getVtableFactory() {
+ return rtl_Instance<
+ bridges::cpp_uno::shared::VtableFactory, InitVtableFactory,
+ osl::MutexGuard, osl::GetGlobalMutex >::create(
+ InitVtableFactory(), osl::GetGlobalMutex());
+}
+
+}
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+void freeCppInterfaceProxy(uno_ExtEnvironment * pEnv, void * pInterface)
+{
+ CppInterfaceProxy * pThis = CppInterfaceProxy::castInterfaceToProxy(
+ pInterface);
+ if (pEnv != pThis->pBridge->getCppEnv()) {
+ OSL_ASSERT(false);
+ }
+
+ (*pThis->pBridge->getUnoEnv()->revokeInterface)(
+ pThis->pBridge->getUnoEnv(), pThis->pUnoI );
+ (*pThis->pUnoI->release)( pThis->pUnoI );
+ ::typelib_typedescription_release(
+ (typelib_TypeDescription *)pThis->pTypeDescr );
+ pThis->pBridge->release();
+
+#if OSL_DEBUG_LEVEL > 1
+ *(int *)pInterface = 0xdeadbabe;
+#endif
+ pThis->~CppInterfaceProxy();
+ delete[] reinterpret_cast< char * >(pThis);
+}
+
+com::sun::star::uno::XInterface * CppInterfaceProxy::create(
+ bridges::cpp_uno::shared::Bridge * pBridge, uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription * pTypeDescr, rtl::OUString const & rOId)
+ SAL_THROW(())
+{
+ typelib_typedescription_complete(
+ reinterpret_cast< typelib_TypeDescription ** >(&pTypeDescr));
+ bridges::cpp_uno::shared::VtableFactory::Vtables aVtables(
+ getVtableFactory()->getVtables(pTypeDescr));
+ bridges::cpp_uno::shared::GuardedArray< char > pMemory(
+ new char[
+ sizeof (CppInterfaceProxy)
+ + (aVtables.count - 1) * sizeof (void **)]);
+ new(pMemory.get()) CppInterfaceProxy(pBridge, pUnoI, pTypeDescr, rOId);
+ CppInterfaceProxy * pProxy = reinterpret_cast< CppInterfaceProxy * >(
+ pMemory.release());
+ for (sal_Int32 i = 0; i < aVtables.count; ++i) {
+ pProxy->vtables[i] = VtableFactory::mapBlockToVtable(
+ aVtables.blocks[i].start);
+ }
+ return castProxyToInterface(pProxy);
+}
+
+void CppInterfaceProxy::acquireProxy() SAL_THROW(())
+{
+ if (1 == osl_incrementInterlockedCount( &nRef ))
+ {
+ // rebirth of proxy zombie
+ // register at cpp env
+ void * pThis = castProxyToInterface( this );
+ (*pBridge->getCppEnv()->registerProxyInterface)(
+ pBridge->getCppEnv(), &pThis, freeCppInterfaceProxy, oid.pData,
+ pTypeDescr );
+ OSL_ASSERT( pThis == castProxyToInterface( this ) );
+ }
+}
+
+void CppInterfaceProxy::releaseProxy() SAL_THROW(())
+{
+ if (! osl_decrementInterlockedCount( &nRef )) // last release
+ {
+ // revoke from cpp env
+ (*pBridge->getCppEnv()->revokeInterface)(
+ pBridge->getCppEnv(), castProxyToInterface( this ) );
+ }
+}
+
+CppInterfaceProxy::CppInterfaceProxy(
+ bridges::cpp_uno::shared::Bridge * pBridge_, uno_Interface * pUnoI_,
+ typelib_InterfaceTypeDescription * pTypeDescr_, rtl::OUString const & rOId_)
+ SAL_THROW(())
+ : nRef( 1 )
+ , pBridge( pBridge_ )
+ , pUnoI( pUnoI_ )
+ , pTypeDescr( pTypeDescr_ )
+ , oid( rOId_ )
+{
+ pBridge->acquire();
+ ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr );
+ (*pUnoI->acquire)( pUnoI );
+ (*pBridge->getUnoEnv()->registerInterface)(
+ pBridge->getUnoEnv(), reinterpret_cast< void ** >( &pUnoI ), oid.pData,
+ pTypeDescr );
+}
+
+CppInterfaceProxy::~CppInterfaceProxy()
+{}
+
+com::sun::star::uno::XInterface * CppInterfaceProxy::castProxyToInterface(
+ CppInterfaceProxy * pProxy)
+{
+ return reinterpret_cast< com::sun::star::uno::XInterface * >(
+ &pProxy->vtables);
+}
+
+CppInterfaceProxy * CppInterfaceProxy::castInterfaceToProxy(void * pInterface)
+{
+ // pInterface == &pProxy->vtables (this emulated offsetof is not truly
+ // portable):
+ char const * const base = reinterpret_cast< char const * >(16);
+ std::ptrdiff_t const offset = reinterpret_cast< char const * >(
+ &reinterpret_cast< CppInterfaceProxy const * >(base)->vtables) - base;
+ return reinterpret_cast< CppInterfaceProxy * >(
+ static_cast< char * >(pInterface) - offset);
+}
+
+} } }
diff --git a/bridges/source/cpp_uno/shared/guardedarray.hxx b/bridges/source/cpp_uno/shared/guardedarray.hxx
new file mode 100644
index 000000000000..b49def85ac64
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/guardedarray.hxx
@@ -0,0 +1,52 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_SHARED_GUARDEDARRAY_HXX
+#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_SHARED_GUARDEDARRAY_HXX
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+template< typename T > class GuardedArray {
+public:
+ explicit GuardedArray(T * thePointer): pointer(thePointer) {}
+
+ ~GuardedArray() { delete[] pointer; }
+
+ T * get() const { return pointer; }
+
+ T * release() { T * p = pointer; pointer = 0; return p; }
+
+private:
+ GuardedArray(GuardedArray &); // not implemented
+ void operator =(GuardedArray); // not implemented
+
+ T * pointer;
+};
+
+} } }
+
+#endif
diff --git a/bridges/source/cpp_uno/shared/makefile.mk b/bridges/source/cpp_uno/shared/makefile.mk
new file mode 100644
index 000000000000..4ce8122f3261
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/makefile.mk
@@ -0,0 +1,53 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ = ..$/..$/..
+PRJNAME = bridges
+
+TARGET = cpp_uno_shared
+ENABLE_EXCEPTIONS = TRUE
+
+.INCLUDE: settings.mk
+
+SLOFILES = \
+ $(SLO)$/bridge.obj \
+ $(SLO)$/component.obj \
+ $(SLO)$/cppinterfaceproxy.obj \
+ $(SLO)$/types.obj \
+ $(SLO)$/unointerfaceproxy.obj \
+ $(SLO)$/vtablefactory.obj \
+ $(SLO)$/vtables.obj
+
+# Disable optimization for cppinterfaceproxy.cxx -
+# attribute constructor / destructor do not get called otherwise.
+.IF "$(COM)" == "GCC"
+NOOPTFILES = \
+ $(SLO)$/cppinterfaceproxy.obj
+.ENDIF
+
+
+.INCLUDE: target.mk
diff --git a/bridges/source/cpp_uno/shared/types.cxx b/bridges/source/cpp_uno/shared/types.cxx
new file mode 100644
index 000000000000..6a08038f9902
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/types.cxx
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include "bridges/cpp_uno/shared/types.hxx"
+#define INCLUDED_BRIDGES_CPP_UNO_SHARED_VTABLES_HXX
+
+#include "typelib/typeclass.h"
+#include "typelib/typedescription.h"
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+bool isSimpleType(typelib_TypeClass typeClass) {
+ return typeClass <= typelib_TypeClass_DOUBLE
+ || typeClass == typelib_TypeClass_ENUM;
+}
+
+bool isSimpleType(typelib_TypeDescriptionReference const * type) {
+ return isSimpleType(type->eTypeClass);
+}
+
+bool isSimpleType(typelib_TypeDescription const * type) {
+ return isSimpleType(type->eTypeClass);
+}
+
+bool relatesToInterfaceType(typelib_TypeDescription const * type) {
+ switch (type->eTypeClass) {
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_INTERFACE:
+ return true;
+
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_CompoundTypeDescription const * p
+ = reinterpret_cast< typelib_CompoundTypeDescription const * >(
+ type);
+ for (sal_Int32 i = 0; i < p->nMembers; ++i) {
+ switch (p->ppTypeRefs[i]->eTypeClass) {
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_INTERFACE:
+ return true;
+
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_SEQUENCE:
+ {
+ typelib_TypeDescription * t = 0;
+ TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
+ bool b = relatesToInterfaceType(t);
+ TYPELIB_DANGER_RELEASE(t);
+ if (b) {
+ return true;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (p->pBaseTypeDescription != 0) {
+ return relatesToInterfaceType(&p->pBaseTypeDescription->aBase);
+ }
+ }
+ break;
+
+ case typelib_TypeClass_SEQUENCE:
+ switch (reinterpret_cast< typelib_IndirectTypeDescription const * >(
+ type)->pType->eTypeClass) {
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_INTERFACE:
+ return true;
+
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_SEQUENCE:
+ {
+ typelib_TypeDescription * t = 0;
+ TYPELIB_DANGER_GET(
+ &t,
+ reinterpret_cast< typelib_IndirectTypeDescription const * >(
+ type)->pType);
+ bool b = relatesToInterfaceType(t);
+ TYPELIB_DANGER_RELEASE(t);
+ return b;
+ }
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+} } }
diff --git a/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx b/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx
new file mode 100644
index 000000000000..1f5580eb2f30
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/unointerfaceproxy.cxx
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
+
+#include "bridges/cpp_uno/shared/bridge.hxx"
+
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "osl/interlck.h"
+#include "typelib/typedescription.h"
+#include "uno/dispatcher.h"
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+void freeUnoInterfaceProxy(uno_ExtEnvironment * pEnv, void * pProxy)
+{
+ UnoInterfaceProxy * pThis =
+ static_cast< UnoInterfaceProxy * >(
+ reinterpret_cast< uno_Interface * >( pProxy ) );
+ if (pEnv != pThis->pBridge->getUnoEnv()) {
+ OSL_ASSERT(false);
+ }
+
+ (*pThis->pBridge->getCppEnv()->revokeInterface)(
+ pThis->pBridge->getCppEnv(), pThis->pCppI );
+ pThis->pCppI->release();
+ ::typelib_typedescription_release(
+ (typelib_TypeDescription *)pThis->pTypeDescr );
+ pThis->pBridge->release();
+
+#if OSL_DEBUG_LEVEL > 1
+ *(int *)pProxy = 0xdeadbabe;
+#endif
+ delete pThis;
+}
+
+void acquireProxy(uno_Interface * pUnoI)
+{
+ if (1 == osl_incrementInterlockedCount(
+ & static_cast< UnoInterfaceProxy * >( pUnoI )->nRef ))
+ {
+ // rebirth of proxy zombie
+ // register at uno env
+#if OSL_DEBUG_LEVEL > 1
+ void * pThis = pUnoI;
+#endif
+ (*static_cast< UnoInterfaceProxy * >( pUnoI )->pBridge->getUnoEnv()->
+ registerProxyInterface)(
+ static_cast< UnoInterfaceProxy * >( pUnoI )->pBridge->getUnoEnv(),
+ reinterpret_cast< void ** >( &pUnoI ), freeUnoInterfaceProxy,
+ static_cast< UnoInterfaceProxy * >( pUnoI )->oid.pData,
+ static_cast< UnoInterfaceProxy * >( pUnoI )->pTypeDescr );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ASSERT( pThis == pUnoI );
+#endif
+ }
+}
+
+void releaseProxy(uno_Interface * pUnoI)
+{
+ if (! osl_decrementInterlockedCount(
+ & static_cast< UnoInterfaceProxy * >( pUnoI )->nRef ))
+ {
+ // revoke from uno env on last release
+ (*static_cast< UnoInterfaceProxy * >( pUnoI )->pBridge->getUnoEnv()->
+ revokeInterface)(
+ static_cast< UnoInterfaceProxy * >( pUnoI )->pBridge->getUnoEnv(),
+ pUnoI );
+ }
+}
+
+UnoInterfaceProxy * UnoInterfaceProxy::create(
+ bridges::cpp_uno::shared::Bridge * pBridge,
+ com::sun::star::uno::XInterface * pCppI,
+ typelib_InterfaceTypeDescription * pTypeDescr,
+ rtl::OUString const & rOId) SAL_THROW(())
+{
+ return new UnoInterfaceProxy(pBridge, pCppI, pTypeDescr, rOId);
+}
+
+UnoInterfaceProxy::UnoInterfaceProxy(
+ bridges::cpp_uno::shared::Bridge * pBridge_,
+ com::sun::star::uno::XInterface * pCppI_,
+ typelib_InterfaceTypeDescription * pTypeDescr_, rtl::OUString const & rOId_)
+ SAL_THROW(())
+ : nRef( 1 )
+ , pBridge( pBridge_ )
+ , pCppI( pCppI_ )
+ , pTypeDescr( pTypeDescr_ )
+ , oid( rOId_ )
+{
+ pBridge->acquire();
+ ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr );
+ if (! ((typelib_TypeDescription *)pTypeDescr)->bComplete)
+ ::typelib_typedescription_complete(
+ (typelib_TypeDescription **)&pTypeDescr );
+ OSL_ENSURE(
+ ((typelib_TypeDescription *)pTypeDescr)->bComplete,
+ "### type is incomplete!" );
+ pCppI->acquire();
+ (*pBridge->getCppEnv()->registerInterface)(
+ pBridge->getCppEnv(), reinterpret_cast< void ** >( &pCppI ), oid.pData,
+ pTypeDescr );
+
+ // uno_Interface
+ acquire = acquireProxy;
+ release = releaseProxy;
+ pDispatcher = unoInterfaceProxyDispatch;
+}
+
+UnoInterfaceProxy::~UnoInterfaceProxy()
+{}
+
+} } }
diff --git a/bridges/source/cpp_uno/shared/vtablefactory.cxx b/bridges/source/cpp_uno/shared/vtablefactory.cxx
new file mode 100644
index 000000000000..58c275a11234
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/vtablefactory.cxx
@@ -0,0 +1,382 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#if defined OS2
+#define INCL_DOS
+#define INCL_DOSMISC
+#endif
+
+#include "bridges/cpp_uno/shared/vtablefactory.hxx"
+
+#include "guardedarray.hxx"
+
+#include "bridges/cpp_uno/shared/vtables.hxx"
+
+#include "osl/thread.h"
+#include "osl/security.hxx"
+#include "osl/file.hxx"
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+#include "rtl/alloc.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typedescription.hxx"
+
+#include <hash_map>
+#include <new>
+#include <vector>
+
+#if defined SAL_UNX
+#include <unistd.h>
+#include <string.h>
+#include <sys/mman.h>
+#elif defined SAL_W32
+#define WIN32_LEAN_AND_MEAN
+#ifdef _MSC_VER
+#pragma warning(push,1) // disable warnings within system headers
+#endif
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#elif defined SAL_OS2
+#define INCL_DOS
+#define INCL_DOSMISC
+#include <os2.h>
+#else
+#error Unsupported platform
+#endif
+
+using bridges::cpp_uno::shared::VtableFactory;
+
+namespace {
+
+extern "C" void * SAL_CALL allocExec(rtl_arena_type *, sal_Size * size) {
+ sal_Size pagesize;
+#if defined SAL_UNX
+#if defined FREEBSD || defined NETBSD
+ pagesize = getpagesize();
+#else
+ pagesize = sysconf(_SC_PAGESIZE);
+#endif
+#elif defined SAL_W32
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ pagesize = info.dwPageSize;
+#elif defined(SAL_OS2)
+ ULONG ulPageSize;
+ DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, &ulPageSize, sizeof(ULONG));
+ pagesize = (sal_Size)ulPageSize;
+#else
+#error Unsupported platform
+#endif
+ sal_Size n = (*size + (pagesize - 1)) & ~(pagesize - 1);
+ void * p;
+#if defined SAL_UNX
+ p = mmap(
+ 0, n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1,
+ 0);
+ if (p == MAP_FAILED) {
+ p = 0;
+ }
+ else if (mprotect (static_cast<char*>(p), n, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
+ {
+ munmap (static_cast<char*>(p), n);
+ p = 0;
+ }
+#elif defined SAL_W32
+ p = VirtualAlloc(0, n, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+#elif defined(SAL_OS2)
+ p = 0;
+ DosAllocMem( &p, n, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
+#endif
+ if (p != 0) {
+ *size = n;
+ }
+ return p;
+}
+
+extern "C" void SAL_CALL freeExec(
+ rtl_arena_type *, void * address, sal_Size size)
+{
+#if defined SAL_UNX
+ munmap(static_cast< char * >(address), size);
+#elif defined SAL_W32
+ (void) size; // unused
+ VirtualFree(address, 0, MEM_RELEASE);
+#elif defined(SAL_OS2)
+ (void) DosFreeMem( address);
+#endif
+}
+
+}
+
+class VtableFactory::GuardedBlocks: public std::vector< Block > {
+public:
+ GuardedBlocks(VtableFactory const & factory):
+ m_factory(factory), m_guarded(true) {}
+
+ ~GuardedBlocks();
+
+ void unguard() { m_guarded = false; }
+
+private:
+ GuardedBlocks(GuardedBlocks &); // not implemented
+ void operator =(GuardedBlocks); // not implemented
+
+ VtableFactory const & m_factory;
+ bool m_guarded;
+};
+
+VtableFactory::GuardedBlocks::~GuardedBlocks() {
+ if (m_guarded) {
+ for (iterator i(begin()); i != end(); ++i) {
+ m_factory.freeBlock(*i);
+ }
+ }
+}
+
+class VtableFactory::BaseOffset {
+public:
+ BaseOffset(typelib_InterfaceTypeDescription * type) { calculate(type, 0); }
+
+ sal_Int32 getFunctionOffset(rtl::OUString const & name) const
+ { return m_map.find(name)->second; }
+
+private:
+ sal_Int32 calculate(
+ typelib_InterfaceTypeDescription * type, sal_Int32 offset);
+
+ typedef std::hash_map< rtl::OUString, sal_Int32, rtl::OUStringHash > Map;
+
+ Map m_map;
+};
+
+sal_Int32 VtableFactory::BaseOffset::calculate(
+ typelib_InterfaceTypeDescription * type, sal_Int32 offset)
+{
+ rtl::OUString name(type->aBase.pTypeName);
+ if (m_map.find(name) == m_map.end()) {
+ for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
+ offset = calculate(type->ppBaseTypes[i], offset);
+ }
+ m_map.insert(Map::value_type(name, offset));
+ typelib_typedescription_complete(
+ reinterpret_cast< typelib_TypeDescription ** >(&type));
+ offset += bridges::cpp_uno::shared::getLocalFunctions(type);
+ }
+ return offset;
+}
+
+VtableFactory::VtableFactory(): m_arena(
+ rtl_arena_create(
+ "bridges::cpp_uno::shared::VtableFactory",
+ sizeof (void *), // to satisfy alignment requirements
+ 0, reinterpret_cast< rtl_arena_type * >(-1), allocExec, freeExec, 0))
+{
+ if (m_arena == 0) {
+ throw std::bad_alloc();
+ }
+}
+
+VtableFactory::~VtableFactory() {
+ {
+ osl::MutexGuard guard(m_mutex);
+ for (Map::iterator i(m_map.begin()); i != m_map.end(); ++i) {
+ for (sal_Int32 j = 0; j < i->second.count; ++j) {
+ freeBlock(i->second.blocks[j]);
+ }
+ delete[] i->second.blocks;
+ }
+ }
+ rtl_arena_destroy(m_arena);
+}
+
+VtableFactory::Vtables VtableFactory::getVtables(
+ typelib_InterfaceTypeDescription * type)
+{
+ rtl::OUString name(type->aBase.pTypeName);
+ osl::MutexGuard guard(m_mutex);
+ Map::iterator i(m_map.find(name));
+ if (i == m_map.end()) {
+ GuardedBlocks blocks(*this);
+ createVtables(blocks, BaseOffset(type), type, true);
+ Vtables vtables;
+ OSL_ASSERT(blocks.size() <= SAL_MAX_INT32);
+ vtables.count = static_cast< sal_Int32 >(blocks.size());
+ bridges::cpp_uno::shared::GuardedArray< Block > guardedBlocks(
+ new Block[vtables.count]);
+ vtables.blocks = guardedBlocks.get();
+ for (sal_Int32 j = 0; j < vtables.count; ++j) {
+ vtables.blocks[j] = blocks[j];
+ }
+ i = m_map.insert(Map::value_type(name, vtables)).first;
+ guardedBlocks.release();
+ blocks.unguard();
+ }
+ return i->second;
+}
+
+#ifdef USE_DOUBLE_MMAP
+bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const
+{
+ sal_Size size = getBlockSize(slotCount);
+ sal_Size pagesize = sysconf(_SC_PAGESIZE);
+ block.size = (size + (pagesize - 1)) & ~(pagesize - 1);
+ block.start = block.exec = NULL;
+ block.fd = -1;
+
+ osl::Security aSecurity;
+ rtl::OUString strDirectory;
+ rtl::OUString strURLDirectory;
+ if (aSecurity.getHomeDir(strURLDirectory))
+ osl::File::getSystemPathFromFileURL(strURLDirectory, strDirectory);
+
+ for (int i = strDirectory.getLength() == 0 ? 1 : 0; i < 2; ++i)
+ {
+ if (!strDirectory.getLength())
+ strDirectory = rtl::OUString::createFromAscii("/tmp");
+
+ strDirectory += rtl::OUString::createFromAscii("/.execoooXXXXXX");
+ rtl::OString aTmpName = rtl::OUStringToOString(strDirectory, osl_getThreadTextEncoding());
+ char *tmpfname = new char[aTmpName.getLength()+1];
+ strncpy(tmpfname, aTmpName.getStr(), aTmpName.getLength()+1);
+ if ((block.fd = mkstemp(tmpfname)) == -1)
+ perror("creation of executable memory area failed");
+ if (block.fd == -1)
+ {
+ delete[] tmpfname;
+ break;
+ }
+ unlink(tmpfname);
+ delete[] tmpfname;
+ if (ftruncate(block.fd, block.size) == -1)
+ {
+ perror("truncation of executable memory area failed");
+ close(block.fd);
+ block.fd = -1;
+ break;
+ }
+ block.start = mmap(NULL, block.size, PROT_READ | PROT_WRITE, MAP_SHARED, block.fd, 0);
+ if (block.start== MAP_FAILED) {
+ block.start = 0;
+ }
+ block.exec = mmap(NULL, block.size, PROT_READ | PROT_EXEC, MAP_SHARED, block.fd, 0);
+ if (block.exec == MAP_FAILED) {
+ block.exec = 0;
+ }
+
+ //All good
+ if (block.start && block.exec && block.fd != -1)
+ break;
+
+ freeBlock(block);
+
+ strDirectory = rtl::OUString();
+ }
+ if (!block.start || !block.exec || block.fd == -1)
+ {
+ //Fall back to non-doublemmaped allocation
+ block.fd = -1;
+ block.start = block.exec = rtl_arena_alloc(m_arena, &block.size);
+ }
+ return (block.start != 0 && block.exec != 0);
+}
+
+void VtableFactory::freeBlock(Block const & block) const {
+ //if the double-map failed we were allocated on the arena
+ if (block.fd == -1 && block.start == block.exec && block.start != NULL)
+ rtl_arena_free(m_arena, block.start, block.size);
+ else
+ {
+ if (block.start) munmap(block.start, block.size);
+ if (block.exec) munmap(block.exec, block.size);
+ if (block.fd != -1) close(block.fd);
+ }
+}
+#else
+bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const
+{
+ block.size = getBlockSize(slotCount);
+ block.start = rtl_arena_alloc(m_arena, &block.size);
+ return block.start != 0;
+}
+
+void VtableFactory::freeBlock(Block const & block) const {
+ rtl_arena_free(m_arena, block.start, block.size);
+}
+#endif
+
+void VtableFactory::createVtables(
+ GuardedBlocks & blocks, BaseOffset const & baseOffset,
+ typelib_InterfaceTypeDescription * type, bool includePrimary) const
+{
+ if (includePrimary) {
+ sal_Int32 slotCount
+ = bridges::cpp_uno::shared::getPrimaryFunctions(type);
+ Block block;
+ if (!createBlock(block, slotCount)) {
+ throw std::bad_alloc();
+ }
+ try {
+ Slot * slots = initializeBlock(block.start, slotCount);
+ unsigned char * codeBegin =
+ reinterpret_cast< unsigned char * >(slots);
+ unsigned char * code = codeBegin;
+ sal_Int32 vtableOffset = blocks.size() * sizeof (Slot *);
+ for (typelib_InterfaceTypeDescription const * type2 = type;
+ type2 != 0; type2 = type2->pBaseTypeDescription)
+ {
+ code = addLocalFunctions(
+ &slots, code,
+#ifdef USE_DOUBLE_MMAP
+ sal_IntPtr(block.exec) - sal_IntPtr(block.start),
+#endif
+ type2,
+ baseOffset.getFunctionOffset(type2->aBase.pTypeName),
+ bridges::cpp_uno::shared::getLocalFunctions(type2),
+ vtableOffset);
+ }
+ flushCode(codeBegin, code);
+#ifdef USE_DOUBLE_MMAP
+ //Finished generating block, swap writable pointer with executable
+ //pointer
+ ::std::swap(block.start, block.exec);
+#endif
+ blocks.push_back(block);
+ } catch (...) {
+ freeBlock(block);
+ throw;
+ }
+ }
+ for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
+ createVtables(blocks, baseOffset, type->ppBaseTypes[i], i != 0);
+ }
+}
diff --git a/bridges/source/cpp_uno/shared/vtables.cxx b/bridges/source/cpp_uno/shared/vtables.cxx
new file mode 100644
index 000000000000..2779d928f24e
--- /dev/null
+++ b/bridges/source/cpp_uno/shared/vtables.cxx
@@ -0,0 +1,154 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include "bridges/cpp_uno/shared/vtables.hxx"
+
+#include "osl/diagnose.h"
+#include "sal/types.h"
+#include "typelib/typedescription.h"
+
+#include <algorithm>
+
+namespace
+{
+
+/**
+ * Calculates the number of vtables associated with an interface type.
+ *
+ * <p>Multiple-inheritance C++ classes have more than one vtable.</p>
+ *
+ * @param type a non-null pointer to an interface type description
+ * @return the number of vtables associated with the given interface type
+ */
+sal_Int32 getVtableCount(typelib_InterfaceTypeDescription const * type) {
+ sal_Int32 n = 0;
+ for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
+ n += getVtableCount(type->ppBaseTypes[i]);
+ }
+ return std::max< sal_Int32 >(n, 1);
+}
+
+/**
+ * Maps a local member index to a local function index.
+ *
+ * <p><em>Local</em> members/functions are those not inherited from any base
+ * types. The number of <em>functions</em> is potentially larger than the
+ * number of <em>members</em>, as each read&ndash;write attribute member counts
+ * as two functions.</p>
+ *
+ * @param type a non-null pointer to an interface type description
+ * @param localMember a local member index, relative to the given interface type
+ * @return the local function index corresponding to the given local member
+ * index, relative to the given interface type
+ */
+sal_Int32 mapLocalMemberToLocalFunction(
+ typelib_InterfaceTypeDescription * type, sal_Int32 localMember)
+{
+ typelib_typedescription_complete(
+ reinterpret_cast< typelib_TypeDescription ** >(&type));
+ sal_Int32 localMemberOffset = type->nAllMembers - type->nMembers;
+ sal_Int32 localFunctionOffset = type->nMapFunctionIndexToMemberIndex
+ - bridges::cpp_uno::shared::getLocalFunctions(type);
+ return type->pMapMemberIndexToFunctionIndex[localMemberOffset + localMember]
+ - localFunctionOffset;
+}
+
+// Since on Solaris we compile with --instances=static, getVtableSlot cannot be
+// a template function, with explicit instantiates for
+// T = typelib_InterfaceAttributeTypeDescription and
+// T = typelib_InterfaceMethodTypeDescription in this file; hence, there are two
+// overloaded versions of getVtableSlot that both delegate to this template
+// function:
+template< typename T > bridges::cpp_uno::shared::VtableSlot doGetVtableSlot(
+ T const * ifcMember)
+{
+ bridges::cpp_uno::shared::VtableSlot slot;
+ slot.offset = 0;
+ T * member = const_cast< T * >(ifcMember);
+ while (member->pBaseRef != 0) {
+ OSL_ASSERT(member->nIndex < member->pInterface->nBaseTypes);
+ for (sal_Int32 i = 0; i < member->nIndex; ++i) {
+ slot.offset += getVtableCount(member->pInterface->ppBaseTypes[i]);
+ }
+ typelib_TypeDescription * desc = 0;
+ typelib_typedescriptionreference_getDescription(
+ &desc, member->pBaseRef);
+ OSL_ASSERT(
+ desc != 0 && desc->eTypeClass == member->aBase.aBase.eTypeClass);
+ if (member != ifcMember) {
+ typelib_typedescription_release(&member->aBase.aBase);
+ }
+ member = reinterpret_cast< T * >(desc);
+ }
+ slot.index
+ = bridges::cpp_uno::shared::getPrimaryFunctions(
+ member->pInterface->pBaseTypeDescription)
+ + mapLocalMemberToLocalFunction(member->pInterface, member->nIndex);
+ if (member != ifcMember) {
+ typelib_typedescription_release(&member->aBase.aBase);
+ }
+ return slot;
+}
+
+}
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+sal_Int32 getLocalFunctions(typelib_InterfaceTypeDescription const * type) {
+ return type->nMembers == 0
+ ? 0
+ : (type->nMapFunctionIndexToMemberIndex
+ - type->pMapMemberIndexToFunctionIndex[
+ type->nAllMembers - type->nMembers]);
+}
+
+sal_Int32 getPrimaryFunctions(typelib_InterfaceTypeDescription * type) {
+ sal_Int32 n = 0;
+ for (; type != 0; type = type->pBaseTypeDescription) {
+ typelib_typedescription_complete(
+ reinterpret_cast< typelib_TypeDescription ** >(&type));
+ n += getLocalFunctions(type);
+ }
+ return n;
+}
+
+VtableSlot getVtableSlot(
+ typelib_InterfaceAttributeTypeDescription const * ifcMember)
+{
+ return doGetVtableSlot(ifcMember);
+}
+
+VtableSlot getVtableSlot(
+ typelib_InterfaceMethodTypeDescription const * ifcMember)
+{
+ return doGetVtableSlot(ifcMember);
+}
+
+} } }