LCOV - code coverage report
Current view: top level - libreoffice/comphelper/source/eventattachermgr - eventattachermgr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 81 355 22.8 %
Date: 2012-12-27 Functions: 20 40 50.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10