summaryrefslogtreecommitdiffstats
path: root/stoc/source/invocation/invocation.cxx
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/invocation.cxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'stoc/source/invocation/invocation.cxx')
-rw-r--r--stoc/source/invocation/invocation.cxx1097
1 files changed, 1097 insertions, 0 deletions
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: */