summaryrefslogtreecommitdiffstats
path: root/stoc/source/invocation
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 /stoc/source/invocation
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.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 '')
-rw-r--r--stoc/source/invocation/invocation.component26
-rw-r--r--stoc/source/invocation/invocation.cxx1097
-rw-r--r--stoc/source/invocation_adapterfactory/iafactory.cxx882
-rw-r--r--stoc/source/invocation_adapterfactory/invocadapt.component26
4 files changed, 2031 insertions, 0 deletions
diff --git a/stoc/source/invocation/invocation.component b/stoc/source/invocation/invocation.component
new file mode 100644
index 000000000..b5027a4d6
--- /dev/null
+++ b/stoc/source/invocation/invocation.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.stoc.Invocation"
+ constructor="stoc_InvocationService_get_implementation">
+ <service name="com.sun.star.script.Invocation"/>
+ </implementation>
+</component>
diff --git a/stoc/source/invocation/invocation.cxx b/stoc/source/invocation/invocation.cxx
new file mode 100644
index 000000000..5463c059e
--- /dev/null
+++ b/stoc/source/invocation/invocation.cxx
@@ -0,0 +1,1097 @@
+/* -*- 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 <comphelper/sequence.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/script/CannotConvertException.hpp>
+#include <com/sun/star/script/XTypeConverter.hpp>
+#include <com/sun/star/script/XInvocation.hpp>
+#include <com/sun/star/script/XInvocation2.hpp>
+#include <com/sun/star/reflection/XIdlReflection.hpp>
+#include <com/sun/star/reflection/theCoreReflection.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/beans/XExactName.hpp>
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+#include <com/sun/star/beans/theIntrospection.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/MethodConcept.hpp>
+#include <com/sun/star/beans/PropertyConcept.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+
+#include <memory>
+#include <vector>
+
+using namespace css::uno;
+using namespace css::lang;
+using namespace css::script;
+using namespace css::reflection;
+using namespace css::beans;
+using namespace css::container;
+using namespace cppu;
+using namespace osl;
+
+namespace stoc_inv
+{
+
+
+// TODO: Implement centrally
+static Reference<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XIdlReflection > & xRefl )
+{
+ return xRefl->forName( rType.getTypeName() );
+}
+
+namespace {
+
+class Invocation_Impl
+ : public OWeakObject
+ , public XInvocation2
+ , public XNameContainer
+ , public XIndexContainer
+ , public XEnumerationAccess
+ , public XExactName
+ , public XMaterialHolder
+ , public XTypeProvider
+{
+public:
+ Invocation_Impl( const Any & rAdapted, const Reference<XTypeConverter> &,
+ const Reference<XIntrospection> &,
+ const Reference<XIdlReflection> &,
+ bool bFromOLE );
+
+ // XInterface
+ virtual Any SAL_CALL queryInterface( const Type & aType) override;
+ virtual void SAL_CALL acquire() noexcept override { OWeakObject::acquire(); }
+ virtual void SAL_CALL release() noexcept override { OWeakObject::release(); }
+
+
+ // XTypeProvider
+ virtual Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ // XMaterialHolder
+ virtual Any SAL_CALL getMaterial() override;
+
+ // XInvocation
+ virtual Reference<XIntrospectionAccess> SAL_CALL getIntrospection() override;
+ virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override;
+ virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override;
+ virtual Any SAL_CALL getValue(const OUString& PropertyName) override;
+ virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override;
+ virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override;
+
+ // XInvocation2
+ virtual Sequence< OUString > SAL_CALL getMemberNames( ) override;
+ virtual Sequence< InvocationInfo > SAL_CALL getInfo( ) override;
+ virtual InvocationInfo SAL_CALL getInfoForName( const OUString& aName, sal_Bool bExact ) override;
+
+ // All Access and Container methods are not thread safe
+ // XElementAccess
+ virtual Type SAL_CALL getElementType() override
+ { return _xElementAccess->getElementType(); }
+
+ virtual sal_Bool SAL_CALL hasElements() override
+ { return _xElementAccess->hasElements(); }
+
+ // XNameContainer
+ virtual void SAL_CALL insertByName( const OUString& Name, const Any& Element ) override
+ { _xNameContainer->insertByName( Name, Element ); }
+
+ virtual void SAL_CALL removeByName( const OUString& Name ) override
+ { _xNameContainer->removeByName( Name ); }
+
+ // XNameReplace
+ virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element ) override
+ { _xNameReplace->replaceByName( Name, Element ); }
+
+ // XNameAccess
+ virtual Any SAL_CALL getByName( const OUString& Name ) override
+ { return _xNameAccess->getByName( Name ); }
+
+ virtual Sequence<OUString> SAL_CALL getElementNames() override
+ { return _xNameAccess->getElementNames(); }
+
+ virtual sal_Bool SAL_CALL hasByName( const OUString& Name ) override
+ { return _xNameAccess->hasByName( Name ); }
+
+ // XIndexContainer
+ virtual void SAL_CALL insertByIndex( sal_Int32 Index, const Any& Element ) override
+ { _xIndexContainer->insertByIndex( Index, Element ); }
+
+ virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override
+ { _xIndexContainer->removeByIndex( Index ); }
+
+ // XIndexReplace
+ virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element ) override
+ { _xIndexReplace->replaceByIndex( Index, Element ); }
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() override
+ { return _xIndexAccess->getCount(); }
+
+ virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override
+ { return _xIndexAccess->getByIndex( Index ); }
+
+ // XEnumerationAccess
+ virtual Reference<XEnumeration> SAL_CALL createEnumeration() override
+ { return _xEnumerationAccess->createEnumeration(); }
+
+ // XExactName
+ virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
+
+
+private:
+ void setMaterial( const Any& rMaterial );
+
+ void getInfoSequenceImpl( Sequence< OUString >* pStringSeq, Sequence< InvocationInfo >* pInfoSeq );
+ void fillInfoForNameAccess( InvocationInfo& rInfo, const OUString& aName );
+ static void fillInfoForProperty( InvocationInfo& rInfo, const Property& rProp );
+ static void fillInfoForMethod( InvocationInfo& rInfo, const Reference< XIdlMethod >& xMethod );
+
+ Reference<XTypeConverter> xTypeConverter;
+ Reference<XIntrospection> xIntrospection;
+ Reference<XIdlReflection> xCoreReflection;
+
+ Any _aMaterial;
+ // _xDirect and (_xIntrospectionAccess, xPropertySet) are exclusive
+ Reference<XInvocation> _xDirect;
+ Reference<XInvocation2> _xDirect2;
+ Reference<XPropertySet> _xPropertySet;
+ Reference<XIntrospectionAccess> _xIntrospectionAccess;
+
+ // supplied Interfaces
+ Reference<XNameContainer> _xNameContainer;
+ Reference<XNameReplace> _xNameReplace;
+ Reference<XNameAccess> _xNameAccess;
+ Reference<XIndexContainer> _xIndexContainer;
+ Reference<XIndexReplace> _xIndexReplace;
+ Reference<XIndexAccess> _xIndexAccess;
+ Reference<XEnumerationAccess> _xEnumerationAccess;
+ Reference<XElementAccess> _xElementAccess;
+
+
+ Reference<XExactName> _xENDirect, _xENIntrospection;
+
+ bool mbFromOLE;
+};
+
+}
+
+Invocation_Impl::Invocation_Impl
+(
+ const Any & rAdapted,
+ const Reference<XTypeConverter> & rTC,
+ const Reference<XIntrospection> & rI,
+ const Reference<XIdlReflection> & rCR,
+ bool bFromOLE
+)
+ : xTypeConverter( rTC )
+ , xIntrospection( rI )
+ , xCoreReflection( rCR )
+ , mbFromOLE( bFromOLE )
+{
+ setMaterial( rAdapted );
+}
+
+//### INTERFACE IMPLEMENTATIONS ####################################################################
+
+
+Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
+{
+ // PropertySet implementation
+ Any a = ::cppu::queryInterface( aType,
+ static_cast< XInvocation* >(this),
+ static_cast< XMaterialHolder* >(this),
+ static_cast< XTypeProvider * >(this) );
+ if( a.hasValue() )
+ {
+ return a;
+ }
+
+ if( aType == cppu::UnoType<XExactName>::get())
+ {
+ // Invocation does not support XExactName, if direct object supports
+ // XInvocation, but not XExactName. Except when called from OLE Automation.
+ if (mbFromOLE ||
+ (_xDirect.is() && _xENDirect.is()) ||
+ (!_xDirect.is() && _xENIntrospection.is()))
+ {
+ return Any( Reference< XExactName >( static_cast< XExactName* >(this) ) );
+ }
+ }
+ else if ( aType == cppu::UnoType<XNameContainer>::get())
+ {
+ if( _xNameContainer.is() )
+ return Any( Reference< XNameContainer >( static_cast< XNameContainer* >(this) ) );
+ }
+ else if ( aType == cppu::UnoType<XNameReplace>::get())
+ {
+ if( _xNameReplace.is() )
+ return Any( Reference< XNameReplace >( static_cast< XNameReplace* >(this) ) );
+ }
+ else if ( aType == cppu::UnoType<XNameAccess>::get())
+ {
+ if( _xNameAccess.is() )
+ return Any( Reference< XNameAccess >( static_cast< XNameAccess* >(this) ) );
+ }
+ else if ( aType == cppu::UnoType<XIndexContainer>::get())
+ {
+ if (_xIndexContainer.is())
+ return Any( Reference< XIndexContainer >( static_cast< XIndexContainer* >(this) ) );
+ }
+ else if ( aType == cppu::UnoType<XIndexReplace>::get())
+ {
+ if (_xIndexReplace.is())
+ return Any( Reference< XIndexReplace >( static_cast< XIndexReplace* >(this) ) );
+ }
+ else if ( aType == cppu::UnoType<XIndexAccess>::get())
+ {
+ if (_xIndexAccess.is())
+ return Any( Reference< XIndexAccess >( static_cast< XIndexAccess* >(this) ) );
+ }
+ else if ( aType == cppu::UnoType<XEnumerationAccess>::get())
+ {
+ if (_xEnumerationAccess.is())
+ return Any( Reference< XEnumerationAccess >( static_cast< XEnumerationAccess* >(this) ) );
+ }
+ else if ( aType == cppu::UnoType<XElementAccess>::get())
+ {
+ if (_xElementAccess.is())
+ {
+ return Any( Reference< XElementAccess >(
+ static_cast< XElementAccess* >(static_cast< XNameContainer* >(this)) ) );
+ }
+ }
+ else if ( aType == cppu::UnoType<XInvocation2>::get())
+ {
+ // Invocation does not support XInvocation2, if direct object supports
+ // XInvocation, but not XInvocation2.
+ if ( mbFromOLE ||
+ ( _xDirect.is() && _xDirect2.is()) ||
+ (!_xDirect.is() && _xIntrospectionAccess.is() ) )
+ {
+ return Any( Reference< XInvocation2 >( static_cast< XInvocation2* >(this) ) );
+ }
+ }
+
+ return OWeakObject::queryInterface( aType );
+}
+
+
+Any Invocation_Impl::getMaterial()
+{
+ // AB, 12.2.1999 Make sure that the material is taken when possible
+ // from the direct Invocation of the Introspection, otherwise structs
+ // are not handled correctly
+ Reference<XMaterialHolder> xMaterialHolder;
+ if( _xDirect.is() )
+ {
+ xMaterialHolder.set( _xDirect, UNO_QUERY );
+ //_xDirect->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
+ }
+ else if( _xIntrospectionAccess.is() )
+ {
+ xMaterialHolder.set( _xIntrospectionAccess, UNO_QUERY );
+ //_xIntrospectionAccess->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
+ }
+ if( xMaterialHolder.is() )
+ {
+ return xMaterialHolder->getMaterial();
+ }
+ return _aMaterial;
+}
+
+
+void Invocation_Impl::setMaterial( const Any& rMaterial )
+{
+ // set the material first and only once
+ _aMaterial = rMaterial;
+
+ // First do this outside the guard
+ _xDirect.set( rMaterial, UNO_QUERY );
+
+ if( !mbFromOLE && _xDirect.is() )
+ {
+ // Consult object directly
+ _xElementAccess.set( _xDirect, UNO_QUERY );
+ _xEnumerationAccess.set( _xDirect, UNO_QUERY );
+ _xIndexAccess.set( _xDirect, UNO_QUERY );
+ _xIndexReplace.set( _xDirect, UNO_QUERY );
+ _xIndexContainer.set( _xDirect, UNO_QUERY );
+ _xNameAccess.set( _xDirect, UNO_QUERY );
+ _xNameReplace.set( _xDirect, UNO_QUERY );
+ _xNameContainer.set( _xDirect, UNO_QUERY );
+ _xENDirect.set( _xDirect, UNO_QUERY );
+ _xDirect2.set( _xDirect, UNO_QUERY );
+ }
+ else
+ {
+ // Make Invocation on the Introspection
+ if (xIntrospection.is())
+ {
+ _xIntrospectionAccess = xIntrospection->inspect( _aMaterial );
+ if( _xIntrospectionAccess.is() )
+ {
+ _xElementAccess.set(
+ _xIntrospectionAccess->queryAdapter(
+ cppu::UnoType<XElementAccess>::get()), UNO_QUERY );
+
+ if( _xElementAccess.is() )
+ {
+ _xEnumerationAccess.set(
+ _xIntrospectionAccess->queryAdapter(
+ cppu::UnoType<XEnumerationAccess>::get()), UNO_QUERY );
+
+ _xIndexAccess.set(
+ _xIntrospectionAccess->queryAdapter(
+ cppu::UnoType<XIndexAccess>::get()), UNO_QUERY );
+
+ if( _xIndexAccess.is() )
+ {
+ _xIndexReplace.set(
+ _xIntrospectionAccess->queryAdapter(
+ cppu::UnoType<XIndexReplace>::get()), UNO_QUERY );
+
+ _xIndexContainer.set(
+ _xIntrospectionAccess->queryAdapter(
+ cppu::UnoType<XIndexContainer>::get()), UNO_QUERY );
+ }
+
+ _xNameAccess.set(
+ _xIntrospectionAccess->queryAdapter(
+ cppu::UnoType<XNameAccess>::get()), UNO_QUERY );
+
+ if( _xNameAccess.is() )
+ {
+ _xNameReplace.set(
+ _xIntrospectionAccess->queryAdapter(
+ cppu::UnoType<XNameReplace>::get()), UNO_QUERY );
+
+ _xNameContainer.set(
+ _xIntrospectionAccess->queryAdapter(
+ cppu::UnoType<XNameContainer>::get()), UNO_QUERY );
+ }
+ }
+
+ _xPropertySet.set( _xIntrospectionAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()),
+ UNO_QUERY );
+
+ _xENIntrospection.set( _xIntrospectionAccess, UNO_QUERY );
+ }
+ }
+ }
+}
+
+
+OUString Invocation_Impl::getExactName( const OUString& rApproximateName )
+{
+ if (_xENDirect.is())
+ return _xENDirect->getExactName( rApproximateName );
+
+ OUString aRet;
+ if (_xENIntrospection.is())
+ aRet = _xENIntrospection->getExactName( rApproximateName );
+ return aRet;
+}
+
+
+Reference<XIntrospectionAccess> Invocation_Impl::getIntrospection()
+{
+ if( _xDirect.is() )
+ return _xDirect->getIntrospection();
+ else
+ return _xIntrospectionAccess;
+}
+
+
+sal_Bool Invocation_Impl::hasMethod( const OUString& Name )
+{
+ if (!mbFromOLE && _xDirect.is())
+ return _xDirect->hasMethod( Name );
+ if( _xIntrospectionAccess.is() )
+ return _xIntrospectionAccess->hasMethod( Name, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
+ return false;
+}
+
+
+sal_Bool Invocation_Impl::hasProperty( const OUString& Name )
+{
+ if (_xDirect.is())
+ {
+ bool bRet = _xDirect->hasProperty( Name );
+ if (bRet || !mbFromOLE)
+ return bRet;
+ }
+ // PropertySet
+ if( _xIntrospectionAccess.is()
+ && _xIntrospectionAccess->hasProperty( Name, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
+ return true;
+ // NameAccess
+ if( _xNameAccess.is() )
+ return _xNameAccess->hasByName( Name );
+ return false;
+}
+
+
+Any Invocation_Impl::getValue( const OUString& PropertyName )
+{
+ try
+ {
+ if (_xDirect.is())
+ return _xDirect->getValue( PropertyName );
+ }
+ catch (Exception &)
+ {
+ if (!mbFromOLE)
+ throw;
+ }
+ try
+ {
+ // PropertySet
+ if( _xIntrospectionAccess.is() && _xPropertySet.is()
+ && _xIntrospectionAccess->hasProperty
+ ( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
+ {
+ return _xPropertySet->getPropertyValue( PropertyName );
+ }
+ // NameAccess
+ if( _xNameAccess.is() && _xNameAccess->hasByName( PropertyName ) )
+ return _xNameAccess->getByName( PropertyName );
+ }
+ catch (UnknownPropertyException &)
+ {
+ throw;
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (Exception &)
+ {
+ }
+
+ throw UnknownPropertyException( "cannot get value " + PropertyName );
+}
+
+
+void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value )
+{
+ try
+ {
+ if (_xDirect.is())
+ {
+ _xDirect->setValue( PropertyName, Value );
+ return;
+ }
+ }
+ catch (Exception &)
+ {
+ if (!mbFromOLE)
+ throw;
+ }
+ try
+ {
+ // Properties
+ if( _xIntrospectionAccess.is() && _xPropertySet.is()
+ && _xIntrospectionAccess->hasProperty(
+ PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
+ {
+ Property aProp = _xIntrospectionAccess->getProperty(
+ PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
+ Reference < XIdlClass > r = TypeToIdlClass( aProp.Type, xCoreReflection );
+ if( r->isAssignableFrom( TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
+ _xPropertySet->setPropertyValue( PropertyName, Value );
+ else if( xTypeConverter.is() )
+ _xPropertySet->setPropertyValue(
+ PropertyName, xTypeConverter->convertTo( Value, aProp.Type ) );
+ else
+ throw RuntimeException( "no type converter service!" );
+ }
+ // NameContainer
+ else if( _xNameContainer.is() )
+ {
+ // Note: This misfeature deliberately not adapted to apply to objects which
+ // have XNameReplace but not XNameContainer
+ Any aConv;
+ Reference < XIdlClass > r =
+ TypeToIdlClass( _xNameContainer->getElementType(), xCoreReflection );
+ if( r->isAssignableFrom(TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
+ aConv = Value;
+ else if( xTypeConverter.is() )
+ aConv = xTypeConverter->convertTo( Value, _xNameContainer->getElementType() );
+ else
+ throw RuntimeException( "no type converter service!" );
+
+ // Replace if present, otherwise insert
+ if (_xNameContainer->hasByName( PropertyName ))
+ _xNameContainer->replaceByName( PropertyName, aConv );
+ else
+ _xNameContainer->insertByName( PropertyName, aConv );
+ }
+ else
+ throw UnknownPropertyException( "no introspection nor name container!" );
+ }
+ catch (UnknownPropertyException &)
+ {
+ throw;
+ }
+ catch (CannotConvertException &)
+ {
+ throw;
+ }
+ catch (InvocationTargetException &)
+ {
+ throw;
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (const Exception & exc)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw InvocationTargetException(
+ "exception occurred in setValue(): " + exc.Message,
+ Reference< XInterface >(), anyEx );
+ }
+}
+
+
+Any Invocation_Impl::invoke( const OUString& FunctionName, const Sequence<Any>& InParams,
+ Sequence<sal_Int16>& OutIndices, Sequence<Any>& OutParams )
+{
+ if (!mbFromOLE && _xDirect.is())
+ return _xDirect->invoke( FunctionName, InParams, OutIndices, OutParams );
+
+ if (_xIntrospectionAccess.is())
+ {
+ // throw NoSuchMethodException if not exist
+ Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod(
+ FunctionName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
+
+ // ParameterInfos
+ Sequence<ParamInfo> aFParams = xMethod->getParameterInfos();
+ const ParamInfo* pFParams = aFParams.getConstArray();
+ sal_Int32 nFParamsLen = aFParams.getLength();
+ if (nFParamsLen != InParams.getLength())
+ {
+ throw IllegalArgumentException(
+ "incorrect number of parameters passed invoking function " + FunctionName +
+ ": expected " + OUString::number(nFParamsLen) + ", got " + OUString::number(InParams.getLength()),
+ static_cast<OWeakObject *>(this), sal_Int16(1) );
+ }
+
+ // IN Parameter
+ const Any* pInParams = InParams.getConstArray();
+
+ // Introspection Invoke Parameter
+ Sequence<Any> aInvokeParams( nFParamsLen );
+ Any* pInvokeParams = aInvokeParams.getArray();
+
+ // OUT Indices
+ OutIndices.realloc( nFParamsLen );
+ sal_Int16* pOutIndices = OutIndices.getArray();
+ sal_uInt32 nOutIndex = 0;
+
+ for ( sal_Int32 nPos = 0; nPos < nFParamsLen; ++nPos )
+ {
+ try
+ {
+ const ParamInfo& rFParam = pFParams[nPos];
+ const Reference<XIdlClass>& rDestType = rFParam.aType;
+
+ // is IN/INOUT parameter?
+ if (rFParam.aMode != ParamMode_OUT)
+ {
+ if (rDestType->isAssignableFrom( TypeToIdlClass( pInParams[nPos].getValueType(), xCoreReflection ) ))
+ {
+ pInvokeParams[nPos] = pInParams[nPos];
+ }
+ else if (xTypeConverter.is())
+ {
+ Type aDestType( rDestType->getTypeClass(), rDestType->getName() );
+ pInvokeParams[nPos] = xTypeConverter->convertTo( pInParams[nPos], aDestType );
+ }
+ else
+ {
+ CannotConvertException aExc;
+ aExc.Context = *this;
+ aExc.Message = "invocation type mismatch!";
+ throw aExc;
+ }
+ }
+
+ // is OUT/INOUT parameter?
+ if (rFParam.aMode != ParamMode_IN)
+ {
+ pOutIndices[nOutIndex] = static_cast<sal_Int16>(nPos);
+ if (rFParam.aMode == ParamMode_OUT)
+ rDestType->createObject( pInvokeParams[nPos] ); // default init
+ ++nOutIndex;
+ }
+ }
+ catch( CannotConvertException& rExc )
+ {
+ rExc.ArgumentIndex = nPos; // Add optional parameter index
+ throw;
+ }
+ }
+
+ // execute Method
+ Any aRet = xMethod->invoke( _aMaterial, aInvokeParams );
+
+ // OUT Params
+ OutIndices.realloc( nOutIndex );
+ OutParams.realloc( nOutIndex );
+
+ std::transform(std::cbegin(OutIndices), std::cend(OutIndices), OutParams.getArray(),
+ [&pInvokeParams](const sal_Int16 nIndex) -> Any { return pInvokeParams[nIndex]; });
+
+ return aRet;
+ }
+
+ RuntimeException aExc;
+ aExc.Context = *this;
+ aExc.Message = "invocation lacking of introspection access!";
+ throw aExc;
+}
+
+namespace {
+
+// Struct to optimize sorting
+struct MemberItem
+{
+ OUString aName;
+
+ // Defines where the member comes from
+ enum class Mode { NameAccess, PropertySet, Method };
+ Mode eMode;
+
+ // Index to respective sequence
+ // (Index to NameAccess sequence for eMode==Mode::NameAccess etc.)
+ sal_Int32 nIndex;
+};
+
+}
+
+// Implementation of getting name or info
+// String sequence will be filled when pStringSeq != NULL
+// Info sequence will be filled when pInfoSeq != NULL
+void Invocation_Impl::getInfoSequenceImpl
+(
+ Sequence< OUString >* pStringSeq,
+ Sequence< InvocationInfo >* pInfoSeq
+)
+{
+ //Sequence< OUString > aStrSeq;
+ //if( !pStringSeq )
+ //pStringSeq = &aStrSeq;
+
+
+ // Get all needed sequences
+ Sequence<OUString> aNameAccessNames;
+ Sequence<Property> aPropertySeq;
+ Sequence< Reference< XIdlMethod > > aMethodSeq;
+
+ if( _xNameAccess.is() )
+ {
+ aNameAccessNames = _xNameAccess->getElementNames();
+ }
+
+ if( _xIntrospectionAccess.is() )
+ {
+ aPropertySeq = _xIntrospectionAccess->getProperties
+ ( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
+
+ aMethodSeq = _xIntrospectionAccess->getMethods
+ ( MethodConcept::ALL - MethodConcept::DANGEROUS );
+ }
+
+ sal_Int32 nNameAccessCount = aNameAccessNames.getLength();
+ sal_Int32 nPropertyCount = aPropertySeq.getLength();
+ sal_Int32 nMethodCount = aMethodSeq.getLength();
+ sal_Int32 nTotalCount = nNameAccessCount + nPropertyCount + nMethodCount;
+
+ // Create and fill array of MemberItems
+ std::unique_ptr< MemberItem []> pItems( new MemberItem[ nTotalCount ] );
+ const OUString* pStrings = aNameAccessNames.getConstArray();
+ const Property* pProps = aPropertySeq.getConstArray();
+ const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
+
+ // Fill array of MemberItems
+ sal_Int32 i, iTotal = 0;
+
+ // Name Access
+ for( i = 0 ; i < nNameAccessCount ; i++, iTotal++ )
+ {
+ MemberItem& rItem = pItems[ iTotal ];
+ rItem.aName = pStrings[ i ];
+ rItem.eMode = MemberItem::Mode::NameAccess;
+ rItem.nIndex = i;
+ }
+
+ // Property set
+ for( i = 0 ; i < nPropertyCount ; i++, iTotal++ )
+ {
+ MemberItem& rItem = pItems[ iTotal ];
+ rItem.aName = pProps[ i ].Name;
+ rItem.eMode = MemberItem::Mode::PropertySet;
+ rItem.nIndex = i;
+ }
+
+ // Methods
+ for( i = 0 ; i < nMethodCount ; i++, iTotal++ )
+ {
+ MemberItem& rItem = pItems[ iTotal ];
+ Reference< XIdlMethod > xMethod = pMethods[ i ];
+ rItem.aName = xMethod->getName();
+ rItem.eMode = MemberItem::Mode::Method;
+ rItem.nIndex = i;
+ }
+
+ // Setting up result sequences
+ OUString* pRetStrings = nullptr;
+ if( pStringSeq )
+ {
+ pStringSeq->realloc( nTotalCount );
+ pRetStrings = pStringSeq->getArray();
+ }
+
+ InvocationInfo* pRetInfos = nullptr;
+ if( pInfoSeq )
+ {
+ pInfoSeq->realloc( nTotalCount );
+ pRetInfos = pInfoSeq->getArray();
+ }
+
+ // Fill result sequences in the correct order of members
+ for( iTotal = 0 ; iTotal < nTotalCount ; iTotal++ )
+ {
+ MemberItem& rItem = pItems[ iTotal ];
+ if( pRetStrings )
+ {
+ pRetStrings[ iTotal ] = rItem.aName;
+ }
+
+ if( pRetInfos )
+ {
+ if( rItem.eMode == MemberItem::Mode::NameAccess )
+ {
+ fillInfoForNameAccess( pRetInfos[ iTotal ], rItem.aName );
+ }
+ else if( rItem.eMode == MemberItem::Mode::PropertySet )
+ {
+ fillInfoForProperty( pRetInfos[ iTotal ], pProps[ rItem.nIndex ] );
+ }
+ else if( rItem.eMode == MemberItem::Mode::Method )
+ {
+ fillInfoForMethod( pRetInfos[ iTotal ], pMethods[ rItem.nIndex ] );
+ }
+ }
+ }
+}
+
+// XInvocation2
+Sequence< OUString > SAL_CALL Invocation_Impl::getMemberNames( )
+{
+ if( _xDirect2.is() )
+ {
+ return _xDirect2->getMemberNames();
+ }
+ Sequence< OUString > aRetSeq;
+ getInfoSequenceImpl( &aRetSeq, nullptr );
+ return aRetSeq;
+}
+
+Sequence< InvocationInfo > SAL_CALL Invocation_Impl::getInfo( )
+{
+ if( _xDirect2.is() )
+ {
+ return _xDirect2->getInfo();
+ }
+ Sequence< InvocationInfo > aRetSeq;
+ getInfoSequenceImpl( nullptr, &aRetSeq );
+ return aRetSeq;
+}
+
+InvocationInfo SAL_CALL Invocation_Impl::getInfoForName( const OUString& aName, sal_Bool bExact )
+{
+ if( _xDirect2.is() )
+ {
+ return _xDirect2->getInfoForName( aName, bExact );
+ }
+
+ bool bFound = false;
+ OUString aExactName = aName;
+ InvocationInfo aRetInfo;
+
+ if( bExact )
+ aExactName = getExactName( aName );
+ if( !aExactName.isEmpty() )
+ {
+ if( _xIntrospectionAccess->hasMethod( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ) )
+ {
+ Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod
+ ( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
+ fillInfoForMethod( aRetInfo, xMethod );
+ bFound = true;
+ }
+ else
+ {
+ if( _xIntrospectionAccess.is() && _xIntrospectionAccess->hasProperty
+ ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
+ {
+ Property aProp = _xIntrospectionAccess->getProperty
+ ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
+ fillInfoForProperty( aRetInfo, aProp );
+ bFound = true;
+ }
+ // NameAccess
+ else if( _xNameAccess.is() && _xNameAccess->hasByName( aExactName ) )
+ {
+ fillInfoForNameAccess( aRetInfo, aExactName );
+ bFound = true;
+ }
+ }
+ }
+ if( !bFound )
+ {
+ throw IllegalArgumentException(
+ "getExactName(), Unknown name " + aName,
+ static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
+ }
+ return aRetInfo;
+}
+
+// Helper functions to fill InvocationInfo for XNameAccess
+void Invocation_Impl::fillInfoForNameAccess
+(
+ InvocationInfo& rInfo,
+ const OUString& aName
+)
+{
+ rInfo.aName = aName;
+ rInfo.eMemberType = MemberType_PROPERTY;
+ rInfo.PropertyAttribute = 0;
+ if( !_xNameContainer.is() )
+ {
+ rInfo.PropertyAttribute = PropertyAttribute::READONLY;
+ }
+ rInfo.aType = _xNameAccess->getElementType();
+}
+
+void Invocation_Impl::fillInfoForProperty
+(
+ InvocationInfo& rInfo,
+ const Property& rProp
+)
+{
+ rInfo.aName = rProp.Name;
+ rInfo.eMemberType = MemberType_PROPERTY;
+ rInfo.PropertyAttribute = rProp.Attributes;
+ rInfo.aType = rProp.Type;
+}
+
+void Invocation_Impl::fillInfoForMethod
+(
+ InvocationInfo& rInfo,
+ const Reference< XIdlMethod >& xMethod
+)
+{
+ rInfo.aName = xMethod->getName();
+ rInfo.eMemberType = MemberType_METHOD;
+ Reference< XIdlClass > xReturnClass = xMethod->getReturnType();
+ Type aReturnType( xReturnClass->getTypeClass(), xReturnClass->getName() );
+ rInfo.aType = aReturnType;
+ Sequence<ParamInfo> aParamInfos = xMethod->getParameterInfos();
+ sal_Int32 nParamCount = aParamInfos.getLength();
+ if( nParamCount <= 0 )
+ return;
+
+ const ParamInfo* pInfo = aParamInfos.getConstArray();
+
+ rInfo.aParamTypes.realloc( nParamCount );
+ Type* pParamTypes = rInfo.aParamTypes.getArray();
+ rInfo.aParamModes.realloc( nParamCount );
+ ParamMode* pParamModes = rInfo.aParamModes.getArray();
+
+ for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
+ {
+ Reference< XIdlClass > xParamClass = pInfo[i].aType;
+ Type aParamType( xParamClass->getTypeClass(), xParamClass->getName() );
+ pParamTypes[ i ] = aParamType;
+ pParamModes[ i ] = pInfo[i].aMode;
+ }
+}
+
+
+// XTypeProvider
+Sequence< Type > SAL_CALL Invocation_Impl::getTypes()
+{
+ static Sequence<Type> s_types = [this]() {
+ std::vector<Type> tmp {
+ cppu::UnoType<XTypeProvider>::get(),
+ cppu::UnoType<XWeak>::get(),
+ cppu::UnoType<XInvocation>::get(),
+ cppu::UnoType<XMaterialHolder>::get() };
+
+ // Invocation does not support XExactName if direct object supports
+ // XInvocation, but not XExactName.
+ if ((_xDirect.is() && _xENDirect.is()) || (!_xDirect.is() && _xENIntrospection.is()))
+ tmp.push_back(cppu::UnoType<XExactName>::get());
+ if (_xNameContainer.is())
+ tmp.push_back(cppu::UnoType<XNameContainer>::get());
+ if (_xNameReplace.is())
+ tmp.push_back(cppu::UnoType<XNameReplace>::get());
+ if (_xNameAccess.is())
+ tmp.push_back(cppu::UnoType<XNameAccess>::get());
+ if (_xIndexContainer.is())
+ tmp.push_back(cppu::UnoType<XIndexContainer>::get());
+ if (_xIndexReplace.is())
+ tmp.push_back(cppu::UnoType<XIndexReplace>::get());
+ if (_xIndexAccess.is())
+ tmp.push_back(cppu::UnoType<XIndexAccess>::get());
+ if (_xEnumerationAccess.is())
+ tmp.push_back(cppu::UnoType<XEnumerationAccess>::get());
+ if (_xElementAccess.is())
+ tmp.push_back(cppu::UnoType<XElementAccess>::get());
+ // Invocation does not support XInvocation2, if direct object supports
+ // XInvocation, but not XInvocation2.
+ if ((_xDirect.is() && _xDirect2.is()) || (!_xDirect.is() && _xIntrospectionAccess.is()))
+ tmp.push_back(cppu::UnoType<XInvocation2>::get());
+
+ return comphelper::containerToSequence(tmp);
+ }();
+ return s_types;
+}
+
+Sequence< sal_Int8 > SAL_CALL Invocation_Impl::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+namespace {
+
+class InvocationService
+ : public WeakImplHelper< XSingleServiceFactory, XServiceInfo >
+{
+public:
+ explicit InvocationService( const Reference<XComponentContext> & xCtx );
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XSingleServiceFactory
+ Reference<XInterface> SAL_CALL createInstance() override;
+ Reference<XInterface> SAL_CALL createInstanceWithArguments(
+ const Sequence<Any>& rArguments ) override;
+private:
+ Reference<XComponentContext> mxCtx;
+ Reference<XMultiComponentFactory> mxSMgr;
+ Reference<XTypeConverter> xTypeConverter;
+ Reference<XIntrospection> xIntrospection;
+ Reference<XIdlReflection> xCoreReflection;
+};
+
+}
+
+InvocationService::InvocationService( const Reference<XComponentContext> & xCtx )
+ : mxCtx( xCtx )
+ , mxSMgr( xCtx->getServiceManager() )
+ , xCoreReflection( css::reflection::theCoreReflection::get(mxCtx) )
+{
+ xTypeConverter.set(
+ mxSMgr->createInstanceWithContext( "com.sun.star.script.Converter", xCtx ),
+ UNO_QUERY );
+ xIntrospection = theIntrospection::get(xCtx);
+}
+
+// XServiceInfo
+OUString InvocationService::getImplementationName()
+{
+ return "com.sun.star.comp.stoc.Invocation";
+}
+
+// XServiceInfo
+sal_Bool InvocationService::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > InvocationService::getSupportedServiceNames()
+{
+ return { "com.sun.star.script.Invocation" };
+}
+
+
+Reference<XInterface> InvocationService::createInstance()
+{
+ //TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
+ return Reference<XInterface>(); // dummy
+}
+
+
+Reference<XInterface> InvocationService::createInstanceWithArguments(
+ const Sequence<Any>& rArguments )
+{
+ if (rArguments.getLength() == 2)
+ {
+ OUString aArg1;
+ if ((rArguments[1] >>= aArg1) &&
+ aArg1 == "FromOLE")
+ {
+ return Reference< XInterface >
+ ( *new Invocation_Impl( *rArguments.getConstArray(),
+ xTypeConverter, xIntrospection, xCoreReflection, true ) );
+ }
+ }
+ if (rArguments.getLength() == 1)
+ {
+ return Reference< XInterface >
+ ( *new Invocation_Impl( *rArguments.getConstArray(),
+ xTypeConverter, xIntrospection, xCoreReflection, false ) );
+ }
+
+ //TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
+ return Reference<XInterface>();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+stoc_InvocationService_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new InvocationService(context));
+}
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/stoc/source/invocation_adapterfactory/iafactory.cxx b/stoc/source/invocation_adapterfactory/iafactory.cxx
new file mode 100644
index 000000000..894b00f42
--- /dev/null
+++ b/stoc/source/invocation_adapterfactory/iafactory.cxx
@@ -0,0 +1,882 @@
+/* -*- 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 <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <osl/mutex.hxx>
+#include <o3tl/sorted_vector.hxx>
+#include <sal/log.hxx>
+
+#include <uno/dispatcher.h>
+#include <uno/data.h>
+#include <uno/any2.h>
+#include <uno/lbnames.h>
+#include <uno/mapping.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <com/sun/star/script/XTypeConverter.hpp>
+#include <com/sun/star/script/XInvocationAdapterFactory.hpp>
+#include <com/sun/star/script/XInvocationAdapterFactory2.hpp>
+#include <com/sun/star/script/XInvocation.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/reflection/InvocationTargetException.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <unordered_map>
+#include <vector>
+
+using namespace ::std;
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace css::uno;
+
+namespace stoc_invadp
+{
+
+
+namespace {
+
+struct hash_ptr
+{
+ size_t operator() ( void * p ) const
+ { return reinterpret_cast<size_t>(p); }
+};
+
+}
+
+typedef o3tl::sorted_vector< void * > t_ptr_set;
+typedef std::unordered_map< void *, t_ptr_set, hash_ptr > t_ptr_map;
+
+namespace {
+
+class FactoryImpl
+ : public ::cppu::WeakImplHelper< lang::XServiceInfo,
+ script::XInvocationAdapterFactory,
+ script::XInvocationAdapterFactory2 >
+{
+public:
+ Mapping m_aUno2Cpp;
+ Mapping m_aCpp2Uno;
+ uno_Interface * m_pConverter;
+
+ typelib_TypeDescription * m_pInvokMethodTD;
+ typelib_TypeDescription * m_pSetValueTD;
+ typelib_TypeDescription * m_pGetValueTD;
+ typelib_TypeDescription * m_pAnySeqTD;
+ typelib_TypeDescription * m_pShortSeqTD;
+ typelib_TypeDescription * m_pConvertToTD;
+
+ Mutex m_mutex;
+ t_ptr_map m_receiver2adapters;
+
+ explicit FactoryImpl( Reference< XComponentContext > const & xContext );
+ virtual ~FactoryImpl() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XInvocationAdapterFactory
+ virtual Reference< XInterface > SAL_CALL createAdapter(
+ const Reference< script::XInvocation > & xReceiver, const Type & rType ) override;
+ // XInvocationAdapterFactory2
+ virtual Reference< XInterface > SAL_CALL createAdapter(
+ const Reference< script::XInvocation > & xReceiver,
+ const Sequence< Type > & rTypes ) override;
+};
+struct AdapterImpl;
+
+struct InterfaceAdapterImpl : public uno_Interface
+{
+ AdapterImpl * m_pAdapter;
+ typelib_InterfaceTypeDescription * m_pTypeDescr;
+};
+
+struct AdapterImpl
+{
+ oslInterlockedCount m_nRef;
+ FactoryImpl * m_pFactory;
+ void * m_key; // map key
+ uno_Interface * m_pReceiver; // XInvocation receiver
+
+ std::vector<InterfaceAdapterImpl> m_vInterfaces;
+
+ // XInvocation calls
+ void getValue(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, uno_Any ** ppException );
+ void setValue(
+ const typelib_TypeDescription * pMemberType,
+ void * pArgs[], uno_Any ** ppException );
+ void invoke(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException );
+
+ bool coerce_assign(
+ void * pDest, typelib_TypeDescriptionReference * pType,
+ uno_Any * pSource, uno_Any * pExc );
+ inline bool coerce_construct(
+ void * pDest, typelib_TypeDescriptionReference * pType,
+ uno_Any * pSource, uno_Any * pExc );
+
+ inline void acquire();
+ inline void release();
+ inline ~AdapterImpl();
+ inline AdapterImpl(
+ void * key, Reference< script::XInvocation > const & xReceiver,
+ const Sequence< Type > & rTypes,
+ FactoryImpl * pFactory );
+
+ // Copy assignment is forbidden and not implemented.
+ AdapterImpl (const AdapterImpl &) = delete;
+ AdapterImpl & operator= (const AdapterImpl &) = delete;
+};
+
+}
+
+inline AdapterImpl::~AdapterImpl()
+{
+ for ( size_t nPos = m_vInterfaces.size(); nPos--; )
+ {
+ ::typelib_typedescription_release(
+ &m_vInterfaces[ nPos ].m_pTypeDescr->aBase );
+ }
+
+ (*m_pReceiver->release)( m_pReceiver );
+ m_pFactory->release();
+}
+
+inline void AdapterImpl::acquire()
+{
+ osl_atomic_increment( &m_nRef );
+}
+
+inline void AdapterImpl::release()
+{
+ bool delete_this = false;
+ {
+ MutexGuard guard( m_pFactory->m_mutex );
+ if (! osl_atomic_decrement( &m_nRef ))
+ {
+ t_ptr_map::iterator iFind(
+ m_pFactory->m_receiver2adapters.find( m_key ) );
+ OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind );
+ t_ptr_set & adapter_set = iFind->second;
+ if (adapter_set.erase( this ) != 1) {
+ OSL_ASSERT( false );
+ }
+ if (adapter_set.empty())
+ {
+ m_pFactory->m_receiver2adapters.erase( iFind );
+ }
+ delete_this = true;
+ }
+ }
+ if (delete_this)
+ delete this;
+}
+
+
+static void constructRuntimeException(
+ uno_Any * pExc, const OUString & rMsg )
+{
+ RuntimeException exc( rMsg );
+ // no conversion needed due to binary compatibility + no convertible type
+ ::uno_type_any_construct(
+ pExc, &exc, cppu::UnoType<decltype(exc)>::get().getTypeLibType(), nullptr );
+}
+
+
+static bool type_equals(
+ typelib_TypeDescriptionReference * pType1,
+ typelib_TypeDescriptionReference * pType2 )
+{
+ return (pType1 == pType2 ||
+ (pType1->pTypeName->length == pType2->pTypeName->length &&
+ 0 == ::rtl_ustr_compare(
+ pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
+}
+
+
+bool AdapterImpl::coerce_assign(
+ void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
+ uno_Any * pOutExc )
+{
+ if (typelib_TypeClass_ANY == pType->eTypeClass)
+ {
+ ::uno_type_any_assign(
+ static_cast<uno_Any *>(pDest), pSource->pData, pSource->pType, nullptr, nullptr );
+ return true;
+ }
+ if (::uno_type_assignData(
+ pDest, pType, pSource->pData, pSource->pType, nullptr, nullptr, nullptr ))
+ {
+ return true;
+ }
+ else // try type converter
+ {
+ uno_Any ret;
+ void * args[ 2 ];
+ args[ 0 ] = pSource;
+ args[ 1 ] = &pType;
+ uno_Any exc;
+ uno_Any * p_exc = &exc;
+
+ // converTo()
+ (*m_pFactory->m_pConverter->pDispatcher)(
+ m_pFactory->m_pConverter,
+ m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
+
+ if (p_exc) // exception occurred
+ {
+ OSL_ASSERT(
+ p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
+ if (typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType<RuntimeException>::get().getTypeLibType(),
+ p_exc->pType ))
+ {
+ // is RuntimeException or derived: rethrow
+ uno_type_any_construct(
+ pOutExc, p_exc->pData, p_exc->pType, nullptr );
+ }
+ else
+ {
+ // set runtime exception
+ constructRuntimeException(
+ pOutExc, "type coercion failed: " +
+ static_cast< Exception const * >(
+ p_exc->pData )->Message );
+ }
+ ::uno_any_destruct( p_exc, nullptr );
+ // pOutExc constructed
+ return false;
+ }
+ else
+ {
+ bool succ = ::uno_type_assignData(
+ pDest, pType, ret.pData, ret.pType, nullptr, nullptr, nullptr );
+ ::uno_any_destruct( &ret, nullptr );
+ OSL_ENSURE(
+ succ, "### conversion succeeded, but assignment failed!?" );
+ if (! succ)
+ {
+ // set runtime exception
+ constructRuntimeException(
+ pOutExc,
+ "type coercion failed: "
+ "conversion succeeded, but assignment failed?!" );
+ }
+ return succ;
+ }
+ }
+}
+
+inline bool AdapterImpl::coerce_construct(
+ void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
+ uno_Any * pExc )
+{
+ if (typelib_TypeClass_ANY == pType->eTypeClass)
+ {
+ ::uno_type_copyData( pDest, pSource, pType, nullptr );
+ return true;
+ }
+ if (type_equals( pType, pSource->pType))
+ {
+ ::uno_type_copyData( pDest, pSource->pData, pType, nullptr );
+ return true;
+ }
+ ::uno_type_constructData( pDest, pType );
+ return coerce_assign( pDest, pType, pSource, pExc );
+}
+
+
+static void handleInvokExc( uno_Any * pDest, uno_Any * pSource )
+{
+ OUString const & name =
+ OUString::unacquired( &pSource->pType->pTypeName );
+
+ if ( name == "com.sun.star.reflection.InvocationTargetException" )
+ {
+ // unwrap invocation target exception
+ uno_Any * target_exc =
+ &static_cast< reflection::InvocationTargetException * >(
+ pSource->pData )->TargetException;
+ ::uno_type_any_construct(
+ pDest, target_exc->pData, target_exc->pType, nullptr );
+ }
+ else // all other exceptions are wrapped to RuntimeException
+ {
+ if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass)
+ {
+ constructRuntimeException(
+ pDest, static_cast<Exception const *>(pSource->pData)->Message );
+ }
+ else
+ {
+ constructRuntimeException(
+ pDest, "no exception has been thrown via invocation?!" );
+ }
+ }
+}
+
+void AdapterImpl::getValue(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, uno_Any ** ppException )
+{
+ uno_Any aInvokRet;
+ void * pInvokArgs[1];
+ pInvokArgs[0] = const_cast<rtl_uString **>(
+ &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
+ uno_Any aInvokExc;
+ uno_Any * pInvokExc = &aInvokExc;
+
+ // getValue()
+ (*m_pReceiver->pDispatcher)(
+ m_pReceiver, m_pFactory->m_pGetValueTD,
+ &aInvokRet, pInvokArgs, &pInvokExc );
+
+ if (pInvokExc) // getValue() call exception
+ {
+ handleInvokExc( *ppException, pInvokExc );
+ ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
+ }
+ else // invocation call succeeded
+ {
+ if (coerce_construct(
+ pReturn,
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
+ pMemberType)->pAttributeTypeRef,
+ &aInvokRet, *ppException ))
+ {
+ *ppException = nullptr; // no exceptions be thrown
+ }
+ ::uno_any_destruct( &aInvokRet, nullptr );
+ }
+}
+
+void AdapterImpl::setValue(
+ const typelib_TypeDescription * pMemberType,
+ void * pArgs[], uno_Any ** ppException )
+{
+ uno_Any aInvokVal;
+ ::uno_type_any_construct(
+ &aInvokVal, pArgs[0],
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
+ pMemberType)->pAttributeTypeRef, nullptr );
+
+ void * pInvokArgs[2];
+ pInvokArgs[0] = const_cast<rtl_uString **>(
+ &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
+ pInvokArgs[1] = &aInvokVal;
+ uno_Any aInvokExc;
+ uno_Any * pInvokExc = &aInvokExc;
+
+ // setValue()
+ (*m_pReceiver->pDispatcher)(
+ m_pReceiver, m_pFactory->m_pSetValueTD, nullptr, pInvokArgs, &pInvokExc );
+
+ if (pInvokExc) // setValue() call exception
+ {
+ handleInvokExc( *ppException, pInvokExc );
+ ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
+ }
+ else // invocation call succeeded
+ {
+ *ppException = nullptr; // no exceptions be thrown
+ }
+
+ ::uno_any_destruct( &aInvokVal, nullptr ); // cleanup
+}
+
+void AdapterImpl::invoke(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException )
+{
+ sal_Int32 nParams =
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType)->nParams;
+ typelib_MethodParameter * pFormalParams =
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType)->pParams;
+
+ // in params
+ uno_Sequence * pInParamsSeq = nullptr;
+ ::uno_sequence_construct(
+ &pInParamsSeq, m_pFactory->m_pAnySeqTD, nullptr, nParams, nullptr );
+ uno_Any * pInAnys = reinterpret_cast<uno_Any *>(pInParamsSeq->elements);
+ sal_Int32 nOutParams = 0;
+ sal_Int32 nPos;
+ for ( nPos = nParams; nPos--; )
+ {
+ typelib_MethodParameter const & rParam = pFormalParams[nPos];
+ if (rParam.bIn) // is in/inout param
+ {
+ ::uno_type_any_assign(
+ &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, nullptr, nullptr );
+ }
+ // else: pure out is empty any
+
+ if (rParam.bOut)
+ ++nOutParams;
+ }
+
+ // out params, out indices
+ uno_Sequence * pOutIndices;
+ uno_Sequence * pOutParams;
+ // return value
+ uno_Any aInvokRet;
+ // perform call
+ void * pInvokArgs[4];
+ pInvokArgs[0] = const_cast<rtl_uString **>(
+ &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
+ pInvokArgs[1] = &pInParamsSeq;
+ pInvokArgs[2] = &pOutIndices;
+ pInvokArgs[3] = &pOutParams;
+ uno_Any aInvokExc;
+ uno_Any * pInvokExc = &aInvokExc;
+
+ // invoke() call
+ (*m_pReceiver->pDispatcher)(
+ m_pReceiver, m_pFactory->m_pInvokMethodTD,
+ &aInvokRet, pInvokArgs, &pInvokExc );
+
+ if (pInvokExc)
+ {
+ handleInvokExc( *ppException, pInvokExc );
+ ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
+ }
+ else // no invocation exception
+ {
+ // write changed out params
+ OSL_ENSURE(
+ pOutParams->nElements == nOutParams &&
+ pOutIndices->nElements == nOutParams,
+ "### out params lens differ!" );
+ if (pOutParams->nElements == nOutParams &&
+ pOutIndices->nElements == nOutParams)
+ {
+ sal_Int16 * pIndices = reinterpret_cast<sal_Int16 *>(pOutIndices->elements);
+ uno_Any * pOut = reinterpret_cast<uno_Any *>(pOutParams->elements);
+ for ( nPos = 0; nPos < nOutParams; ++nPos )
+ {
+ sal_Int32 nIndex = pIndices[nPos];
+ OSL_ENSURE( nIndex < nParams, "### illegal index!" );
+ typelib_MethodParameter const & rParam = pFormalParams[nIndex];
+ bool succ;
+ if (rParam.bIn) // is in/inout param
+ {
+ succ = coerce_assign(
+ pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
+ *ppException );
+ }
+ else // pure out
+ {
+ succ = coerce_construct(
+ pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
+ *ppException );
+ }
+ if (! succ) // cleanup of out params
+ {
+ for ( sal_Int32 n = 0; n <= nPos; ++n )
+ {
+ sal_Int32 nIndex2 = pIndices[n];
+ OSL_ENSURE( nIndex2 < nParams, "### illegal index!" );
+ typelib_MethodParameter const & rParam2 =
+ pFormalParams[nIndex2];
+ if (! rParam2.bIn) // is pure out param
+ {
+ ::uno_type_destructData(
+ pArgs[nIndex2], rParam2.pTypeRef, nullptr );
+ }
+ }
+ }
+ }
+ if (nPos == pOutIndices->nElements)
+ {
+ // out param copy ok; write return value
+ if (coerce_construct(
+ pReturn,
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(
+ pMemberType)->pReturnTypeRef,
+ &aInvokRet, *ppException ))
+ {
+ *ppException = nullptr; // no exception
+ }
+ }
+ }
+ else
+ {
+ // set runtime exception
+ constructRuntimeException(
+ *ppException,
+ "out params lengths differ after invocation call!" );
+ }
+ // cleanup invok out params
+ ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, nullptr );
+ ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, nullptr );
+ // cleanup invok return value
+ ::uno_any_destruct( &aInvokRet, nullptr );
+ }
+ // cleanup constructed in params
+ ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, nullptr );
+}
+
+extern "C"
+{
+
+static void adapter_acquire( uno_Interface * pUnoI )
+{
+ static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
+}
+
+static void adapter_release( uno_Interface * pUnoI )
+{
+ static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
+}
+
+static void adapter_dispatch(
+ uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException )
+{
+ // query to emulated interface
+ switch (reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->nPosition)
+ {
+ case 0: // queryInterface()
+ {
+ AdapterImpl * that =
+ static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
+ *ppException = nullptr; // no exc
+ typelib_TypeDescriptionReference * pDemanded =
+ *static_cast<typelib_TypeDescriptionReference **>(pArgs[0]);
+ // pInterfaces[0] is XInterface
+ for ( size_t nPos = 0; nPos < that->m_vInterfaces.size(); ++nPos )
+ {
+ typelib_InterfaceTypeDescription * pTD =
+ that->m_vInterfaces[nPos].m_pTypeDescr;
+ while (pTD)
+ {
+ if (type_equals( pTD->aBase.pWeakRef, pDemanded ))
+ {
+ uno_Interface * pUnoI2 = &that->m_vInterfaces[nPos];
+ ::uno_any_construct(
+ static_cast<uno_Any *>(pReturn), &pUnoI2,
+ &pTD->aBase, nullptr );
+ return;
+ }
+ pTD = pTD->pBaseTypeDescription;
+ }
+ }
+ ::uno_any_construct( static_cast<uno_Any *>(pReturn), nullptr, nullptr, nullptr ); // clear()
+ break;
+ }
+ case 1: // acquire()
+ *ppException = nullptr; // no exc
+ adapter_acquire( pUnoI );
+ break;
+ case 2: // release()
+ *ppException = nullptr; // no exc
+ adapter_release( pUnoI );
+ break;
+
+ default:
+ {
+ AdapterImpl * that =
+ static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
+ if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
+ {
+ that->invoke( pMemberType, pReturn, pArgs, ppException );
+ }
+ else // attribute
+ {
+ if (pReturn)
+ that->getValue( pMemberType, pReturn, ppException );
+ else
+ that->setValue( pMemberType, pArgs, ppException );
+ }
+ }
+ }
+}
+}
+
+AdapterImpl::AdapterImpl(
+ void * key, Reference< script::XInvocation > const & xReceiver,
+ const Sequence< Type > & rTypes,
+ FactoryImpl * pFactory )
+ : m_nRef( 1 ),
+ m_pFactory( pFactory ),
+ m_key( key ),
+ m_vInterfaces( rTypes.getLength() )
+{
+ // init adapters
+ const Type * pTypes = rTypes.getConstArray();
+ for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
+ {
+ InterfaceAdapterImpl * pInterface = &m_vInterfaces[nPos];
+ pInterface->acquire = adapter_acquire;
+ pInterface->release = adapter_release;
+ pInterface->pDispatcher = adapter_dispatch;
+ pInterface->m_pAdapter = this;
+ pInterface->m_pTypeDescr = nullptr;
+ pTypes[nPos].getDescription(
+ reinterpret_cast<typelib_TypeDescription **>(&pInterface->m_pTypeDescr) );
+ OSL_ASSERT( pInterface->m_pTypeDescr );
+ if (! pInterface->m_pTypeDescr)
+ {
+ for ( sal_Int32 n = 0; n < nPos; ++n )
+ {
+ ::typelib_typedescription_release(
+ &m_vInterfaces[ n ].m_pTypeDescr->aBase );
+ }
+ throw RuntimeException(
+ "cannot retrieve all interface type infos!" );
+ }
+ }
+
+ // map receiver
+ m_pReceiver = static_cast<uno_Interface *>(m_pFactory->m_aCpp2Uno.mapInterface(
+ xReceiver.get(), cppu::UnoType<decltype(xReceiver)>::get() ));
+ OSL_ASSERT( nullptr != m_pReceiver );
+ if (! m_pReceiver)
+ {
+ throw RuntimeException( "cannot map receiver!" );
+ }
+
+ m_pFactory->acquire();
+}
+
+
+FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext )
+ : m_aUno2Cpp(Mapping( UNO_LB_UNO, CPPU_CURRENT_LANGUAGE_BINDING_NAME )),
+ m_aCpp2Uno(Mapping( CPPU_CURRENT_LANGUAGE_BINDING_NAME, UNO_LB_UNO)),
+ m_pInvokMethodTD( nullptr ),
+ m_pSetValueTD( nullptr ),
+ m_pGetValueTD( nullptr ),
+ m_pAnySeqTD( nullptr ),
+ m_pShortSeqTD( nullptr ),
+ m_pConvertToTD( nullptr )
+{
+ // C++/UNO bridge
+ OSL_ENSURE(
+ m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" );
+
+ // type converter
+ Reference< script::XTypeConverter > xConverter(
+ xContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.script.Converter",
+ xContext ),
+ UNO_QUERY_THROW );
+ m_pConverter = static_cast<uno_Interface *>(m_aCpp2Uno.mapInterface(
+ xConverter.get(), cppu::UnoType<decltype(xConverter)>::get() ));
+ OSL_ASSERT( nullptr != m_pConverter );
+
+ // some type info:
+ // sequence< any >
+ Type const & rAnySeqType = cppu::UnoType<Sequence< Any >>::get();
+ rAnySeqType.getDescription( &m_pAnySeqTD );
+ // sequence< short >
+ const Type & rShortSeqType =
+ cppu::UnoType<Sequence< sal_Int16 >>::get();
+ rShortSeqType.getDescription( &m_pShortSeqTD );
+ // script.XInvocation
+ typelib_TypeDescription * pTD = nullptr;
+ const Type & rInvType = cppu::UnoType<script::XInvocation>::get();
+ TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
+ typelib_InterfaceTypeDescription * pITD;
+ pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
+ if( ! pITD->aBase.bComplete )
+ typelib_typedescription_complete( &pTD );
+ ::typelib_typedescriptionreference_getDescription(
+ &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke()
+ ::typelib_typedescriptionreference_getDescription(
+ &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue()
+ ::typelib_typedescriptionreference_getDescription(
+ &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue()
+ // script.XTypeConverter
+ const Type & rTCType =
+ cppu::UnoType<script::XTypeConverter>::get();
+ TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() );
+ pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
+ ::typelib_typedescriptionreference_getDescription(
+ &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo()
+ TYPELIB_DANGER_RELEASE( pTD );
+
+ if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD ||
+ !m_pConvertToTD ||
+ !m_pAnySeqTD || !m_pShortSeqTD)
+ {
+ throw RuntimeException( "missing type descriptions!" );
+ }
+}
+
+FactoryImpl::~FactoryImpl()
+{
+ ::typelib_typedescription_release( m_pInvokMethodTD );
+ ::typelib_typedescription_release( m_pSetValueTD );
+ ::typelib_typedescription_release( m_pGetValueTD );
+ ::typelib_typedescription_release( m_pAnySeqTD );
+ ::typelib_typedescription_release( m_pShortSeqTD );
+ ::typelib_typedescription_release( m_pConvertToTD );
+
+ (*m_pConverter->release)( m_pConverter );
+
+#if OSL_DEBUG_LEVEL > 0
+ assert(m_receiver2adapters.empty() && "still adapters out there!?");
+#endif
+}
+
+
+static AdapterImpl * lookup_adapter(
+ t_ptr_set ** pp_adapter_set,
+ t_ptr_map & map, void * key, Sequence< Type > const & rTypes )
+{
+ t_ptr_set & adapters_set = map[ key ];
+ *pp_adapter_set = &adapters_set;
+ if (adapters_set.empty())
+ return nullptr; // shortcut
+ // find matching adapter
+ Type const * pTypes = rTypes.getConstArray();
+ sal_Int32 nTypes = rTypes.getLength();
+ for (const auto& rpAdapter : adapters_set)
+ {
+ AdapterImpl * that = static_cast< AdapterImpl * >( rpAdapter );
+ // iterate through all types if that is a matching adapter
+ sal_Int32 nPosTypes;
+ for ( nPosTypes = nTypes; nPosTypes--; )
+ {
+ Type const & rType = pTypes[ nPosTypes ];
+ // find in adapter's type list
+ sal_Int32 nPos;
+ for ( nPos = that->m_vInterfaces.size(); nPos--; )
+ {
+ if (::typelib_typedescriptionreference_isAssignableFrom(
+ rType.getTypeLibType(),
+ that->m_vInterfaces[ nPos ].m_pTypeDescr->aBase.pWeakRef ))
+ {
+ // found
+ break;
+ }
+ }
+ if (nPos < 0) // type not found => next adapter
+ break;
+ }
+ if (nPosTypes < 0) // all types found
+ return that;
+ }
+ return nullptr;
+}
+
+// XInvocationAdapterFactory2 impl
+
+Reference< XInterface > FactoryImpl::createAdapter(
+ const Reference< script::XInvocation > & xReceiver,
+ const Sequence< Type > & rTypes )
+{
+ Reference< XInterface > xRet;
+ if (xReceiver.is() && rTypes.hasElements())
+ {
+ t_ptr_set * adapter_set;
+ AdapterImpl * that;
+ Reference< XInterface > xKey( xReceiver, UNO_QUERY );
+ {
+ ClearableMutexGuard guard( m_mutex );
+ that = lookup_adapter(
+ &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
+ if (nullptr == that) // no entry
+ {
+ guard.clear();
+ // create adapter; already acquired: m_nRef == 1
+ AdapterImpl * pNew =
+ new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
+ // lookup again
+ ClearableMutexGuard guard2( m_mutex );
+ that = lookup_adapter(
+ &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
+ if (nullptr == that) // again no entry
+ {
+ pair< t_ptr_set::const_iterator, bool > i(adapter_set->insert(pNew));
+ SAL_WARN_IF(
+ !i.second, "stoc",
+ "set already contains " << *(i.first) << " != " << pNew);
+ that = pNew;
+ }
+ else
+ {
+ that->acquire();
+ guard2.clear();
+ delete pNew; // has never been inserted
+ }
+ }
+ else // found adapter
+ {
+ that->acquire();
+ }
+ }
+ // map one interface to C++
+ uno_Interface * pUnoI = that->m_vInterfaces.data();
+ m_aUno2Cpp.mapInterface(
+ reinterpret_cast<void **>(&xRet), pUnoI, cppu::UnoType<decltype(xRet)>::get() );
+ that->release();
+ OSL_ASSERT( xRet.is() );
+ if (! xRet.is())
+ {
+ throw RuntimeException( "mapping UNO to C++ failed!" );
+ }
+ }
+ return xRet;
+}
+// XInvocationAdapterFactory impl
+
+Reference< XInterface > FactoryImpl::createAdapter(
+ const Reference< script::XInvocation > & xReceiver, const Type & rType )
+{
+ return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) );
+}
+
+// XServiceInfo
+
+OUString FactoryImpl::getImplementationName()
+{
+ return "com.sun.star.comp.stoc.InvocationAdapterFactory";
+}
+
+sal_Bool FactoryImpl::supportsService( const OUString & rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > FactoryImpl::getSupportedServiceNames()
+{
+ return { "com.sun.star.script.InvocationAdapterFactory" };
+}
+
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+stoc_invocation_adapter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new stoc_invadp::FactoryImpl(context));
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/stoc/source/invocation_adapterfactory/invocadapt.component b/stoc/source/invocation_adapterfactory/invocadapt.component
new file mode 100644
index 000000000..ec1723e22
--- /dev/null
+++ b/stoc/source/invocation_adapterfactory/invocadapt.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.stoc.InvocationAdapterFactory"
+ constructor="stoc_invocation_adapter_get_implementation" single-instance="true">
+ <service name="com.sun.star.script.InvocationAdapterFactory"/>
+ </implementation>
+</component>