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

Generated by: LCOV version 1.10