LibreOffice Module comphelper (master)  1
eventattachermgr.cxx
Go to the documentation of this file.
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 <sal/config.h>
21 
22 #include <o3tl/any.hxx>
23 #include <osl/mutex.hxx>
24 #include <osl/diagnose.h>
26 #include <comphelper/sequence.hxx>
27 #include <com/sun/star/beans/theIntrospection.hpp>
28 #include <com/sun/star/io/XObjectInputStream.hpp>
29 #include <com/sun/star/io/XPersistObject.hpp>
30 #include <com/sun/star/io/XObjectOutputStream.hpp>
31 #include <com/sun/star/io/XMarkableStream.hpp>
32 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
33 #include <com/sun/star/lang/XInitialization.hpp>
34 #include <com/sun/star/reflection/theCoreReflection.hpp>
35 #include <com/sun/star/reflection/XIdlClass.hpp>
36 #include <com/sun/star/reflection/XIdlReflection.hpp>
37 #include <com/sun/star/reflection/XIdlMethod.hpp>
38 #include <com/sun/star/script/CannotConvertException.hpp>
39 #include <com/sun/star/script/Converter.hpp>
40 #include <com/sun/star/script/XEventAttacher2.hpp>
41 #include <com/sun/star/script/XEventAttacherManager.hpp>
42 #include <com/sun/star/script/XScriptListener.hpp>
43 #include <cppuhelper/weak.hxx>
45 #include <cppuhelper/exc_hlp.hxx>
46 #include <cppuhelper/implbase.hxx>
47 #include <rtl/ref.hxx>
48 
49 #include <deque>
50 #include <algorithm>
51 
52 using namespace com::sun::star::uno;
53 using namespace com::sun::star::io;
54 using namespace com::sun::star::lang;
55 using namespace com::sun::star::beans;
56 using namespace com::sun::star::script;
57 using namespace com::sun::star::reflection;
58 using namespace cppu;
59 using namespace osl;
60 
61 
62 namespace comphelper
63 {
64 
65 
67 {
69  std::vector< Reference< XEventListener > > aAttachedListenerSeq;
71 };
72 
74 {
75  std::deque< ScriptEventDescriptor > aEventList;
76  std::deque< AttachedObject_Impl > aObjList;
77 };
78 
79 
81  : public WeakImplHelper< XEventAttacherManager, XPersistObject >
82 {
84  std::deque< AttacherIndex_Impl > aIndex;
85  Mutex aLock;
86  // Container for the ScriptListener
88  // Instance of EventAttacher
93  sal_Int16 nVersion;
94 public:
96  const Reference< XComponentContext >& rContext );
97 
98  // Methods of XEventAttacherManager
99  virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent) override;
100  virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents) override;
101  virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam) override;
102  virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index) override;
103  virtual void SAL_CALL insertEntry(sal_Int32 Index) override;
104  virtual void SAL_CALL removeEntry(sal_Int32 Index) override;
105  virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index) override;
106  virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper) override;
107  virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject) override;
108  virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener) override;
109  virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener) override;
110 
111  // Methods of XPersistObject
112  virtual OUString SAL_CALL getServiceName() override;
113  virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) override;
114  virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) override;
115 
116 private:
118  Reference< XIdlReflection > getReflection();
119 
126  std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex );
127 };
128 
129 
130 // Implementation of an EventAttacher-subclass 'AllListeners', which
131 // only passes individual events of the general AllListeners.
132 class AttacherAllListener_Impl : public WeakImplHelper< XAllListener >
133 {
135  OUString const aScriptType;
136  OUString const aScriptCode;
137 
139  void convertToEventReturn( Any & rRet, const Type & rRetType );
140 public:
141  AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
142  const OUString & rScriptCode_ );
143 
144  // Methods of XAllListener
145  virtual void SAL_CALL firing(const AllEventObject& Event) override;
146  virtual Any SAL_CALL approveFiring(const AllEventObject& Event) override;
147 
148  // Methods of XEventListener
149  virtual void SAL_CALL disposing(const EventObject& Source) override;
150 };
151 
152 
153 AttacherAllListener_Impl::AttacherAllListener_Impl
154 (
155  ImplEventAttacherManager* pManager_,
156  const OUString & rScriptType_,
157  const OUString & rScriptCode_
158 )
159  : mxManager( pManager_ )
160  , aScriptType( rScriptType_ )
161  , aScriptCode( rScriptCode_ )
162 {
163 }
164 
165 
166 // Methods of XAllListener
167 void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
168 {
169  ScriptEvent aScriptEvent;
170  aScriptEvent.Source = static_cast<OWeakObject *>(mxManager.get()); // get correct XInterface
171  aScriptEvent.ListenerType = Event.ListenerType;
172  aScriptEvent.MethodName = Event.MethodName;
173  aScriptEvent.Arguments = Event.Arguments;
174  aScriptEvent.Helper = Event.Helper;
175  aScriptEvent.ScriptType = aScriptType;
176  aScriptEvent.ScriptCode = aScriptCode;
177 
178  // Iterate over all listeners and pass events.
179  OInterfaceIteratorHelper2 aIt( mxManager->aScriptListeners );
180  while( aIt.hasMoreElements() )
181  static_cast<XScriptListener *>(aIt.next())->firing( aScriptEvent );
182 }
183 
184 
185 // Convert to the standard event return
186 void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
187 {
188  // no return value? Set to the specified values
189  if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
190  {
191  switch( rRetType.getTypeClass() )
192  {
193  case TypeClass_INTERFACE:
194  {
195  rRet <<= Reference< XInterface >();
196  }
197  break;
198 
199  case TypeClass_BOOLEAN:
200  rRet <<= true;
201  break;
202 
203  case TypeClass_STRING:
204  rRet <<= OUString();
205  break;
206 
207  case TypeClass_FLOAT: rRet <<= float(0); break;
208  case TypeClass_DOUBLE: rRet <<= 0.0; break;
209  case TypeClass_BYTE: rRet <<= sal_uInt8(0); break;
210  case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
211  case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
212  case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
213  case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
214 
215  default:
216  OSL_ASSERT(false);
217  break;
218  }
219  }
220  else if( !rRet.getValueType().equals( rRetType ) )
221  {
222  if( !mxManager->xConverter.is() )
223  throw CannotConvertException();
224  rRet = mxManager->xConverter->convertTo( rRet, rRetType );
225  }
226 }
227 
228 // Methods of XAllListener
229 Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
230 {
231  ScriptEvent aScriptEvent;
232  aScriptEvent.Source = static_cast<OWeakObject *>(mxManager.get()); // get correct XInterface
233  aScriptEvent.ListenerType = Event.ListenerType;
234  aScriptEvent.MethodName = Event.MethodName;
235  aScriptEvent.Arguments = Event.Arguments;
236  aScriptEvent.Helper = Event.Helper;
237  aScriptEvent.ScriptType = aScriptType;
238  aScriptEvent.ScriptCode = aScriptCode;
239 
240  Any aRet;
241  // Iterate over all listeners and pass events.
242  OInterfaceIteratorHelper2 aIt( mxManager->aScriptListeners );
243  while( aIt.hasMoreElements() )
244  {
245  aRet = static_cast<XScriptListener *>(aIt.next())->approveFiring( aScriptEvent );
246  try
247  {
248  Reference< XIdlClass > xListenerType = mxManager->getReflection()->
249  forName( Event.ListenerType.getTypeName() );
250  Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
251  if( xMeth.is() )
252  {
253  Reference< XIdlClass > xRetType = xMeth->getReturnType();
254  Type aRetType(xRetType->getTypeClass(), xRetType->getName());
255  convertToEventReturn( aRet, aRetType );
256  }
257 
258  switch( aRet.getValueType().getTypeClass() )
259  {
260  case TypeClass_INTERFACE:
261  {
262  // Interface not null, return
264  aRet >>= x;
265  if( x.is() )
266  return aRet;
267  }
268  break;
269 
270  case TypeClass_BOOLEAN:
271  // FALSE -> Return
272  if( !(*o3tl::forceAccess<bool>(aRet)) )
273  return aRet;
274  break;
275 
276  case TypeClass_STRING:
277  // none empty string -> return
278  if( !o3tl::forceAccess<OUString>(aRet)->isEmpty() )
279  return aRet;
280  break;
281 
282  // none zero number -> return
283  case TypeClass_FLOAT: if( *o3tl::forceAccess<float>(aRet) ) return aRet; break;
284  case TypeClass_DOUBLE: if( *o3tl::forceAccess<double>(aRet) ) return aRet; break;
285  case TypeClass_BYTE: if( *o3tl::forceAccess<sal_Int8>(aRet) ) return aRet; break;
286  case TypeClass_SHORT: if( *o3tl::forceAccess<sal_Int16>(aRet) ) return aRet; break;
287  case TypeClass_LONG: if( *o3tl::forceAccess<sal_Int32>(aRet) ) return aRet; break;
288  case TypeClass_UNSIGNED_SHORT: if( *o3tl::forceAccess<sal_uInt16>(aRet) ) return aRet; break;
289  case TypeClass_UNSIGNED_LONG: if( *o3tl::forceAccess<sal_uInt32>(aRet) ) return aRet; break;
290 
291  default:
292  OSL_ASSERT(false);
293  break;
294  }
295  }
296  catch (const CannotConvertException&)
297  {
298  // silent ignore conversions errors from a script call
299  Reference< XIdlClass > xListenerType = mxManager->getReflection()->
300  forName( Event.ListenerType.getTypeName() );
301  Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
302  if( xMeth.is() )
303  {
304  Reference< XIdlClass > xRetType = xMeth->getReturnType();
305  Type aRetType(xRetType->getTypeClass(), xRetType->getName());
306  aRet.clear();
307  try
308  {
309  convertToEventReturn( aRet, aRetType );
310  }
311  catch (const CannotConvertException& e)
312  {
313  css::uno::Any anyEx = cppu::getCaughtException();
314  throw css::lang::WrappedTargetRuntimeException(
315  "wrapped CannotConvertException " + e.Message,
316  css::uno::Reference<css::uno::XInterface>(), anyEx);
317  }
318  }
319  }
320  }
321  return aRet;
322 }
323 
324 // Methods of XEventListener
325 void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
326 {
327  // It is up to the container to release the object
328 }
329 
330 // Constructor method for EventAttacherManager
332 {
333  Reference< XIntrospection > xIntrospection = theIntrospection::get( rxContext );
334  return new ImplEventAttacherManager( xIntrospection, rxContext );
335 }
336 
337 
338 ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
339  const Reference< XComponentContext >& rContext )
340  : aScriptListeners( aLock )
341  , mxContext( rContext )
342  , nVersion(0)
343 {
344  if ( rContext.is() )
345  {
346  Reference< XInterface > xIFace( rContext->getServiceManager()->createInstanceWithContext(
347  "com.sun.star.script.EventAttacher", rContext) );
348  if ( xIFace.is() )
349  {
350  xAttacher.set( xIFace, UNO_QUERY );
351  }
352  xConverter = Converter::create(rContext);
353  }
354 
355  Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
356  if( xInit.is() )
357  {
358  Sequence< Any > Arguments( 1 );
359  Arguments[0] <<= rIntrospection;
360  xInit->initialize( Arguments );
361  }
362 }
363 
365 {
366  Guard< Mutex > aGuard( aLock );
367  // Do we already have a service? If not, create one.
368  if( !mxCoreReflection.is() )
369  {
370  mxCoreReflection = theCoreReflection::get(mxContext);
371  }
372  return mxCoreReflection;
373 }
374 
375 
376 std::deque< AttacherIndex_Impl >::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex )
377 {
378  if ( (_nIndex < 0) || (static_cast<sal_uInt32>(_nIndex) >= aIndex.size()) )
379  throw IllegalArgumentException();
380 
381  std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin() + _nIndex;
382  return aIt;
383 }
384 
385 // Methods of XEventAttacherManager
387 (
388  sal_Int32 nIndex,
389  const ScriptEventDescriptor& ScriptEvent
390 )
391 {
392  Guard< Mutex > aGuard( aLock );
393 
394  // Examine the index and apply the array
395  std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
396 
397  ScriptEventDescriptor aEvt = ScriptEvent;
398  sal_Int32 nLastDot = aEvt.ListenerType.lastIndexOf('.');
399  if (nLastDot != -1)
400  aEvt.ListenerType = aEvt.ListenerType.copy(nLastDot+1);
401  aIt->aEventList.push_back( aEvt );
402 
403  // register new Event
404  for( auto& rObj : aIt->aObjList )
405  {
407  new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
408  try
409  {
410  rObj.aAttachedListenerSeq.push_back( xAttacher->attachSingleEventListener( rObj.xTarget, xAll,
411  rObj.aHelper, ScriptEvent.ListenerType,
412  ScriptEvent.AddListenerParam, ScriptEvent.EventMethod ) );
413  }
414  catch( Exception& )
415  {
416  }
417  }
418 }
419 
420 
422 (
423  sal_Int32 nIndex,
424  const Sequence< ScriptEventDescriptor >& ScriptEvents
425 )
426 {
427  Guard< Mutex > aGuard( aLock );
428 
429  // Examine the index and apply the array
430  std::deque< AttachedObject_Impl > aList = implCheckIndex( nIndex )->aObjList;
431  for( const auto& rObj : aList )
432  detach( nIndex, rObj.xTarget );
433 
434  const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
435  sal_Int32 nLen = ScriptEvents.getLength();
436  for( sal_Int32 i = 0 ; i < nLen ; i++ )
437  registerScriptEvent( nIndex, pArray[ i ] );
438 
439  for( const auto& rObj : aList )
440  attach( nIndex, rObj.xTarget, rObj.aHelper );
441 }
442 
443 
445 (
446  sal_Int32 nIndex,
447  const OUString& ListenerType,
448  const OUString& EventMethod,
449  const OUString& ToRemoveListenerParam
450 )
451 {
452  Guard< Mutex > aGuard( aLock );
453 
454  std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
455 
456  std::deque< AttachedObject_Impl > aList = aIt->aObjList;
457  for( const auto& rObj : aList )
458  detach( nIndex, rObj.xTarget );
459 
460  OUString aLstType = ListenerType;
461  sal_Int32 nLastDot = aLstType.lastIndexOf('.');
462  if (nLastDot != -1)
463  aLstType = aLstType.copy(nLastDot+1);
464 
465  auto aEvtIt = std::find_if(aIt->aEventList.begin(), aIt->aEventList.end(),
466  [&aLstType, &EventMethod, &ToRemoveListenerParam](const ScriptEventDescriptor& rEvent) {
467  return aLstType == rEvent.ListenerType
468  && EventMethod == rEvent.EventMethod
469  && ToRemoveListenerParam == rEvent.AddListenerParam;
470  });
471  if (aEvtIt != aIt->aEventList.end())
472  aIt->aEventList.erase( aEvtIt );
473 
474  for( const auto& rObj : aList )
475  attach( nIndex, rObj.xTarget, rObj.aHelper );
476 }
477 
478 
479 void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
480 {
481  Guard< Mutex > aGuard( aLock );
482  std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
483 
484  std::deque< AttachedObject_Impl > aList = aIt->aObjList;
485  for( const auto& rObj : aList )
486  detach( nIndex, rObj.xTarget );
487  aIt->aEventList.clear();
488  for( const auto& rObj : aList )
489  attach( nIndex, rObj.xTarget, rObj.aHelper );
490 }
491 
492 
493 void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
494 {
495  Guard< Mutex > aGuard( aLock );
496  if( nIndex < 0 )
497  throw IllegalArgumentException();
498 
499  if ( static_cast< std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
500  aIndex.resize(nIndex+1);
501 
502  AttacherIndex_Impl aTmp;
503  aIndex.insert( aIndex.begin() + nIndex, aTmp );
504 }
505 
506 
507 void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
508 {
509  Guard< Mutex > aGuard( aLock );
510  std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
511 
512  std::deque< AttachedObject_Impl > aList = aIt->aObjList;
513  for( const auto& rObj : aList )
514  detach( nIndex, rObj.xTarget );
515 
516  aIndex.erase( aIt );
517 }
518 
519 
521 {
522  Guard< Mutex > aGuard( aLock );
523  std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
524  return comphelper::containerToSequence(aIt->aEventList);
525 }
526 
527 
528 void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
529 {
530  Guard< Mutex > aGuard( aLock );
531  if( nIndex < 0 || !xObject.is() )
532  throw IllegalArgumentException();
533 
534  if( static_cast< std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
535  {
536  // read older files
537  if( nVersion != 1 )
538  throw IllegalArgumentException();
539  insertEntry( nIndex );
540  attach( nIndex, xObject, Helper );
541  return;
542  }
543 
544  std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
545 
546  AttachedObject_Impl aTmp;
547  aTmp.xTarget = xObject;
548  aTmp.aHelper = Helper;
549  aCurrentPosition->aObjList.push_back( aTmp );
550 
551  AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
552  rCurObj.aAttachedListenerSeq = std::vector< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
553 
554  if (aCurrentPosition->aEventList.empty())
555  return;
556 
557  Sequence<css::script::EventListener> aEvents(aCurrentPosition->aEventList.size());
558  css::script::EventListener* p = aEvents.getArray();
559  size_t i = 0;
560  for (const auto& rEvent : aCurrentPosition->aEventList)
561  {
562  css::script::EventListener aListener;
563  aListener.AllListener =
564  new AttacherAllListener_Impl(this, rEvent.ScriptType, rEvent.ScriptCode);
565  aListener.Helper = rCurObj.aHelper;
566  aListener.ListenerType = rEvent.ListenerType;
567  aListener.EventMethod = rEvent.EventMethod;
568  aListener.AddListenerParam = rEvent.AddListenerParam;
569  p[i++] = aListener;
570  }
571 
572  try
573  {
574  rCurObj.aAttachedListenerSeq = comphelper::sequenceToContainer<std::vector<Reference< XEventListener >>>(
575  xAttacher->attachMultipleEventListeners(rCurObj.xTarget, aEvents));
576  }
577  catch (const Exception&)
578  {
579  // Fail gracefully.
580  }
581 }
582 
583 
584 void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
585 {
586  Guard< Mutex > aGuard( aLock );
587  //return;
588  if( nIndex < 0 || static_cast< std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
589  throw IllegalArgumentException();
590 
591  std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
592  auto aObjIt = std::find_if(aCurrentPosition->aObjList.begin(), aCurrentPosition->aObjList.end(),
593  [&xObject](const AttachedObject_Impl& rObj) { return rObj.xTarget == xObject; });
594  if (aObjIt != aCurrentPosition->aObjList.end())
595  {
596  sal_Int32 i = 0;
597  for( const auto& rEvt : aCurrentPosition->aEventList )
598  {
599  if( aObjIt->aAttachedListenerSeq[i].is() )
600  {
601  try
602  {
603  xAttacher->removeListener( aObjIt->xTarget, rEvt.ListenerType,
604  rEvt.AddListenerParam, aObjIt->aAttachedListenerSeq[i] );
605  }
606  catch( Exception& )
607  {
608  }
609  }
610  ++i;
611  }
612  aCurrentPosition->aObjList.erase( aObjIt );
613  }
614 }
615 
617 {
618  Guard< Mutex > aGuard( aLock );
619  aScriptListeners.addInterface( aListener );
620 }
621 
623 {
624  Guard< Mutex > aGuard( aLock );
625  aScriptListeners.removeInterface( aListener );
626 }
627 
628 
629 // Methods of XPersistObject
631 {
632  return "com.sun.star.uno.script.EventAttacherManager";
633 }
634 
636 {
637  Guard< Mutex > aGuard( aLock );
638  // Don't run without XMarkableStream
639  Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
640  if( !xMarkStream.is() )
641  return;
642 
643  // Write out the version
644  OutStream->writeShort( 2 );
645 
646  // Remember position for length
647  sal_Int32 nObjLenMark = xMarkStream->createMark();
648  OutStream->writeLong( 0 );
649 
650  OutStream->writeLong( aIndex.size() );
651 
652  // Write out sequences
653  for( const auto& rIx : aIndex )
654  {
655  OutStream->writeLong( rIx.aEventList.size() );
656  for( const auto& rDesc : rIx.aEventList )
657  {
658  OutStream->writeUTF( rDesc.ListenerType );
659  OutStream->writeUTF( rDesc.EventMethod );
660  OutStream->writeUTF( rDesc.AddListenerParam );
661  OutStream->writeUTF( rDesc.ScriptType );
662  OutStream->writeUTF( rDesc.ScriptCode );
663  }
664  }
665 
666  // The length is now known
667  sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
668  xMarkStream->jumpToMark( nObjLenMark );
669  OutStream->writeLong( nObjLen );
670  xMarkStream->jumpToFurthest();
671  xMarkStream->deleteMark( nObjLenMark );
672 }
673 
675 {
676  Guard< Mutex > aGuard( aLock );
677  // Don't run without XMarkableStream
678  Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
679  if( !xMarkStream.is() )
680  return;
681 
682  // Read in the version
683  nVersion = InStream->readShort();
684 
685  // At first there's the data according to version 1 --
686  // this part needs to be kept in later versions.
687  sal_Int32 nLen = InStream->readLong();
688 
689  // Position for comparative purposes
690  sal_Int32 nObjLenMark = xMarkStream->createMark();
691 
692  // Number of read sequences
693  sal_Int32 nItemCount = InStream->readLong();
694 
695  for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
696  {
697  insertEntry( i );
698  // Read the length of the sequence
699  sal_Int32 nSeqLen = InStream->readLong();
700 
701  // Display the sequences and read the descriptions
702  Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
703  ScriptEventDescriptor* pArray = aSEDSeq.getArray();
704  for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
705  {
706  ScriptEventDescriptor& rDesc = pArray[ j ];
707  rDesc.ListenerType = InStream->readUTF();
708  rDesc.EventMethod = InStream->readUTF();
709  rDesc.AddListenerParam = InStream->readUTF();
710  rDesc.ScriptType = InStream->readUTF();
711  rDesc.ScriptCode = InStream->readUTF();
712  }
713  registerScriptEvents( i, aSEDSeq );
714  }
715 
716  // Have we read the specified length?
717  sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
718  if( nRealLen != nLen )
719  {
720  // Only if the StreamVersion is > 1 and the date still follows, can
721  // this be true. Otherwise, something is completely gone.
722  if( nRealLen > nLen || nVersion == 1 )
723  {
724  OSL_FAIL( "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
725  }
726  else
727  { // TODO: Examine if caching the dates would be useful
728  // But for now, it's easier to skip it.
729  sal_Int32 nSkipCount = nLen - nRealLen;
730  InStream->skipBytes( nSkipCount );
731  }
732  }
733  xMarkStream->jumpToFurthest();
734  xMarkStream->deleteMark( nObjLenMark );
735 }
736 
737 } // namespace comphelper
738 
739 
740 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
virtual void SAL_CALL insertEntry(sal_Int32 Index) override
virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString &ListenerType, const OUString &EventMethod, const OUString &removeListenerParam) override
virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor > &ScriptEvents) override
bool hasMoreElements() const
Return true, if there are more elements in the iterator.
Reference< XComponentContext > mxContext
Reference< XIdlReflection > mxCoreReflection
Reference< XEventAttacherManager > createEventAttacherManager(const Reference< XComponentContext > &rxContext)
sal_Int32 addInterface(const css::uno::Reference< css::uno::XInterface > &rxIFace)
Inserts an element into the container.
Reference< XIdlReflection > getReflection()
virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index) override
virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener > &Listener) override
sal_Int32 removeInterface(const css::uno::Reference< css::uno::XInterface > &rxIFace)
Removes an element from the container.
float x
Any SAL_CALL getCaughtException()
virtual void SAL_CALL write(const Reference< XObjectOutputStream > &OutStream) override
OInterfaceContainerHelper2 aScriptListeners
rtl::Reference< ImplEventAttacherManager > mxManager
std::deque< AttacherIndex_Impl > aIndex
Reference< XInterface > xTarget
int i
std::deque< ScriptEventDescriptor > aEventList
Reference< XEventAttacher2 > xAttacher
virtual void SAL_CALL removeEntry(sal_Int32 Index) override
This is the iterator of an InterfaceContainerHelper.
virtual OUString SAL_CALL getServiceName() override
virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface > &Object, const Any &Helper) override
virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index) override
virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface > &xObject) override
virtual void SAL_CALL addScriptListener(const Reference< XScriptListener > &aListener) override
unsigned char sal_uInt8
std::vector< Reference< XEventListener > > aAttachedListenerSeq
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Copy from a container into a Sequence.
Definition: sequence.hxx:182
std::deque< AttachedObject_Impl > aObjList
virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor &ScriptEvent) override
css::uno::XInterface * next()
Return the next element of the iterator.
Reference< XTypeConverter > xConverter
std::deque< AttacherIndex_Impl >::iterator implCheckIndex(sal_Int32 _nIndex)
checks if _nIndex is a valid index, throws an IllegalArgumentException if not...
virtual void SAL_CALL read(const Reference< XObjectInputStream > &InStream) override