1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #include <osl/diagnose.h>
28 #include <com/sun/star/lang/XServiceInfo.hpp>
29 #include <com/sun/star/lang/XInitialization.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
32 #include <com/sun/star/registry/XRegistryKey.hpp>
33 #include <com/sun/star/beans/XIntrospection.hpp>
34 #include <com/sun/star/beans/MethodConcept.hpp>
35 #include <com/sun/star/script/XEventAttacher.hpp>
36 #include <com/sun/star/script/XTypeConverter.hpp>
37 #include <com/sun/star/script/XAllListener.hpp>
38 #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
39 #include <com/sun/star/reflection/XIdlReflection.hpp>
40 
41 // InvocationToAllListenerMapper
42 #include <com/sun/star/script/XInvocation.hpp>
43 #include <cppuhelper/weak.hxx>
44 #include <cppuhelper/factory.hxx>
45 #include <cppuhelper/implbase1.hxx>
46 #include <cppuhelper/implbase3.hxx>
47 
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::registry;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::beans;
52 using namespace com::sun::star::script;
53 using namespace com::sun::star::reflection;
54 using namespace cppu;
55 using namespace osl;
56 using namespace rtl;
57 
58 
59 #define SERVICENAME "com.sun.star.script.EventAttacher"
60 #define IMPLNAME	"com.sun.star.comp.EventAttacher"
61 
62 namespace comp_EventAttacher {
63 
64 //*************************************************************************
65 //  class InvocationToAllListenerMapper
66 //  helper class to map XInvocation to XAllListener
67 //*************************************************************************
68 class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation >
69 {
70 public:
71 	InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
72 		const Reference< XAllListener >& AllListener, const Any& Helper );
73 
74 	// XInvocation
75     virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException );
76     virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
77 		throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException );
78     virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value)
79 		throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException );
80     virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException );
81     virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException );
82     virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException );
83 
84 private:
85 	Reference< XIdlReflection >  m_xCoreReflection;
86 	Reference< XAllListener >	 m_xAllListener;
87 	Reference< XIdlClass >  	 m_xListenerType;
88 	Any 						 m_Helper;
89 };
90 
91 
92 // Function to replace AllListenerAdapterService::createAllListerAdapter
93 Reference< XInterface > createAllListenerAdapter
94 (
95 	const Reference< XInvocationAdapterFactory >& xInvocationAdapterFactory,
96 	const Reference< XIdlClass >& xListenerType,
97 	const Reference< XAllListener >& xListener,
98 	const Any& Helper
99 )
100 {
101 	Reference< XInterface > xAdapter;
102 	if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
103 	{
104 	   Reference< XInvocation >	xInvocationToAllListenerMapper =
105 			(XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper );
106 		Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName());
107 		xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, aListenerType );
108 	}
109 	return xAdapter;
110 }
111 
112 
113 //--------------------------------------------------------------------------------------------------
114 // InvocationToAllListenerMapper
115 InvocationToAllListenerMapper::InvocationToAllListenerMapper
116 	( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
117 		: m_xAllListener( AllListener )
118 		, m_xListenerType( ListenerType )
119 		, m_Helper( Helper )
120 {
121 }
122 
123 //*************************************************************************
124 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void)
125 	throw( RuntimeException )
126 {
127 	return Reference< XIntrospectionAccess >();
128 }
129 
130 //*************************************************************************
131 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
132 	Sequence< sal_Int16 >& , Sequence< Any >& )
133 		throw( IllegalArgumentException, CannotConvertException,
134 		InvocationTargetException, RuntimeException )
135 {
136 	Any aRet;
137 
138 	// Check if to firing or approveFiring has to be called
139 	Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
140 	sal_Bool bApproveFiring = sal_False;
141 	if( !xMethod.is() )
142 		return aRet;
143     Reference< XIdlClass > xReturnType = xMethod->getReturnType();
144     Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
145 	if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
146 		aExceptionSeq.getLength() > 0 )
147 	{
148 		bApproveFiring = sal_True;
149 	}
150 	else
151 	{
152 	    Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
153 		sal_uInt32 nParamCount = aParamSeq.getLength();
154 		if( nParamCount > 1 )
155 		{
156 			const ParamInfo* pInfos = aParamSeq.getConstArray();
157 			for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
158 			{
159 				if( pInfos[ i ].aMode != ParamMode_IN )
160 				{
161 					bApproveFiring = sal_True;
162 					break;
163 				}
164 			}
165 		}
166 	}
167 
168     AllEventObject aAllEvent;
169     aAllEvent.Source = (OWeakObject*) this;
170     aAllEvent.Helper = m_Helper;
171     aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName());
172     aAllEvent.MethodName = FunctionName;
173     aAllEvent.Arguments = Params;
174 	if( bApproveFiring )
175 		aRet = m_xAllListener->approveFiring( aAllEvent );
176 	else
177 		m_xAllListener->firing( aAllEvent );
178 	return aRet;
179 }
180 
181 //*************************************************************************
182 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& )
183 	throw( UnknownPropertyException, CannotConvertException,
184 		   InvocationTargetException, RuntimeException )
185 {
186 }
187 
188 //*************************************************************************
189 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& )
190 	throw( UnknownPropertyException, RuntimeException )
191 {
192 	return Any();
193 }
194 
195 //*************************************************************************
196 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
197 	throw( RuntimeException )
198 {
199 	Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
200 	return xMethod.is();
201 }
202 
203 //*************************************************************************
204 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
205 	throw( RuntimeException )
206 {
207 	Reference< XIdlField > xField = m_xListenerType->getField( Name );
208 	return xField.is();
209 }
210 
211 //*************************************************************************
212 //  class EventAttacherImpl
213 //  represents an implementation of the EventAttacher service
214 //*************************************************************************
215 class EventAttacherImpl : public WeakImplHelper3 < XEventAttacher, XInitialization, XServiceInfo >
216 {
217 public:
218 	EventAttacherImpl( const Reference< XMultiServiceFactory >& );
219 	~EventAttacherImpl();
220 
221     // XServiceInfo
222     virtual OUString SAL_CALL getImplementationName(  ) throw(RuntimeException);
223     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
224     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw(RuntimeException);
225     static OUString SAL_CALL getImplementationName_Static(  );
226     static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static(  );
227 
228 	// XInitialization
229     virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
230 		throw( Exception, RuntimeException);
231 
232 	// Methoden von XEventAttacher
233     virtual Reference< XEventListener > SAL_CALL attachListener(const Reference< XInterface >& xObject,
234 			const Reference< XAllListener >& AllListener, const Any& Helper,
235 			const OUString& ListenerType, const OUString& AddListenerParam)
236 		throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
237     virtual Reference< XEventListener > SAL_CALL attachSingleEventListener(const Reference< XInterface >& xObject,
238 			const Reference< XAllListener >& AllListener, const Any& Helper,
239 			const OUString& ListenerType, const OUString& AddListenerParam,
240 			const OUString& EventMethod)
241 		throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
242     virtual void SAL_CALL removeListener(const Reference< XInterface >& xObject,
243 			const OUString& ListenerType, const OUString& AddListenerParam,
244 			const Reference< XEventListener >& aToRemoveListener)
245 		throw( IllegalArgumentException, IntrospectionException, RuntimeException );
246 
247 	// used by FilterAllListener_Impl
248 	Reference< XTypeConverter > getConverter() throw( Exception );
249 
250 	friend class FilterAllListenerImpl;
251 private:
252 	Mutex								m_aMutex;
253 	Reference< XMultiServiceFactory >	m_xSMgr;
254 
255 	// Services merken
256 	Reference< XIntrospection >				m_xIntrospection;
257 	Reference< XIdlReflection >				m_xReflection;
258 	Reference< XTypeConverter >				m_xConverter;
259 	Reference< XInvocationAdapterFactory >	m_xInvocationAdapterFactory;
260 
261 	// needed services
262 	Reference< XIntrospection >				getIntrospection() throw( Exception );
263 	Reference< XIdlReflection >				getReflection() throw( Exception );
264 	Reference< XInvocationAdapterFactory >	getInvocationAdapterService() throw( Exception );
265 };
266 
267 
268 //*************************************************************************
269 EventAttacherImpl::EventAttacherImpl( const Reference< XMultiServiceFactory >& rSMgr )
270 	: m_xSMgr( rSMgr )
271 {
272 }
273 
274 //*************************************************************************
275 EventAttacherImpl::~EventAttacherImpl()
276 {
277 }
278 
279 //*************************************************************************
280 Reference< XInterface > SAL_CALL EventAttacherImpl_CreateInstance( const Reference< XMultiServiceFactory >& rSMgr ) throw( Exception )
281 {
282 	Reference< XInterface >	xRet;
283 	XEventAttacher *pEventAttacher = (XEventAttacher*) new EventAttacherImpl(rSMgr);
284 
285 	if (pEventAttacher)
286 	{
287 		xRet = Reference<XInterface>::query(pEventAttacher);
288 	}
289 
290 	return xRet;
291 }
292 
293 //*************************************************************************
294 OUString SAL_CALL EventAttacherImpl::getImplementationName(  )
295 	throw(RuntimeException)
296 {
297 	return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
298 }
299 
300 //*************************************************************************
301 sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName )
302 	throw(RuntimeException)
303 {
304 	Sequence< OUString > aSNL = getSupportedServiceNames();
305 	const OUString * pArray = aSNL.getArray();
306 	for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
307 		if( pArray[i] == ServiceName )
308 			return sal_True;
309 	return sal_False;
310 }
311 
312 //*************************************************************************
313 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames(  )
314 	throw(RuntimeException)
315 {
316 	return getSupportedServiceNames_Static();
317 }
318 
319 //*************************************************************************
320 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames_Static(  )
321 {
322 	OUString aStr( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME ) );
323 	return Sequence< OUString >( &aStr, 1 );
324 }
325 
326 //*************************************************************************
327 void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments) throw( Exception, RuntimeException )
328 {
329 	// get services from the argument list
330 	const Any * pArray = Arguments.getConstArray();
331 	for( sal_Int32 i = 0; i < Arguments.getLength(); i++ )
332 	{
333 		if( pArray[i].getValueType().getTypeClass() != TypeClass_INTERFACE )
334 			throw IllegalArgumentException();
335 
336 		// InvocationAdapter service ?
337 		Reference< XInvocationAdapterFactory > xALAS;
338 		pArray[i] >>= xALAS;
339 		if( xALAS.is() )
340 		{
341 			Guard< Mutex > aGuard( m_aMutex );
342 			m_xInvocationAdapterFactory = xALAS;
343 		}
344 		// Introspection service ?
345 		Reference< XIntrospection > xI;
346 		pArray[i] >>= xI;
347 		if( xI.is() )
348 		{
349 			Guard< Mutex > aGuard( m_aMutex );
350 			m_xIntrospection = xI;
351 		}
352 		// Reflection service ?
353 		Reference< XIdlReflection > xIdlR;
354 		pArray[i] >>= xIdlR;
355 		if( xIdlR.is() )
356 		{
357 			Guard< Mutex > aGuard( m_aMutex );
358 			m_xReflection = xIdlR;
359 		}
360 		// Converter Service ?
361 		Reference< XTypeConverter > xC;
362 		pArray[i] >>= xC;
363 		if( xC.is() )
364 		{
365 			Guard< Mutex > aGuard( m_aMutex );
366 			m_xConverter = xC;
367 		}
368 
369 		// no right interface
370 		if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() )
371 			throw IllegalArgumentException();
372 	}
373 }
374 
375 //*************************************************************************
376 //*** Private Hilfs-Methoden ***
377 Reference< XIntrospection > EventAttacherImpl::getIntrospection() throw( Exception )
378 {
379 	Guard< Mutex > aGuard( m_aMutex );
380 	// Haben wir den Service schon? Sonst anlegen
381 	if( !m_xIntrospection.is() )
382 	{
383 		Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString::createFromAscii("com.sun.star.beans.Introspection") ) );
384 		m_xIntrospection = Reference< XIntrospection >( xIFace, UNO_QUERY );
385 	}
386 	return m_xIntrospection;
387 }
388 
389 //*************************************************************************
390 //*** Private Hilfs-Methoden ***
391 Reference< XIdlReflection > EventAttacherImpl::getReflection() throw( Exception )
392 {
393 	Guard< Mutex > aGuard( m_aMutex );
394 	// Haben wir den Service schon? Sonst anlegen
395 	if( !m_xReflection.is() )
396 	{
397 		Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString::createFromAscii("com.sun.star.reflection.CoreReflection") ) );
398 		m_xReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY);
399 	}
400 	return m_xReflection;
401 }
402 
403 //*************************************************************************
404 //*** Private Hilfs-Methoden ***
405 Reference< XInvocationAdapterFactory > EventAttacherImpl::getInvocationAdapterService() throw( Exception )
406 {
407 	Guard< Mutex > aGuard( m_aMutex );
408 	// Haben wir den Service schon? Sonst anlegen
409 	if( !m_xInvocationAdapterFactory.is() )
410 	{
411 		Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString::createFromAscii("com.sun.star.script.InvocationAdapterFactory") ) );
412 		m_xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >( xIFace, UNO_QUERY );
413 	}
414 	return m_xInvocationAdapterFactory;
415 }
416 
417 
418 //*************************************************************************
419 //*** Private Hilfs-Methoden ***
420 Reference< XTypeConverter > EventAttacherImpl::getConverter() throw( Exception )
421 {
422 	Guard< Mutex > aGuard( m_aMutex );
423 	// Haben wir den Service schon? Sonst anlegen
424 	if( !m_xConverter.is() )
425 	{
426 		Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString::createFromAscii("com.sun.star.script.Converter") ) );
427 		m_xConverter = Reference< XTypeConverter >( xIFace, UNO_QUERY );
428 	}
429 	return m_xConverter;
430 }
431 
432 //------------------------------------------------------------------------
433 //------------------------------------------------------------------------
434 //------------------------------------------------------------------------
435 // Implementation eines EventAttacher-bezogenen AllListeners, der
436 // nur einzelne Events an einen allgemeinen AllListener weiterleitet
437 class FilterAllListenerImpl : public WeakImplHelper1< XAllListener  >
438 {
439 public:
440 	FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
441 						   const Reference< XAllListener >& AllListener_ );
442 
443 	// XAllListener
444     virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException );
445     virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException );
446 
447 	// XEventListener
448     virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
449 
450 private:
451 	// convert
452 	void convertToEventReturn( Any & rRet, const Type& rRetType )
453 			throw( CannotConvertException );
454 
455 	EventAttacherImpl *			m_pEA;
456 	Reference< XInterface >		m_xEAHold;
457 	OUString					m_EventMethod;
458 	Reference< XAllListener > 	m_AllListener;
459 };
460 
461 //*************************************************************************
462 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
463 											  const Reference< XAllListener >& AllListener_ )
464 		: m_pEA( pEA_ )
465 		, m_xEAHold( *pEA_ )
466 		, m_EventMethod( EventMethod_ )
467 		, m_AllListener( AllListener_ )
468 {
469 }
470 
471 //*************************************************************************
472 void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event)
473 	throw( RuntimeException )
474 {
475 	// Nur durchreichen, wenn es die richtige Methode ist
476 	if( Event.MethodName == m_EventMethod && m_AllListener.is() )
477 		m_AllListener->firing( Event );
478 }
479 
480 //*************************************************************************
481 // Convert to the standard event return
482 void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType )
483 	throw( CannotConvertException )
484 {
485 	// no return value? Set to the specified values
486 	if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
487 	{
488 		switch( rRetType.getTypeClass()  )
489 		{
490 			case TypeClass_INTERFACE:
491 				{
492 				rRet <<= Reference< XInterface >();
493 				}
494 				break;
495 
496 			case TypeClass_BOOLEAN:
497 				rRet <<= sal_True;
498 				break;
499 
500 			case TypeClass_STRING:
501 				rRet <<= OUString();
502 				break;
503 
504 			case TypeClass_FLOAT:			rRet <<= float(0);	break;
505 			case TypeClass_DOUBLE:			rRet <<= double(0.0);	break;
506 			case TypeClass_BYTE:			rRet <<= sal_uInt8( 0 );	break;
507 			case TypeClass_SHORT:			rRet <<= sal_Int16( 0 );	break;
508 			case TypeClass_LONG:			rRet <<= sal_Int32( 0 );	break;
509 			case TypeClass_UNSIGNED_SHORT:	rRet <<= sal_uInt16( 0 );	break;
510 			case TypeClass_UNSIGNED_LONG:	rRet <<= sal_uInt32( 0 );	break;
511                      default:
512 			break;
513 		}
514 	}
515 	else if( !rRet.getValueType().equals( rRetType ) )
516 	{
517 		Reference< XTypeConverter > xConverter = m_pEA->getConverter();
518 		if( xConverter.is() )
519 			rRet = xConverter->convertTo( rRet, rRetType );
520 		else
521 			throw CannotConvertException(); // TODO TypeConversionException
522 	}
523 }
524 
525 //*************************************************************************
526 Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
527 	throw( InvocationTargetException, RuntimeException )
528 {
529 	Any aRet;
530 
531 	// Nur durchreichen, wenn es die richtige Methode ist
532 	if( Event.MethodName == m_EventMethod && m_AllListener.is() )
533 		aRet = m_AllListener->approveFiring( Event );
534 	else
535 	{
536 		// Convert to the standard event return
537 		try
538 		{
539 			Reference< XIdlClass > xListenerType = m_pEA->getReflection()->
540 						forName( Event.ListenerType.getTypeName() );
541 			Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
542 			if( xMeth.is() )
543 			{
544 				Reference< XIdlClass > xRetType = xMeth->getReturnType();
545 				Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
546 				convertToEventReturn( aRet, aRetType );
547 			}
548 		}
549 		catch( CannotConvertException& e )
550 		{
551 			throw InvocationTargetException( OUString(), Reference< XInterface >(), Any(&e, ::getCppuType( (CannotConvertException*)0)) );
552 		}
553 	}
554 	return aRet;
555 }
556 
557 //*************************************************************************
558 void FilterAllListenerImpl::disposing(const EventObject& )
559 	throw( RuntimeException )
560 {
561 	// TODO: ???
562 }
563 
564 
565 //*************************************************************************
566 Reference< XEventListener > EventAttacherImpl::attachListener
567 (
568 	const Reference< XInterface >& xObject,
569 	const Reference< XAllListener >& AllListener,
570 	const Any& Helper,
571 	const OUString& ListenerType,
572 	const OUString& AddListenerParam
573 )
574 	throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
575 {
576 	if( !xObject.is() || !AllListener.is() )
577 		throw IllegalArgumentException();
578 
579 	Reference< XEventListener > xRet = NULL;
580 
581 	// InvocationAdapterService holen
582 	Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService();
583 	if( !xInvocationAdapterFactory.is() )
584 		throw ServiceNotRegisteredException();
585 
586 	// Listener-Klasse per Reflection besorgen
587 	Reference< XIdlReflection > xReflection = getReflection();
588 	if( !xReflection.is() )
589 		throw ServiceNotRegisteredException();
590 
591 	// Anmelden, dazu passende addListener-Methode aufrufen
592 	// Zunaechst ueber Introspection gehen, da die Methoden in der gleichen
593 	// Weise analysiert werden koennen. Fuer bessere Performance entweder
594 	// hier nochmal implementieren oder die Impl-Methode der Introspection
595 	// fuer diesen Zweck konfigurierbar machen.
596 
597 	// Introspection-Service holen
598 	Reference< XIntrospection > xIntrospection = getIntrospection();
599 	if( !xIntrospection.is() )
600 		return xRet;
601 
602 	// und unspecten
603 	Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) );
604 
605 	Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
606 	if( !xAccess.is() )
607 		return xRet;
608 
609 	// Name der addListener-Methode zusammenbasteln
610 	OUString aAddListenerName;
611 	OUString aListenerName( ListenerType );
612 	sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
613 	// set index to the interface name without package name
614 	if( nIndex == -1 )
615 		// not found
616 		nIndex = 0;
617 	else
618 		nIndex++;
619 	if( aListenerName[nIndex] == 'X' )
620 		// erase X from the interface name
621 		aListenerName = aListenerName.copy( nIndex +1 );
622 	aAddListenerName = OUString( RTL_CONSTASCII_USTRINGPARAM( "add" ) ) + aListenerName;
623 
624 	// Methoden nach der passenden addListener-Methode durchsuchen
625 	Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
626 	sal_uInt32 i, nLen = aMethodSeq.getLength();
627 	const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
628 
629 	for( i = 0 ; i < nLen ; i++ )
630 	{
631 		// Methode ansprechen
632 		const Reference< XIdlMethod >& rxMethod = pMethods[i];
633 
634 		// Ist es die richtige Methode?
635 		OUString aMethName = rxMethod->getName();
636 
637 		if( aAddListenerName == aMethName )
638 		{
639 			Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
640 			sal_uInt32 nParamCount = params.getLength();
641 
642 			Reference< XIdlClass > xListenerType;
643 			if( nParamCount == 1 )
644 				xListenerType = params.getConstArray()[0];
645 			else if( nParamCount == 2 )
646 				xListenerType = params.getConstArray()[1];
647 
648 			// Adapter zum eigentlichen Listener-Typ anfordern
649 			Reference< XInterface > xAdapter = createAllListenerAdapter
650 				( xInvocationAdapterFactory, xListenerType, AllListener, Helper );
651 
652 			if( !xAdapter.is() )
653 				throw CannotCreateAdapterException();
654 			xRet = Reference< XEventListener >( xAdapter, UNO_QUERY );
655 
656 
657 			// Nur der Listener als Parameter?
658 			if( nParamCount == 1 )
659 			{
660 				Sequence< Any > args( 1 );
661 				args.getArray()[0] <<= xAdapter;
662 				try
663 				{
664 					rxMethod->invoke( aObjAny, args );
665 				}
666 				catch( InvocationTargetException& )
667 				{
668 					throw IntrospectionException();
669 				}
670 			}
671 			// Sonst den Zusatzparameter mit uebergeben
672 			else if( nParamCount == 2 )
673 			{
674 				Sequence< Any > args( 2 );
675 				Any* pAnys = args.getArray();
676 
677 				// Typ des 1. Parameters pruefen
678 				Reference< XIdlClass > xParamClass = params.getConstArray()[0];
679 				if( xParamClass->getTypeClass() == TypeClass_STRING )
680 				{
681 					pAnys[0] <<= AddListenerParam;
682 				}
683 
684 				// 2. Parameter == Listener? TODO: Pruefen!
685 				pAnys[1] <<= xAdapter;
686 
687 				// TODO: Konvertierung String -> ?
688 				// else
689 				try
690 				{
691 					rxMethod->invoke( aObjAny, args );
692 				}
693 				catch( InvocationTargetException& )
694 				{
695 					throw IntrospectionException();
696 				}
697 			}
698 			break;
699 			// else...
700 			// Alles andere wird nicht unterstuetzt
701 		}
702 	}
703 
704 	return xRet;
705 }
706 
707 // XEventAttacher
708 Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
709 (
710 	const Reference< XInterface >& xObject,
711 	const Reference< XAllListener >& AllListener,
712 	const Any& Helper,
713 	const OUString& ListenerType,
714 	const OUString& AddListenerParam,
715 	const OUString& EventMethod
716 )
717 	throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
718 {
719 	// FilterListener anmelden
720 	Reference< XAllListener > aFilterListener = (XAllListener*)
721 		new FilterAllListenerImpl( this, EventMethod, AllListener );
722 	return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
723 }
724 
725 // XEventAttacher
726 void EventAttacherImpl::removeListener
727 (
728 	const Reference< XInterface >& xObject,
729 	const OUString& ListenerType,
730 	const OUString& AddListenerParam,
731 	const Reference< XEventListener >& aToRemoveListener
732 )
733 	throw( IllegalArgumentException, IntrospectionException, RuntimeException )
734 {
735 	if( !xObject.is() || !aToRemoveListener.is() )
736 		throw IllegalArgumentException();
737 
738 	// Listener-Klasse per Reflection besorgen
739 	Reference< XIdlReflection > xReflection = getReflection();
740 	if( !xReflection.is() )
741 		throw IntrospectionException();
742 
743 	// Abmelden, dazu passende removeListener-Methode aufrufen
744 	// Zunaechst ueber Introspection gehen, da die Methoden in der gleichen
745 	// Weise analysiert werden koennen. Fuer bessere Performance entweder
746 	// hier nochmal implementieren oder die Impl-Methode der Introspection
747 	// fuer diesen Zweck konfigurierbar machen.
748 
749 	// Introspection-Service holen
750 	Reference< XIntrospection > xIntrospection = getIntrospection();
751 	if( !xIntrospection.is() )
752 		throw IntrospectionException();
753 
754 	// und inspecten
755 	Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) );
756 	Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
757 	if( !xAccess.is() )
758 		throw IntrospectionException();
759 
760 	// Name der removeListener-Methode zusammenbasteln
761 	OUString aRemoveListenerName;
762 	OUString aListenerName( ListenerType );
763 	sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
764 	// set index to the interface name without package name
765 	if( nIndex == -1 )
766 		// not found
767 		nIndex = 0;
768 	else
769 		nIndex++;
770 	if( aListenerName[nIndex] == 'X' )
771 		// erase X from the interface name
772 		aListenerName = aListenerName.copy( nIndex +1 );
773 	aRemoveListenerName = OUString( RTL_CONSTASCII_USTRINGPARAM("remove") ) + aListenerName;
774 
775 	// Methoden nach der passenden addListener-Methode durchsuchen
776 	Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
777 	sal_uInt32 i, nLen = aMethodSeq.getLength();
778 	const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
779 	for( i = 0 ; i < nLen ; i++ )
780 	{
781 		// Methode ansprechen
782 		const Reference< XIdlMethod >& rxMethod = pMethods[i];
783 
784 		// Ist es die richtige Methode?
785 		if( aRemoveListenerName == rxMethod->getName() )
786 		{
787 			Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
788 			sal_uInt32 nParamCount = params.getLength();
789 
790 			// Nur der Listener als Parameter?
791 			if( nParamCount == 1 )
792 			{
793 				Sequence< Any > args( 1 );
794 				args.getArray()[0] <<= aToRemoveListener;
795 				try
796 				{
797 					rxMethod->invoke( aObjAny, args );
798 				}
799 				catch( InvocationTargetException& )
800 				{
801 					throw IntrospectionException();
802 				}
803 			}
804 			// Sonst den Zusatzparameter mit uebergeben
805 			else if( nParamCount == 2 )
806 			{
807 				Sequence< Any > args( 2 );
808 				Any* pAnys = args.getArray();
809 
810 				// Typ des 1. Parameters pruefen
811 				Reference< XIdlClass > xParamClass = params.getConstArray()[0];
812 				if( xParamClass->getTypeClass() == TypeClass_STRING )
813 					pAnys[0] <<= AddListenerParam;
814 
815 				// 2. Parameter == Listener? TODO: Pruefen!
816 				pAnys[1] <<= aToRemoveListener;
817 
818 				// TODO: Konvertierung String -> ?
819 				// else
820 				try
821 				{
822 					rxMethod->invoke( aObjAny, args );
823 				}
824 				catch( InvocationTargetException& )
825 				{
826 					throw IntrospectionException();
827 				}
828 			}
829 			break;
830 		}
831 	}
832 }
833 
834 }
835 
836 extern "C"
837 {
838 //==================================================================================================
839 void SAL_CALL component_getImplementationEnvironment(
840 	const sal_Char ** ppEnvTypeName, uno_Environment ** )
841 {
842 	*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
843 }
844 //==================================================================================================
845 void * SAL_CALL component_getFactory(
846 	const sal_Char * pImplName, void * pServiceManager, void * )
847 {
848 	void * pRet = 0;
849 
850 	if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
851 	{
852 		Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory(
853 			reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
854 			OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ),
855 			::comp_EventAttacher::EventAttacherImpl_CreateInstance,
856 			::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) );
857 
858 		if (xFactory.is())
859 		{
860 			xFactory->acquire();
861 			pRet = xFactory.get();
862 		}
863 	}
864 
865 	return pRet;
866 }
867 }
868 
869 
870 
871