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