Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / stoc / source / invocation / invocation.cxx
blob82dfbac5a417c8bd113587c0e9268475cd8b2204
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/XTypeConverter.hpp>
31 #include <com/sun/star/script/XInvocation.hpp>
32 #include <com/sun/star/script/XInvocation2.hpp>
33 #include <com/sun/star/reflection/XIdlReflection.hpp>
34 #include <com/sun/star/reflection/theCoreReflection.hpp>
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <com/sun/star/container/XIndexContainer.hpp>
37 #include <com/sun/star/container/XEnumerationAccess.hpp>
38 #include <com/sun/star/beans/XExactName.hpp>
39 #include <com/sun/star/beans/XMaterialHolder.hpp>
40 #include <com/sun/star/beans/theIntrospection.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/beans/MethodConcept.hpp>
44 #include <com/sun/star/beans/PropertyConcept.hpp>
45 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
46 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <com/sun/star/lang/XTypeProvider.hpp>
49 #include <com/sun/star/registry/XRegistryKey.hpp>
51 #include <memory>
52 #include <rtl/ustrbuf.hxx>
53 #include <rtl/strbuf.hxx>
55 #define SERVICENAME "com.sun.star.script.Invocation"
56 #define IMPLNAME "com.sun.star.comp.stoc.Invocation"
58 using namespace css::uno;
59 using namespace css::lang;
60 using namespace css::script;
61 using namespace css::reflection;
62 using namespace css::beans;
63 using namespace css::registry;
64 using namespace css::container;
65 using namespace cppu;
66 using namespace osl;
68 namespace stoc_inv
70 static Sequence< OUString > inv_getSupportedServiceNames()
72 Sequence< OUString > seqNames { SERVICENAME };
73 return seqNames;
76 static OUString inv_getImplementationName()
78 return OUString(IMPLNAME);
81 // TODO: Implement centrally
82 inline Reference<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XIdlReflection > & xRefl )
84 return xRefl->forName( rType.getTypeName() );
88 class Invocation_Impl
89 : public OWeakObject
90 , public XInvocation2
91 , public XNameContainer
92 , public XIndexContainer
93 , public XEnumerationAccess
94 , public XExactName
95 , public XMaterialHolder
96 , public XTypeProvider
98 public:
99 Invocation_Impl( const Any & rAdapted, const Reference<XTypeConverter> &,
100 const Reference<XIntrospection> &,
101 const Reference<XIdlReflection> & );
103 // XInterface
104 virtual Any SAL_CALL queryInterface( const Type & aType) override;
105 virtual void SAL_CALL acquire() throw() override { OWeakObject::acquire(); }
106 virtual void SAL_CALL release() throw() override { OWeakObject::release(); }
109 // XTypeProvider
110 virtual Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
111 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
113 // XMaterialHolder
114 virtual Any SAL_CALL getMaterial() override;
116 // XInvocation
117 virtual Reference<XIntrospectionAccess> SAL_CALL getIntrospection() override;
118 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override;
119 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override;
120 virtual Any SAL_CALL getValue(const OUString& PropertyName) override;
121 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override;
122 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override;
124 // XInvocation2
125 virtual Sequence< OUString > SAL_CALL getMemberNames( ) override;
126 virtual Sequence< InvocationInfo > SAL_CALL getInfo( ) override;
127 virtual InvocationInfo SAL_CALL getInfoForName( const OUString& aName, sal_Bool bExact ) override;
129 // All Access and Container methods are not thread safe
130 // XElementAccess
131 virtual Type SAL_CALL getElementType() override
132 { return _xElementAccess->getElementType(); }
134 virtual sal_Bool SAL_CALL hasElements() override
135 { return _xElementAccess->hasElements(); }
137 // XNameContainer
138 virtual void SAL_CALL insertByName( const OUString& Name, const Any& Element ) override
139 { _xNameContainer->insertByName( Name, Element ); }
141 virtual void SAL_CALL removeByName( const OUString& Name ) override
142 { _xNameContainer->removeByName( Name ); }
144 // XNameReplace
145 virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element ) override
146 { _xNameReplace->replaceByName( Name, Element ); }
148 // XNameAccess
149 virtual Any SAL_CALL getByName( const OUString& Name ) override
150 { return _xNameAccess->getByName( Name ); }
152 virtual Sequence<OUString> SAL_CALL getElementNames() override
153 { return _xNameAccess->getElementNames(); }
155 virtual sal_Bool SAL_CALL hasByName( const OUString& Name ) override
156 { return _xNameAccess->hasByName( Name ); }
158 // XIndexContainer
159 virtual void SAL_CALL insertByIndex( sal_Int32 Index, const Any& Element ) override
160 { _xIndexContainer->insertByIndex( Index, Element ); }
162 virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override
163 { _xIndexContainer->removeByIndex( Index ); }
165 // XIndexReplace
166 virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element ) override
167 { _xIndexReplace->replaceByIndex( Index, Element ); }
169 // XIndexAccess
170 virtual sal_Int32 SAL_CALL getCount() override
171 { return _xIndexAccess->getCount(); }
173 virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override
174 { return _xIndexAccess->getByIndex( Index ); }
176 // XEnumerationAccess
177 virtual Reference<XEnumeration> SAL_CALL createEnumeration() override
178 { return _xEnumerationAccess->createEnumeration(); }
180 // XExactName
181 virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
184 private:
185 void setMaterial( const Any& rMaterial );
187 void getInfoSequenceImpl( Sequence< OUString >* pStringSeq, Sequence< InvocationInfo >* pInfoSeq );
188 void fillInfoForNameAccess( InvocationInfo& rInfo, const OUString& aName );
189 static void fillInfoForProperty( InvocationInfo& rInfo, const Property& rProp );
190 static void fillInfoForMethod( InvocationInfo& rInfo, const Reference< XIdlMethod >& xMethod );
192 Reference<XTypeConverter> xTypeConverter;
193 Reference<XIntrospection> xIntrospection;
194 Reference<XIdlReflection> xCoreReflection;
196 Any _aMaterial;
197 // _xDirect and (_xIntrospectionAccess, xPropertySet) are exclusive
198 Reference<XInvocation> _xDirect;
199 Reference<XInvocation2> _xDirect2;
200 Reference<XPropertySet> _xPropertySet;
201 Reference<XIntrospectionAccess> _xIntrospectionAccess;
203 // supplied Interfaces
204 Reference<XNameContainer> _xNameContainer;
205 Reference<XNameReplace> _xNameReplace;
206 Reference<XNameAccess> _xNameAccess;
207 Reference<XIndexContainer> _xIndexContainer;
208 Reference<XIndexReplace> _xIndexReplace;
209 Reference<XIndexAccess> _xIndexAccess;
210 Reference<XEnumerationAccess> _xEnumerationAccess;
211 Reference<XElementAccess> _xElementAccess;
214 Reference<XExactName> _xENDirect, _xENIntrospection;
218 Invocation_Impl::Invocation_Impl
220 const Any & rAdapted,
221 const Reference<XTypeConverter> & rTC,
222 const Reference<XIntrospection> & rI,
223 const Reference<XIdlReflection> & rCR
225 : xTypeConverter( rTC )
226 , xIntrospection( rI )
227 , xCoreReflection( rCR )
229 setMaterial( rAdapted );
232 //### INTERFACE IMPLEMENTATIONS ####################################################################
235 Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
237 // PropertySet implementation
238 Any a = ::cppu::queryInterface( aType,
239 static_cast< XInvocation* >(this),
240 static_cast< XMaterialHolder* >(this),
241 static_cast< XTypeProvider * >(this) );
242 if( a.hasValue() )
244 return a;
247 if( aType == cppu::UnoType<XExactName>::get())
249 // Invocation does not support XExactName, if direct object supports
250 // XInvocation, but not XExactName.
251 if ((_xDirect.is() && _xENDirect.is()) ||
252 (!_xDirect.is() && _xENIntrospection.is()))
254 return makeAny( Reference< XExactName >( static_cast< XExactName* >(this) ) );
257 else if ( aType == cppu::UnoType<XNameContainer>::get())
259 if( _xNameContainer.is() )
260 return makeAny( Reference< XNameContainer >( static_cast< XNameContainer* >(this) ) );
262 else if ( aType == cppu::UnoType<XNameReplace>::get())
264 if( _xNameReplace.is() )
265 return makeAny( Reference< XNameReplace >( static_cast< XNameReplace* >(this) ) );
267 else if ( aType == cppu::UnoType<XNameAccess>::get())
269 if( _xNameAccess.is() )
270 return makeAny( Reference< XNameAccess >( static_cast< XNameAccess* >(this) ) );
272 else if ( aType == cppu::UnoType<XIndexContainer>::get())
274 if (_xIndexContainer.is())
275 return makeAny( Reference< XIndexContainer >( static_cast< XIndexContainer* >(this) ) );
277 else if ( aType == cppu::UnoType<XIndexReplace>::get())
279 if (_xIndexReplace.is())
280 return makeAny( Reference< XIndexReplace >( static_cast< XIndexReplace* >(this) ) );
282 else if ( aType == cppu::UnoType<XIndexAccess>::get())
284 if (_xIndexAccess.is())
285 return makeAny( Reference< XIndexAccess >( static_cast< XIndexAccess* >(this) ) );
287 else if ( aType == cppu::UnoType<XEnumerationAccess>::get())
289 if (_xEnumerationAccess.is())
290 return makeAny( Reference< XEnumerationAccess >( static_cast< XEnumerationAccess* >(this) ) );
292 else if ( aType == cppu::UnoType<XElementAccess>::get())
294 if (_xElementAccess.is())
296 return makeAny( Reference< XElementAccess >(
297 static_cast< XElementAccess* >(static_cast< XNameContainer* >(this)) ) );
300 else if ( aType == cppu::UnoType<XInvocation2>::get())
302 // Invocation does not support XInvocation2, if direct object supports
303 // XInvocation, but not XInvocation2.
304 if ( ( _xDirect.is() && _xDirect2.is()) ||
305 (!_xDirect.is() && _xIntrospectionAccess.is() ) )
307 return makeAny( Reference< XInvocation2 >( static_cast< XInvocation2* >(this) ) );
311 return OWeakObject::queryInterface( aType );
315 Any Invocation_Impl::getMaterial()
317 // AB, 12.2.1999 Make sure that the material is taken when possible
318 // from the direct Invocation of the Introspection, otherwise structs
319 // are not handled correctly
320 Reference<XMaterialHolder> xMaterialHolder;
321 if( _xDirect.is() )
323 xMaterialHolder.set( _xDirect, UNO_QUERY );
324 //_xDirect->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
326 else if( _xIntrospectionAccess.is() )
328 xMaterialHolder.set( _xIntrospectionAccess, UNO_QUERY );
329 //_xIntrospectionAccess->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
331 if( xMaterialHolder.is() )
333 return xMaterialHolder->getMaterial();
335 return _aMaterial;
339 void Invocation_Impl::setMaterial( const Any& rMaterial )
341 // set the material first and only once
342 _aMaterial = rMaterial;
344 // First do this outside the guard
345 _xDirect.set( rMaterial, UNO_QUERY );
347 if( _xDirect.is() )
349 // Consult object directly
350 _xElementAccess.set( _xDirect, UNO_QUERY );
351 _xEnumerationAccess.set( _xDirect, UNO_QUERY );
352 _xIndexAccess.set( _xDirect, UNO_QUERY );
353 _xIndexReplace.set( _xDirect, UNO_QUERY );
354 _xIndexContainer.set( _xDirect, UNO_QUERY );
355 _xNameAccess.set( _xDirect, UNO_QUERY );
356 _xNameReplace.set( _xDirect, UNO_QUERY );
357 _xNameContainer.set( _xDirect, UNO_QUERY );
358 _xENDirect.set( _xDirect, UNO_QUERY );
359 _xDirect2.set( _xDirect, UNO_QUERY );
361 else
363 // Make Invocation on the Introspection
364 if (xIntrospection.is())
366 _xIntrospectionAccess = xIntrospection->inspect( _aMaterial );
367 if( _xIntrospectionAccess.is() )
369 _xElementAccess.set(
370 _xIntrospectionAccess->queryAdapter(
371 cppu::UnoType<XElementAccess>::get()), UNO_QUERY );
373 if( _xElementAccess.is() )
375 _xEnumerationAccess.set(
376 _xIntrospectionAccess->queryAdapter(
377 cppu::UnoType<XEnumerationAccess>::get()), UNO_QUERY );
379 _xIndexAccess.set(
380 _xIntrospectionAccess->queryAdapter(
381 cppu::UnoType<XIndexAccess>::get()), UNO_QUERY );
383 if( _xIndexAccess.is() )
385 _xIndexReplace.set(
386 _xIntrospectionAccess->queryAdapter(
387 cppu::UnoType<XIndexReplace>::get()), UNO_QUERY );
389 _xIndexContainer.set(
390 _xIntrospectionAccess->queryAdapter(
391 cppu::UnoType<XIndexContainer>::get()), UNO_QUERY );
394 _xNameAccess.set(
395 _xIntrospectionAccess->queryAdapter(
396 cppu::UnoType<XNameAccess>::get()), UNO_QUERY );
398 if( _xNameAccess.is() )
400 _xNameReplace.set(
401 _xIntrospectionAccess->queryAdapter(
402 cppu::UnoType<XNameReplace>::get()), UNO_QUERY );
404 _xNameContainer.set(
405 _xIntrospectionAccess->queryAdapter(
406 cppu::UnoType<XNameContainer>::get()), UNO_QUERY );
410 _xPropertySet.set( _xIntrospectionAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()),
411 UNO_QUERY );
413 _xENIntrospection.set( _xIntrospectionAccess, UNO_QUERY );
420 OUString Invocation_Impl::getExactName( const OUString& rApproximateName )
422 if (_xENDirect.is())
423 return _xENDirect->getExactName( rApproximateName );
425 OUString aRet;
426 if (_xENIntrospection.is())
427 aRet = _xENIntrospection->getExactName( rApproximateName );
428 return aRet;
432 Reference<XIntrospectionAccess> Invocation_Impl::getIntrospection()
434 if( _xDirect.is() )
435 return _xDirect->getIntrospection();
436 else
437 return _xIntrospectionAccess;
441 sal_Bool Invocation_Impl::hasMethod( const OUString& Name )
443 if (_xDirect.is())
444 return _xDirect->hasMethod( Name );
445 if( _xIntrospectionAccess.is() )
446 return _xIntrospectionAccess->hasMethod( Name, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
447 return false;
451 sal_Bool Invocation_Impl::hasProperty( const OUString& Name )
453 if (_xDirect.is())
454 return _xDirect->hasProperty( Name );
455 // PropertySet
456 if( _xIntrospectionAccess.is()
457 && _xIntrospectionAccess->hasProperty( Name, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
458 return true;
459 // NameAccess
460 if( _xNameAccess.is() )
461 return _xNameAccess->hasByName( Name );
462 return false;
466 Any Invocation_Impl::getValue( const OUString& PropertyName )
468 if (_xDirect.is())
469 return _xDirect->getValue( PropertyName );
472 // PropertySet
473 if( _xIntrospectionAccess.is() && _xPropertySet.is()
474 && _xIntrospectionAccess->hasProperty
475 ( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
477 return _xPropertySet->getPropertyValue( PropertyName );
479 // NameAccess
480 if( _xNameAccess.is() && _xNameAccess->hasByName( PropertyName ) )
481 return _xNameAccess->getByName( PropertyName );
483 catch (UnknownPropertyException &)
485 throw;
487 catch (RuntimeException &)
489 throw;
491 catch (Exception &)
495 throw UnknownPropertyException( "cannot get value " + PropertyName );
499 void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value )
501 if (_xDirect.is())
502 _xDirect->setValue( PropertyName, Value );
503 else
507 // Properties
508 if( _xIntrospectionAccess.is() && _xPropertySet.is()
509 && _xIntrospectionAccess->hasProperty(
510 PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
512 Property aProp = _xIntrospectionAccess->getProperty(
513 PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
514 Reference < XIdlClass > r = TypeToIdlClass( aProp.Type, xCoreReflection );
515 if( r->isAssignableFrom( TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
516 _xPropertySet->setPropertyValue( PropertyName, Value );
517 else if( xTypeConverter.is() )
518 _xPropertySet->setPropertyValue(
519 PropertyName, xTypeConverter->convertTo( Value, aProp.Type ) );
520 else
521 throw RuntimeException( "no type converter service!" );
523 // NameContainer
524 else if( _xNameContainer.is() )
526 // Note: This misfeature deliberately not adapted to apply to objects which
527 // have XNameReplace but not XNameContainer
528 Any aConv;
529 Reference < XIdlClass > r =
530 TypeToIdlClass( _xNameContainer->getElementType(), xCoreReflection );
531 if( r->isAssignableFrom(TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
532 aConv = Value;
533 else if( xTypeConverter.is() )
534 aConv = xTypeConverter->convertTo( Value, _xNameContainer->getElementType() );
535 else
536 throw RuntimeException( "no type converter service!" );
538 // Replace if present, otherwise insert
539 if (_xNameContainer->hasByName( PropertyName ))
540 _xNameContainer->replaceByName( PropertyName, aConv );
541 else
542 _xNameContainer->insertByName( PropertyName, aConv );
544 else
545 throw UnknownPropertyException( "no introspection nor name container!" );
547 catch (UnknownPropertyException &)
549 throw;
551 catch (CannotConvertException &)
553 throw;
555 catch (InvocationTargetException &)
557 throw;
559 catch (RuntimeException &)
561 throw;
563 catch (const Exception & exc)
565 throw InvocationTargetException(
566 "exception occurred in setValue(): " + exc.Message,
567 Reference< XInterface >(), makeAny( exc /* though sliced */ ) );
573 Any Invocation_Impl::invoke( const OUString& FunctionName, const Sequence<Any>& InParams,
574 Sequence<sal_Int16>& OutIndices, Sequence<Any>& OutParams )
576 if (_xDirect.is())
577 return _xDirect->invoke( FunctionName, InParams, OutIndices, OutParams );
579 if (_xIntrospectionAccess.is())
581 // throw NoSuchMethodException if not exist
582 Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod(
583 FunctionName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
585 // ParameterInfos
586 Sequence<ParamInfo> aFParams = xMethod->getParameterInfos();
587 const ParamInfo* pFParams = aFParams.getConstArray();
588 sal_Int32 nFParamsLen = aFParams.getLength();
589 if (nFParamsLen != InParams.getLength())
591 throw IllegalArgumentException(
592 "incorrect number of parameters passed invoking function " + FunctionName +
593 ": expected " + OUString::number(nFParamsLen) + ", got " + OUString::number(InParams.getLength()),
594 static_cast<OWeakObject *>(this), sal_Int16(1) );
597 // IN Parameter
598 const Any* pInParams = InParams.getConstArray();
600 // Introspection Invoke Parameter
601 Sequence<Any> aInvokeParams( nFParamsLen );
602 Any* pInvokeParams = aInvokeParams.getArray();
604 // OUT Indices
605 OutIndices.realloc( nFParamsLen );
606 sal_Int16* pOutIndices = OutIndices.getArray();
607 sal_uInt32 nOutIndex = 0;
609 for ( sal_Int32 nPos = 0; nPos < nFParamsLen; ++nPos )
613 const ParamInfo& rFParam = pFParams[nPos];
614 const Reference<XIdlClass>& rDestType = rFParam.aType;
616 // is IN/INOUT parameter?
617 if (rFParam.aMode != ParamMode_OUT)
619 if (rDestType->isAssignableFrom( TypeToIdlClass( pInParams[nPos].getValueType(), xCoreReflection ) ))
621 pInvokeParams[nPos] = pInParams[nPos];
623 else if (xTypeConverter.is())
625 Type aDestType( rDestType->getTypeClass(), rDestType->getName() );
626 pInvokeParams[nPos] = xTypeConverter->convertTo( pInParams[nPos], aDestType );
628 else
630 CannotConvertException aExc;
631 aExc.Context = *this;
632 aExc.Message = "invocation type mismatch!";
633 throw aExc;
637 // is OUT/INOUT parameter?
638 if (rFParam.aMode != ParamMode_IN)
640 pOutIndices[nOutIndex] = static_cast<sal_Int16>(nPos);
641 if (rFParam.aMode == ParamMode_OUT)
642 rDestType->createObject( pInvokeParams[nPos] ); // default init
643 ++nOutIndex;
646 catch( CannotConvertException& rExc )
648 rExc.ArgumentIndex = nPos; // Add optional parameter index
649 throw;
653 // execute Method
654 Any aRet = xMethod->invoke( _aMaterial, aInvokeParams );
656 // OUT Params
657 OutIndices.realloc( nOutIndex );
658 pOutIndices = OutIndices.getArray();
659 OutParams.realloc( nOutIndex );
660 Any* pOutParams = OutParams.getArray();
662 while (nOutIndex--)
664 pOutParams[nOutIndex] = pInvokeParams[ pOutIndices[nOutIndex] ];
667 return aRet;
670 RuntimeException aExc;
671 aExc.Context = *this;
672 aExc.Message = "invocation lacking of introspection access!";
673 throw aExc;
677 // Struct to optimize sorting
678 struct MemberItem
680 OUString aName;
682 // Defines where the member comes from
683 enum Mode { NAMEACCESS, PROPERTYSET, METHOD } eMode;
685 // Index to respective sequence
686 // (Index to NameAccess sequence for eMode==NAMEACCESS etc.)
687 sal_Int32 nIndex;
690 // Implementation of getting name or info
691 // String sequence will be filled when pStringSeq != NULL
692 // Info sequence will be filled when pInfoSeq != NULL
693 void Invocation_Impl::getInfoSequenceImpl
695 Sequence< OUString >* pStringSeq,
696 Sequence< InvocationInfo >* pInfoSeq
699 //Sequence< OUString > aStrSeq;
700 //if( !pStringSeq )
701 //pStringSeq = &aStrSeq;
704 // Get all needed sequences
705 Sequence<OUString> aNameAccessNames;
706 Sequence<Property> aPropertySeq;
707 Sequence< Reference< XIdlMethod > > aMethodSeq;
709 if( _xNameAccess.is() )
711 aNameAccessNames = _xNameAccess->getElementNames();
714 if( _xIntrospectionAccess.is() )
716 aPropertySeq = _xIntrospectionAccess->getProperties
717 ( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
719 aMethodSeq = _xIntrospectionAccess->getMethods
720 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
723 sal_Int32 nNameAccessCount = aNameAccessNames.getLength();
724 sal_Int32 nPropertyCount = aPropertySeq.getLength();
725 sal_Int32 nMethodCount = aMethodSeq.getLength();
726 sal_Int32 nTotalCount = nNameAccessCount + nPropertyCount + nMethodCount;
728 // Create and fill array of MemberItems
729 std::unique_ptr< MemberItem []> pItems( new MemberItem[ nTotalCount ] );
730 const OUString* pStrings = aNameAccessNames.getConstArray();
731 const Property* pProps = aPropertySeq.getConstArray();
732 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
734 // Fill array of MemberItems
735 sal_Int32 i, iTotal = 0;
737 // Name Access
738 for( i = 0 ; i < nNameAccessCount ; i++, iTotal++ )
740 MemberItem& rItem = pItems[ iTotal ];
741 rItem.aName = pStrings[ i ];
742 rItem.eMode = MemberItem::NAMEACCESS;
743 rItem.nIndex = i;
746 // Property set
747 for( i = 0 ; i < nPropertyCount ; i++, iTotal++ )
749 MemberItem& rItem = pItems[ iTotal ];
750 rItem.aName = pProps[ i ].Name;
751 rItem.eMode = MemberItem::PROPERTYSET;
752 rItem.nIndex = i;
755 // Methods
756 for( i = 0 ; i < nMethodCount ; i++, iTotal++ )
758 MemberItem& rItem = pItems[ iTotal ];
759 Reference< XIdlMethod > xMethod = pMethods[ i ];
760 rItem.aName = xMethod->getName();
761 rItem.eMode = MemberItem::METHOD;
762 rItem.nIndex = i;
765 // Setting up result sequences
766 OUString* pRetStrings = nullptr;
767 if( pStringSeq )
769 pStringSeq->realloc( nTotalCount );
770 pRetStrings = pStringSeq->getArray();
773 InvocationInfo* pRetInfos = nullptr;
774 if( pInfoSeq )
776 pInfoSeq->realloc( nTotalCount );
777 pRetInfos = pInfoSeq->getArray();
780 // Fill result sequences in the correct order of members
781 for( iTotal = 0 ; iTotal < nTotalCount ; iTotal++ )
783 MemberItem& rItem = pItems[ iTotal ];
784 if( pRetStrings )
786 pRetStrings[ iTotal ] = rItem.aName;
789 if( pRetInfos )
791 if( rItem.eMode == MemberItem::NAMEACCESS )
793 fillInfoForNameAccess( pRetInfos[ iTotal ], rItem.aName );
795 else if( rItem.eMode == MemberItem::PROPERTYSET )
797 fillInfoForProperty( pRetInfos[ iTotal ], pProps[ rItem.nIndex ] );
799 else if( rItem.eMode == MemberItem::METHOD )
801 fillInfoForMethod( pRetInfos[ iTotal ], pMethods[ rItem.nIndex ] );
807 // XInvocation2
808 Sequence< OUString > SAL_CALL Invocation_Impl::getMemberNames( )
810 if( _xDirect2.is() )
812 return _xDirect2->getMemberNames();
814 Sequence< OUString > aRetSeq;
815 getInfoSequenceImpl( &aRetSeq, nullptr );
816 return aRetSeq;
819 Sequence< InvocationInfo > SAL_CALL Invocation_Impl::getInfo( )
821 if( _xDirect2.is() )
823 return _xDirect2->getInfo();
825 Sequence< InvocationInfo > aRetSeq;
826 getInfoSequenceImpl( nullptr, &aRetSeq );
827 return aRetSeq;
830 InvocationInfo SAL_CALL Invocation_Impl::getInfoForName( const OUString& aName, sal_Bool bExact )
832 if( _xDirect2.is() )
834 return _xDirect2->getInfoForName( aName, bExact );
837 bool bFound = false;
838 OUString aExactName = aName;
839 InvocationInfo aRetInfo;
841 if( bExact )
842 aExactName = getExactName( aName );
843 if( !aExactName.isEmpty() )
845 if( _xIntrospectionAccess->hasMethod( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ) )
847 Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod
848 ( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
849 fillInfoForMethod( aRetInfo, xMethod );
850 bFound = true;
852 else
854 if( _xIntrospectionAccess.is() && _xIntrospectionAccess->hasProperty
855 ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
857 Property aProp = _xIntrospectionAccess->getProperty
858 ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
859 fillInfoForProperty( aRetInfo, aProp );
860 bFound = true;
862 // NameAccess
863 else if( _xNameAccess.is() && _xNameAccess->hasByName( aExactName ) )
865 fillInfoForNameAccess( aRetInfo, aExactName );
866 bFound = true;
870 if( !bFound )
872 throw IllegalArgumentException(
873 "getExactName(), Unknown name " + aName,
874 static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
876 return aRetInfo;
879 // Helper functions to fill InvocationInfo for XNameAccess
880 void Invocation_Impl::fillInfoForNameAccess
882 InvocationInfo& rInfo,
883 const OUString& aName
886 rInfo.aName = aName;
887 rInfo.eMemberType = MemberType_PROPERTY;
888 rInfo.PropertyAttribute = 0;
889 if( !_xNameContainer.is() )
891 rInfo.PropertyAttribute = PropertyAttribute::READONLY;
893 rInfo.aType = _xNameAccess->getElementType();
896 void Invocation_Impl::fillInfoForProperty
898 InvocationInfo& rInfo,
899 const Property& rProp
902 rInfo.aName = rProp.Name;
903 rInfo.eMemberType = MemberType_PROPERTY;
904 rInfo.PropertyAttribute = rProp.Attributes;
905 rInfo.aType = rProp.Type;
908 void Invocation_Impl::fillInfoForMethod
910 InvocationInfo& rInfo,
911 const Reference< XIdlMethod >& xMethod
914 rInfo.aName = xMethod->getName();
915 rInfo.eMemberType = MemberType_METHOD;
916 Reference< XIdlClass > xReturnClass = xMethod->getReturnType();
917 Type aReturnType( xReturnClass->getTypeClass(), xReturnClass->getName() );
918 rInfo.aType = aReturnType;
919 Sequence<ParamInfo> aParamInfos = xMethod->getParameterInfos();
920 sal_Int32 nParamCount = aParamInfos.getLength();
921 if( nParamCount > 0 )
923 const ParamInfo* pInfo = aParamInfos.getConstArray();
925 rInfo.aParamTypes.realloc( nParamCount );
926 Type* pParamTypes = rInfo.aParamTypes.getArray();
927 rInfo.aParamModes.realloc( nParamCount );
928 ParamMode* pParamModes = rInfo.aParamModes.getArray();
930 for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
932 Reference< XIdlClass > xParamClass = pInfo[i].aType;
933 Type aParamType( xParamClass->getTypeClass(), xParamClass->getName() );
934 pParamTypes[ i ] = aParamType;
935 pParamModes[ i ] = pInfo[i].aMode;
941 // XTypeProvider
942 Sequence< Type > SAL_CALL Invocation_Impl::getTypes()
944 static Sequence< Type > const * s_pTypes = nullptr;
945 if (! s_pTypes)
947 Sequence< Type > types( 4 + 10 );
948 Type * pTypes = types.getArray();
949 sal_Int32 n = 0;
951 pTypes[ n++ ] = cppu::UnoType<XTypeProvider>::get();
952 pTypes[ n++ ] = cppu::UnoType<XWeak>::get();
953 pTypes[ n++ ] = cppu::UnoType<XInvocation>::get();
954 pTypes[ n++ ] = cppu::UnoType<XMaterialHolder>::get();
956 // Invocation does not support XExactName if direct object supports
957 // XInvocation, but not XExactName.
958 if ((_xDirect.is() && _xENDirect.is()) ||
959 (!_xDirect.is() && _xENIntrospection.is()))
961 pTypes[ n++ ] = cppu::UnoType<XExactName>::get();
963 if( _xNameContainer.is() )
965 pTypes[ n++ ] = cppu::UnoType<XNameContainer>::get();
967 if( _xNameReplace.is() )
969 pTypes[ n++ ] = cppu::UnoType<XNameReplace>::get();
971 if( _xNameAccess.is() )
973 pTypes[ n++ ] = cppu::UnoType<XNameAccess>::get();
975 if (_xIndexContainer.is())
977 pTypes[ n++ ] = cppu::UnoType<XIndexContainer>::get();
979 if (_xIndexReplace.is())
981 pTypes[ n++ ] = cppu::UnoType<XIndexReplace>::get();
983 if (_xIndexAccess.is())
985 pTypes[ n++ ] = cppu::UnoType<XIndexAccess>::get();
987 if (_xEnumerationAccess.is())
989 pTypes[ n++ ] = cppu::UnoType<XEnumerationAccess>::get();
991 if (_xElementAccess.is())
993 pTypes[ n++ ] = cppu::UnoType<XElementAccess>::get();
995 // Invocation does not support XInvocation2, if direct object supports
996 // XInvocation, but not XInvocation2.
997 if ( ( _xDirect.is() && _xDirect2.is()) ||
998 (!_xDirect.is() && _xIntrospectionAccess.is() ) )
1000 pTypes[ n++ ] = cppu::UnoType<XInvocation2>::get();
1003 types.realloc( n );
1005 // store types
1006 MutexGuard guard( Mutex::getGlobalMutex() );
1007 if (! s_pTypes)
1009 static Sequence< Type > s_types( types );
1010 s_pTypes = &s_types;
1013 return *s_pTypes;
1016 Sequence< sal_Int8 > SAL_CALL Invocation_Impl::getImplementationId( )
1018 return css::uno::Sequence<sal_Int8>();
1022 class InvocationService
1023 : public WeakImplHelper< XSingleServiceFactory, XServiceInfo >
1025 public:
1026 explicit InvocationService( const Reference<XComponentContext> & xCtx );
1028 // XServiceInfo
1029 OUString SAL_CALL getImplementationName() override;
1030 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
1031 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
1033 // XSingleServiceFactory
1034 Reference<XInterface> SAL_CALL createInstance() override;
1035 Reference<XInterface> SAL_CALL createInstanceWithArguments(
1036 const Sequence<Any>& rArguments ) override;
1037 private:
1038 Reference<XComponentContext> mxCtx;
1039 Reference<XMultiComponentFactory> mxSMgr;
1040 Reference<XTypeConverter> xTypeConverter;
1041 Reference<XIntrospection> xIntrospection;
1042 Reference<XIdlReflection> xCoreReflection;
1045 InvocationService::InvocationService( const Reference<XComponentContext> & xCtx )
1046 : mxCtx( xCtx )
1047 , mxSMgr( xCtx->getServiceManager() )
1048 , xCoreReflection( css::reflection::theCoreReflection::get(mxCtx) )
1050 xTypeConverter.set(
1051 mxSMgr->createInstanceWithContext( "com.sun.star.script.Converter", xCtx ),
1052 UNO_QUERY );
1053 xIntrospection = theIntrospection::get(xCtx);
1056 // XServiceInfo
1057 OUString InvocationService::getImplementationName()
1059 return inv_getImplementationName();
1062 // XServiceInfo
1063 sal_Bool InvocationService::supportsService(const OUString& ServiceName)
1065 return cppu::supportsService(this, ServiceName);
1068 // XServiceInfo
1069 Sequence< OUString > InvocationService::getSupportedServiceNames()
1071 return inv_getSupportedServiceNames();
1075 Reference<XInterface> InvocationService::createInstance()
1077 //TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
1078 return Reference<XInterface>(); // dummy
1082 Reference<XInterface> InvocationService::createInstanceWithArguments(
1083 const Sequence<Any>& rArguments )
1085 if (rArguments.getLength() == 1)
1087 return Reference< XInterface >
1088 ( *new Invocation_Impl( *rArguments.getConstArray(),
1089 xTypeConverter, xIntrospection, xCoreReflection ) );
1091 else
1093 //TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
1094 return Reference<XInterface>();
1098 /// @throws RuntimeException
1099 Reference<XInterface> InvocationService_CreateInstance( const Reference<XComponentContext> & xCtx )
1101 Reference<XInterface> xService( *new InvocationService( xCtx ) );
1102 return xService;
1107 using namespace stoc_inv;
1108 static const struct ImplementationEntry g_entries[] =
1111 InvocationService_CreateInstance, inv_getImplementationName,
1112 inv_getSupportedServiceNames, createSingleComponentFactory,
1113 nullptr, 0
1115 { nullptr, nullptr, nullptr, nullptr, nullptr, 0 }
1118 extern "C" SAL_DLLPUBLIC_EXPORT void * invocation_component_getFactory(
1119 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
1121 return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
1124 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */