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

Generated by: LCOV version 1.10