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