LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/comphelper/source/eventattachermgr - eventattachermgr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 249 362 68.8 %
Date: 2013-07-09 Functions: 35 40 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      20             : 
      21             : #if defined( UNX )
      22             : #include <wchar.h>
      23             : #endif
      24             : #include <osl/mutex.hxx>
      25             : #include <osl/diagnose.h>
      26             : #include <comphelper/eventattachermgr.hxx>
      27             : #include <comphelper/processfactory.hxx>
      28             : #include <com/sun/star/beans/Introspection.hpp>
      29             : #include <com/sun/star/io/XObjectInputStream.hpp>
      30             : #include <com/sun/star/io/XPersistObject.hpp>
      31             : #include <com/sun/star/io/XObjectOutputStream.hpp>
      32             : #include <com/sun/star/io/XMarkableStream.hpp>
      33             : #include <com/sun/star/lang/XInitialization.hpp>
      34             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      35             : #include <com/sun/star/reflection/theCoreReflection.hpp>
      36             : #include <com/sun/star/reflection/XIdlClass.hpp>
      37             : #include <com/sun/star/reflection/XIdlReflection.hpp>
      38             : #include <com/sun/star/reflection/XIdlMethod.hpp>
      39             : #include <com/sun/star/script/Converter.hpp>
      40             : #include <com/sun/star/script/XEngineListener.hpp>
      41             : #include <com/sun/star/script/XEventAttacher2.hpp>
      42             : #include <com/sun/star/script/XEventAttacherManager.hpp>
      43             : #include <com/sun/star/script/XScriptListener.hpp>
      44             : #include <cppuhelper/weak.hxx>
      45             : #include <cppuhelper/interfacecontainer.hxx>
      46             : #include <cppuhelper/implbase1.hxx>
      47             : #include <cppuhelper/implbase2.hxx>
      48             : 
      49             : #include <deque>
      50             : #include <algorithm>
      51             : #include <functional>
      52             : 
      53             : using namespace com::sun::star::uno;
      54             : using namespace com::sun::star::io;
      55             : using namespace com::sun::star::lang;
      56             : using namespace com::sun::star::beans;
      57             : using namespace com::sun::star::script;
      58             : using namespace com::sun::star::reflection;
      59             : using namespace cppu;
      60             : using namespace osl;
      61             : 
      62             : 
      63             : namespace comphelper
      64             : {
      65             : 
      66             : //-----------------------------------------------------------------------------
      67        4119 : struct AttachedObject_Impl
      68             : {
      69             :     Reference< XInterface >                 xTarget;
      70             :     Sequence< Reference< XEventListener > > aAttachedListenerSeq;
      71             :     Any                                     aHelper;
      72             : 
      73             :     bool    operator<( const AttachedObject_Impl & ) const;
      74             :     bool    operator==( const AttachedObject_Impl & ) const;
      75             : };
      76             : 
      77        3407 : struct AttacherIndex_Impl
      78             : {
      79             :     ::std::deque< ScriptEventDescriptor > aEventList;
      80             :     ::std::deque< AttachedObject_Impl > aObjList;
      81             : 
      82             :     bool    operator<( const AttacherIndex_Impl & ) const;
      83             :     bool    operator==( const AttacherIndex_Impl & ) const;
      84             : };
      85             : 
      86             : //-----------------------------------------------------------------------------
      87             : class ImplEventAttacherManager
      88             :     : public WeakImplHelper2< XEventAttacherManager, XPersistObject >
      89             : {
      90             :     friend class AttacherAllListener_Impl;
      91             :     ::std::deque< AttacherIndex_Impl >  aIndex;
      92             :     Mutex aLock;
      93             :     // Container for the ScriptListener
      94             :     OInterfaceContainerHelper           aScriptListeners;
      95             :     // Instance of EventAttacher
      96             :     Reference< XEventAttacher2 >        xAttacher;
      97             :     Reference< XComponentContext >      mxContext;
      98             :     Reference< XIdlReflection >         mxCoreReflection;
      99             :     Reference< XIntrospection >         mxIntrospection;
     100             :     Reference< XTypeConverter >         xConverter;
     101             :     sal_Int16                           nVersion;
     102             : public:
     103             :     ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
     104             :                               const Reference< XComponentContext > xContext );
     105             :     ~ImplEventAttacherManager();
     106             : 
     107             :     // Methods of XEventAttacherManager
     108             :     virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent)
     109             :         throw( IllegalArgumentException, RuntimeException );
     110             :     virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents)
     111             :         throw( IllegalArgumentException, RuntimeException );
     112             :     virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam)
     113             :         throw( IllegalArgumentException, RuntimeException );
     114             :     virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index)
     115             :         throw( IllegalArgumentException, RuntimeException );
     116             :     virtual void SAL_CALL insertEntry(sal_Int32 Index)
     117             :         throw( IllegalArgumentException, RuntimeException );
     118             :     virtual void SAL_CALL removeEntry(sal_Int32 Index)
     119             :         throw( IllegalArgumentException, RuntimeException );
     120             :     virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index)
     121             :         throw( IllegalArgumentException, RuntimeException );
     122             :     virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper)
     123             :         throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException );
     124             :     virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
     125             :         throw( IllegalArgumentException, RuntimeException );
     126             :     virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener)
     127             :         throw( IllegalArgumentException, RuntimeException );
     128             :     virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener)
     129             :         throw( IllegalArgumentException, RuntimeException );
     130             : 
     131             :     // Methods of XPersistObject
     132             :     virtual OUString SAL_CALL getServiceName(void) throw( RuntimeException );
     133             :     virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) throw( IOException, RuntimeException );
     134             :     virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) throw( IOException, RuntimeException );
     135             : 
     136             : private:
     137             :     Reference< XIdlReflection > getReflection() throw( Exception );
     138             : 
     139             :     /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
     140             :     @param _nIndex
     141             :         the index to check
     142             :     @return
     143             :         the iterator pointing to the position indicated by the index
     144             :     */
     145             :     ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) );
     146             : };
     147             : 
     148             : //========================================================================
     149             : //========================================================================
     150             : //========================================================================
     151             : 
     152             : 
     153             : // Implementation of an EventAttacher-subclass 'AllListeners', which
     154             : // only passes individual events of the general AllListeners.
     155          78 : class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
     156             : {
     157             :     ImplEventAttacherManager*           mpManager;
     158             :     Reference< XEventAttacherManager >  xManager;
     159             :     OUString                            aScriptType;
     160             :     OUString                            aScriptCode;
     161             : 
     162             :     void convertToEventReturn( Any & rRet, const Type & rRetType )
     163             :         throw( CannotConvertException );
     164             : public:
     165             :     AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
     166             :                                 const OUString & rScriptCode_ );
     167             : 
     168             :     // Methods of XAllListener
     169             :     virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException );
     170             :     virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException );
     171             : 
     172             :     // Methods of XEventListener
     173             :     virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
     174             : };
     175             : 
     176             : //========================================================================
     177          39 : AttacherAllListener_Impl::AttacherAllListener_Impl
     178             : (
     179             :     ImplEventAttacherManager*   pManager_,
     180             :     const OUString &             rScriptType_,
     181             :     const OUString &             rScriptCode_
     182             : )
     183             :     : mpManager( pManager_ )
     184             :     , xManager( pManager_ )
     185             :     , aScriptType( rScriptType_ )
     186          39 :     , aScriptCode( rScriptCode_ )
     187             : {
     188          39 : }
     189             : 
     190             : 
     191             : //========================================================================
     192             : // Methods of XAllListener
     193           1 : void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
     194             :     throw( RuntimeException )
     195             : {
     196           1 :     ScriptEvent aScriptEvent;
     197           1 :     aScriptEvent.Source         = (OWeakObject *)mpManager; // get correct XInterface
     198           1 :     aScriptEvent.ListenerType   = Event.ListenerType;
     199           1 :     aScriptEvent.MethodName     = Event.MethodName;
     200           1 :     aScriptEvent.Arguments      = Event.Arguments;
     201           1 :     aScriptEvent.Helper         = Event.Helper;
     202           1 :     aScriptEvent.ScriptType     = aScriptType;
     203           1 :     aScriptEvent.ScriptCode     = aScriptCode;
     204             : 
     205             :     // Iterate over all listeners and pass events.
     206           2 :     OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
     207           4 :     while( aIt.hasMoreElements() )
     208           3 :         ((XScriptListener *)aIt.next())->firing( aScriptEvent );
     209           1 : }
     210             : 
     211             : //========================================================================
     212             : // Convert to the standard event return
     213           0 : void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
     214             :     throw( CannotConvertException )
     215             : {
     216             :     // no return value? Set to the specified values
     217           0 :     if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
     218             :     {
     219           0 :         switch( rRetType.getTypeClass()  )
     220             :         {
     221             :             case TypeClass_INTERFACE:
     222             :                 {
     223           0 :                 rRet <<= Reference< XInterface >();
     224             :                 }
     225           0 :                 break;
     226             : 
     227             :             case TypeClass_BOOLEAN:
     228           0 :                 rRet <<= sal_True;
     229           0 :                 break;
     230             : 
     231             :             case TypeClass_STRING:
     232           0 :                 rRet <<= OUString();
     233           0 :                 break;
     234             : 
     235           0 :             case TypeClass_FLOAT:           rRet <<= float(0);  break;
     236           0 :             case TypeClass_DOUBLE:          rRet <<= double(0.0);  break;
     237           0 :             case TypeClass_BYTE:            rRet <<= sal_uInt8(0);      break;
     238           0 :             case TypeClass_SHORT:           rRet <<= sal_Int16( 0 );    break;
     239           0 :             case TypeClass_LONG:            rRet <<= sal_Int32( 0 );    break;
     240           0 :             case TypeClass_UNSIGNED_SHORT:  rRet <<= sal_uInt16( 0 );   break;
     241           0 :             case TypeClass_UNSIGNED_LONG:   rRet <<= sal_uInt32( 0 );   break;
     242             : 
     243             :             default:
     244             :                 OSL_ASSERT(false);
     245           0 :                 break;
     246             :         }
     247             :     }
     248           0 :     else if( !rRet.getValueType().equals( rRetType ) )
     249             :     {
     250           0 :         if( mpManager->xConverter.is() )
     251           0 :             rRet = mpManager->xConverter->convertTo( rRet, rRetType );
     252             :         else
     253           0 :             throw CannotConvertException();
     254             :     }
     255           0 : }
     256             : 
     257             : //========================================================================
     258             : // Methods of XAllListener
     259           0 : Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
     260             :     throw( InvocationTargetException, RuntimeException )
     261             : {
     262           0 :     ScriptEvent aScriptEvent;
     263           0 :     aScriptEvent.Source         = (OWeakObject *)mpManager; // get correct XInterface
     264           0 :     aScriptEvent.ListenerType   = Event.ListenerType;
     265           0 :     aScriptEvent.MethodName     = Event.MethodName;
     266           0 :     aScriptEvent.Arguments      = Event.Arguments;
     267           0 :     aScriptEvent.Helper         = Event.Helper;
     268           0 :     aScriptEvent.ScriptType     = aScriptType;
     269           0 :     aScriptEvent.ScriptCode     = aScriptCode;
     270             : 
     271           0 :     Any aRet;
     272             :     // Iterate over all listeners and pass events.
     273           0 :     OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
     274           0 :     while( aIt.hasMoreElements() )
     275             :     {
     276           0 :         aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent );
     277             :         try
     278             :         {
     279           0 :             Reference< XIdlClass > xListenerType = mpManager->getReflection()->
     280           0 :                         forName( Event.ListenerType.getTypeName() );
     281           0 :             Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
     282           0 :             if( xMeth.is() )
     283             :             {
     284           0 :                 Reference< XIdlClass > xRetType = xMeth->getReturnType();
     285           0 :                 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
     286           0 :                 convertToEventReturn( aRet, aRetType );
     287             :             }
     288             : 
     289           0 :             switch( aRet.getValueType().getTypeClass()  )
     290             :             {
     291             :                 case TypeClass_INTERFACE:
     292             :                     {
     293             :                     // Interface not null, return
     294           0 :                     Reference< XInterface > x;
     295           0 :                     aRet >>= x;
     296           0 :                     if( x.is() )
     297           0 :                         return aRet;
     298             :                     }
     299           0 :                     break;
     300             : 
     301             :                 case TypeClass_BOOLEAN:
     302             :                     // FALSE -> Return
     303           0 :                     if( !(*(sal_Bool*)aRet.getValue()) )
     304           0 :                         return aRet;
     305           0 :                     break;
     306             : 
     307             :                 case TypeClass_STRING:
     308             :                     // none empty string -> return
     309           0 :                     if( !((OUString*)aRet.getValue())->isEmpty() )
     310           0 :                         return aRet;
     311           0 :                     break;
     312             : 
     313             :                     // none zero number -> return
     314           0 :                 case TypeClass_FLOAT:           if( *((float*)aRet.getValue()) )    return aRet; break;
     315           0 :                 case TypeClass_DOUBLE:          if( *((double*)aRet.getValue()) )   return aRet; break;
     316           0 :                 case TypeClass_BYTE:            if( *((sal_uInt8*)aRet.getValue()) )    return aRet; break;
     317           0 :                 case TypeClass_SHORT:           if( *((sal_Int16*)aRet.getValue()) )    return aRet; break;
     318           0 :                 case TypeClass_LONG:            if( *((sal_Int32*)aRet.getValue()) )    return aRet; break;
     319           0 :                 case TypeClass_UNSIGNED_SHORT:  if( *((sal_uInt16*)aRet.getValue()) )   return aRet; break;
     320           0 :                 case TypeClass_UNSIGNED_LONG:   if( *((sal_uInt32*)aRet.getValue()) )   return aRet; break;
     321             : 
     322             :                 default:
     323             :                     OSL_ASSERT(false);
     324           0 :                     break;
     325           0 :             }
     326             :         }
     327           0 :         catch( CannotConvertException& )
     328             :         {
     329             :             // silent ignore conversions errors from a script call
     330           0 :             Reference< XIdlClass > xListenerType = mpManager->getReflection()->
     331           0 :                         forName( Event.ListenerType.getTypeName() );
     332           0 :             Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
     333           0 :             if( xMeth.is() )
     334             :             {
     335           0 :                 Reference< XIdlClass > xRetType = xMeth->getReturnType();
     336           0 :                 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
     337           0 :                 aRet.clear();
     338           0 :                 convertToEventReturn( aRet, aRetType );
     339           0 :             }
     340             :         }
     341             :     }
     342           0 :     return aRet;
     343             : }
     344             : 
     345             : //========================================================================
     346             : // Methods of XEventListener
     347           0 : void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
     348             :     throw( RuntimeException )
     349             : {
     350             :     // It is up to the container to release the object
     351           0 : }
     352             : 
     353             : 
     354             : // Constructor method for EventAttacherManager
     355         394 : Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XComponentContext > & rxContext )
     356             :     throw( Exception )
     357             : {
     358         394 :     Reference< XIntrospection > xIntrospection = Introspection::create( rxContext );
     359         394 :     return new ImplEventAttacherManager( xIntrospection, rxContext );
     360             : }
     361             : 
     362             : //-----------------------------------------------------------------------------
     363         394 : ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
     364             :                                                     const Reference< XComponentContext > xContext )
     365             :     : aScriptListeners( aLock )
     366             :     , mxContext( xContext )
     367         394 :     , mxIntrospection( rIntrospection )
     368             : {
     369         394 :     if ( xContext.is() )
     370             :     {
     371         788 :         Reference< XInterface > xIFace( xContext->getServiceManager()->createInstanceWithContext(
     372         394 :              OUString( "com.sun.star.script.EventAttacher" ), xContext)  );
     373         394 :         if ( xIFace.is() )
     374             :         {
     375         341 :             xAttacher = Reference< XEventAttacher2 >::query( xIFace );
     376             :         }
     377         394 :         xConverter = Converter::create(xContext);
     378             :     }
     379             : 
     380         394 :     Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
     381         394 :     if( xInit.is() )
     382             :     {
     383         341 :         Sequence< Any > Arguments( 1 );
     384         341 :         Arguments[0] <<= rIntrospection;
     385         341 :         xInit->initialize( Arguments );
     386         394 :     }
     387         394 : }
     388             : 
     389             : //-----------------------------------------------------------------------------
     390         776 : ImplEventAttacherManager::~ImplEventAttacherManager()
     391             : {
     392         776 : }
     393             : 
     394           0 : Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception )
     395             : {
     396           0 :     Guard< Mutex > aGuard( aLock );
     397             :     // Do we already have a service? If not, create one.
     398           0 :     if( !mxCoreReflection.is() )
     399             :     {
     400           0 :         mxCoreReflection = theCoreReflection::get(mxContext);
     401             :     }
     402           0 :     return mxCoreReflection;
     403             : }
     404             : 
     405             : 
     406             : //-----------------------------------------------------------------------------
     407         776 : ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) )
     408             : {
     409         776 :     if (_nIndex < 0)
     410           0 :         throw IllegalArgumentException();
     411             : 
     412         776 :     ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
     413         776 :     for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
     414             :         ;
     415             : 
     416         776 :     if( aIt == aIndex.end() )
     417           0 :         throw IllegalArgumentException();
     418             : 
     419         776 :     return aIt;
     420             : }
     421             : 
     422             : namespace {
     423             : 
     424             : class DetachObject : public std::unary_function<AttachedObject_Impl, void>
     425             : {
     426             :     ImplEventAttacherManager& mrMgr;
     427             :     sal_Int32 mnIdx;
     428             : public:
     429         741 :     DetachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
     430         741 :         mrMgr(rMgr), mnIdx(nIdx) {}
     431             : 
     432         259 :     void operator() (AttachedObject_Impl& rObj)
     433             :     {
     434         259 :         mrMgr.detach(mnIdx, rObj.xTarget);
     435         259 :     }
     436             : };
     437             : 
     438             : class AttachObject : public std::unary_function<AttachedObject_Impl, void>
     439             : {
     440             :     ImplEventAttacherManager& mrMgr;
     441             :     sal_Int32 mnIdx;
     442             : public:
     443         250 :     AttachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
     444         250 :         mrMgr(rMgr), mnIdx(nIdx) {}
     445             : 
     446         244 :     void operator() (AttachedObject_Impl& rObj)
     447             :     {
     448         244 :         mrMgr.attach(mnIdx, rObj.xTarget, rObj.aHelper);
     449         244 :     }
     450             : };
     451             : 
     452             : }
     453             : 
     454             : //-----------------------------------------------------------------------------
     455             : // Methods of XEventAttacherManager
     456          22 : void SAL_CALL ImplEventAttacherManager::registerScriptEvent
     457             : (
     458             :     sal_Int32 nIndex,
     459             :     const ScriptEventDescriptor& ScriptEvent
     460             : )
     461             :     throw( IllegalArgumentException, RuntimeException )
     462             : {
     463          22 :     Guard< Mutex > aGuard( aLock );
     464             : 
     465             :     // Examine the index and apply the array
     466          22 :     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
     467             : 
     468          44 :     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
     469             : 
     470          44 :     ScriptEventDescriptor aEvt = ScriptEvent;
     471          22 :     const sal_Unicode* pLastDot = aEvt.ListenerType.getStr();
     472          22 :     pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
     473          22 :     if( pLastDot )
     474          22 :         aEvt.ListenerType = pLastDot +1;
     475          22 :     (*aIt).aEventList.push_back( aEvt );
     476             : 
     477             :     // register new new Event
     478          22 :     ::std::deque< AttachedObject_Impl >::iterator aObjIt =  (*aIt).aObjList.begin();
     479          22 :     ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
     480          46 :     while( aObjIt != aObjEnd )
     481             :     {
     482             :         // resize
     483           2 :         sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
     484           2 :         (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
     485           2 :         Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
     486             : 
     487             :         Reference< XAllListener > xAll =
     488           2 :             new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
     489             :         try
     490             :         {
     491           8 :         pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
     492           2 :                         (*aObjIt).aHelper, ScriptEvent.ListenerType,
     493           4 :                         ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
     494             :         }
     495           0 :         catch( Exception& )
     496             :         {
     497             :         }
     498             : 
     499           2 :         ++aObjIt;
     500          24 :     }
     501          22 : }
     502             : 
     503             : //-----------------------------------------------------------------------------
     504         246 : void SAL_CALL ImplEventAttacherManager::registerScriptEvents
     505             : (
     506             :     sal_Int32 nIndex,
     507             :     const Sequence< ScriptEventDescriptor >& ScriptEvents
     508             : )
     509             :     throw( IllegalArgumentException, RuntimeException )
     510             : {
     511         246 :     Guard< Mutex > aGuard( aLock );
     512             : 
     513             :     // Examine the index and apply the array
     514         246 :     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
     515             : 
     516         492 :     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
     517         246 :     ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
     518             : 
     519         246 :     const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
     520         246 :     sal_Int32 nLen = ScriptEvents.getLength();
     521         265 :     for( sal_Int32 i = 0 ; i < nLen ; i++ )
     522          19 :         registerScriptEvent( nIndex, pArray[ i ] );
     523             : 
     524         492 :     ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
     525         246 : }
     526             : 
     527             : //-----------------------------------------------------------------------------
     528           1 : void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
     529             : (
     530             :     sal_Int32 nIndex,
     531             :     const OUString& ListenerType,
     532             :     const OUString& EventMethod,
     533             :     const OUString& ToRemoveListenerParam
     534             : )
     535             :     throw( IllegalArgumentException, RuntimeException )
     536             : {
     537           1 :     Guard< Mutex > aGuard( aLock );
     538             : 
     539           1 :     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
     540             : 
     541           2 :     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
     542           1 :     ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
     543             : 
     544           2 :     OUString aLstType = ListenerType;
     545           1 :     const sal_Unicode * pLastDot = aLstType.getStr();
     546           1 :     pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
     547           1 :     if( pLastDot )
     548           1 :         aLstType = pLastDot +1;
     549             : 
     550           1 :     ::std::deque< ScriptEventDescriptor >::iterator aEvtIt =    (*aIt).aEventList.begin();
     551           1 :     ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd =   (*aIt).aEventList.end();
     552           2 :     while( aEvtIt != aEvtEnd )
     553             :     {
     554           2 :         if( aLstType            == (*aEvtIt).ListenerType
     555           1 :           && EventMethod            == (*aEvtIt).EventMethod
     556           2 :           && ToRemoveListenerParam  == (*aEvtIt).AddListenerParam )
     557             :         {
     558           1 :             (*aIt).aEventList.erase( aEvtIt );
     559           1 :             break;
     560             :         }
     561             : 
     562           0 :         ++aEvtIt;
     563             :     }
     564           2 :     ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
     565           1 : }
     566             : 
     567             : //-----------------------------------------------------------------------------
     568           3 : void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
     569             :     throw( IllegalArgumentException, RuntimeException )
     570             : {
     571           3 :     Guard< Mutex > aGuard( aLock );
     572           3 :     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
     573             : 
     574           6 :     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
     575           3 :     ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
     576           3 :     (*aIt).aEventList.clear();
     577           6 :     ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
     578           3 : }
     579             : 
     580             : //-----------------------------------------------------------------------------
     581         514 : void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
     582             :     throw( IllegalArgumentException, RuntimeException )
     583             : {
     584         514 :     Guard< Mutex > aGuard( aLock );
     585         514 :     if( nIndex < 0 )
     586           0 :         throw IllegalArgumentException();
     587             : 
     588         514 :     if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
     589         323 :         aIndex.resize(nIndex+1);
     590             : 
     591        1028 :     AttacherIndex_Impl aTmp;
     592        1028 :     aIndex.insert( aIndex.begin() + nIndex, aTmp );
     593         514 : }
     594             : 
     595             : //-----------------------------------------------------------------------------
     596         491 : void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
     597             :     throw( IllegalArgumentException, RuntimeException )
     598             : {
     599         491 :     Guard< Mutex > aGuard( aLock );
     600         491 :     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
     601             : 
     602         982 :     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
     603         491 :     ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
     604         982 :     aIndex.erase( aIt );
     605         491 : }
     606             : 
     607             : //-----------------------------------------------------------------------------
     608          13 : Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
     609             :     throw( IllegalArgumentException, RuntimeException )
     610             : {
     611          13 :     Guard< Mutex > aGuard( aLock );
     612          13 :     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
     613             : 
     614          13 :     Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
     615          13 :     ScriptEventDescriptor * pArray = aSeq.getArray();
     616             : 
     617          13 :     ::std::deque< ScriptEventDescriptor >::iterator aEvtIt =    (*aIt).aEventList.begin();
     618          13 :     ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd =   (*aIt).aEventList.end();
     619          13 :     sal_Int32 i = 0;
     620          32 :     while( aEvtIt != aEvtEnd )
     621             :     {
     622           6 :         pArray[i++] = *aEvtIt;
     623           6 :         ++aEvtIt;
     624             :     }
     625          13 :     return aSeq;
     626             : }
     627             : 
     628             : //-----------------------------------------------------------------------------
     629         899 : void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
     630             :     throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException )
     631             : {
     632         899 :     Guard< Mutex > aGuard( aLock );
     633         899 :     if( nIndex < 0 || !xObject.is() )
     634           0 :         throw IllegalArgumentException();
     635             : 
     636         899 :     if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
     637             :     {
     638             :         // read older files
     639           0 :         if( nVersion == 1 )
     640             :         {
     641           0 :             insertEntry( nIndex );
     642           0 :             attach( nIndex, xObject, Helper );
     643           0 :             return;
     644             :         }
     645             :         else
     646           0 :             throw IllegalArgumentException();
     647             :     }
     648             : 
     649         899 :     ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
     650             : 
     651         916 :     AttachedObject_Impl aTmp;
     652         899 :     aTmp.xTarget = xObject;
     653         899 :     aTmp.aHelper = Helper;
     654         899 :     aCurrentPosition->aObjList.push_back( aTmp );
     655             : 
     656             :     //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
     657         899 :     AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
     658         899 :     rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
     659             : 
     660         899 :     if (aCurrentPosition->aEventList.empty())
     661         882 :         return;
     662             : 
     663          34 :     Sequence<com::sun::star::script::EventListener> aEvents(aCurrentPosition->aEventList.size());
     664          17 :     std::deque<ScriptEventDescriptor>::iterator itr = aCurrentPosition->aEventList.begin();
     665          17 :     std::deque<ScriptEventDescriptor>::iterator itrEnd = aCurrentPosition->aEventList.end();
     666          17 :     ::com::sun::star::script::EventListener* p = aEvents.getArray();
     667          17 :     size_t i = 0;
     668          54 :     for (; itr != itrEnd; ++itr)
     669             :     {
     670          37 :         com::sun::star::script::EventListener aListener;
     671         111 :         aListener.AllListener =
     672         148 :             new AttacherAllListener_Impl(this, itr->ScriptType, itr->ScriptCode);
     673          37 :         aListener.Helper = rCurObj.aHelper;
     674          37 :         aListener.ListenerType = itr->ListenerType;
     675          37 :         aListener.EventMethod = itr->EventMethod;
     676          37 :         aListener.AddListenerParam = itr->AddListenerParam;
     677          37 :         p[i++] = aListener;
     678          37 :     }
     679             : 
     680             :     try
     681             :     {
     682          34 :         rCurObj.aAttachedListenerSeq =
     683          34 :             xAttacher->attachMultipleEventListeners(rCurObj.xTarget, aEvents);
     684             :     }
     685           0 :     catch (const Exception&)
     686             :     {
     687             :         // Fail gracefully.
     688          17 :     }
     689             : }
     690             : 
     691             : //-----------------------------------------------------------------------------
     692         892 : void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
     693             :     throw( IllegalArgumentException, RuntimeException )
     694             : {
     695         892 :     Guard< Mutex > aGuard( aLock );
     696             :     //return;
     697         892 :     if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
     698           0 :         throw IllegalArgumentException();
     699             : 
     700         892 :     ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
     701         892 :     ::std::deque< AttachedObject_Impl >::iterator aObjIt =  aCurrentPosition->aObjList.begin();
     702         892 :     ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
     703        1949 :     while( aObjIt != aObjEnd )
     704             :     {
     705        1042 :         if( (*aObjIt).xTarget == xObject )
     706             :         {
     707         877 :             Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
     708             : 
     709         877 :             ::std::deque< ScriptEventDescriptor >::iterator aEvtIt =    aCurrentPosition->aEventList.begin();
     710         877 :             ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd =   aCurrentPosition->aEventList.end();
     711         877 :             sal_Int32 i = 0;
     712        1793 :             while( aEvtIt != aEvtEnd )
     713             :             {
     714          39 :                 if( pArray[i].is() )
     715             :                 {
     716             :                     try
     717             :                     {
     718          57 :                     xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
     719          57 :                                                 (*aEvtIt).AddListenerParam, pArray[i] );
     720             :                     }
     721           0 :                     catch( Exception& )
     722             :                     {
     723             :                     }
     724             :                 }
     725          39 :                 i++;
     726          39 :                 ++aEvtIt;
     727             :             }
     728         877 :             aCurrentPosition->aObjList.erase( aObjIt );
     729         877 :             break;
     730             :         }
     731         165 :         ++aObjIt;
     732         892 :     }
     733         892 : }
     734             : 
     735         757 : void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
     736             :     throw( IllegalArgumentException, RuntimeException )
     737             : {
     738         757 :     Guard< Mutex > aGuard( aLock );
     739         757 :     aScriptListeners.addInterface( aListener );
     740         757 : }
     741             : 
     742         753 : void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
     743             :     throw( IllegalArgumentException, RuntimeException )
     744             : {
     745         753 :     Guard< Mutex > aGuard( aLock );
     746         753 :     aScriptListeners.removeInterface( aListener );
     747         753 : }
     748             : 
     749             : 
     750             : // Methods of XPersistObject
     751           0 : OUString SAL_CALL ImplEventAttacherManager::getServiceName(void)
     752             :     throw( RuntimeException )
     753             : {
     754           0 :     return OUString( "com.sun.star.uno.script.EventAttacherManager" );
     755             : }
     756             : 
     757           1 : void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
     758             :     throw( IOException, RuntimeException )
     759             : {
     760           1 :     Guard< Mutex > aGuard( aLock );
     761             :     // Don't run without XMarkableStream
     762           2 :     Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
     763           1 :     if( !xMarkStream.is() )
     764           1 :         return;
     765             : 
     766             :     // Write out the version
     767           1 :     OutStream->writeShort( 2 );
     768             : 
     769             :     // Remember position for length
     770           1 :     sal_Int32 nObjLenMark = xMarkStream->createMark();
     771           1 :     OutStream->writeLong( 0L );
     772             : 
     773           1 :     OutStream->writeLong( aIndex.size() );
     774             : 
     775             :     // Write out sequences
     776           1 :     ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
     777           1 :     ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
     778           5 :     while( aIt != aEnd )
     779             :     {
     780             :         // Write out the length of the sequence and all descriptions
     781           3 :         OutStream->writeLong( (*aIt).aEventList.size() );
     782           3 :         ::std::deque< ScriptEventDescriptor >::iterator aEvtIt =    (*aIt).aEventList.begin();
     783           3 :         ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
     784           6 :         while( aEvtIt != aEvtEnd )
     785             :         {
     786           0 :             const ScriptEventDescriptor& rDesc = (*aEvtIt);
     787           0 :             OutStream->writeUTF( rDesc.ListenerType );
     788           0 :             OutStream->writeUTF( rDesc.EventMethod );
     789           0 :             OutStream->writeUTF( rDesc.AddListenerParam );
     790           0 :             OutStream->writeUTF( rDesc.ScriptType );
     791           0 :             OutStream->writeUTF( rDesc.ScriptCode );
     792             : 
     793           0 :             ++aEvtIt;
     794             :         }
     795           3 :         ++aIt;
     796             :     }
     797             : 
     798             :     // The length is now known
     799           1 :     sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
     800           1 :     xMarkStream->jumpToMark( nObjLenMark );
     801           1 :     OutStream->writeLong( nObjLen );
     802           1 :     xMarkStream->jumpToFurthest();
     803           2 :     xMarkStream->deleteMark( nObjLenMark );
     804             : }
     805             : 
     806           1 : void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
     807             :     throw( IOException, RuntimeException )
     808             : {
     809           1 :     Guard< Mutex > aGuard( aLock );
     810             :     // Don't run without XMarkableStream
     811           2 :     Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
     812           1 :     if( !xMarkStream.is() )
     813           1 :         return;
     814             : 
     815             :     // Read in the version
     816           1 :     nVersion = InStream->readShort();
     817             : 
     818             :     // At first there's the data according to version 1 --
     819             :     // this part needs to be kept in later versions.
     820           1 :     sal_Int32 nLen = InStream->readLong();
     821             : 
     822             :     // Position for comparative purposes
     823           1 :     sal_Int32 nObjLenMark = xMarkStream->createMark();
     824             : 
     825             :     // Number of read sequences
     826           1 :     sal_Int32 nItemCount = InStream->readLong();
     827             : 
     828           4 :     for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
     829             :     {
     830           3 :         insertEntry( i );
     831             :         // Read the length of the sequence
     832           3 :         sal_Int32 nSeqLen = InStream->readLong();
     833             : 
     834             :         // Display the sequences and read the descriptions
     835           3 :         Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
     836           3 :         ScriptEventDescriptor* pArray = aSEDSeq.getArray();
     837           3 :         for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
     838             :         {
     839           0 :             ScriptEventDescriptor& rDesc = pArray[ j ];
     840           0 :             rDesc.ListenerType = InStream->readUTF();
     841           0 :             rDesc.EventMethod = InStream->readUTF();
     842           0 :             rDesc.AddListenerParam = InStream->readUTF();
     843           0 :             rDesc.ScriptType = InStream->readUTF();
     844           0 :             rDesc.ScriptCode = InStream->readUTF();
     845             :         }
     846           3 :         registerScriptEvents( i, aSEDSeq );
     847           3 :     }
     848             : 
     849             :     // Have we read the specified length?
     850           1 :     sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
     851           1 :     if( nRealLen != nLen )
     852             :     {
     853             :         // Only if the StreamVersion is > 1 and the date still follows, can
     854             :         // this be true. Otherwise, something is completely gone.
     855           0 :         if( nRealLen > nLen || nVersion == 1 )
     856             :         {
     857             :             OSL_FAIL( "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
     858             :         }
     859             :         else
     860             :         {   // TODO: Examine if caching the dates would be useful
     861             :             // But for now, it's easier to skip it.
     862           0 :             sal_Int32 nSkipCount = nLen - nRealLen;
     863           0 :             InStream->skipBytes( nSkipCount );
     864             :         }
     865             :     }
     866           1 :     xMarkStream->jumpToFurthest();
     867           2 :     xMarkStream->deleteMark( nObjLenMark );
     868             : }
     869             : 
     870             : } // namesapce comphelper
     871             : 
     872             : 
     873             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10