1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26
27 //--------------------------------------------------------------------------------------------------------
28 #include <com/sun/star/beans/PropertyValue.hpp>
29
30 #ifndef _COM_SUN_STAR_UTL_URL_HPP_
31 #include <com/sun/star/util/URL.hpp>
32 #endif
33
34 #ifndef _COM_SUN_STAR_UTL_XURLTRANSFORMER_HPP_
35 #include <com/sun/star/util/XURLTransformer.hpp>
36 #endif
37 #include <tools/urlobj.hxx>
38 #include <tools/diagnose_ex.h>
39 #include <svl/macitem.hxx>
40 #include <sfx2/appuno.hxx>
41 #include <sfx2/objsh.hxx>
42 #include <sfx2/sfxbasemodel.hxx>
43 #include <sfx2/evntconf.hxx>
44 #include <unotools/eventcfg.hxx>
45
46 #include <unotools/securityoptions.hxx>
47 #include <comphelper/processfactory.hxx>
48 #include <comphelper/namedvaluecollection.hxx>
49 #include "eventsupplier.hxx"
50
51 #include <sfx2/app.hxx>
52 #include "sfx2/sfxresid.hxx"
53
54 #include <sfx2/sfxsids.hrc>
55 #include "sfxlocal.hrc"
56 #include <sfx2/docfile.hxx>
57 #include <sfx2/viewfrm.hxx>
58 #include <sfx2/frame.hxx>
59
60 //--------------------------------------------------------------------------------------------------------
61
62 #define MACRO_PRFIX "macro://"
63 #define MACRO_POSTFIX "()"
64
65 //--------------------------------------------------------------------------------------------------------
66
67 #define PROPERTYVALUE ::com::sun::star::beans::PropertyValue
68 #define UNO_QUERY ::com::sun::star::uno::UNO_QUERY
69
70 namespace css = ::com::sun::star;
71 using ::com::sun::star::uno::Sequence;
72 using ::com::sun::star::beans::PropertyValue;
73
74 //--------------------------------------------------------------------------------------------------------
75 // --- XNameReplace ---
76 //--------------------------------------------------------------------------------------------------------
replaceByName(const OUSTRING & aName,const ANY & rElement)77 void SAL_CALL SfxEvents_Impl::replaceByName( const OUSTRING & aName, const ANY & rElement )
78 {
79 ::osl::MutexGuard aGuard( maMutex );
80
81 // find the event in the list and replace the data
82 long nCount = maEventNames.getLength();
83 for ( long i=0; i<nCount; i++ )
84 {
85 if ( maEventNames[i] == aName )
86 {
87 // check for correct type of the element
88 if ( !::comphelper::NamedValueCollection::canExtractFrom( rElement ) )
89 throw ILLEGALARGUMENTEXCEPTION();
90 ::comphelper::NamedValueCollection const aEventDescriptor( rElement );
91
92 // create Configuration at first, creation might call this method also and that would overwrite everything
93 // we might have stored before!
94 if ( mpObjShell && !mpObjShell->IsLoading() )
95 mpObjShell->SetModified( sal_True );
96
97 ::comphelper::NamedValueCollection aNormalizedDescriptor;
98 NormalizeMacro( aEventDescriptor, aNormalizedDescriptor, mpObjShell );
99
100 ::rtl::OUString sType;
101 if ( ( aNormalizedDescriptor.size() == 1 )
102 && ( aNormalizedDescriptor.has( PROP_EVENT_TYPE ) == 0 )
103 && ( aNormalizedDescriptor.get( PROP_EVENT_TYPE ) >>= sType )
104 && ( sType.getLength() == 0 )
105 )
106 {
107 // An empty event type means no binding. Therefore reset data
108 // to reflect that state.
109 // (that's for compatibility only. Nowadays, the Tools/Customize dialog should
110 // set an empty sequence to indicate the request for resetting the assignment.)
111 OSL_ENSURE( false, "legacy event assignment format detected" );
112 aNormalizedDescriptor.clear();
113 }
114
115 if ( !aNormalizedDescriptor.empty() )
116 {
117 maEventData[i] <<= aNormalizedDescriptor.getPropertyValues();
118 }
119 else
120 {
121 maEventData[i].clear();
122 }
123 return;
124 }
125 }
126
127 throw NOSUCHELEMENTEXCEPTION();
128 }
129
130 //--------------------------------------------------------------------------------------------------------
131 // --- XNameAccess ---
132 //--------------------------------------------------------------------------------------------------------
getByName(const OUSTRING & aName)133 ANY SAL_CALL SfxEvents_Impl::getByName( const OUSTRING& aName )
134 {
135 ::osl::MutexGuard aGuard( maMutex );
136
137 // find the event in the list and return the data
138
139 long nCount = maEventNames.getLength();
140
141 for ( long i=0; i<nCount; i++ )
142 {
143 if ( maEventNames[i] == aName )
144 return maEventData[i];
145 }
146
147 throw NOSUCHELEMENTEXCEPTION();
148 }
149
150 //--------------------------------------------------------------------------------------------------------
getElementNames()151 SEQUENCE< OUSTRING > SAL_CALL SfxEvents_Impl::getElementNames()
152 {
153 return maEventNames;
154 }
155
156 //--------------------------------------------------------------------------------------------------------
hasByName(const OUSTRING & aName)157 sal_Bool SAL_CALL SfxEvents_Impl::hasByName( const OUSTRING& aName )
158 {
159 ::osl::MutexGuard aGuard( maMutex );
160
161 // find the event in the list and return the data
162
163 long nCount = maEventNames.getLength();
164
165 for ( long i=0; i<nCount; i++ )
166 {
167 if ( maEventNames[i] == aName )
168 return sal_True;
169 }
170
171 return sal_False;
172 }
173
174 //--------------------------------------------------------------------------------------------------------
175 // --- XElementAccess ( parent of XNameAccess ) ---
176 //--------------------------------------------------------------------------------------------------------
getElementType()177 UNOTYPE SAL_CALL SfxEvents_Impl::getElementType()
178 {
179 UNOTYPE aElementType = ::getCppuType( (const SEQUENCE < PROPERTYVALUE > *)0 );
180 return aElementType;
181 }
182
183 //--------------------------------------------------------------------------------------------------------
hasElements()184 sal_Bool SAL_CALL SfxEvents_Impl::hasElements()
185 {
186 ::osl::MutexGuard aGuard( maMutex );
187
188 if ( maEventNames.getLength() )
189 return sal_True;
190 else
191 return sal_False;
192 }
193
Execute(ANY & aEventData,const css::document::DocumentEvent & aTrigger,SfxObjectShell * pDoc)194 static void Execute( ANY& aEventData, const css::document::DocumentEvent& aTrigger, SfxObjectShell* pDoc )
195 {
196 SEQUENCE < PROPERTYVALUE > aProperties;
197 if ( aEventData >>= aProperties )
198 {
199 OUSTRING aPrefix = OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_PRFIX ) );
200 OUSTRING aType;
201 OUSTRING aScript;
202 OUSTRING aLibrary;
203 OUSTRING aMacroName;
204 OUSTRING aReferer;
205
206 sal_Int32 nCount = aProperties.getLength();
207
208 if ( !nCount )
209 return;
210
211 sal_Int32 nIndex = 0;
212 while ( nIndex < nCount )
213 {
214 if ( aProperties[ nIndex ].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 )
215 aProperties[ nIndex ].Value >>= aType;
216 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_SCRIPT ) == 0 )
217 aProperties[ nIndex ].Value >>= aScript;
218 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_LIBRARY ) == 0 )
219 aProperties[ nIndex ].Value >>= aLibrary;
220 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_MACRO_NAME ) == 0 )
221 aProperties[ nIndex ].Value >>= aMacroName;
222 else if ( aProperties[ nIndex ].Name.compareToAscii( "Referer" ) == 0 )
223 aProperties[ nIndex ].Value >>= aReferer;
224 else {
225 DBG_ERROR("Unknown property value!");
226 }
227 nIndex += 1;
228 }
229
230 if ( aType.compareToAscii( STAR_BASIC ) == 0 && aScript.getLength() )
231 {
232 com::sun::star::uno::Any aAny;
233 SfxMacroLoader::loadMacro( aScript, aAny, aReferer, pDoc );
234 }
235 else if ( aType.compareToAscii( "Service" ) == 0 ||
236 aType.compareToAscii( "Script" ) == 0 )
237 {
238 if ( aScript.getLength() )
239 {
240 SfxViewFrame* pView = pDoc ?
241 SfxViewFrame::GetFirst( pDoc ) :
242 SfxViewFrame::Current();
243
244 ::com::sun::star::uno::Reference
245 < ::com::sun::star::util::XURLTransformer > xTrans(
246 ::comphelper::getProcessServiceFactory()->createInstance(
247 rtl::OUString::createFromAscii(
248 "com.sun.star.util.URLTransformer" ) ),
249 UNO_QUERY );
250
251 ::com::sun::star::util::URL aURL;
252 aURL.Complete = aScript;
253 xTrans->parseStrict( aURL );
254
255 if ( aURL.Protocol.equals( ::rtl::OUString::createFromAscii( "vnd.sun.star.script:" ) ) )
256 {
257 ::com::sun::star::uno::Reference
258 < ::com::sun::star::frame::XDispatchProvider > xProv;
259
260 if ( pView != NULL )
261 {
262 xProv = ::com::sun::star::uno::Reference
263 < ::com::sun::star::frame::XDispatchProvider > (
264 pView->GetFrame().GetFrameInterface(), UNO_QUERY );
265 }
266 else
267 {
268 xProv = ::com::sun::star::uno::Reference
269 < ::com::sun::star::frame::XDispatchProvider > (
270 ::comphelper::getProcessServiceFactory()->createInstance(
271 rtl::OUString::createFromAscii(
272 "com.sun.star.frame.Desktop" ) ),
273 UNO_QUERY );
274 }
275
276 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatch > xDisp;
277 if ( xProv.is() )
278 xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
279
280 if ( xDisp.is() )
281 {
282 //::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue > aArgs(1);
283 //aArgs[0].Name = rtl::OUString::createFromAscii("Referer");
284 //aArs[0].Value <<= ::rtl::OUString( pDoc->GetMedium()->GetName() );
285 //xDisp->dispatch( aURL, aArgs );
286
287 css::beans::PropertyValue aEventParam;
288 aEventParam.Value <<= aTrigger;
289 css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs( &aEventParam, 1 );
290 xDisp->dispatch( aURL, aDispatchArgs );
291 }
292 }
293 }
294 }
295 else if ( aType.getLength() == 0 )
296 {
297 // Empty type means no active binding for the event. Just ignore do nothing.
298 }
299 else
300 {
301 DBG_ERRORFILE( "notifyEvent(): Unsupported event type" );
302 }
303 }
304 }
305
306 //--------------------------------------------------------------------------------------------------------
307 // --- ::document::XEventListener ---
308 //--------------------------------------------------------------------------------------------------------
notifyEvent(const DOCEVENTOBJECT & aEvent)309 void SAL_CALL SfxEvents_Impl::notifyEvent( const DOCEVENTOBJECT& aEvent )
310 {
311 ::osl::ClearableMutexGuard aGuard( maMutex );
312
313 // get the event name, find the coresponding data, execute the data
314
315 OUSTRING aName = aEvent.EventName;
316 long nCount = maEventNames.getLength();
317 long nIndex = 0;
318 sal_Bool bFound = sal_False;
319
320 while ( !bFound && ( nIndex < nCount ) )
321 {
322 if ( maEventNames[nIndex] == aName )
323 bFound = sal_True;
324 else
325 nIndex += 1;
326 }
327
328 if ( !bFound )
329 return;
330
331 ANY aEventData = maEventData[ nIndex ];
332 aGuard.clear();
333 Execute( aEventData, css::document::DocumentEvent(aEvent.Source, aEvent.EventName, NULL, css::uno::Any()), mpObjShell );
334 }
335
336 //--------------------------------------------------------------------------------------------------------
337 // --- ::lang::XEventListener ---
338 //--------------------------------------------------------------------------------------------------------
disposing(const EVENTOBJECT &)339 void SAL_CALL SfxEvents_Impl::disposing( const EVENTOBJECT& /*Source*/ )
340 {
341 ::osl::MutexGuard aGuard( maMutex );
342
343 if ( mxBroadcaster.is() )
344 {
345 mxBroadcaster->removeEventListener( this );
346 mxBroadcaster = NULL;
347 }
348 }
349
350 //--------------------------------------------------------------------------------------------------------
351 //
352 //--------------------------------------------------------------------------------------------------------
SfxEvents_Impl(SfxObjectShell * pShell,REFERENCE<XEVENTBROADCASTER> xBroadcaster)353 SfxEvents_Impl::SfxEvents_Impl( SfxObjectShell* pShell,
354 REFERENCE< XEVENTBROADCASTER > xBroadcaster )
355 {
356 // get the list of supported events and store it
357 if ( pShell )
358 maEventNames = pShell->GetEventNames();
359 else
360 maEventNames = GlobalEventConfig().getElementNames();
361
362 maEventData = SEQUENCE < ANY > ( maEventNames.getLength() );
363
364 mpObjShell = pShell;
365 mxBroadcaster = xBroadcaster;
366
367 if ( mxBroadcaster.is() )
368 mxBroadcaster->addEventListener( this );
369 }
370
371 //--------------------------------------------------------------------------------------------------------
~SfxEvents_Impl()372 SfxEvents_Impl::~SfxEvents_Impl()
373 {
374 }
375
376 //--------------------------------------------------------------------------------------------------------
ConvertToMacro(const ANY & rElement,SfxObjectShell * pObjShell,sal_Bool bNormalizeMacro)377 SvxMacro* SfxEvents_Impl::ConvertToMacro( const ANY& rElement, SfxObjectShell* pObjShell, sal_Bool bNormalizeMacro )
378 {
379 SvxMacro* pMacro = NULL;
380 SEQUENCE < PROPERTYVALUE > aProperties;
381 ANY aAny;
382 if ( bNormalizeMacro )
383 NormalizeMacro( rElement, aAny, pObjShell );
384 else
385 aAny = rElement;
386
387 if ( aAny >>= aProperties )
388 {
389 OUSTRING aType;
390 OUSTRING aScriptURL;
391 OUSTRING aLibrary;
392 OUSTRING aMacroName;
393
394 long nCount = aProperties.getLength();
395 long nIndex = 0;
396
397 if ( !nCount )
398 return pMacro;
399
400 while ( nIndex < nCount )
401 {
402 if ( aProperties[ nIndex ].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 )
403 aProperties[ nIndex ].Value >>= aType;
404 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_SCRIPT ) == 0 )
405 aProperties[ nIndex ].Value >>= aScriptURL;
406 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_LIBRARY ) == 0 )
407 aProperties[ nIndex ].Value >>= aLibrary;
408 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_MACRO_NAME ) == 0 )
409 aProperties[ nIndex ].Value >>= aMacroName;
410 else {
411 DBG_ERROR("Unknown property value!");
412 }
413 nIndex += 1;
414 }
415
416 // Get the type
417 ScriptType eType( STARBASIC );
418 if ( aType.compareToAscii( STAR_BASIC ) == COMPARE_EQUAL )
419 eType = STARBASIC;
420 else if ( aType.compareToAscii( "Script" ) == COMPARE_EQUAL && aScriptURL.getLength() )
421 eType = EXTENDED_STYPE;
422 else if ( aType.compareToAscii( SVX_MACRO_LANGUAGE_JAVASCRIPT ) == COMPARE_EQUAL )
423 eType = JAVASCRIPT;
424 else {
425 DBG_ERRORFILE( "ConvertToMacro: Unknown macro type" );
426 }
427
428 if ( aMacroName.getLength() )
429 {
430 if ( aLibrary.compareToAscii("application") == 0 )
431 aLibrary = SFX_APP()->GetName();
432 else
433 aLibrary = ::rtl::OUString();
434 pMacro = new SvxMacro( aMacroName, aLibrary, eType );
435 }
436 else if ( eType == EXTENDED_STYPE )
437 pMacro = new SvxMacro( aScriptURL, aType );
438 }
439
440 return pMacro;
441 }
442
NormalizeMacro(const ANY & rEvent,ANY & rRet,SfxObjectShell * pDoc)443 void SfxEvents_Impl::NormalizeMacro( const ANY& rEvent, ANY& rRet, SfxObjectShell* pDoc )
444 {
445 const ::comphelper::NamedValueCollection aEventDescriptor( rEvent );
446 ::comphelper::NamedValueCollection aEventDescriptorOut;
447
448 NormalizeMacro( aEventDescriptor, aEventDescriptorOut, pDoc );
449
450 rRet <<= aEventDescriptorOut.getPropertyValues();
451 }
452
NormalizeMacro(const::comphelper::NamedValueCollection & i_eventDescriptor,::comphelper::NamedValueCollection & o_normalizedDescriptor,SfxObjectShell * i_document)453 void SfxEvents_Impl::NormalizeMacro( const ::comphelper::NamedValueCollection& i_eventDescriptor,
454 ::comphelper::NamedValueCollection& o_normalizedDescriptor, SfxObjectShell* i_document )
455 {
456 SfxObjectShell* pDoc = i_document;
457 if ( !pDoc )
458 pDoc = SfxObjectShell::Current();
459
460 ::rtl::OUString aType = i_eventDescriptor.getOrDefault( PROP_EVENT_TYPE, ::rtl::OUString() );
461 ::rtl::OUString aScript = i_eventDescriptor.getOrDefault( PROP_SCRIPT, ::rtl::OUString() );
462 ::rtl::OUString aLibrary = i_eventDescriptor.getOrDefault( PROP_LIBRARY, ::rtl::OUString() );
463 ::rtl::OUString aMacroName = i_eventDescriptor.getOrDefault( PROP_MACRO_NAME, ::rtl::OUString() );
464
465 if ( aType.getLength() )
466 o_normalizedDescriptor.put( PROP_EVENT_TYPE, aType );
467 if ( aScript.getLength() )
468 o_normalizedDescriptor.put( PROP_SCRIPT, aScript );
469
470 if ( aType.compareToAscii( STAR_BASIC ) == 0 )
471 {
472 if ( aScript.getLength() )
473 {
474 if ( !aMacroName.getLength() || !aLibrary.getLength() )
475 {
476 sal_Int32 nHashPos = aScript.indexOf( '/', 8 );
477 sal_Int32 nArgsPos = aScript.indexOf( '(' );
478 if ( ( nHashPos != STRING_NOTFOUND ) && ( nHashPos < nArgsPos ) )
479 {
480 OUSTRING aBasMgrName( INetURLObject::decode( aScript.copy( 8, nHashPos-8 ), INET_HEX_ESCAPE, INetURLObject::DECODE_WITH_CHARSET ) );
481 if ( aBasMgrName.compareToAscii(".") == 0 )
482 aLibrary = pDoc->GetTitle();
483 /*
484 else if ( aBasMgrName.getLength() )
485 aLibrary = aBasMgrName;
486 */
487 else
488 aLibrary = SFX_APP()->GetName();
489
490 // Get the macro name
491 aMacroName = aScript.copy( nHashPos+1, nArgsPos - nHashPos - 1 );
492 }
493 else
494 {
495 DBG_ERRORFILE( "ConvertToMacro: Unknown macro url format" );
496 }
497 }
498 }
499 else if ( aMacroName.getLength() )
500 {
501 aScript = OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_PRFIX ) );
502 if ( aLibrary.compareTo( SFX_APP()->GetName() ) != 0 && aLibrary.compareToAscii("StarDesktop") != 0 && aLibrary.compareToAscii("application") != 0 )
503 aScript += String('.');
504
505 aScript += String('/');
506 aScript += aMacroName;
507 aScript += OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_POSTFIX ) );
508 }
509 else
510 // wrong properties
511 return;
512
513 if ( aLibrary.compareToAscii("document") != 0 )
514 {
515 if ( !aLibrary.getLength() || (pDoc && ( String(aLibrary) == pDoc->GetTitle( SFX_TITLE_APINAME ) || String(aLibrary) == pDoc->GetTitle() )) )
516 aLibrary = String::CreateFromAscii("document");
517 else
518 aLibrary = String::CreateFromAscii("application");
519 }
520
521 o_normalizedDescriptor.put( PROP_SCRIPT, aScript );
522 o_normalizedDescriptor.put( PROP_LIBRARY, aLibrary );
523 o_normalizedDescriptor.put( PROP_MACRO_NAME, aMacroName );
524 }
525 }
526
ModelCollectionEnumeration(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)527 ModelCollectionEnumeration::ModelCollectionEnumeration(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
528 : ModelCollectionMutexBase( )
529 , m_xSMGR (xSMGR )
530 , m_pEnumerationIt (m_lModels.begin())
531 {
532 }
533
~ModelCollectionEnumeration()534 ModelCollectionEnumeration::~ModelCollectionEnumeration()
535 {
536 }
537
setModelList(const TModelList & rList)538 void ModelCollectionEnumeration::setModelList(const TModelList& rList)
539 {
540 // SAFE ->
541 ::osl::ResettableMutexGuard aLock(m_aLock);
542 m_lModels = rList;
543 m_pEnumerationIt = m_lModels.begin();
544 aLock.clear();
545 // <- SAFE
546 }
547
hasMoreElements()548 sal_Bool SAL_CALL ModelCollectionEnumeration::hasMoreElements()
549 {
550 // SAFE ->
551 ::osl::ResettableMutexGuard aLock(m_aLock);
552 return (m_pEnumerationIt != m_lModels.end());
553 // <- SAFE
554 }
555
nextElement()556 css::uno::Any SAL_CALL ModelCollectionEnumeration::nextElement()
557 {
558 // SAFE ->
559 ::osl::ResettableMutexGuard aLock(m_aLock);
560 if (m_pEnumerationIt == m_lModels.end())
561 throw css::container::NoSuchElementException(
562 ::rtl::OUString::createFromAscii("End of model enumeration reached."),
563 static_cast< css::container::XEnumeration* >(this));
564 css::uno::Reference< css::frame::XModel > xModel(*m_pEnumerationIt, UNO_QUERY);
565 ++m_pEnumerationIt;
566 aLock.clear();
567 // <- SAFE
568
569 return css::uno::makeAny(xModel);
570 }
571
572 SFX_IMPL_XSERVICEINFO( SfxGlobalEvents_Impl, "com.sun.star.frame.GlobalEventBroadcaster", "com.sun.star.comp.sfx2.GlobalEventBroadcaster" )
573 SFX_IMPL_ONEINSTANCEFACTORY( SfxGlobalEvents_Impl );
574
575 //-----------------------------------------------------------------------------
SfxGlobalEvents_Impl(const com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & xSMGR)576 SfxGlobalEvents_Impl::SfxGlobalEvents_Impl( const com::sun::star::uno::Reference < ::com::sun::star::lang::XMultiServiceFactory >& xSMGR)
577 : ModelCollectionMutexBase( )
578 , m_xSMGR (xSMGR )
579 , m_aLegacyListeners (m_aLock)
580 , m_aDocumentListeners (m_aLock)
581 , pImp (0 )
582 {
583 m_refCount++;
584 SFX_APP();
585 pImp = new GlobalEventConfig();
586 m_xEvents = pImp;
587 m_xJobExecutorListener = css::uno::Reference< css::document::XEventListener >(
588 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.task.JobExecutor")),
589 UNO_QUERY);
590 m_refCount--;
591 }
592
593 //-----------------------------------------------------------------------------
~SfxGlobalEvents_Impl()594 SfxGlobalEvents_Impl::~SfxGlobalEvents_Impl()
595 {
596 }
597
598 //-----------------------------------------------------------------------------
getEvents()599 css::uno::Reference< css::container::XNameReplace > SAL_CALL SfxGlobalEvents_Impl::getEvents()
600 {
601 // SAFE ->
602 ::osl::ResettableMutexGuard aLock(m_aLock);
603 return m_xEvents;
604 // <- SAFE
605 }
606
607 //-----------------------------------------------------------------------------
addEventListener(const css::uno::Reference<css::document::XEventListener> & xListener)608 void SAL_CALL SfxGlobalEvents_Impl::addEventListener(const css::uno::Reference< css::document::XEventListener >& xListener)
609 {
610 // container is threadsafe
611 m_aLegacyListeners.addInterface(xListener);
612 }
613
614 //-----------------------------------------------------------------------------
removeEventListener(const css::uno::Reference<css::document::XEventListener> & xListener)615 void SAL_CALL SfxGlobalEvents_Impl::removeEventListener(const css::uno::Reference< css::document::XEventListener >& xListener)
616 {
617 // container is threadsafe
618 m_aLegacyListeners.removeInterface(xListener);
619 }
620
621 //-----------------------------------------------------------------------------
addDocumentEventListener(const css::uno::Reference<css::document::XDocumentEventListener> & _Listener)622 void SAL_CALL SfxGlobalEvents_Impl::addDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& _Listener )
623 {
624 m_aDocumentListeners.addInterface( _Listener );
625 }
626
627 //-----------------------------------------------------------------------------
removeDocumentEventListener(const css::uno::Reference<css::document::XDocumentEventListener> & _Listener)628 void SAL_CALL SfxGlobalEvents_Impl::removeDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& _Listener )
629 {
630 m_aDocumentListeners.removeInterface( _Listener );
631 }
632
633 //-----------------------------------------------------------------------------
notifyDocumentEvent(const::rtl::OUString &,const css::uno::Reference<css::frame::XController2> &,const css::uno::Any &)634 void SAL_CALL SfxGlobalEvents_Impl::notifyDocumentEvent( const ::rtl::OUString& /*_EventName*/,
635 const css::uno::Reference< css::frame::XController2 >& /*_ViewController*/, const css::uno::Any& /*_Supplement*/ )
636 {
637 // we're a multiplexer only, no chance to generate artificial events here
638 throw css::lang::NoSupportException(::rtl::OUString(), *this);
639 }
640
641 //-----------------------------------------------------------------------------
notifyEvent(const css::document::EventObject & aEvent)642 void SAL_CALL SfxGlobalEvents_Impl::notifyEvent(const css::document::EventObject& aEvent)
643 {
644 css::document::DocumentEvent aDocEvent(aEvent.Source, aEvent.EventName, NULL, css::uno::Any());
645 implts_notifyJobExecution(aEvent);
646 implts_checkAndExecuteEventBindings(aDocEvent);
647 implts_notifyListener(aDocEvent);
648 }
649
650 //-----------------------------------------------------------------------------
documentEventOccured(const::css::document::DocumentEvent & _Event)651 void SAL_CALL SfxGlobalEvents_Impl::documentEventOccured( const ::css::document::DocumentEvent& _Event )
652 {
653 implts_notifyJobExecution(css::document::EventObject(_Event.Source, _Event.EventName));
654 implts_checkAndExecuteEventBindings(_Event);
655 implts_notifyListener(_Event);
656 }
657
658 //-----------------------------------------------------------------------------
disposing(const css::lang::EventObject & aEvent)659 void SAL_CALL SfxGlobalEvents_Impl::disposing(const css::lang::EventObject& aEvent)
660 {
661 css::uno::Reference< css::frame::XModel > xDoc(aEvent.Source, UNO_QUERY);
662
663 // SAFE ->
664 ::osl::ResettableMutexGuard aLock(m_aLock);
665 TModelList::iterator pIt = impl_searchDoc(xDoc);
666 if (pIt != m_lModels.end())
667 m_lModels.erase(pIt);
668 aLock.clear();
669 // <- SAFE
670 }
671
672 //-----------------------------------------------------------------------------
has(const css::uno::Any & aElement)673 sal_Bool SAL_CALL SfxGlobalEvents_Impl::has(const css::uno::Any& aElement)
674 {
675 css::uno::Reference< css::frame::XModel > xDoc;
676 aElement >>= xDoc;
677
678 sal_Bool bHas = sal_False;
679
680 // SAFE ->
681 ::osl::ResettableMutexGuard aLock(m_aLock);
682 TModelList::iterator pIt = impl_searchDoc(xDoc);
683 if (pIt != m_lModels.end())
684 bHas = sal_True;
685 aLock.clear();
686 // <- SAFE
687
688 return bHas;
689 }
690
691 //-----------------------------------------------------------------------------
insert(const css::uno::Any & aElement)692 void SAL_CALL SfxGlobalEvents_Impl::insert( const css::uno::Any& aElement )
693 {
694 css::uno::Reference< css::frame::XModel > xDoc;
695 aElement >>= xDoc;
696 if (!xDoc.is())
697 throw css::lang::IllegalArgumentException(
698 ::rtl::OUString::createFromAscii("Can't locate at least the model parameter."),
699 static_cast< css::container::XSet* >(this),
700 0);
701
702 // SAFE ->
703 ::osl::ResettableMutexGuard aLock(m_aLock);
704 TModelList::iterator pIt = impl_searchDoc(xDoc);
705 if (pIt != m_lModels.end())
706 throw css::container::ElementExistException(
707 ::rtl::OUString(),
708 static_cast< css::container::XSet* >(this));
709 m_lModels.push_back(xDoc);
710 aLock.clear();
711 // <- SAFE
712
713 css::uno::Reference< css::document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, UNO_QUERY );
714 if (xDocBroadcaster.is())
715 xDocBroadcaster->addDocumentEventListener(this);
716 else
717 {
718 // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster
719 css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xDoc, UNO_QUERY);
720 if (xBroadcaster.is())
721 xBroadcaster->addEventListener(static_cast< css::document::XEventListener* >(this));
722 }
723 }
724
725 //-----------------------------------------------------------------------------
remove(const css::uno::Any & aElement)726 void SAL_CALL SfxGlobalEvents_Impl::remove( const css::uno::Any& aElement )
727 {
728 css::uno::Reference< css::frame::XModel > xDoc;
729 aElement >>= xDoc;
730 if (!xDoc.is())
731 throw css::lang::IllegalArgumentException(
732 ::rtl::OUString::createFromAscii("Can't locate at least the model parameter."),
733 static_cast< css::container::XSet* >(this),
734 0);
735
736 // SAFE ->
737 ::osl::ResettableMutexGuard aLock(m_aLock);
738 TModelList::iterator pIt = impl_searchDoc(xDoc);
739 if (pIt == m_lModels.end())
740 throw css::container::NoSuchElementException(
741 ::rtl::OUString(),
742 static_cast< css::container::XSet* >(this));
743 m_lModels.erase(pIt);
744 aLock.clear();
745 // <- SAFE
746
747 css::uno::Reference< css::document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, UNO_QUERY );
748 if (xDocBroadcaster.is())
749 xDocBroadcaster->removeDocumentEventListener(this);
750 else
751 {
752 // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster
753 css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xDoc, UNO_QUERY);
754 if (xBroadcaster.is())
755 xBroadcaster->removeEventListener(static_cast< css::document::XEventListener* >(this));
756 }
757 }
758
759 //-----------------------------------------------------------------------------
createEnumeration()760 css::uno::Reference< css::container::XEnumeration > SAL_CALL SfxGlobalEvents_Impl::createEnumeration()
761 {
762 // SAFE ->
763 ::osl::ResettableMutexGuard aLock(m_aLock);
764 ModelCollectionEnumeration* pEnum = new ModelCollectionEnumeration(m_xSMGR);
765 pEnum->setModelList(m_lModels);
766 css::uno::Reference< css::container::XEnumeration > xEnum(
767 static_cast< css::container::XEnumeration* >(pEnum),
768 UNO_QUERY);
769 aLock.clear();
770 // <- SAFE
771
772 return xEnum;
773 }
774
775 //-----------------------------------------------------------------------------
getElementType()776 css::uno::Type SAL_CALL SfxGlobalEvents_Impl::getElementType()
777 {
778 return ::getCppuType(static_cast< css::uno::Reference< css::frame::XModel >* >(NULL));
779 }
780
781 //-----------------------------------------------------------------------------
hasElements()782 sal_Bool SAL_CALL SfxGlobalEvents_Impl::hasElements()
783 {
784 // SAFE ->
785 ::osl::ResettableMutexGuard aLock(m_aLock);
786 return (m_lModels.size()>0);
787 // <- SAFE
788 }
789
790 //-----------------------------------------------------------------------------
implts_notifyJobExecution(const css::document::EventObject & aEvent)791 void SfxGlobalEvents_Impl::implts_notifyJobExecution(const css::document::EventObject& aEvent)
792 {
793 try
794 {
795 // SAFE ->
796 ::osl::ResettableMutexGuard aLock(m_aLock);
797 css::uno::Reference< css::document::XEventListener > xJobExecutor(m_xJobExecutorListener);
798 aLock.clear();
799 // <- SAFE
800 if (xJobExecutor.is())
801 xJobExecutor->notifyEvent(aEvent);
802 }
803 catch(const css::uno::RuntimeException& exRun)
804 { throw exRun; }
805 catch(const css::uno::Exception&)
806 {}
807 }
808
809 //-----------------------------------------------------------------------------
implts_checkAndExecuteEventBindings(const css::document::DocumentEvent & aEvent)810 void SfxGlobalEvents_Impl::implts_checkAndExecuteEventBindings(const css::document::DocumentEvent& aEvent)
811 {
812 try
813 {
814 // SAFE ->
815 ::osl::ResettableMutexGuard aLock(m_aLock);
816 css::uno::Reference< css::container::XNameReplace > xEvents = m_xEvents;
817 aLock.clear();
818 // <- SAFE
819
820 css::uno::Any aAny;
821 if ( xEvents.is() && xEvents->hasByName( aEvent.EventName ) )
822 aAny = xEvents->getByName(aEvent.EventName);
823 Execute(aAny, aEvent, 0);
824 }
825 catch ( css::uno::RuntimeException const & )
826 {
827 throw;
828 }
829 catch ( css::uno::Exception const & )
830 {
831 DBG_UNHANDLED_EXCEPTION();
832 }
833 }
834
835 //-----------------------------------------------------------------------------
implts_notifyListener(const css::document::DocumentEvent & aEvent)836 void SfxGlobalEvents_Impl::implts_notifyListener(const css::document::DocumentEvent& aEvent)
837 {
838 // containers are threadsafe
839 css::document::EventObject aLegacyEvent(aEvent.Source, aEvent.EventName);
840 m_aLegacyListeners.notifyEach( &css::document::XEventListener::notifyEvent, aLegacyEvent );
841
842 m_aDocumentListeners.notifyEach( &css::document::XDocumentEventListener::documentEventOccured, aEvent );
843 }
844
845 //-----------------------------------------------------------------------------
846 // not threadsafe ... must be locked from outside!
impl_searchDoc(const css::uno::Reference<css::frame::XModel> & xModel)847 TModelList::iterator SfxGlobalEvents_Impl::impl_searchDoc(const css::uno::Reference< css::frame::XModel >& xModel)
848 {
849 if (!xModel.is())
850 return m_lModels.end();
851
852 TModelList::iterator pIt;
853 for ( pIt = m_lModels.begin();
854 pIt != m_lModels.end() ;
855 ++pIt )
856 {
857 css::uno::Reference< css::frame::XModel > xContainerDoc(*pIt, UNO_QUERY);
858 if (xContainerDoc == xModel)
859 break;
860 }
861
862 return pIt;
863 }
864