LibreOffice Module eventattacher (master) 1
eventattacher.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#include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
20#include <com/sun/star/lang/XServiceInfo.hpp>
21#include <com/sun/star/lang/XInitialization.hpp>
22#include <com/sun/star/beans/IntrospectionException.hpp>
23#include <com/sun/star/beans/theIntrospection.hpp>
24#include <com/sun/star/beans/MethodConcept.hpp>
25#include <com/sun/star/script/CannotConvertException.hpp>
26#include <com/sun/star/script/CannotCreateAdapterException.hpp>
27#include <com/sun/star/script/XEventAttacher2.hpp>
28#include <com/sun/star/script/Converter.hpp>
29#include <com/sun/star/script/XAllListener.hpp>
30#include <com/sun/star/script/InvocationAdapterFactory.hpp>
31#include <com/sun/star/reflection/theCoreReflection.hpp>
32#include <com/sun/star/reflection/XIdlReflection.hpp>
33
34// InvocationToAllListenerMapper
35#include <com/sun/star/script/XInvocation.hpp>
37#include <cppuhelper/weak.hxx>
41
42#include <mutex>
43#include <utility>
44
45namespace com::sun::star::lang { class XMultiServiceFactory; }
46
47using namespace com::sun::star::uno;
48using namespace com::sun::star::registry;
49using namespace com::sun::star::lang;
50using namespace com::sun::star::beans;
51using namespace com::sun::star::script;
52using namespace com::sun::star::reflection;
53using namespace cppu;
54using namespace osl;
55
56
58
59
60// class InvocationToAllListenerMapper
61// helper class to map XInvocation to XAllListener
62
63namespace {
64
65class InvocationToAllListenerMapper : public WeakImplHelper< XInvocation >
66{
67public:
68 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
69 const Reference< XAllListener >& AllListener, Any Helper );
70
71 // XInvocation
72 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() override;
73 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override;
74 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override;
75 virtual Any SAL_CALL getValue(const OUString& PropertyName) override;
76 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override;
77 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override;
78
79private:
83};
84
85}
86
87// Function to replace AllListenerAdapterService::createAllListerAdapter
89(
90 const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory,
91 const Reference< XIdlClass >& xListenerType,
92 const Reference< XAllListener >& xListener,
93 const Any& Helper
94)
95{
97 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
98 {
99 Reference< XInvocation > xInvocationToAllListenerMapper =
100 new InvocationToAllListenerMapper(xListenerType, xListener, Helper);
101 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName());
102 Sequence<Type> arg2 { aListenerType };
103 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, arg2 );
104 }
105 return xAdapter;
106}
107
108
109// InvocationToAllListenerMapper
110InvocationToAllListenerMapper::InvocationToAllListenerMapper
111 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, Any Helper )
112 : m_xAllListener( AllListener )
113 , m_xListenerType( ListenerType )
114 , m_Helper(std::move( Helper ))
115{
116}
117
118
119Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection()
120{
122}
123
124
125Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
127{
128 Any aRet;
129
130 // Check if to firing or approveFiring has to be called
131 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
132 bool bApproveFiring = false;
133 if( !xMethod.is() )
134 return aRet;
135 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
136 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
137 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
138 aExceptionSeq.hasElements() )
139 {
140 bApproveFiring = true;
141 }
142 else
143 {
144 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
145 sal_uInt32 nParamCount = aParamSeq.getLength();
146 if( nParamCount > 1 )
147 {
148 const ParamInfo* pInfo = aParamSeq.getConstArray();
149 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
150 {
151 if( pInfo[ i ].aMode != ParamMode_IN )
152 {
153 bApproveFiring = true;
154 break;
155 }
156 }
157 }
158 }
159
160 AllEventObject aAllEvent;
161 aAllEvent.Source = getXWeak();
162 aAllEvent.Helper = m_Helper;
163 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName());
164 aAllEvent.MethodName = FunctionName;
165 aAllEvent.Arguments = Params;
166 if( bApproveFiring )
167 aRet = m_xAllListener->approveFiring( aAllEvent );
168 else
169 m_xAllListener->firing( aAllEvent );
170 return aRet;
171}
172
173
174void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& )
175{
176}
177
178
179Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& )
180{
181 return Any();
182}
183
184
185sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
186{
188 return xMethod.is();
189}
190
191
192sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
193{
194 Reference< XIdlField > xField = m_xListenerType->getField( Name );
195 return xField.is();
196}
197
198
199// class EventAttacherImpl
200// represents an implementation of the EventAttacher service
201
202namespace {
203
204class EventAttacherImpl : public WeakImplHelper < XEventAttacher2, XInitialization, XServiceInfo >
205{
206public:
207 explicit EventAttacherImpl( const Reference< XComponentContext >& );
208
209 // XServiceInfo
210 virtual OUString SAL_CALL getImplementationName( ) override;
211 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
212 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
213
214 // XInitialization
215 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
216
217 // methods of XEventAttacher
218 virtual Reference< XEventListener > SAL_CALL attachListener(const Reference< XInterface >& xObject,
219 const Reference< XAllListener >& AllListener, const Any& Helper,
220 const OUString& ListenerType, const OUString& AddListenerParam) override;
221 virtual Reference< XEventListener > SAL_CALL attachSingleEventListener(const Reference< XInterface >& xObject,
222 const Reference< XAllListener >& AllListener, const Any& Helper,
223 const OUString& ListenerType, const OUString& AddListenerParam,
224 const OUString& EventMethod) override;
225 virtual void SAL_CALL removeListener(const Reference< XInterface >& xObject,
226 const OUString& ListenerType, const OUString& AddListenerParam,
227 const Reference< XEventListener >& aToRemoveListener) override;
228
229 // XEventAttacher2
230 virtual Sequence< Reference<XEventListener> > SAL_CALL attachMultipleEventListeners(
231 const Reference<XInterface>& xObject, const Sequence<css::script::EventListener>& aListeners ) override;
232
233 // used by FilterAllListener_Impl
235 Reference< XTypeConverter > getConverter();
236
237 friend class FilterAllListenerImpl;
238
239private:
240 static Reference<XEventListener> attachListenerForTarget(
241 const Reference<XIntrospectionAccess>& xAccess,
242 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
243 const Reference<XAllListener>& xAllListener,
244 const Any& aObject,
245 const Any& aHelper,
246 const OUString& aListenerType,
247 const OUString& aAddListenerParam );
248
249 Sequence< Reference<XEventListener> > attachListeners(
250 const Reference<XInterface>& xObject,
251 const Sequence< Reference<XAllListener> >& AllListeners,
252 const Sequence<css::script::EventListener>& aListeners );
253
254private:
255 std::mutex m_aMutex;
257
258 // Save Services
263
264 // needed services
266 Reference< XIntrospection > getIntrospection();
268 Reference< XIdlReflection > getReflection();
270 Reference< XInvocationAdapterFactory2 > getInvocationAdapterService();
271};
272
273}
274
275EventAttacherImpl::EventAttacherImpl( const Reference< XComponentContext >& rxContext )
276 : m_xContext( rxContext )
277{
278}
279
281OUString SAL_CALL EventAttacherImpl::getImplementationName( )
282{
283 return "com.sun.star.comp.EventAttacher";
284}
285
286sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName )
287{
288 return cppu::supportsService(this, ServiceName);
289}
290
291Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames( )
292{
293 return { "com.sun.star.script.EventAttacher" };
294}
295
296void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments)
297{
298 // get services from the argument list
299 for( const Any& arg : Arguments )
300 {
301 if( arg.getValueType().getTypeClass() != TypeClass_INTERFACE )
302 throw IllegalArgumentException();
303
304 // InvocationAdapter service ?
306 arg >>= xALAS;
307 if( xALAS.is() )
308 {
309 std::scoped_lock aGuard( m_aMutex );
311 }
312 // Introspection service ?
314 arg >>= xI;
315 if( xI.is() )
316 {
317 std::scoped_lock aGuard( m_aMutex );
318 m_xIntrospection = xI;
319 }
320 // Reflection service ?
322 arg >>= xIdlR;
323 if( xIdlR.is() )
324 {
325 std::scoped_lock aGuard( m_aMutex );
326 m_xReflection = xIdlR;
327 }
328 // Converter Service ?
330 arg >>= xC;
331 if( xC.is() )
332 {
333 std::scoped_lock aGuard( m_aMutex );
334 m_xConverter = xC;
335 }
336
337 // no right interface
338 if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() )
339 throw IllegalArgumentException();
340 }
341}
342
343
344//*** Private helper methods ***
345Reference< XIntrospection > EventAttacherImpl::getIntrospection()
346{
347 std::scoped_lock aGuard( m_aMutex );
348 if( !m_xIntrospection.is() )
349 {
350 m_xIntrospection = theIntrospection::get( m_xContext );
351 }
352 return m_xIntrospection;
353}
354
355
356//*** Private helper methods ***
357Reference< XIdlReflection > EventAttacherImpl::getReflection()
358{
359 std::scoped_lock aGuard( m_aMutex );
360 if( !m_xReflection.is() )
361 {
362 m_xReflection = theCoreReflection::get(m_xContext);
363 }
364 return m_xReflection;
365}
366
367
368//*** Private helper methods ***
369Reference< XInvocationAdapterFactory2 > EventAttacherImpl::getInvocationAdapterService()
370{
371 std::scoped_lock aGuard( m_aMutex );
373 {
374 m_xInvocationAdapterFactory = InvocationAdapterFactory::create(m_xContext);
375 }
377}
378
379
380//*** Private helper methods ***
381Reference< XTypeConverter > EventAttacherImpl::getConverter()
382{
383 std::scoped_lock aGuard( m_aMutex );
384 if( !m_xConverter.is() )
385 {
386 m_xConverter = Converter::create(m_xContext);
387 }
388 return m_xConverter;
389}
390
391namespace {
392
393// Implementation of an EventAttacher-related AllListeners, which brings
394// a few Events to a general AllListener
395class FilterAllListenerImpl : public WeakImplHelper< XAllListener >
396{
397public:
398 FilterAllListenerImpl( EventAttacherImpl * pEA_, OUString EventMethod_,
399 const Reference< XAllListener >& AllListener_ );
400
401 // XAllListener
402 virtual void SAL_CALL firing(const AllEventObject& Event) override;
403 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) override;
404
405 // XEventListener
406 virtual void SAL_CALL disposing(const EventObject& Source) override;
407
408private:
409 // convert
412 void convertToEventReturn( Any & rRet, const Type& rRetType );
413
414 EventAttacherImpl * m_pEA;
417};
418
419}
420
421FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, OUString EventMethod_,
422 const Reference< XAllListener >& AllListener_ )
423 : m_pEA( pEA_ )
424 , m_EventMethod(std::move( EventMethod_ ))
425 , m_AllListener( AllListener_ )
426{
427}
428
429
430void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event)
431{
432 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
433 m_AllListener->firing( Event );
434}
435
436// Convert to the standard event return
437void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType )
438{
439 // no return value? Set to the specified values
440 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
441 {
442 switch( rRetType.getTypeClass() )
443 {
444 case TypeClass_INTERFACE:
445 {
446 rRet <<= Reference< XInterface >();
447 }
448 break;
449
450 case TypeClass_BOOLEAN:
451 rRet <<= true;
452 break;
453
454 case TypeClass_STRING:
455 rRet <<= OUString();
456 break;
457
458 case TypeClass_FLOAT: rRet <<= float(0); break;
459 case TypeClass_DOUBLE: rRet <<= 0.0; break;
460 case TypeClass_BYTE: rRet <<= sal_uInt8( 0 ); break;
461 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
462 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
463 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
464 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
465 default:
466 break;
467 }
468 }
469 else if( !rRet.getValueType().equals( rRetType ) )
470 {
472 if( !xConverter.is() )
473 throw CannotConvertException(); // TODO TypeConversionException
474 rRet = xConverter->convertTo( rRet, rRetType );
475 }
476}
477
478
479Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
480{
481 Any aRet;
482
483 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
484 aRet = m_AllListener->approveFiring( Event );
485 else
486 {
487 // Convert to the standard event return
488 try
489 {
490 Reference< XIdlClass > xListenerType = m_pEA->getReflection()->
491 forName( Event.ListenerType.getTypeName() );
492 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
493 if( xMeth.is() )
494 {
495 Reference< XIdlClass > xRetType = xMeth->getReturnType();
496 Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
497 convertToEventReturn( aRet, aRetType );
498 }
499 }
500 catch( const CannotConvertException& )
501 {
502 css::uno::Any anyEx = cppu::getCaughtException();
503 throw InvocationTargetException( OUString(), Reference< XInterface >(), anyEx );
504 }
505 }
506 return aRet;
507}
508
509
510void FilterAllListenerImpl::disposing(const EventObject& )
511{
512 // TODO: ???
513}
514
515
516Reference< XEventListener > EventAttacherImpl::attachListener
517(
518 const Reference< XInterface >& xObject,
519 const Reference< XAllListener >& AllListener,
520 const Any& Helper,
521 const OUString& ListenerType,
522 const OUString& AddListenerParam
523)
524{
525 if( !xObject.is() || !AllListener.is() )
526 throw IllegalArgumentException();
527
528 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
529 if( !xInvocationAdapterFactory.is() )
530 throw ServiceNotRegisteredException();
531
532 Reference< XIdlReflection > xReflection = getReflection();
533 if( !xReflection.is() )
534 throw ServiceNotRegisteredException();
535
536 // Sign in, Call the fitting addListener method
537 // First Introspection, as the Methods can be analyzed in the same way
538 // For better performance it is implemented here again or make the Impl-Method
539 // of the Introspection configurable for this purpose.
540 Reference< XIntrospection > xIntrospection = getIntrospection();
541 if( !xIntrospection.is() )
543
544 // Inspect Introspection
545 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
546
547 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
548 if( !xAccess.is() )
550
551 return attachListenerForTarget(
552 xAccess, xInvocationAdapterFactory, AllListener, aObjAny, Helper,
553 ListenerType, AddListenerParam);
554}
555
556Reference<XEventListener> EventAttacherImpl::attachListenerForTarget(
557 const Reference<XIntrospectionAccess>& xAccess,
558 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
559 const Reference<XAllListener>& xAllListener,
560 const Any& aObject,
561 const Any& aHelper,
562 const OUString& aListenerType,
563 const OUString& aAddListenerParam)
564{
566
567 // Construct the name of the addListener-Method.
568 sal_Int32 nIndex = aListenerType.lastIndexOf('.');
569 // set index to the interface name without package name
570 if( nIndex == -1 )
571 // not found
572 nIndex = 0;
573 else
574 nIndex++;
575
576 OUString aListenerName = (!aListenerType.isEmpty() && aListenerType[nIndex] == 'X') ? aListenerType.copy(nIndex+1) : aListenerType;
577 OUString aAddListenerName = "add" + aListenerName;
578
579 // Send Methods to the correct addListener-Method
580 const Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
581 for (const Reference< XIdlMethod >& rxMethod : aMethodSeq)
582 {
583 // Is it the correct method?
584 OUString aMethName = rxMethod->getName();
585
586 if (aAddListenerName != aMethName)
587 continue;
588
589 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
590 sal_uInt32 nParamCount = params.getLength();
591
592 Reference< XIdlClass > xListenerType;
593 if( nParamCount == 1 )
594 xListenerType = params.getConstArray()[0];
595 else if( nParamCount == 2 )
596 xListenerType = params.getConstArray()[1];
597
598 // Request Adapter for the actual Listener type
600 xInvocationAdapterFactory, xListenerType, xAllListener, aHelper );
601
602 if( !xAdapter.is() )
603 throw CannotCreateAdapterException();
604 xRet.set( xAdapter, UNO_QUERY );
605
606 // Just the Listener as parameter?
607 if( nParamCount == 1 )
608 {
610 args.getArray()[0] <<= xAdapter;
611 try
612 {
613 rxMethod->invoke( aObject, args );
614 }
615 catch( const InvocationTargetException& )
616 {
617 throw IntrospectionException();
618 }
619 }
620 // Else, pass the other parameter now
621 else if( nParamCount == 2 )
622 {
624 Any* pAnys = args.getArray();
625
626 // Check the type of the 1st parameter
627 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
628 if( xParamClass->getTypeClass() == TypeClass_STRING )
629 {
630 pAnys[0] <<= aAddListenerParam;
631 }
632
633 // 2nd Parameter == Listener? TODO: Test!
634 pAnys[1] <<= xAdapter;
635
636 // TODO: Convert String -> ?
637 // else
638 try
639 {
640 rxMethod->invoke( aObject, args );
641 }
642 catch( const InvocationTargetException& )
643 {
644 throw IntrospectionException();
645 }
646 }
647 break;
648 // else...
649 // Anything else is not supported
650 }
651
652 return xRet;
653}
654
655Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
656 const Reference<XInterface>& xObject,
657 const Sequence< Reference<XAllListener> >& AllListeners,
658 const Sequence<css::script::EventListener>& aListeners )
659{
660 sal_Int32 nCount = aListeners.getLength();
661 if (nCount != AllListeners.getLength())
662 // This is a prerequisite!
663 throw RuntimeException();
664
665 if (!xObject.is())
666 throw IllegalArgumentException();
667
668 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
669 if( !xInvocationAdapterFactory.is() )
670 throw ServiceNotRegisteredException();
671
672 Reference< XIdlReflection > xReflection = getReflection();
673 if( !xReflection.is() )
674 throw ServiceNotRegisteredException();
675
676 // Sign in, Call the fitting addListener method
677 // First Introspection, as the Methods can be analyzed in the same way
678 // For better performance it is implemented here again or make the Impl-Method
679 // of the Introspection configurable for this purpose.
680 Reference< XIntrospection > xIntrospection = getIntrospection();
681 if( !xIntrospection.is() )
683
684 // Inspect Introspection
685 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get() );
686
687 Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
688 if (!xAccess.is())
690
692 Reference<XEventListener>* pArray = aRet.getArray();
693
694 for (sal_Int32 i = 0; i < nCount; ++i)
695 {
696 pArray[i] = attachListenerForTarget(
697 xAccess, xInvocationAdapterFactory, AllListeners[ i ],
698 aObjAny, aListeners[i].Helper, aListeners[i].ListenerType, aListeners[i].AddListenerParam);
699 }
700
701 return aRet;
702}
703
704// XEventAttacher
705Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
706(
707 const Reference< XInterface >& xObject,
708 const Reference< XAllListener >& AllListener,
709 const Any& Helper,
710 const OUString& ListenerType,
711 const OUString& AddListenerParam,
712 const OUString& EventMethod
713)
714{
715 // Subscribe FilterListener
716 Reference<XAllListener> aFilterListener
717 = new FilterAllListenerImpl(this, EventMethod, AllListener);
718 return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
719}
720
721// XEventAttacher
722void EventAttacherImpl::removeListener
723(
724 const Reference< XInterface >& xObject,
725 const OUString& ListenerType,
726 const OUString& AddListenerParam,
727 const Reference< XEventListener >& aToRemoveListener
728)
729{
730 if( !xObject.is() || !aToRemoveListener.is() )
731 throw IllegalArgumentException();
732
733 Reference< XIdlReflection > xReflection = getReflection();
734 if( !xReflection.is() )
735 throw IntrospectionException();
736
737 // Sign off, Call the fitting removeListener method
738 // First Introspection, as the Methods can be analyzed in the same way
739 // For better performance it is implemented here again or make the Impl-Method
740 // of the Introspection configurable for this purpose.
741 Reference< XIntrospection > xIntrospection = getIntrospection();
742 if( !xIntrospection.is() )
743 throw IntrospectionException();
744
745 //Inspect Introspection
746 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
747 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
748 if( !xAccess.is() )
749 throw IntrospectionException();
750
751 // Create name of the removeListener-Method
752 OUString aRemoveListenerName;
753 OUString aListenerName( ListenerType );
754 sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
755 // set index to the interface name without package name
756 if( nIndex == -1 )
757 // not found
758 nIndex = 0;
759 else
760 nIndex++;
761 if( aListenerName[nIndex] == 'X' )
762 // erase X from the interface name
763 aListenerName = aListenerName.copy( nIndex +1 );
764 aRemoveListenerName = "remove" + aListenerName;
765
766 // Search methods for the correct removeListener method
767 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
768 sal_uInt32 i, nLen = aMethodSeq.getLength();
769 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
770 for( i = 0 ; i < nLen ; i++ )
771 {
772 // Call Method
773 const Reference< XIdlMethod >& rxMethod = pMethods[i];
774
775 // Is it the right method?
776 if( aRemoveListenerName == rxMethod->getName() )
777 {
778 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
779 sal_uInt32 nParamCount = params.getLength();
780
781 // Just the Listener as parameter?
782 if( nParamCount == 1 )
783 {
785 args.getArray()[0] <<= aToRemoveListener;
786 try
787 {
788 rxMethod->invoke( aObjAny, args );
789 }
790 catch( const InvocationTargetException& )
791 {
792 throw IntrospectionException();
793 }
794 }
795 // Else pass the other parameter
796 else if( nParamCount == 2 )
797 {
799 Any* pAnys = args.getArray();
800
801 // Check the type of the 1st parameter
802 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
803 if( xParamClass->getTypeClass() == TypeClass_STRING )
804 pAnys[0] <<= AddListenerParam;
805
806 // 2nd parameter == Listener? TODO: Test!
807 pAnys[1] <<= aToRemoveListener;
808
809 // TODO: Convert String -> ?
810 // else
811 try
812 {
813 rxMethod->invoke( aObjAny, args );
814 }
815 catch( const InvocationTargetException& )
816 {
817 throw IntrospectionException();
818 }
819 }
820 break;
821 }
822 }
823}
824
825Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
826 const Reference<XInterface>& xObject, const Sequence<css::script::EventListener>& aListeners )
827{
828 sal_Int32 nCount = aListeners.getLength();
829 Sequence< Reference<XAllListener> > aFilterListeners(nCount);
830 auto aFilterListenersRange = asNonConstRange(aFilterListeners);
831 for (sal_Int32 i = 0; i < nCount; ++i)
832 {
833 aFilterListenersRange[i]
834 = new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener);
835 }
836
837 return attachListeners(xObject, aFilterListeners, aListeners);
838}
839
840}
841
842extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
844 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
845{
846 return cppu::acquire(new comp_EventAttacher::EventAttacherImpl(context));
847}
848
849
850/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SbMethodRef xMethod
bool is() const
int nCount
Listeners aListeners
std::mutex m_aMutex
OUString m_EventMethod
Reference< XTypeConverter > m_xConverter
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * eventattacher_EventAttacher(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Reference< XIdlReflection > m_xReflection
Reference< XIntrospection > m_xIntrospection
Reference< XIdlClass > m_xListenerType
EventAttacherImpl * m_pEA
Reference< XInvocationAdapterFactory2 > m_xInvocationAdapterFactory
Reference< XAllListener > m_AllListener
Reference< XComponentContext > m_xContext
Any m_Helper
Reference< XAllListener > m_xAllListener
Reference< XTypeConverter > xConverter
sal_Int32 nIndex
Reference< XIntrospection > xIntrospection
void removeListener(const InterfaceRef &xObject, const css::uno::Reference< css::lang::XEventListener > &xListener)
static Reference< XInterface > createAllListenerAdapter(const Reference< XInvocationAdapterFactory2 > &xInvocationAdapterFactory, const Reference< XIdlClass > &xListenerType, const Reference< XAllListener > &xListener, const Any &Helper)
bool hasProperty(const OUString &_rName, const Reference< XPropertySet > &_rxSet)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
Type
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)
args
def invoke(object, methodname, argTuple)
RegError REGISTRY_CALLTYPE setValue(RegKeyHandle hKey, rtl_uString *keyName, RegValueType valueType, RegValue pData, sal_uInt32 valueSize)
OUString Name
unsigned char sal_uInt8
unsigned char sal_Bool