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