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