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