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