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