LibreOffice Module stoc (master) 1
invocation.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
23#include <cppuhelper/weak.hxx>
26
27#include <com/sun/star/script/CannotConvertException.hpp>
28#include <com/sun/star/script/XTypeConverter.hpp>
29#include <com/sun/star/script/XInvocation.hpp>
30#include <com/sun/star/script/XInvocation2.hpp>
31#include <com/sun/star/reflection/XIdlReflection.hpp>
32#include <com/sun/star/reflection/theCoreReflection.hpp>
33#include <com/sun/star/container/XNameContainer.hpp>
34#include <com/sun/star/container/XIndexContainer.hpp>
35#include <com/sun/star/container/XEnumerationAccess.hpp>
36#include <com/sun/star/beans/XExactName.hpp>
37#include <com/sun/star/beans/XMaterialHolder.hpp>
38#include <com/sun/star/beans/theIntrospection.hpp>
39#include <com/sun/star/beans/XPropertySet.hpp>
40#include <com/sun/star/beans/PropertyAttribute.hpp>
41#include <com/sun/star/beans/MethodConcept.hpp>
42#include <com/sun/star/beans/PropertyConcept.hpp>
43#include <com/sun/star/lang/XSingleServiceFactory.hpp>
44#include <com/sun/star/lang/XServiceInfo.hpp>
45#include <com/sun/star/lang/XTypeProvider.hpp>
46
47#include <memory>
48#include <vector>
49
50using namespace css::uno;
51using namespace css::lang;
52using namespace css::script;
53using namespace css::reflection;
54using namespace css::beans;
55using namespace css::container;
56using namespace cppu;
57using namespace osl;
58
59namespace stoc_inv
60{
61
62
63// TODO: Implement centrally
64static Reference<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XIdlReflection > & xRefl )
65{
66 return xRefl->forName( rType.getTypeName() );
67}
68
69namespace {
70
71class Invocation_Impl
72 : public OWeakObject
73 , public XInvocation2
74 , public XNameContainer
75 , public XIndexContainer
76 , public XEnumerationAccess
77 , public XExactName
78 , public XMaterialHolder
79 , public XTypeProvider
80{
81public:
82 Invocation_Impl( const Any & rAdapted, const Reference<XTypeConverter> &,
83 const Reference<XIntrospection> &,
84 const Reference<XIdlReflection> &,
85 bool bFromOLE );
86
87 // XInterface
88 virtual Any SAL_CALL queryInterface( const Type & aType) override;
89 virtual void SAL_CALL acquire() noexcept override { OWeakObject::acquire(); }
90 virtual void SAL_CALL release() noexcept override { OWeakObject::release(); }
91
92
93 // XTypeProvider
94 virtual Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
95 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
96
97 // XMaterialHolder
98 virtual Any SAL_CALL getMaterial() override;
99
100 // XInvocation
101 virtual Reference<XIntrospectionAccess> SAL_CALL getIntrospection() override;
102 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override;
103 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override;
104 virtual Any SAL_CALL getValue(const OUString& PropertyName) override;
105 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override;
106 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override;
107
108 // XInvocation2
109 virtual Sequence< OUString > SAL_CALL getMemberNames( ) override;
110 virtual Sequence< InvocationInfo > SAL_CALL getInfo( ) override;
111 virtual InvocationInfo SAL_CALL getInfoForName( const OUString& aName, sal_Bool bExact ) override;
112
113 // All Access and Container methods are not thread safe
114 // XElementAccess
115 virtual Type SAL_CALL getElementType() override
116 { return _xElementAccess->getElementType(); }
117
118 virtual sal_Bool SAL_CALL hasElements() override
119 { return _xElementAccess->hasElements(); }
120
121 // XNameContainer
122 virtual void SAL_CALL insertByName( const OUString& Name, const Any& Element ) override
123 { _xNameContainer->insertByName( Name, Element ); }
124
125 virtual void SAL_CALL removeByName( const OUString& Name ) override
126 { _xNameContainer->removeByName( Name ); }
127
128 // XNameReplace
129 virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element ) override
130 { _xNameReplace->replaceByName( Name, Element ); }
131
132 // XNameAccess
133 virtual Any SAL_CALL getByName( const OUString& Name ) override
134 { return _xNameAccess->getByName( Name ); }
135
136 virtual Sequence<OUString> SAL_CALL getElementNames() override
137 { return _xNameAccess->getElementNames(); }
138
139 virtual sal_Bool SAL_CALL hasByName( const OUString& Name ) override
140 { return _xNameAccess->hasByName( Name ); }
141
142 // XIndexContainer
143 virtual void SAL_CALL insertByIndex( sal_Int32 Index, const Any& Element ) override
144 { _xIndexContainer->insertByIndex( Index, Element ); }
145
146 virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override
147 { _xIndexContainer->removeByIndex( Index ); }
148
149 // XIndexReplace
150 virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element ) override
151 { _xIndexReplace->replaceByIndex( Index, Element ); }
152
153 // XIndexAccess
154 virtual sal_Int32 SAL_CALL getCount() override
155 { return _xIndexAccess->getCount(); }
156
157 virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override
158 { return _xIndexAccess->getByIndex( Index ); }
159
160 // XEnumerationAccess
161 virtual Reference<XEnumeration> SAL_CALL createEnumeration() override
162 { return _xEnumerationAccess->createEnumeration(); }
163
164 // XExactName
165 virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
166
167
168private:
169 void setMaterial( const Any& rMaterial );
170
171 void getInfoSequenceImpl( Sequence< OUString >* pStringSeq, Sequence< InvocationInfo >* pInfoSeq );
172 void fillInfoForNameAccess( InvocationInfo& rInfo, const OUString& aName );
173 static void fillInfoForProperty( InvocationInfo& rInfo, const Property& rProp );
174 static void fillInfoForMethod( InvocationInfo& rInfo, const Reference< XIdlMethod >& xMethod );
175
176 Reference<XTypeConverter> xTypeConverter;
177 Reference<XIntrospection> xIntrospection;
178 Reference<XIdlReflection> xCoreReflection;
179
181 // _xDirect and (_xIntrospectionAccess, xPropertySet) are exclusive
182 Reference<XInvocation> _xDirect;
183 Reference<XInvocation2> _xDirect2;
184 Reference<XPropertySet> _xPropertySet;
185 Reference<XIntrospectionAccess> _xIntrospectionAccess;
186
187 // supplied Interfaces
188 Reference<XNameContainer> _xNameContainer;
189 Reference<XNameReplace> _xNameReplace;
190 Reference<XNameAccess> _xNameAccess;
191 Reference<XIndexContainer> _xIndexContainer;
192 Reference<XIndexReplace> _xIndexReplace;
193 Reference<XIndexAccess> _xIndexAccess;
194 Reference<XEnumerationAccess> _xEnumerationAccess;
195 Reference<XElementAccess> _xElementAccess;
196
197
198 Reference<XExactName> _xENDirect, _xENIntrospection;
199
201};
202
203}
204
205Invocation_Impl::Invocation_Impl
206(
207 const Any & rAdapted,
208 const Reference<XTypeConverter> & rTC,
209 const Reference<XIntrospection> & rI,
210 const Reference<XIdlReflection> & rCR,
211 bool bFromOLE
212)
213 : xTypeConverter( rTC )
214 , xIntrospection( rI )
215 , xCoreReflection( rCR )
216 , mbFromOLE( bFromOLE )
217{
218 setMaterial( rAdapted );
219}
220
221//### INTERFACE IMPLEMENTATIONS ####################################################################
222
223
224Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
225{
226 // PropertySet implementation
227 Any a = ::cppu::queryInterface( aType,
228 static_cast< XInvocation* >(this),
229 static_cast< XMaterialHolder* >(this),
230 static_cast< XTypeProvider * >(this) );
231 if( a.hasValue() )
232 {
233 return a;
234 }
235
236 if( aType == cppu::UnoType<XExactName>::get())
237 {
238 // Invocation does not support XExactName, if direct object supports
239 // XInvocation, but not XExactName. Except when called from OLE Automation.
240 if (mbFromOLE ||
241 (_xDirect.is() && _xENDirect.is()) ||
242 (!_xDirect.is() && _xENIntrospection.is()))
243 {
244 return Any( Reference< XExactName >( static_cast< XExactName* >(this) ) );
245 }
246 }
247 else if ( aType == cppu::UnoType<XNameContainer>::get())
248 {
249 if( _xNameContainer.is() )
250 return Any( Reference< XNameContainer >( static_cast< XNameContainer* >(this) ) );
251 }
252 else if ( aType == cppu::UnoType<XNameReplace>::get())
253 {
254 if( _xNameReplace.is() )
255 return Any( Reference< XNameReplace >( static_cast< XNameReplace* >(this) ) );
256 }
257 else if ( aType == cppu::UnoType<XNameAccess>::get())
258 {
259 if( _xNameAccess.is() )
260 return Any( Reference< XNameAccess >( static_cast< XNameAccess* >(this) ) );
261 }
262 else if ( aType == cppu::UnoType<XIndexContainer>::get())
263 {
264 if (_xIndexContainer.is())
265 return Any( Reference< XIndexContainer >( static_cast< XIndexContainer* >(this) ) );
266 }
267 else if ( aType == cppu::UnoType<XIndexReplace>::get())
268 {
269 if (_xIndexReplace.is())
270 return Any( Reference< XIndexReplace >( static_cast< XIndexReplace* >(this) ) );
271 }
272 else if ( aType == cppu::UnoType<XIndexAccess>::get())
273 {
274 if (_xIndexAccess.is())
275 return Any( Reference< XIndexAccess >( static_cast< XIndexAccess* >(this) ) );
276 }
277 else if ( aType == cppu::UnoType<XEnumerationAccess>::get())
278 {
279 if (_xEnumerationAccess.is())
280 return Any( Reference< XEnumerationAccess >( static_cast< XEnumerationAccess* >(this) ) );
281 }
282 else if ( aType == cppu::UnoType<XElementAccess>::get())
283 {
284 if (_xElementAccess.is())
285 {
286 return Any( Reference< XElementAccess >(
287 static_cast< XElementAccess* >(static_cast< XNameContainer* >(this)) ) );
288 }
289 }
290 else if ( aType == cppu::UnoType<XInvocation2>::get())
291 {
292 // Invocation does not support XInvocation2, if direct object supports
293 // XInvocation, but not XInvocation2.
294 if ( mbFromOLE ||
295 ( _xDirect.is() && _xDirect2.is()) ||
296 (!_xDirect.is() && _xIntrospectionAccess.is() ) )
297 {
298 return Any( Reference< XInvocation2 >( static_cast< XInvocation2* >(this) ) );
299 }
300 }
301
302 return OWeakObject::queryInterface( aType );
303}
304
305
306Any Invocation_Impl::getMaterial()
307{
308 // AB, 12.2.1999 Make sure that the material is taken when possible
309 // from the direct Invocation of the Introspection, otherwise structs
310 // are not handled correctly
311 Reference<XMaterialHolder> xMaterialHolder;
312 if( _xDirect.is() )
313 {
314 xMaterialHolder.set( _xDirect, UNO_QUERY );
315 //_xDirect->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
316 }
317 else if( _xIntrospectionAccess.is() )
318 {
319 xMaterialHolder.set( _xIntrospectionAccess, UNO_QUERY );
320 //_xIntrospectionAccess->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
321 }
322 if( xMaterialHolder.is() )
323 {
324 return xMaterialHolder->getMaterial();
325 }
326 return _aMaterial;
327}
328
329
330void Invocation_Impl::setMaterial( const Any& rMaterial )
331{
332 // set the material first and only once
333 _aMaterial = rMaterial;
334
335 // First do this outside the guard
336 _xDirect.set( rMaterial, UNO_QUERY );
337
338 if( !mbFromOLE && _xDirect.is() )
339 {
340 // Consult object directly
341 _xElementAccess.set( _xDirect, UNO_QUERY );
342 _xEnumerationAccess.set( _xDirect, UNO_QUERY );
343 _xIndexAccess.set( _xDirect, UNO_QUERY );
344 _xIndexReplace.set( _xDirect, UNO_QUERY );
345 _xIndexContainer.set( _xDirect, UNO_QUERY );
346 _xNameAccess.set( _xDirect, UNO_QUERY );
347 _xNameReplace.set( _xDirect, UNO_QUERY );
348 _xNameContainer.set( _xDirect, UNO_QUERY );
349 _xENDirect.set( _xDirect, UNO_QUERY );
350 _xDirect2.set( _xDirect, UNO_QUERY );
351 }
352 else
353 {
354 // Make Invocation on the Introspection
355 if (xIntrospection.is())
356 {
358 if( _xIntrospectionAccess.is() )
359 {
360 _xElementAccess.set(
361 _xIntrospectionAccess->queryAdapter(
363
364 if( _xElementAccess.is() )
365 {
367 _xIntrospectionAccess->queryAdapter(
369
370 _xIndexAccess.set(
371 _xIntrospectionAccess->queryAdapter(
372 cppu::UnoType<XIndexAccess>::get()), UNO_QUERY );
373
374 if( _xIndexAccess.is() )
375 {
376 _xIndexReplace.set(
377 _xIntrospectionAccess->queryAdapter(
378 cppu::UnoType<XIndexReplace>::get()), UNO_QUERY );
379
381 _xIntrospectionAccess->queryAdapter(
383 }
384
385 _xNameAccess.set(
386 _xIntrospectionAccess->queryAdapter(
387 cppu::UnoType<XNameAccess>::get()), UNO_QUERY );
388
389 if( _xNameAccess.is() )
390 {
391 _xNameReplace.set(
392 _xIntrospectionAccess->queryAdapter(
393 cppu::UnoType<XNameReplace>::get()), UNO_QUERY );
394
395 _xNameContainer.set(
396 _xIntrospectionAccess->queryAdapter(
398 }
399 }
400
402 UNO_QUERY );
403
405 }
406 }
407 }
408}
409
410
411OUString Invocation_Impl::getExactName( const OUString& rApproximateName )
412{
413 if (_xENDirect.is())
414 return _xENDirect->getExactName( rApproximateName );
415
416 OUString aRet;
417 if (_xENIntrospection.is())
418 aRet = _xENIntrospection->getExactName( rApproximateName );
419 return aRet;
420}
421
422
423Reference<XIntrospectionAccess> Invocation_Impl::getIntrospection()
424{
425 if( _xDirect.is() )
426 return _xDirect->getIntrospection();
427 else
429}
430
431
432sal_Bool Invocation_Impl::hasMethod( const OUString& Name )
433{
434 if (!mbFromOLE && _xDirect.is())
435 return _xDirect->hasMethod( Name );
436 if( _xIntrospectionAccess.is() )
437 return _xIntrospectionAccess->hasMethod( Name, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
438 return false;
439}
440
441
442sal_Bool Invocation_Impl::hasProperty( const OUString& Name )
443{
444 if (_xDirect.is())
445 {
446 bool bRet = _xDirect->hasProperty( Name );
447 if (bRet || !mbFromOLE)
448 return bRet;
449 }
450 // PropertySet
451 if( _xIntrospectionAccess.is()
452 && _xIntrospectionAccess->hasProperty( Name, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
453 return true;
454 // NameAccess
455 if( _xNameAccess.is() )
456 return _xNameAccess->hasByName( Name );
457 return false;
458}
459
460
461Any Invocation_Impl::getValue( const OUString& PropertyName )
462{
463 try
464 {
465 if (_xDirect.is())
466 return _xDirect->getValue( PropertyName );
467 }
468 catch (Exception &)
469 {
470 if (!mbFromOLE)
471 throw;
472 }
473 try
474 {
475 // PropertySet
476 if( _xIntrospectionAccess.is() && _xPropertySet.is()
477 && _xIntrospectionAccess->hasProperty
478 ( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
479 {
480 return _xPropertySet->getPropertyValue( PropertyName );
481 }
482 // NameAccess
483 if( _xNameAccess.is() && _xNameAccess->hasByName( PropertyName ) )
484 return _xNameAccess->getByName( PropertyName );
485 }
486 catch (UnknownPropertyException &)
487 {
488 throw;
489 }
490 catch (RuntimeException &)
491 {
492 throw;
493 }
494 catch (Exception &)
495 {
496 }
497
498 throw UnknownPropertyException( "cannot get value " + PropertyName );
499}
500
501
502void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value )
503{
504 try
505 {
506 if (_xDirect.is())
507 {
508 _xDirect->setValue( PropertyName, Value );
509 return;
510 }
511 }
512 catch (Exception &)
513 {
514 if (!mbFromOLE)
515 throw;
516 }
517 try
518 {
519 // Properties
520 if( _xIntrospectionAccess.is() && _xPropertySet.is()
521 && _xIntrospectionAccess->hasProperty(
522 PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
523 {
524 Property aProp = _xIntrospectionAccess->getProperty(
525 PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
526 Reference < XIdlClass > r = TypeToIdlClass( aProp.Type, xCoreReflection );
527 if( r->isAssignableFrom( TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
528 _xPropertySet->setPropertyValue( PropertyName, Value );
529 else if( xTypeConverter.is() )
530 _xPropertySet->setPropertyValue(
531 PropertyName, xTypeConverter->convertTo( Value, aProp.Type ) );
532 else
533 throw RuntimeException( "no type converter service!" );
534 }
535 // NameContainer
536 else if( _xNameContainer.is() )
537 {
538 // Note: This misfeature deliberately not adapted to apply to objects which
539 // have XNameReplace but not XNameContainer
540 Any aConv;
541 Reference < XIdlClass > r =
542 TypeToIdlClass( _xNameContainer->getElementType(), xCoreReflection );
543 if( r->isAssignableFrom(TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
544 aConv = Value;
545 else if( xTypeConverter.is() )
546 aConv = xTypeConverter->convertTo( Value, _xNameContainer->getElementType() );
547 else
548 throw RuntimeException( "no type converter service!" );
549
550 // Replace if present, otherwise insert
551 if (_xNameContainer->hasByName( PropertyName ))
552 _xNameContainer->replaceByName( PropertyName, aConv );
553 else
554 _xNameContainer->insertByName( PropertyName, aConv );
555 }
556 else
557 throw UnknownPropertyException( "no introspection nor name container!" );
558 }
559 catch (UnknownPropertyException &)
560 {
561 throw;
562 }
563 catch (CannotConvertException &)
564 {
565 throw;
566 }
567 catch (InvocationTargetException &)
568 {
569 throw;
570 }
571 catch (RuntimeException &)
572 {
573 throw;
574 }
575 catch (const Exception & exc)
576 {
577 css::uno::Any anyEx = cppu::getCaughtException();
578 throw InvocationTargetException(
579 "exception occurred in setValue(): " + exc.Message,
580 Reference< XInterface >(), anyEx );
581 }
582}
583
584
585Any Invocation_Impl::invoke( const OUString& FunctionName, const Sequence<Any>& InParams,
586 Sequence<sal_Int16>& OutIndices, Sequence<Any>& OutParams )
587{
588 if (!mbFromOLE && _xDirect.is())
589 return _xDirect->invoke( FunctionName, InParams, OutIndices, OutParams );
590
591 if (_xIntrospectionAccess.is())
592 {
593 // throw NoSuchMethodException if not exist
594 Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod(
595 FunctionName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
596
597 // ParameterInfos
598 Sequence<ParamInfo> aFParams = xMethod->getParameterInfos();
599 const ParamInfo* pFParams = aFParams.getConstArray();
600 sal_Int32 nFParamsLen = aFParams.getLength();
601 if (nFParamsLen != InParams.getLength())
602 {
603 throw IllegalArgumentException(
604 "incorrect number of parameters passed invoking function " + FunctionName +
605 ": expected " + OUString::number(nFParamsLen) + ", got " + OUString::number(InParams.getLength()),
606 getXWeak(), sal_Int16(1) );
607 }
608
609 // IN Parameter
610 const Any* pInParams = InParams.getConstArray();
611
612 // Introspection Invoke Parameter
613 Sequence<Any> aInvokeParams( nFParamsLen );
614 Any* pInvokeParams = aInvokeParams.getArray();
615
616 // OUT Indices
617 OutIndices.realloc( nFParamsLen );
618 sal_Int16* pOutIndices = OutIndices.getArray();
619 sal_uInt32 nOutIndex = 0;
620
621 for ( sal_Int32 nPos = 0; nPos < nFParamsLen; ++nPos )
622 {
623 try
624 {
625 const ParamInfo& rFParam = pFParams[nPos];
626 const Reference<XIdlClass>& rDestType = rFParam.aType;
627
628 // is IN/INOUT parameter?
629 if (rFParam.aMode != ParamMode_OUT)
630 {
631 if (rDestType->isAssignableFrom( TypeToIdlClass( pInParams[nPos].getValueType(), xCoreReflection ) ))
632 {
633 pInvokeParams[nPos] = pInParams[nPos];
634 }
635 else if (xTypeConverter.is())
636 {
637 Type aDestType( rDestType->getTypeClass(), rDestType->getName() );
638 pInvokeParams[nPos] = xTypeConverter->convertTo( pInParams[nPos], aDestType );
639 }
640 else
641 {
642 CannotConvertException aExc;
643 aExc.Context = *this;
644 aExc.Message = "invocation type mismatch!";
645 throw aExc;
646 }
647 }
648
649 // is OUT/INOUT parameter?
650 if (rFParam.aMode != ParamMode_IN)
651 {
652 pOutIndices[nOutIndex] = static_cast<sal_Int16>(nPos);
653 if (rFParam.aMode == ParamMode_OUT)
654 rDestType->createObject( pInvokeParams[nPos] ); // default init
655 ++nOutIndex;
656 }
657 }
658 catch( CannotConvertException& rExc )
659 {
660 rExc.ArgumentIndex = nPos; // Add optional parameter index
661 throw;
662 }
663 }
664
665 // execute Method
666 Any aRet = xMethod->invoke( _aMaterial, aInvokeParams );
667
668 // OUT Params
669 OutIndices.realloc( nOutIndex );
670 OutParams.realloc( nOutIndex );
671
672 std::transform(std::cbegin(OutIndices), std::cend(OutIndices), OutParams.getArray(),
673 [&pInvokeParams](const sal_Int16 nIndex) -> Any { return pInvokeParams[nIndex]; });
674
675 return aRet;
676 }
677
678 RuntimeException aExc;
679 aExc.Context = *this;
680 aExc.Message = "invocation lacking of introspection access!";
681 throw aExc;
682}
683
684namespace {
685
686// Struct to optimize sorting
687struct MemberItem
688{
689 OUString aName;
690
691 // Defines where the member comes from
692 enum class Mode { NameAccess, PropertySet, Method };
694
695 // Index to respective sequence
696 // (Index to NameAccess sequence for eMode==Mode::NameAccess etc.)
697 sal_Int32 nIndex;
698};
699
700}
701
702// Implementation of getting name or info
703// String sequence will be filled when pStringSeq != NULL
704// Info sequence will be filled when pInfoSeq != NULL
705void Invocation_Impl::getInfoSequenceImpl
706(
707 Sequence< OUString >* pStringSeq,
708 Sequence< InvocationInfo >* pInfoSeq
709)
710{
711 //Sequence< OUString > aStrSeq;
712 //if( !pStringSeq )
713 //pStringSeq = &aStrSeq;
714
715
716 // Get all needed sequences
717 Sequence<OUString> aNameAccessNames;
718 Sequence<Property> aPropertySeq;
719 Sequence< Reference< XIdlMethod > > aMethodSeq;
720
721 if( _xNameAccess.is() )
722 {
723 aNameAccessNames = _xNameAccess->getElementNames();
724 }
725
726 if( _xIntrospectionAccess.is() )
727 {
728 aPropertySeq = _xIntrospectionAccess->getProperties
729 ( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
730
731 aMethodSeq = _xIntrospectionAccess->getMethods
732 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
733 }
734
735 sal_Int32 nNameAccessCount = aNameAccessNames.getLength();
736 sal_Int32 nPropertyCount = aPropertySeq.getLength();
737 sal_Int32 nMethodCount = aMethodSeq.getLength();
738 sal_Int32 nTotalCount = nNameAccessCount + nPropertyCount + nMethodCount;
739
740 // Create and fill array of MemberItems
741 std::unique_ptr< MemberItem []> pItems( new MemberItem[ nTotalCount ] );
742 const OUString* pStrings = aNameAccessNames.getConstArray();
743 const Property* pProps = aPropertySeq.getConstArray();
744 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
745
746 // Fill array of MemberItems
747 sal_Int32 i, iTotal = 0;
748
749 // Name Access
750 for( i = 0 ; i < nNameAccessCount ; i++, iTotal++ )
751 {
752 MemberItem& rItem = pItems[ iTotal ];
753 rItem.aName = pStrings[ i ];
754 rItem.eMode = MemberItem::Mode::NameAccess;
755 rItem.nIndex = i;
756 }
757
758 // Property set
759 for( i = 0 ; i < nPropertyCount ; i++, iTotal++ )
760 {
761 MemberItem& rItem = pItems[ iTotal ];
762 rItem.aName = pProps[ i ].Name;
763 rItem.eMode = MemberItem::Mode::PropertySet;
764 rItem.nIndex = i;
765 }
766
767 // Methods
768 for( i = 0 ; i < nMethodCount ; i++, iTotal++ )
769 {
770 MemberItem& rItem = pItems[ iTotal ];
771 Reference< XIdlMethod > xMethod = pMethods[ i ];
772 rItem.aName = xMethod->getName();
773 rItem.eMode = MemberItem::Mode::Method;
774 rItem.nIndex = i;
775 }
776
777 // Setting up result sequences
778 OUString* pRetStrings = nullptr;
779 if( pStringSeq )
780 {
781 pStringSeq->realloc( nTotalCount );
782 pRetStrings = pStringSeq->getArray();
783 }
784
785 InvocationInfo* pRetInfos = nullptr;
786 if( pInfoSeq )
787 {
788 pInfoSeq->realloc( nTotalCount );
789 pRetInfos = pInfoSeq->getArray();
790 }
791
792 // Fill result sequences in the correct order of members
793 for( iTotal = 0 ; iTotal < nTotalCount ; iTotal++ )
794 {
795 MemberItem& rItem = pItems[ iTotal ];
796 if( pRetStrings )
797 {
798 pRetStrings[ iTotal ] = rItem.aName;
799 }
800
801 if( pRetInfos )
802 {
803 if( rItem.eMode == MemberItem::Mode::NameAccess )
804 {
805 fillInfoForNameAccess( pRetInfos[ iTotal ], rItem.aName );
806 }
807 else if( rItem.eMode == MemberItem::Mode::PropertySet )
808 {
809 fillInfoForProperty( pRetInfos[ iTotal ], pProps[ rItem.nIndex ] );
810 }
811 else if( rItem.eMode == MemberItem::Mode::Method )
812 {
813 fillInfoForMethod( pRetInfos[ iTotal ], pMethods[ rItem.nIndex ] );
814 }
815 }
816 }
817}
818
819// XInvocation2
820Sequence< OUString > SAL_CALL Invocation_Impl::getMemberNames( )
821{
822 if( _xDirect2.is() )
823 {
824 return _xDirect2->getMemberNames();
825 }
826 Sequence< OUString > aRetSeq;
827 getInfoSequenceImpl( &aRetSeq, nullptr );
828 return aRetSeq;
829}
830
831Sequence< InvocationInfo > SAL_CALL Invocation_Impl::getInfo( )
832{
833 if( _xDirect2.is() )
834 {
835 return _xDirect2->getInfo();
836 }
837 Sequence< InvocationInfo > aRetSeq;
838 getInfoSequenceImpl( nullptr, &aRetSeq );
839 return aRetSeq;
840}
841
842InvocationInfo SAL_CALL Invocation_Impl::getInfoForName( const OUString& aName, sal_Bool bExact )
843{
844 if( _xDirect2.is() )
845 {
846 return _xDirect2->getInfoForName( aName, bExact );
847 }
848
849 bool bFound = false;
850 OUString aExactName = aName;
851 InvocationInfo aRetInfo;
852
853 if( bExact )
854 aExactName = getExactName( aName );
855 if( !aExactName.isEmpty() )
856 {
857 if( _xIntrospectionAccess->hasMethod( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ) )
858 {
859 Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod
860 ( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
861 fillInfoForMethod( aRetInfo, xMethod );
862 bFound = true;
863 }
864 else
865 {
866 if( _xIntrospectionAccess.is() && _xIntrospectionAccess->hasProperty
867 ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
868 {
869 Property aProp = _xIntrospectionAccess->getProperty
870 ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
871 fillInfoForProperty( aRetInfo, aProp );
872 bFound = true;
873 }
874 // NameAccess
875 else if( _xNameAccess.is() && _xNameAccess->hasByName( aExactName ) )
876 {
877 fillInfoForNameAccess( aRetInfo, aExactName );
878 bFound = true;
879 }
880 }
881 }
882 if( !bFound )
883 {
884 throw IllegalArgumentException(
885 "getExactName(), Unknown name " + aName,
886 getXWeak(), 0 );
887 }
888 return aRetInfo;
889}
890
891// Helper functions to fill InvocationInfo for XNameAccess
892void Invocation_Impl::fillInfoForNameAccess
893(
894 InvocationInfo& rInfo,
895 const OUString& aName
896)
897{
898 rInfo.aName = aName;
899 rInfo.eMemberType = MemberType_PROPERTY;
900 rInfo.PropertyAttribute = 0;
901 if( !_xNameContainer.is() )
902 {
903 rInfo.PropertyAttribute = PropertyAttribute::READONLY;
904 }
905 rInfo.aType = _xNameAccess->getElementType();
906}
907
908void Invocation_Impl::fillInfoForProperty
909(
910 InvocationInfo& rInfo,
911 const Property& rProp
912)
913{
914 rInfo.aName = rProp.Name;
915 rInfo.eMemberType = MemberType_PROPERTY;
916 rInfo.PropertyAttribute = rProp.Attributes;
917 rInfo.aType = rProp.Type;
918}
919
920void Invocation_Impl::fillInfoForMethod
921(
922 InvocationInfo& rInfo,
923 const Reference< XIdlMethod >& xMethod
924)
925{
926 rInfo.aName = xMethod->getName();
927 rInfo.eMemberType = MemberType_METHOD;
928 Reference< XIdlClass > xReturnClass = xMethod->getReturnType();
929 Type aReturnType( xReturnClass->getTypeClass(), xReturnClass->getName() );
930 rInfo.aType = aReturnType;
931 Sequence<ParamInfo> aParamInfos = xMethod->getParameterInfos();
932 sal_Int32 nParamCount = aParamInfos.getLength();
933 if( nParamCount <= 0 )
934 return;
935
936 const ParamInfo* pInfo = aParamInfos.getConstArray();
937
938 rInfo.aParamTypes.realloc( nParamCount );
939 Type* pParamTypes = rInfo.aParamTypes.getArray();
940 rInfo.aParamModes.realloc( nParamCount );
941 ParamMode* pParamModes = rInfo.aParamModes.getArray();
942
943 for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
944 {
945 Reference< XIdlClass > xParamClass = pInfo[i].aType;
946 Type aParamType( xParamClass->getTypeClass(), xParamClass->getName() );
947 pParamTypes[ i ] = aParamType;
948 pParamModes[ i ] = pInfo[i].aMode;
949 }
950}
951
952
953// XTypeProvider
954Sequence< Type > SAL_CALL Invocation_Impl::getTypes()
955{
956 static Sequence<Type> s_types = [this]() {
957 std::vector<Type> tmp {
962
963 // Invocation does not support XExactName if direct object supports
964 // XInvocation, but not XExactName.
965 if ((_xDirect.is() && _xENDirect.is()) || (!_xDirect.is() && _xENIntrospection.is()))
966 tmp.push_back(cppu::UnoType<XExactName>::get());
967 if (_xNameContainer.is())
968 tmp.push_back(cppu::UnoType<XNameContainer>::get());
969 if (_xNameReplace.is())
970 tmp.push_back(cppu::UnoType<XNameReplace>::get());
971 if (_xNameAccess.is())
972 tmp.push_back(cppu::UnoType<XNameAccess>::get());
973 if (_xIndexContainer.is())
975 if (_xIndexReplace.is())
976 tmp.push_back(cppu::UnoType<XIndexReplace>::get());
977 if (_xIndexAccess.is())
978 tmp.push_back(cppu::UnoType<XIndexAccess>::get());
979 if (_xEnumerationAccess.is())
981 if (_xElementAccess.is())
982 tmp.push_back(cppu::UnoType<XElementAccess>::get());
983 // Invocation does not support XInvocation2, if direct object supports
984 // XInvocation, but not XInvocation2.
985 if ((_xDirect.is() && _xDirect2.is()) || (!_xDirect.is() && _xIntrospectionAccess.is()))
986 tmp.push_back(cppu::UnoType<XInvocation2>::get());
987
989 }();
990 return s_types;
991}
992
993Sequence< sal_Int8 > SAL_CALL Invocation_Impl::getImplementationId( )
994{
995 return css::uno::Sequence<sal_Int8>();
996}
997
998namespace {
999
1000class InvocationService
1001 : public WeakImplHelper< XSingleServiceFactory, XServiceInfo >
1002{
1003public:
1004 explicit InvocationService( const Reference<XComponentContext> & xCtx );
1005
1006 // XServiceInfo
1007 OUString SAL_CALL getImplementationName() override;
1008 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
1009 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
1010
1011 // XSingleServiceFactory
1012 Reference<XInterface> SAL_CALL createInstance() override;
1013 Reference<XInterface> SAL_CALL createInstanceWithArguments(
1014 const Sequence<Any>& rArguments ) override;
1015private:
1016 Reference<XComponentContext> mxCtx;
1017 Reference<XMultiComponentFactory> mxSMgr;
1018 Reference<XTypeConverter> xTypeConverter;
1019 Reference<XIntrospection> xIntrospection;
1020 Reference<XIdlReflection> xCoreReflection;
1021};
1022
1023}
1024
1025InvocationService::InvocationService( const Reference<XComponentContext> & xCtx )
1026 : mxCtx( xCtx )
1027 , mxSMgr( xCtx->getServiceManager() )
1028 , xCoreReflection( css::reflection::theCoreReflection::get(mxCtx) )
1029{
1030 xTypeConverter.set(
1031 mxSMgr->createInstanceWithContext( "com.sun.star.script.Converter", xCtx ),
1032 UNO_QUERY );
1033 xIntrospection = theIntrospection::get(xCtx);
1034}
1035
1036// XServiceInfo
1037OUString InvocationService::getImplementationName()
1038{
1039 return "com.sun.star.comp.stoc.Invocation";
1040}
1041
1042// XServiceInfo
1043sal_Bool InvocationService::supportsService(const OUString& ServiceName)
1044{
1045 return cppu::supportsService(this, ServiceName);
1046}
1047
1048// XServiceInfo
1049Sequence< OUString > InvocationService::getSupportedServiceNames()
1050{
1051 return { "com.sun.star.script.Invocation" };
1052}
1053
1054
1055Reference<XInterface> InvocationService::createInstance()
1056{
1057 //TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
1058 return Reference<XInterface>(); // dummy
1059}
1060
1061
1062Reference<XInterface> InvocationService::createInstanceWithArguments(
1063 const Sequence<Any>& rArguments )
1064{
1065 if (rArguments.getLength() == 2)
1066 {
1067 OUString aArg1;
1068 if ((rArguments[1] >>= aArg1) &&
1069 aArg1 == "FromOLE")
1070 {
1071 return Reference< XInterface >
1072 ( *new Invocation_Impl( *rArguments.getConstArray(),
1074 }
1075 }
1076 if (rArguments.getLength() == 1)
1077 {
1078 return Reference< XInterface >
1079 ( *new Invocation_Impl( *rArguments.getConstArray(),
1081 }
1082
1083 //TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
1084 return Reference<XInterface>();
1085}
1086
1087extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1089 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
1090{
1091 return cppu::acquire(new InvocationService(context));
1092}
1093
1094}
1095
1096
1097/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
struct _ADOIndex Index
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
SbMethodRef xMethod
css::uno::Type const & get()
Reference< XNameAccess > _xNameAccess
Definition: invocation.cxx:190
Reference< XIndexAccess > _xIndexAccess
Definition: invocation.cxx:193
Reference< XIntrospectionAccess > _xIntrospectionAccess
Definition: invocation.cxx:185
Reference< XNameContainer > _xNameContainer
Definition: invocation.cxx:188
Reference< XExactName > _xENDirect
Definition: invocation.cxx:198
Reference< XInvocation > _xDirect
Definition: invocation.cxx:182
sal_Int32 nIndex
Definition: invocation.cxx:697
OUString aName
Definition: invocation.cxx:689
Reference< XIntrospection > xIntrospection
Definition: invocation.cxx:177
Reference< XIndexReplace > _xIndexReplace
Definition: invocation.cxx:192
bool mbFromOLE
Definition: invocation.cxx:200
Reference< XExactName > _xENIntrospection
Definition: invocation.cxx:198
Reference< XIndexContainer > _xIndexContainer
Definition: invocation.cxx:191
Reference< XElementAccess > _xElementAccess
Definition: invocation.cxx:195
Mode eMode
Definition: invocation.cxx:693
Reference< XInvocation2 > _xDirect2
Definition: invocation.cxx:183
Reference< XMultiComponentFactory > mxSMgr
Reference< XNameReplace > _xNameReplace
Definition: invocation.cxx:189
Any _aMaterial
Definition: invocation.cxx:180
Reference< XIdlReflection > xCoreReflection
Definition: invocation.cxx:178
Reference< XComponentContext > mxCtx
Reference< XPropertySet > _xPropertySet
Definition: invocation.cxx:184
Reference< XEnumerationAccess > _xEnumerationAccess
Definition: invocation.cxx:194
Reference< XTypeConverter > xTypeConverter
Definition: invocation.cxx:176
uno_Any a
sal_uInt16 nPos
bool hasProperty(const OUString &_rName, const Reference< XPropertySet > &_rxSet)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
Type
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Any SAL_CALL getCaughtException()
Value
int i
css::beans::Optional< css::uno::Any > getValue(std::u16string_view id)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * stoc_InvocationService_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
static Reference< XIdlClass > TypeToIdlClass(const Type &rType, const Reference< XIdlReflection > &xRefl)
Definition: invocation.cxx:64
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
def invoke(object, methodname, argTuple)
Mode
RegError REGISTRY_CALLTYPE setValue(RegKeyHandle hKey, rtl_uString *keyName, RegValueType valueType, RegValue pData, sal_uInt32 valueSize)
unsigned char sal_Bool
Method