Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / stoc / source / invocation / invocation.cxx
blobb2db04095cac622796d4bb75c69e422bdfc9bf81
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/mutex.hxx>
21 #include <cppuhelper/queryinterface.hxx>
22 #include <cppuhelper/weak.hxx>
23 #include <cppuhelper/factory.hxx>
24 #include <cppuhelper/implementationentry.hxx>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <cppuhelper/typeprovider.hxx>
27 #include <cppuhelper/implbase.hxx>
29 #include <com/sun/star/script/CannotConvertException.hpp>
30 #include <com/sun/star/script/FailReason.hpp>
31 #include <com/sun/star/script/XTypeConverter.hpp>
32 #include <com/sun/star/script/XInvocation.hpp>
33 #include <com/sun/star/script/XInvocation2.hpp>
34 #include <com/sun/star/reflection/XIdlReflection.hpp>
35 #include <com/sun/star/reflection/theCoreReflection.hpp>
36 #include <com/sun/star/container/XNameContainer.hpp>
37 #include <com/sun/star/container/XIndexContainer.hpp>
38 #include <com/sun/star/container/XEnumerationAccess.hpp>
39 #include <com/sun/star/beans/XExactName.hpp>
40 #include <com/sun/star/beans/XMaterialHolder.hpp>
41 #include <com/sun/star/beans/theIntrospection.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/beans/PropertyAttribute.hpp>
44 #include <com/sun/star/beans/MethodConcept.hpp>
45 #include <com/sun/star/beans/PropertyConcept.hpp>
46 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
47 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <com/sun/star/lang/XServiceInfo.hpp>
49 #include <com/sun/star/lang/XTypeProvider.hpp>
50 #include <com/sun/star/registry/XRegistryKey.hpp>
52 #include <memory>
53 #include <rtl/ustrbuf.hxx>
54 #include <rtl/strbuf.hxx>
56 #define SERVICENAME "com.sun.star.script.Invocation"
57 #define IMPLNAME "com.sun.star.comp.stoc.Invocation"
59 using namespace css::uno;
60 using namespace css::lang;
61 using namespace css::script;
62 using namespace css::reflection;
63 using namespace css::beans;
64 using namespace css::registry;
65 using namespace css::container;
66 using namespace cppu;
67 using namespace osl;
69 namespace stoc_inv
71 static Sequence< OUString > inv_getSupportedServiceNames()
73 Sequence< OUString > seqNames { SERVICENAME };
74 return seqNames;
77 static OUString inv_getImplementationName()
79 return OUString(IMPLNAME);
82 // TODO: Implement centrally
83 inline Reference<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XIdlReflection > & xRefl )
85 return xRefl->forName( rType.getTypeName() );
89 class Invocation_Impl
90 : public OWeakObject
91 , public XInvocation2
92 , public XNameContainer
93 , public XIndexContainer
94 , public XEnumerationAccess
95 , public XExactName
96 , public XMaterialHolder
97 , public XTypeProvider
99 public:
100 Invocation_Impl( const Any & rAdapted, const Reference<XTypeConverter> &,
101 const Reference<XIntrospection> &,
102 const Reference<XIdlReflection> & );
104 // XInterface
105 virtual Any SAL_CALL queryInterface( const Type & aType) override;
106 virtual void SAL_CALL acquire() throw() override { OWeakObject::acquire(); }
107 virtual void SAL_CALL release() throw() override { OWeakObject::release(); }
110 // XTypeProvider
111 virtual Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
112 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
114 // XMaterialHolder
115 virtual Any SAL_CALL getMaterial() override;
117 // XInvocation
118 virtual Reference<XIntrospectionAccess> SAL_CALL getIntrospection() override;
119 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override;
120 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override;
121 virtual Any SAL_CALL getValue(const OUString& PropertyName) override;
122 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override;
123 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override;
125 // XInvocation2
126 virtual Sequence< OUString > SAL_CALL getMemberNames( ) override;
127 virtual Sequence< InvocationInfo > SAL_CALL getInfo( ) override;
128 virtual InvocationInfo SAL_CALL getInfoForName( const OUString& aName, sal_Bool bExact ) override;
130 // All Access and Container methods are not thread safe
131 // XElementAccess
132 virtual Type SAL_CALL getElementType() override
133 { return _xElementAccess->getElementType(); }
135 virtual sal_Bool SAL_CALL hasElements() override
136 { return _xElementAccess->hasElements(); }
138 // XNameContainer
139 virtual void SAL_CALL insertByName( const OUString& Name, const Any& Element ) override
140 { _xNameContainer->insertByName( Name, Element ); }
142 virtual void SAL_CALL removeByName( const OUString& Name ) override
143 { _xNameContainer->removeByName( Name ); }
145 // XNameReplace
146 virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element ) override
147 { _xNameReplace->replaceByName( Name, Element ); }
149 // XNameAccess
150 virtual Any SAL_CALL getByName( const OUString& Name ) override
151 { return _xNameAccess->getByName( Name ); }
153 virtual Sequence<OUString> SAL_CALL getElementNames() override
154 { return _xNameAccess->getElementNames(); }
156 virtual sal_Bool SAL_CALL hasByName( const OUString& Name ) override
157 { return _xNameAccess->hasByName( Name ); }
159 // XIndexContainer
160 virtual void SAL_CALL insertByIndex( sal_Int32 Index, const Any& Element ) override
161 { _xIndexContainer->insertByIndex( Index, Element ); }
163 virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override
164 { _xIndexContainer->removeByIndex( Index ); }
166 // XIndexReplace
167 virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element ) override
168 { _xIndexReplace->replaceByIndex( Index, Element ); }
170 // XIndexAccess
171 virtual sal_Int32 SAL_CALL getCount() override
172 { return _xIndexAccess->getCount(); }
174 virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override
175 { return _xIndexAccess->getByIndex( Index ); }
177 // XEnumerationAccess
178 virtual Reference<XEnumeration> SAL_CALL createEnumeration() override
179 { return _xEnumerationAccess->createEnumeration(); }
181 // XExactName
182 virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
185 private:
186 void setMaterial( const Any& rMaterial );
188 void getInfoSequenceImpl( Sequence< OUString >* pStringSeq, Sequence< InvocationInfo >* pInfoSeq );
189 void fillInfoForNameAccess( InvocationInfo& rInfo, const OUString& aName );
190 static void fillInfoForProperty( InvocationInfo& rInfo, const Property& rProp );
191 static void fillInfoForMethod( InvocationInfo& rInfo, const Reference< XIdlMethod >& xMethod );
193 Reference<XTypeConverter> xTypeConverter;
194 Reference<XIntrospection> xIntrospection;
195 Reference<XIdlReflection> xCoreReflection;
197 Any _aMaterial;
198 // _xDirect and (_xIntrospectionAccess, xPropertySet) are exclusive
199 Reference<XInvocation> _xDirect;
200 Reference<XInvocation2> _xDirect2;
201 Reference<XPropertySet> _xPropertySet;
202 Reference<XIntrospectionAccess> _xIntrospectionAccess;
204 // supplied Interfaces
205 Reference<XNameContainer> _xNameContainer;
206 Reference<XNameReplace> _xNameReplace;
207 Reference<XNameAccess> _xNameAccess;
208 Reference<XIndexContainer> _xIndexContainer;
209 Reference<XIndexReplace> _xIndexReplace;
210 Reference<XIndexAccess> _xIndexAccess;
211 Reference<XEnumerationAccess> _xEnumerationAccess;
212 Reference<XElementAccess> _xElementAccess;
215 Reference<XExactName> _xENDirect, _xENIntrospection;
219 Invocation_Impl::Invocation_Impl
221 const Any & rAdapted,
222 const Reference<XTypeConverter> & rTC,
223 const Reference<XIntrospection> & rI,
224 const Reference<XIdlReflection> & rCR
226 : xTypeConverter( rTC )
227 , xIntrospection( rI )
228 , xCoreReflection( rCR )
230 setMaterial( rAdapted );
233 //### INTERFACE IMPLEMENTATIONS ####################################################################
236 Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
238 // PropertySet implementation
239 Any a = ::cppu::queryInterface( aType,
240 (static_cast< XInvocation* >(this)),
241 (static_cast< XMaterialHolder* >(this)),
242 (static_cast< XTypeProvider * >(this)) );
243 if( a.hasValue() )
245 return a;
248 if( aType == cppu::UnoType<XExactName>::get())
250 // Invocation does not support XExactName, if direct object supports
251 // XInvocation, but not XExactName.
252 if ((_xDirect.is() && _xENDirect.is()) ||
253 (!_xDirect.is() && _xENIntrospection.is()))
255 return makeAny( Reference< XExactName >( (static_cast< XExactName* >(this)) ) );
258 else if ( aType == cppu::UnoType<XNameContainer>::get())
260 if( _xNameContainer.is() )
261 return makeAny( Reference< XNameContainer >( (static_cast< XNameContainer* >(this)) ) );
263 else if ( aType == cppu::UnoType<XNameReplace>::get())
265 if( _xNameReplace.is() )
266 return makeAny( Reference< XNameReplace >( (static_cast< XNameReplace* >(this)) ) );
268 else if ( aType == cppu::UnoType<XNameAccess>::get())
270 if( _xNameAccess.is() )
271 return makeAny( Reference< XNameAccess >( (static_cast< XNameAccess* >(this)) ) );
273 else if ( aType == cppu::UnoType<XIndexContainer>::get())
275 if (_xIndexContainer.is())
276 return makeAny( Reference< XIndexContainer >( (static_cast< XIndexContainer* >(this)) ) );
278 else if ( aType == cppu::UnoType<XIndexReplace>::get())
280 if (_xIndexReplace.is())
281 return makeAny( Reference< XIndexReplace >( (static_cast< XIndexReplace* >(this)) ) );
283 else if ( aType == cppu::UnoType<XIndexAccess>::get())
285 if (_xIndexAccess.is())
286 return makeAny( Reference< XIndexAccess >( (static_cast< XIndexAccess* >(this)) ) );
288 else if ( aType == cppu::UnoType<XEnumerationAccess>::get())
290 if (_xEnumerationAccess.is())
291 return makeAny( Reference< XEnumerationAccess >( (static_cast< XEnumerationAccess* >(this)) ) );
293 else if ( aType == cppu::UnoType<XElementAccess>::get())
295 if (_xElementAccess.is())
297 return makeAny( Reference< XElementAccess >(
298 (static_cast< XElementAccess* >((static_cast< XNameContainer* >(this))) ) ) );
301 else if ( aType == cppu::UnoType<XInvocation2>::get())
303 // Invocation does not support XInvocation2, if direct object supports
304 // XInvocation, but not XInvocation2.
305 if ( ( _xDirect.is() && _xDirect2.is()) ||
306 (!_xDirect.is() && _xIntrospectionAccess.is() ) )
308 return makeAny( Reference< XInvocation2 >( (static_cast< XInvocation2* >(this)) ) );
312 return OWeakObject::queryInterface( aType );
316 Any Invocation_Impl::getMaterial()
318 // AB, 12.2.1999 Make sure that the material is taken when possible
319 // from the direct Invocation of the Introspection, otherwise structs
320 // are not handled correctly
321 Reference<XMaterialHolder> xMaterialHolder;
322 if( _xDirect.is() )
324 xMaterialHolder.set( _xDirect, UNO_QUERY );
325 //_xDirect->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
327 else if( _xIntrospectionAccess.is() )
329 xMaterialHolder.set( _xIntrospectionAccess, UNO_QUERY );
330 //_xIntrospectionAccess->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
332 if( xMaterialHolder.is() )
334 return xMaterialHolder->getMaterial();
336 return _aMaterial;
340 void Invocation_Impl::setMaterial( const Any& rMaterial )
342 // set the material first and only once
343 _aMaterial = rMaterial;
345 // First do this outside the guard
346 _xDirect.set( rMaterial, UNO_QUERY );
348 if( _xDirect.is() )
350 // Consult object directly
351 _xElementAccess.set( _xDirect, UNO_QUERY );
352 _xEnumerationAccess.set( _xDirect, UNO_QUERY );
353 _xIndexAccess.set( _xDirect, UNO_QUERY );
354 _xIndexReplace.set( _xDirect, UNO_QUERY );
355 _xIndexContainer.set( _xDirect, UNO_QUERY );
356 _xNameAccess.set( _xDirect, UNO_QUERY );
357 _xNameReplace.set( _xDirect, UNO_QUERY );
358 _xNameContainer.set( _xDirect, UNO_QUERY );
359 _xENDirect.set( _xDirect, UNO_QUERY );
360 _xDirect2.set( _xDirect, UNO_QUERY );
362 // only once!!!
363 //_xIntrospectionAccess = XIntrospectionAccessRef();
364 //_xPropertySet = XPropertySetRef();
366 else
368 // Make Invocation on the Introspection
369 if (xIntrospection.is())
371 _xIntrospectionAccess = xIntrospection->inspect( _aMaterial );
372 if( _xIntrospectionAccess.is() )
374 _xElementAccess.set(
375 _xIntrospectionAccess->queryAdapter(
376 cppu::UnoType<XElementAccess>::get()), UNO_QUERY );
378 if( _xElementAccess.is() )
380 _xEnumerationAccess.set(
381 _xIntrospectionAccess->queryAdapter(
382 cppu::UnoType<XEnumerationAccess>::get()), UNO_QUERY );
384 _xIndexAccess.set(
385 _xIntrospectionAccess->queryAdapter(
386 cppu::UnoType<XIndexAccess>::get()), UNO_QUERY );
388 if( _xIndexAccess.is() )
390 _xIndexReplace.set(
391 _xIntrospectionAccess->queryAdapter(
392 cppu::UnoType<XIndexReplace>::get()), UNO_QUERY );
394 _xIndexContainer.set(
395 _xIntrospectionAccess->queryAdapter(
396 cppu::UnoType<XIndexContainer>::get()), UNO_QUERY );
399 _xNameAccess.set(
400 _xIntrospectionAccess->queryAdapter(
401 cppu::UnoType<XNameAccess>::get()), UNO_QUERY );
403 if( _xNameAccess.is() )
405 _xNameReplace.set(
406 _xIntrospectionAccess->queryAdapter(
407 cppu::UnoType<XNameReplace>::get()), UNO_QUERY );
409 _xNameContainer.set(
410 _xIntrospectionAccess->queryAdapter(
411 cppu::UnoType<XNameContainer>::get()), UNO_QUERY );
415 _xPropertySet.set( _xIntrospectionAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()),
416 UNO_QUERY );
418 _xENIntrospection.set( _xIntrospectionAccess, UNO_QUERY );
421 /* only once !!!
422 _xDirect = XInvocationRef();
423 if( !_xIntrospectionAccess.is() )
425 // reset
426 _xElementAccess = XElementAccessRef();
427 _xEnumerationAccess = XEnumerationAccessRef();
428 _xIndexAccess = XIndexAccessRef();
429 _xIndexContainer = XIndexContainerRef();
430 _xNameAccess = XNameAccessRef();
431 _xNameContainer = XNameContainerRef();
432 _xPropertySet = XPropertySetRef();
439 OUString Invocation_Impl::getExactName( const OUString& rApproximateName )
441 if (_xENDirect.is())
442 return _xENDirect->getExactName( rApproximateName );
444 OUString aRet;
445 if (_xENIntrospection.is())
446 aRet = _xENIntrospection->getExactName( rApproximateName );
447 return aRet;
451 Reference<XIntrospectionAccess> Invocation_Impl::getIntrospection()
453 if( _xDirect.is() )
454 return _xDirect->getIntrospection();
455 else
456 return _xIntrospectionAccess;
460 sal_Bool Invocation_Impl::hasMethod( const OUString& Name )
462 if (_xDirect.is())
463 return _xDirect->hasMethod( Name );
464 if( _xIntrospectionAccess.is() )
465 return _xIntrospectionAccess->hasMethod( Name, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
466 return false;
470 sal_Bool Invocation_Impl::hasProperty( const OUString& Name )
472 if (_xDirect.is())
473 return _xDirect->hasProperty( Name );
474 // PropertySet
475 if( _xIntrospectionAccess.is()
476 && _xIntrospectionAccess->hasProperty( Name, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
477 return true;
478 // NameAccess
479 if( _xNameAccess.is() )
480 return _xNameAccess->hasByName( Name );
481 return false;
485 Any Invocation_Impl::getValue( const OUString& PropertyName )
487 if (_xDirect.is())
488 return _xDirect->getValue( PropertyName );
491 // PropertySet
492 if( _xIntrospectionAccess.is() && _xPropertySet.is()
493 && _xIntrospectionAccess->hasProperty
494 ( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
496 return _xPropertySet->getPropertyValue( PropertyName );
498 // NameAccess
499 if( _xNameAccess.is() && _xNameAccess->hasByName( PropertyName ) )
500 return _xNameAccess->getByName( PropertyName );
502 catch (UnknownPropertyException &)
504 throw;
506 catch (RuntimeException &)
508 throw;
510 catch (Exception &)
514 throw UnknownPropertyException( "cannot get value " + PropertyName );
518 void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value )
520 if (_xDirect.is())
521 _xDirect->setValue( PropertyName, Value );
522 else
526 // Properties
527 if( _xIntrospectionAccess.is() && _xPropertySet.is()
528 && _xIntrospectionAccess->hasProperty(
529 PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
531 Property aProp = _xIntrospectionAccess->getProperty(
532 PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
533 Reference < XIdlClass > r = TypeToIdlClass( aProp.Type, xCoreReflection );
534 if( r->isAssignableFrom( TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
535 _xPropertySet->setPropertyValue( PropertyName, Value );
536 else if( xTypeConverter.is() )
537 _xPropertySet->setPropertyValue(
538 PropertyName, xTypeConverter->convertTo( Value, aProp.Type ) );
539 else
540 throw RuntimeException( "no type converter service!" );
542 // NameContainer
543 else if( _xNameContainer.is() )
545 // Note: This misfeature deliberately not adapted to apply to objects which
546 // have XNameReplace but not XNameContainer
547 Any aConv;
548 Reference < XIdlClass > r =
549 TypeToIdlClass( _xNameContainer->getElementType(), xCoreReflection );
550 if( r->isAssignableFrom(TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
551 aConv = Value;
552 else if( xTypeConverter.is() )
553 aConv = xTypeConverter->convertTo( Value, _xNameContainer->getElementType() );
554 else
555 throw RuntimeException( "no type converter service!" );
557 // Replace if present, otherwise insert
558 if (_xNameContainer->hasByName( PropertyName ))
559 _xNameContainer->replaceByName( PropertyName, aConv );
560 else
561 _xNameContainer->insertByName( PropertyName, aConv );
563 else
564 throw UnknownPropertyException( "no introspection nor name container!" );
566 catch (UnknownPropertyException &)
568 throw;
570 catch (CannotConvertException &)
572 throw;
574 catch (InvocationTargetException &)
576 throw;
578 catch (RuntimeException &)
580 throw;
582 catch (const Exception & exc)
584 throw InvocationTargetException(
585 "exception occurred in setValue(): " + exc.Message,
586 Reference< XInterface >(), makeAny( exc /* though sliced */ ) );
592 Any Invocation_Impl::invoke( const OUString& FunctionName, const Sequence<Any>& InParams,
593 Sequence<sal_Int16>& OutIndices, Sequence<Any>& OutParams )
595 if (_xDirect.is())
596 return _xDirect->invoke( FunctionName, InParams, OutIndices, OutParams );
598 if (_xIntrospectionAccess.is())
600 // throw NoSuchMethodException if not exist
601 Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod(
602 FunctionName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
604 // ParameterInfos
605 Sequence<ParamInfo> aFParams = xMethod->getParameterInfos();
606 const ParamInfo* pFParams = aFParams.getConstArray();
607 sal_Int32 nFParamsLen = aFParams.getLength();
608 if (nFParamsLen != InParams.getLength())
610 throw IllegalArgumentException(
611 "incorrect number of parameters passed invoking function " + FunctionName +
612 "expected " + OUString::number(nFParamsLen) + ", got " + OUString::number(InParams.getLength()),
613 static_cast<OWeakObject *>(this), (sal_Int16) 1 );
616 // IN Parameter
617 const Any* pInParams = InParams.getConstArray();
619 // Introspection Invoke Parameter
620 Sequence<Any> aInvokeParams( nFParamsLen );
621 Any* pInvokeParams = aInvokeParams.getArray();
623 // OUT Indices
624 OutIndices.realloc( nFParamsLen );
625 sal_Int16* pOutIndices = OutIndices.getArray();
626 sal_uInt32 nOutIndex = 0;
628 for ( sal_Int32 nPos = 0; nPos < nFParamsLen; ++nPos )
632 const ParamInfo& rFParam = pFParams[nPos];
633 const Reference<XIdlClass>& rDestType = rFParam.aType;
635 // is IN/INOUT parameter?
636 if (rFParam.aMode != ParamMode_OUT)
638 if (rDestType->isAssignableFrom( TypeToIdlClass( pInParams[nPos].getValueType(), xCoreReflection ) ))
640 pInvokeParams[nPos] = pInParams[nPos];
642 else if (xTypeConverter.is())
644 Type aDestType( rDestType->getTypeClass(), rDestType->getName() );
645 pInvokeParams[nPos] = xTypeConverter->convertTo( pInParams[nPos], aDestType );
647 else
649 CannotConvertException aExc;
650 aExc.Context = *this;
651 aExc.Message = "invocation type mismatch!";
652 throw aExc;
656 // is OUT/INOUT parameter?
657 if (rFParam.aMode != ParamMode_IN)
659 pOutIndices[nOutIndex] = (sal_Int16)nPos;
660 if (rFParam.aMode == ParamMode_OUT)
661 rDestType->createObject( pInvokeParams[nPos] ); // default init
662 ++nOutIndex;
665 catch( CannotConvertException& rExc )
667 rExc.ArgumentIndex = nPos; // Add optional parameter index
668 throw;
672 // execute Method
673 Any aRet = xMethod->invoke( _aMaterial, aInvokeParams );
675 // OUT Params
676 OutIndices.realloc( nOutIndex );
677 pOutIndices = OutIndices.getArray();
678 OutParams.realloc( nOutIndex );
679 Any* pOutParams = OutParams.getArray();
681 while (nOutIndex--)
683 pOutParams[nOutIndex] = pInvokeParams[ pOutIndices[nOutIndex] ];
686 return aRet;
689 RuntimeException aExc;
690 aExc.Context = *this;
691 aExc.Message = "invocation lacking of introspection access!";
692 throw aExc;
696 // Struct to optimize sorting
697 struct MemberItem
699 OUString aName;
701 // Defines where the member comes from
702 enum Mode { NAMEACCESS, PROPERTYSET, METHOD } eMode;
704 // Index to respective sequence
705 // (Index to NameAccess sequence for eMode==NAMEACCESS etc.)
706 sal_Int32 nIndex;
709 // Implementation of getting name or info
710 // String sequence will be filled when pStringSeq != NULL
711 // Info sequence will be filled when pInfoSeq != NULL
712 void Invocation_Impl::getInfoSequenceImpl
714 Sequence< OUString >* pStringSeq,
715 Sequence< InvocationInfo >* pInfoSeq
718 //Sequence< OUString > aStrSeq;
719 //if( !pStringSeq )
720 //pStringSeq = &aStrSeq;
723 // Get all needed sequences
724 Sequence<OUString> aNameAccessNames;
725 Sequence<Property> aPropertySeq;
726 Sequence< Reference< XIdlMethod > > aMethodSeq;
728 if( _xNameAccess.is() )
730 aNameAccessNames = _xNameAccess->getElementNames();
733 if( _xIntrospectionAccess.is() )
735 aPropertySeq = _xIntrospectionAccess->getProperties
736 ( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
738 aMethodSeq = _xIntrospectionAccess->getMethods
739 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
742 sal_Int32 nNameAccessCount = aNameAccessNames.getLength();
743 sal_Int32 nPropertyCount = aPropertySeq.getLength();
744 sal_Int32 nMethodCount = aMethodSeq.getLength();
745 sal_Int32 nTotalCount = nNameAccessCount + nPropertyCount + nMethodCount;
747 // Create and fill array of MemberItems
748 std::unique_ptr< MemberItem []> pItems( new MemberItem[ nTotalCount ] );
749 const OUString* pStrings = aNameAccessNames.getConstArray();
750 const Property* pProps = aPropertySeq.getConstArray();
751 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
753 // Fill array of MemberItems
754 sal_Int32 i, iTotal = 0;
756 // Name Access
757 for( i = 0 ; i < nNameAccessCount ; i++, iTotal++ )
759 MemberItem& rItem = pItems[ iTotal ];
760 rItem.aName = pStrings[ i ];
761 rItem.eMode = MemberItem::NAMEACCESS;
762 rItem.nIndex = i;
765 // Property set
766 for( i = 0 ; i < nPropertyCount ; i++, iTotal++ )
768 MemberItem& rItem = pItems[ iTotal ];
769 rItem.aName = pProps[ i ].Name;
770 rItem.eMode = MemberItem::PROPERTYSET;
771 rItem.nIndex = i;
774 // Methods
775 for( i = 0 ; i < nMethodCount ; i++, iTotal++ )
777 MemberItem& rItem = pItems[ iTotal ];
778 Reference< XIdlMethod > xMethod = pMethods[ i ];
779 rItem.aName = xMethod->getName();
780 rItem.eMode = MemberItem::METHOD;
781 rItem.nIndex = i;
784 // Setting up result sequences
785 OUString* pRetStrings = nullptr;
786 if( pStringSeq )
788 pStringSeq->realloc( nTotalCount );
789 pRetStrings = pStringSeq->getArray();
792 InvocationInfo* pRetInfos = nullptr;
793 if( pInfoSeq )
795 pInfoSeq->realloc( nTotalCount );
796 pRetInfos = pInfoSeq->getArray();
799 // Fill result sequences in the correct order of members
800 for( iTotal = 0 ; iTotal < nTotalCount ; iTotal++ )
802 MemberItem& rItem = pItems[ iTotal ];
803 if( pRetStrings )
805 pRetStrings[ iTotal ] = rItem.aName;
808 if( pRetInfos )
810 if( rItem.eMode == MemberItem::NAMEACCESS )
812 fillInfoForNameAccess( pRetInfos[ iTotal ], rItem.aName );
814 else if( rItem.eMode == MemberItem::PROPERTYSET )
816 fillInfoForProperty( pRetInfos[ iTotal ], pProps[ rItem.nIndex ] );
818 else if( rItem.eMode == MemberItem::METHOD )
820 fillInfoForMethod( pRetInfos[ iTotal ], pMethods[ rItem.nIndex ] );
826 // XInvocation2
827 Sequence< OUString > SAL_CALL Invocation_Impl::getMemberNames( )
829 if( _xDirect2.is() )
831 return _xDirect2->getMemberNames();
833 Sequence< OUString > aRetSeq;
834 getInfoSequenceImpl( &aRetSeq, nullptr );
835 return aRetSeq;
838 Sequence< InvocationInfo > SAL_CALL Invocation_Impl::getInfo( )
840 if( _xDirect2.is() )
842 return _xDirect2->getInfo();
844 Sequence< InvocationInfo > aRetSeq;
845 getInfoSequenceImpl( nullptr, &aRetSeq );
846 return aRetSeq;
849 InvocationInfo SAL_CALL Invocation_Impl::getInfoForName( const OUString& aName, sal_Bool bExact )
851 if( _xDirect2.is() )
853 return _xDirect2->getInfoForName( aName, bExact );
856 bool bFound = false;
857 OUString aExactName = aName;
858 InvocationInfo aRetInfo;
860 if( bExact )
861 aExactName = getExactName( aName );
862 if( !aExactName.isEmpty() )
864 if( _xIntrospectionAccess->hasMethod( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ) )
866 Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod
867 ( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
868 fillInfoForMethod( aRetInfo, xMethod );
869 bFound = true;
871 else
873 if( _xIntrospectionAccess.is() && _xIntrospectionAccess->hasProperty
874 ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
876 Property aProp = _xIntrospectionAccess->getProperty
877 ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
878 fillInfoForProperty( aRetInfo, aProp );
879 bFound = true;
881 // NameAccess
882 else if( _xNameAccess.is() && _xNameAccess->hasByName( aExactName ) )
884 fillInfoForNameAccess( aRetInfo, aExactName );
885 bFound = true;
889 if( !bFound )
891 throw IllegalArgumentException(
892 "getExactName(), Unknown name " + aName,
893 static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
895 return aRetInfo;
898 // Helper functions to fill InvocationInfo for XNameAccess
899 void Invocation_Impl::fillInfoForNameAccess
901 InvocationInfo& rInfo,
902 const OUString& aName
905 rInfo.aName = aName;
906 rInfo.eMemberType = MemberType_PROPERTY;
907 rInfo.PropertyAttribute = 0;
908 if( !_xNameContainer.is() )
910 rInfo.PropertyAttribute = PropertyAttribute::READONLY;
912 rInfo.aType = _xNameAccess->getElementType();
915 void Invocation_Impl::fillInfoForProperty
917 InvocationInfo& rInfo,
918 const Property& rProp
921 rInfo.aName = rProp.Name;
922 rInfo.eMemberType = MemberType_PROPERTY;
923 rInfo.PropertyAttribute = rProp.Attributes;
924 rInfo.aType = rProp.Type;
927 void Invocation_Impl::fillInfoForMethod
929 InvocationInfo& rInfo,
930 const Reference< XIdlMethod >& xMethod
933 rInfo.aName = xMethod->getName();
934 rInfo.eMemberType = MemberType_METHOD;
935 Reference< XIdlClass > xReturnClass = xMethod->getReturnType();
936 Type aReturnType( xReturnClass->getTypeClass(), xReturnClass->getName() );
937 rInfo.aType = aReturnType;
938 Sequence<ParamInfo> aParamInfos = xMethod->getParameterInfos();
939 sal_Int32 nParamCount = aParamInfos.getLength();
940 if( nParamCount > 0 )
942 const ParamInfo* pInfo = aParamInfos.getConstArray();
944 rInfo.aParamTypes.realloc( nParamCount );
945 Type* pParamTypes = rInfo.aParamTypes.getArray();
946 rInfo.aParamModes.realloc( nParamCount );
947 ParamMode* pParamModes = rInfo.aParamModes.getArray();
949 for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
951 Reference< XIdlClass > xParamClass = pInfo[i].aType;
952 Type aParamType( xParamClass->getTypeClass(), xParamClass->getName() );
953 pParamTypes[ i ] = aParamType;
954 pParamModes[ i ] = pInfo[i].aMode;
960 // XTypeProvider
961 Sequence< Type > SAL_CALL Invocation_Impl::getTypes()
963 static Sequence< Type > const * s_pTypes = nullptr;
964 if (! s_pTypes)
966 Sequence< Type > types( 4 + 10 );
967 Type * pTypes = types.getArray();
968 sal_Int32 n = 0;
970 pTypes[ n++ ] = cppu::UnoType<XTypeProvider>::get();
971 pTypes[ n++ ] = cppu::UnoType<XWeak>::get();
972 pTypes[ n++ ] = cppu::UnoType<XInvocation>::get();
973 pTypes[ n++ ] = cppu::UnoType<XMaterialHolder>::get();
975 // Invocation does not support XExactName if direct object supports
976 // XInvocation, but not XExactName.
977 if ((_xDirect.is() && _xENDirect.is()) ||
978 (!_xDirect.is() && _xENIntrospection.is()))
980 pTypes[ n++ ] = cppu::UnoType<XExactName>::get();
982 if( _xNameContainer.is() )
984 pTypes[ n++ ] = cppu::UnoType<XNameContainer>::get();
986 if( _xNameReplace.is() )
988 pTypes[ n++ ] = cppu::UnoType<XNameReplace>::get();
990 if( _xNameAccess.is() )
992 pTypes[ n++ ] = cppu::UnoType<XNameAccess>::get();
994 if (_xIndexContainer.is())
996 pTypes[ n++ ] = cppu::UnoType<XIndexContainer>::get();
998 if (_xIndexReplace.is())
1000 pTypes[ n++ ] = cppu::UnoType<XIndexReplace>::get();
1002 if (_xIndexAccess.is())
1004 pTypes[ n++ ] = cppu::UnoType<XIndexAccess>::get();
1006 if (_xEnumerationAccess.is())
1008 pTypes[ n++ ] = cppu::UnoType<XEnumerationAccess>::get();
1010 if (_xElementAccess.is())
1012 pTypes[ n++ ] = cppu::UnoType<XElementAccess>::get();
1014 // Invocation does not support XInvocation2, if direct object supports
1015 // XInvocation, but not XInvocation2.
1016 if ( ( _xDirect.is() && _xDirect2.is()) ||
1017 (!_xDirect.is() && _xIntrospectionAccess.is() ) )
1019 pTypes[ n++ ] = cppu::UnoType<XInvocation2>::get();
1022 types.realloc( n );
1024 // store types
1025 MutexGuard guard( Mutex::getGlobalMutex() );
1026 if (! s_pTypes)
1028 static Sequence< Type > s_types( types );
1029 s_pTypes = &s_types;
1032 return *s_pTypes;
1035 Sequence< sal_Int8 > SAL_CALL Invocation_Impl::getImplementationId( )
1037 return css::uno::Sequence<sal_Int8>();
1041 class InvocationService
1042 : public WeakImplHelper< XSingleServiceFactory, XServiceInfo >
1044 public:
1045 explicit InvocationService( const Reference<XComponentContext> & xCtx );
1047 // XServiceInfo
1048 OUString SAL_CALL getImplementationName() override;
1049 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
1050 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
1052 // XSingleServiceFactory
1053 Reference<XInterface> SAL_CALL createInstance() override;
1054 Reference<XInterface> SAL_CALL createInstanceWithArguments(
1055 const Sequence<Any>& rArguments ) override;
1056 private:
1057 Reference<XComponentContext> mxCtx;
1058 Reference<XMultiComponentFactory> mxSMgr;
1059 Reference<XTypeConverter> xTypeConverter;
1060 Reference<XIntrospection> xIntrospection;
1061 Reference<XIdlReflection> xCoreReflection;
1064 InvocationService::InvocationService( const Reference<XComponentContext> & xCtx )
1065 : mxCtx( xCtx )
1066 , mxSMgr( xCtx->getServiceManager() )
1067 , xCoreReflection( css::reflection::theCoreReflection::get(mxCtx) )
1069 xTypeConverter.set(
1070 mxSMgr->createInstanceWithContext( "com.sun.star.script.Converter", xCtx ),
1071 UNO_QUERY );
1072 xIntrospection = theIntrospection::get(xCtx);
1075 // XServiceInfo
1076 OUString InvocationService::getImplementationName()
1078 return inv_getImplementationName();
1081 // XServiceInfo
1082 sal_Bool InvocationService::supportsService(const OUString& ServiceName)
1084 return cppu::supportsService(this, ServiceName);
1087 // XServiceInfo
1088 Sequence< OUString > InvocationService::getSupportedServiceNames()
1090 return inv_getSupportedServiceNames();
1094 Reference<XInterface> InvocationService::createInstance()
1096 //TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
1097 return Reference<XInterface>(); // dummy
1101 Reference<XInterface> InvocationService::createInstanceWithArguments(
1102 const Sequence<Any>& rArguments )
1104 if (rArguments.getLength() == 1)
1106 return Reference< XInterface >
1107 ( *new Invocation_Impl( *rArguments.getConstArray(),
1108 xTypeConverter, xIntrospection, xCoreReflection ) );
1110 else
1112 //TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
1113 return Reference<XInterface>();
1117 /// @throws RuntimeException
1118 Reference<XInterface> SAL_CALL InvocationService_CreateInstance( const Reference<XComponentContext> & xCtx )
1120 Reference<XInterface> xService( *new InvocationService( xCtx ) );
1121 return xService;
1126 using namespace stoc_inv;
1127 static const struct ImplementationEntry g_entries[] =
1130 InvocationService_CreateInstance, inv_getImplementationName,
1131 inv_getSupportedServiceNames, createSingleComponentFactory,
1132 nullptr, 0
1134 { nullptr, nullptr, nullptr, nullptr, nullptr, 0 }
1137 extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL invocation_component_getFactory(
1138 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
1140 return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
1143 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */