Coverage Report

Created: 2025-07-07 10:01

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