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