1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_________________________________________________________________________________________________________________
32 //	my own includes
33 //_________________________________________________________________________________________________________________
34 #include <loadenv/loadenv.hxx>
35 
36 #ifndef __FRAMEWORK_LOADENV_TARGETHELPER_HXX_
37 #include <loadenv/targethelper.hxx>
38 #endif
39 
40 #ifndef __FRAMEWORK_DESKTOP_HXX_
41 #include <services/desktop.hxx>
42 #endif
43 #include <helper/ocomponentaccess.hxx>
44 #include <dispatch/dispatchprovider.hxx>
45 
46 #ifndef __FRAMEWORK_DISPATCH_INTERCEPTIONHELPER_HXX_
47 #include <dispatch/interceptionhelper.hxx>
48 #endif
49 #include <classes/taskcreator.hxx>
50 #include <threadhelp/transactionguard.hxx>
51 #include <threadhelp/writeguard.hxx>
52 #include <threadhelp/readguard.hxx>
53 #include <services.h>
54 #include <general.h>
55 #include <properties.h>
56 
57 #include <classes/resource.hrc>
58 #include <classes/fwkresid.hxx>
59 
60 //_________________________________________________________________________________________________________________
61 //	interface includes
62 //_________________________________________________________________________________________________________________
63 #include <com/sun/star/beans/PropertyAttribute.hpp>
64 #include <com/sun/star/frame/FrameSearchFlag.hpp>
65 #include <com/sun/star/awt/XToolkit.hpp>
66 #include <com/sun/star/awt/XWindow.hpp>
67 #include <com/sun/star/awt/XWindowPeer.hpp>
68 #include <com/sun/star/awt/WindowDescriptor.hpp>
69 #include <com/sun/star/awt/WindowAttribute.hpp>
70 #include <com/sun/star/awt/PosSize.hpp>
71 #include <com/sun/star/util/XURLTransformer.hpp>
72 #include <com/sun/star/task/XInteractionAbort.hpp>
73 #include <com/sun/star/task/XInteractionApprove.hpp>
74 #include <com/sun/star/document/XInteractionFilterSelect.hpp>
75 #include <com/sun/star/document/AmbigousFilterRequest.hpp>
76 #include <com/sun/star/task/ErrorCodeRequest.hpp>
77 #include <com/sun/star/ucb/InteractiveIOException.hpp>
78 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
79 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
80 #include <com/sun/star/frame/DispatchResultState.hpp>
81 #include <com/sun/star/lang/IllegalArgumentException.hpp>
82 #include <com/sun/star/lang/DisposedException.hpp>
83 #include <com/sun/star/util/XCloseable.hpp>
84 #include <com/sun/star/document/MacroExecMode.hpp>
85 #include <com/sun/star/document/UpdateDocMode.hpp>
86 #include <com/sun/star/frame/XTerminateListener2.hpp>
87 
88 //_________________________________________________________________________________________________________________
89 //	includes of other projects
90 //_________________________________________________________________________________________________________________
91 #include <cppuhelper/queryinterface.hxx>
92 #include <cppuhelper/typeprovider.hxx>
93 #include <cppuhelper/factory.hxx>
94 #include <cppuhelper/proptypehlp.hxx>
95 #include <rtl/ustrbuf.hxx>
96 #include <rtl/logfile.hxx>
97 #include <vcl/svapp.hxx>
98 
99 #ifndef __RSC
100 #include <tools/errinf.hxx>
101 #endif
102 #include <comphelper/extract.hxx>
103 
104 #include <fwkdllapi.h>
105 
106 //_________________________________________________________________________________________________________________
107 //	namespace
108 //_________________________________________________________________________________________________________________
109 
110 namespace framework{
111 
112 //_________________________________________________________________________________________________________________
113 //	non exported const
114 //_________________________________________________________________________________________________________________
115 
116 //_________________________________________________________________________________________________________________
117 //	non exported definitions
118 //_________________________________________________________________________________________________________________
119 
120 //_________________________________________________________________________________________________________________
121 //	declarations
122 //_________________________________________________________________________________________________________________
123 
124 //*****************************************************************************************************************
125 //	XInterface, XTypeProvider, XServiceInfo
126 //*****************************************************************************************************************
127 DEFINE_XINTERFACE_15                    (   Desktop                                                  ,
128                                             OWeakObject                                              ,
129                                             DIRECT_INTERFACE( css::lang::XTypeProvider              ),
130                                             DIRECT_INTERFACE( css::lang::XServiceInfo               ),
131                                             DIRECT_INTERFACE( css::frame::XDesktop                  ),
132                                             DIRECT_INTERFACE( css::frame::XComponentLoader          ),
133                                             DIRECT_INTERFACE( css::frame::XTasksSupplier            ),
134                                             DIRECT_INTERFACE( css::frame::XDispatchProvider         ),
135                                             DIRECT_INTERFACE( css::frame::XDispatchProviderInterception),
136                                             DIRECT_INTERFACE( css::frame::XFramesSupplier           ),
137                                             DIRECT_INTERFACE( css::frame::XFrame                    ),
138                                             DIRECT_INTERFACE( css::lang::XComponent                 ),
139                                             DIRECT_INTERFACE( css::frame::XDispatchResultListener   ),
140                                             DIRECT_INTERFACE( css::lang::XEventListener             ),
141                                             DIRECT_INTERFACE( css::task::XInteractionHandler        ),
142                                             DIRECT_INTERFACE( css::beans::XPropertySet				),
143                                             DIRECT_INTERFACE( css::frame::XUntitledNumbers          )
144 										)
145 
146 DEFINE_XTYPEPROVIDER_15                 (   Desktop                                                 ,
147                                             css::lang::XTypeProvider                                ,
148                                             css::lang::XServiceInfo                                 ,
149                                             css::frame::XDesktop                                    ,
150                                             css::frame::XComponentLoader                            ,
151                                             css::frame::XTasksSupplier                              ,
152                                             css::frame::XDispatchProvider                           ,
153                                             css::frame::XDispatchProviderInterception               ,
154                                             css::frame::XFramesSupplier                             ,
155                                             css::frame::XFrame                                      ,
156                                             css::lang::XComponent                                   ,
157                                             css::frame::XDispatchResultListener                     ,
158                                             css::lang::XEventListener                               ,
159                                             css::task::XInteractionHandler                          ,
160                                             css::beans::XPropertySet                                ,
161                                             css::frame::XUntitledNumbers
162 										)
163 
164 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE  (   Desktop                                                 ,
165                                             ::cppu::OWeakObject                                     ,
166                                             SERVICENAME_DESKTOP                                     ,
167 											IMPLEMENTATIONNAME_DESKTOP
168 										)
169 
170 DEFINE_INIT_SERVICE                     (   Desktop,
171                                             {
172                                                 /*Attention
173                                                     I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
174                                                     to create a new instance of this class by our own supported service factory.
175                                                     see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
176                                                 */
177 
178                                                 //-------------------------------------------------------------------------------------------------------------
179                                                 // Initialize a new XFrames-helper-object to handle XIndexAccess and XElementAccess.
180                                                 // We hold member as reference ... not as pointer too!
181                                                 // Attention: We share our frame container with this helper. Container is threadsafe himself ... So I think we can do that.
182                                                 // But look on dispose() for right order of deinitialization.
183                                                 OFrames* pFramesHelper = new OFrames( m_xFactory, this, &m_aChildTaskContainer );
184                                                 m_xFramesHelper = css::uno::Reference< css::frame::XFrames >( static_cast< ::cppu::OWeakObject* >(pFramesHelper), css::uno::UNO_QUERY );
185 
186                                                 //-------------------------------------------------------------------------------------------------------------
187                                                 // Initialize a new dispatchhelper-object to handle dispatches.
188                                                 // We use these helper as slave for our interceptor helper ... not directly!
189                                                 // But he is event listener on THIS instance!
190                                                 DispatchProvider* pDispatchHelper = new DispatchProvider( m_xFactory, this );
191                                                 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( static_cast< ::cppu::OWeakObject* >(pDispatchHelper), css::uno::UNO_QUERY );
192 
193                                                 //-------------------------------------------------------------------------------------------------------------
194                                                 // Initialize a new interception helper object to handle dispatches and implement an interceptor mechanism.
195                                                 // Set created dispatch provider as slowest slave of it.
196                                                 // Hold interception helper by reference only - not by pointer!
197                                                 // So it's easiear to destroy it.
198                                                 InterceptionHelper* pInterceptionHelper = new InterceptionHelper( this, xDispatchProvider );
199                                                 m_xDispatchHelper = css::uno::Reference< css::frame::XDispatchProvider >( static_cast< ::cppu::OWeakObject* >(pInterceptionHelper), css::uno::UNO_QUERY );
200 
201                                                 ::rtl::OUStringBuffer sUntitledPrefix (256);
202                                                 sUntitledPrefix.append      (::rtl::OUString( String( FwkResId( STR_UNTITLED_DOCUMENT ))));
203                                                 sUntitledPrefix.appendAscii (" ");
204 
205                                                 ::comphelper::NumberedCollection* pNumbers = new ::comphelper::NumberedCollection ();
206                                                 m_xTitleNumberGenerator = css::uno::Reference< css::frame::XUntitledNumbers >(static_cast< ::cppu::OWeakObject* >(pNumbers), css::uno::UNO_QUERY_THROW);
207                                                 pNumbers->setOwner          ( static_cast< ::cppu::OWeakObject* >(this) );
208                                                 pNumbers->setUntitledPrefix ( sUntitledPrefix.makeStringAndClear ()     );
209 
210                                                 // Safe impossible cases
211                                                 // We can't work without this helper!
212                                                 LOG_ASSERT2( m_xFramesHelper.is  ()==sal_False, "Desktop::Desktop()", "Frames helper is not valid. XFrames, XIndexAccess and XElementAcces are not supported!\n")
213                                                 LOG_ASSERT2( m_xDispatchHelper.is()==sal_False, "Desktop::Desktop()", "Dispatch helper is not valid. XDispatch will not work correctly!\n"                      )
214 
215                                                 // Enable object for real working!
216                                                 // Otherwise all calls will be rejected ...
217                                                 m_aTransactionManager.setWorkingMode( E_WORK );
218                                             }
219                                         )
220 
221 /*-************************************************************************************************************//**
222     @short      standard constructor to create instance by factory
223     @descr      This constructor initialize a new instance of this class by valid factory,
224                 and will be set valid values on his member and baseclasses.
225 
226     @attention  a)  Don't use your own reference during an UNO-Service-ctor! There is no guarantee, that you
227                     will get over this. (e.g. using of your reference as parameter to initialize some member)
228                     Do such things in DEFINE_INIT_SERVICE() method, which is called automaticly after your ctor!!!
229                 b)  Baseclass OBroadcastHelper is a typedef in namespace cppu!
230                     The microsoft compiler has some problems to handle it right BY using namespace explicitly ::cppu::OBroadcastHelper.
231                     If we write it without a namespace or expand the typedef to OBrodcastHelperVar<...> -> it will be OK!?
232                     I don't know why! (other compiler not tested .. but it works!)
233 
234     @seealso    method DEFINE_INIT_SERVICE()
235 
236     @param      "xFactory" is the multi service manager, which create this instance.
237                 The value must be different from NULL!
238     @return     -
239 
240     @onerror    We throw an ASSERT in debug version or do nothing in relaese version.
241 *//*-*************************************************************************************************************/
242 Desktop::Desktop( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
243 		//	Init baseclasses first
244         //  Attention: Don't change order of initialization!
245         //      ThreadHelpBase is a struct with a lock as member. We can't use a lock as direct member!
246         //      We must garant right initialization and a valid value of this to initialize other baseclasses!
247         :   ThreadHelpBase          ( &Application::GetSolarMutex()                 )
248         ,   TransactionBase         (                                               )
249         ,   ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >           ( m_aLock.getShareableOslMutex()         )
250         ,   ::cppu::OPropertySetHelper  ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) )
251         ,   ::cppu::OWeakObject     (                                               )
252 		// Init member
253 		#ifdef ENABLE_ASSERTIONS
254         ,   m_bIsTerminated         ( sal_False                                     )   // see dispose() for further informations!
255 		#endif
256         ,   m_xFactory              ( xFactory                                      )
257         ,   m_aChildTaskContainer   (                                               )
258         ,   m_aListenerContainer    ( m_aLock.getShareableOslMutex()                )
259         ,   m_xFramesHelper         (                                               )
260         ,   m_xDispatchHelper       (                                               )
261         ,   m_eLoadState            ( E_NOTSET                                      )
262         ,   m_xLastFrame            (                                               )
263         ,   m_aInteractionRequest   (                                               )
264         ,   m_bSuspendQuickstartVeto( sal_False										)
265         ,   m_aCommandOptions       (                                               )
266         ,   m_sName                 (                                               )
267         ,   m_sTitle                (                                               )
268         ,   m_xDispatchRecorderSupplier(                                            )
269         ,   m_xPipeTerminator       (                                               )
270         ,   m_xQuickLauncher        (                                               )
271         ,   m_xSWThreadManager      (                                               )
272         ,   m_xSfxTerminator        (                                               )
273         ,   m_xTitleNumberGenerator (                                               )
274 {
275 	// Safe impossible cases
276 	// We don't accept all incoming parameter.
277     LOG_ASSERT2( implcp_ctor( xFactory ), "Desktop::Desktop()", "Invalid parameter detected!")
278 }
279 
280 /*-************************************************************************************************************//**
281 	@short		standard destructor
282 	@descr		This one do NOTHING! Use dispose() instaed of this.
283 
284 	@seealso	method dispose()
285 
286 	@param		-
287 	@return		-
288 
289 	@onerror	-
290 *//*-*************************************************************************************************************/
291 Desktop::~Desktop()
292 {
293     LOG_ASSERT2( m_bIsTerminated                       ==sal_False, "Desktop::~Desktop()", "Who forgot to terminate the desktop service?" )
294     LOG_ASSERT2( m_aTransactionManager.getWorkingMode()!=E_CLOSE  , "Desktop::~Desktop()", "Who forgot to dispose this service?"          )
295 }
296 
297 //=============================================================================
298 sal_Bool SAL_CALL Desktop::terminate()
299     throw( css::uno::RuntimeException )
300 {
301     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
302 
303     SYNCHRONIZED_START
304         ReadGuard aReadLock( m_aLock );
305 
306         css::uno::Reference< css::frame::XTerminateListener > xPipeTerminator    = m_xPipeTerminator;
307         css::uno::Reference< css::frame::XTerminateListener > xQuickLauncher     = m_xQuickLauncher;
308         css::uno::Reference< css::frame::XTerminateListener > xSWThreadManager   = m_xSWThreadManager;
309         css::uno::Reference< css::frame::XTerminateListener > xSfxTerminator     = m_xSfxTerminator;
310 
311         css::lang::EventObject                                aEvent             ( static_cast< ::cppu::OWeakObject* >(this) );
312         ::sal_Bool											  bAskQuickStart     = !m_bSuspendQuickstartVeto                  ;
313 
314         aReadLock.unlock();
315     SYNCHRONIZED_END
316 
317     //-------------------------------------------------------------------------------------------------------------
318     // Ask normal terminate listener. They could stop terminate without closing any open document.
319     Desktop::TTerminateListenerList lCalledTerminationListener;
320     ::sal_Bool                      bVeto = sal_False;
321     impl_sendQueryTerminationEvent(lCalledTerminationListener, bVeto);
322     if ( bVeto )
323     {
324         impl_sendCancelTerminationEvent(lCalledTerminationListener);
325         return sal_False;
326     }
327 
328     //-------------------------------------------------------------------------------------------------------------
329     // try to close all open frames.
330     // Allow using of any UI ... because Desktop.terminate() was designed as UI functionality in the past.
331     ::sal_Bool bAllowUI      = sal_True;
332     ::sal_Bool bFramesClosed = impl_closeFrames(bAllowUI);
333     if ( ! bFramesClosed )
334     {
335         impl_sendCancelTerminationEvent(lCalledTerminationListener);
336         return sal_False;
337     }
338 
339     //-------------------------------------------------------------------------------------------------------------
340     // Normal listener had no problem ...
341     // all frames was closed ...
342     // now it's time to ask our specialized listener.
343     // They are handled these way because they wish to hinder the office on termination
344     // but they wish also closing of all frames.
345 
346 	// Note further:
347     //    We shouldn't ask quicklauncher in case it was allowed from outside only.
348     //    This is special trick to "ignore existing quick starter" for debug purposes.
349 
350     // Attention:
351     // Order of alled listener is important !
352     // some of them are harmless .-)
353     // But some of them can be dangerous. E.g. it would be dangerous if we close our pipe
354     // and dont terminate in real because another listener throws a veto exception .-)
355 
356     ::sal_Bool bTerminate = sal_False;
357     try
358     {
359         if(
360             ( bAskQuickStart      ) &&
361             ( xQuickLauncher.is() )
362           )
363         {
364             xQuickLauncher->queryTermination( aEvent );
365             lCalledTerminationListener.push_back( xQuickLauncher );
366         }
367 
368         if ( xSWThreadManager.is() )
369         {
370             xSWThreadManager->queryTermination( aEvent );
371             lCalledTerminationListener.push_back( xSWThreadManager );
372         }
373 
374         if ( xPipeTerminator.is() )
375         {
376             xPipeTerminator->queryTermination( aEvent );
377             lCalledTerminationListener.push_back( xPipeTerminator );
378         }
379 
380         if ( xSfxTerminator.is() )
381         {
382             xSfxTerminator->queryTermination( aEvent );
383             lCalledTerminationListener.push_back( xSfxTerminator );
384         }
385 
386         bTerminate = sal_True;
387     }
388     catch(const css::frame::TerminationVetoException&)
389     {
390         bTerminate = sal_False;
391     }
392 
393     if ( ! bTerminate )
394         impl_sendCancelTerminationEvent(lCalledTerminationListener);
395     else
396     {
397         #ifdef ENABLE_ASSERTIONS
398             // "Protect" us against dispose before terminate calls!
399             // see dispose() for further informations.
400             /* SAFE AREA --------------------------------------------------------------------------------------- */
401             WriteGuard aWriteLock( m_aLock );
402             m_bIsTerminated = sal_True;
403             aWriteLock.unlock();
404             /* UNSAFE AREA ------------------------------------------------------------------------------------- */
405         #endif
406 
407         impl_sendNotifyTerminationEvent();
408 
409         if(
410             ( bAskQuickStart      ) &&
411             ( xQuickLauncher.is() )
412           )
413         {
414             xQuickLauncher->notifyTermination( aEvent );
415         }
416 
417         if ( xSWThreadManager.is() )
418             xSWThreadManager->notifyTermination( aEvent );
419 
420         if ( xPipeTerminator.is() )
421             xPipeTerminator->notifyTermination( aEvent );
422 
423         // Must be realy the last listener to be called.
424         // Because it shutdown the whole process asynchronous !
425         if ( xSfxTerminator.is() )
426             xSfxTerminator->notifyTermination( aEvent );
427     }
428 
429     return bTerminate;
430 }
431 
432 
433 //=============================================================================
434 void SAL_CALL Desktop::addTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener )
435     throw( css::uno::RuntimeException )
436 {
437     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
438 
439     css::uno::Reference< css::lang::XServiceInfo > xInfo( xListener, css::uno::UNO_QUERY );
440     if ( xInfo.is() )
441     {
442         ::rtl::OUString sImplementationName = xInfo->getImplementationName();
443 
444         // SYCNHRONIZED ->
445         WriteGuard aWriteLock( m_aLock );
446 
447         if( sImplementationName.equals(IMPLEMENTATIONNAME_SFXTERMINATOR) )
448         {
449             m_xSfxTerminator = xListener;
450             return;
451         }
452         if( sImplementationName.equals(IMPLEMENTATIONNAME_PIPETERMINATOR) )
453         {
454             m_xPipeTerminator = xListener;
455             return;
456         }
457         if( sImplementationName.equals(IMPLEMENTATIONNAME_QUICKLAUNCHER) )
458         {
459             m_xQuickLauncher = xListener;
460             return;
461         }
462         if( sImplementationName.equals(IMPLEMENTATIONNAME_SWTHREADMANAGER) )
463         {
464             m_xSWThreadManager = xListener;
465             return;
466         }
467 
468         aWriteLock.unlock();
469         // <- SYCNHRONIZED
470     }
471 
472     // No lock required ... container is threadsafe by itself.
473     m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ), xListener );
474 }
475 
476 //=============================================================================
477 void SAL_CALL Desktop::removeTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener )
478     throw( css::uno::RuntimeException )
479 {
480     TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
481 
482     css::uno::Reference< css::lang::XServiceInfo > xInfo( xListener, css::uno::UNO_QUERY );
483     if ( xInfo.is() )
484     {
485         ::rtl::OUString sImplementationName = xInfo->getImplementationName();
486 
487         // SYCNHRONIZED ->
488         WriteGuard aWriteLock( m_aLock );
489 
490         if( sImplementationName.equals(IMPLEMENTATIONNAME_SFXTERMINATOR) )
491         {
492             m_xSfxTerminator.clear();
493             return;
494         }
495 
496         if( sImplementationName.equals(IMPLEMENTATIONNAME_PIPETERMINATOR) )
497         {
498             m_xPipeTerminator.clear();
499             return;
500         }
501 
502         if( sImplementationName.equals(IMPLEMENTATIONNAME_QUICKLAUNCHER) )
503         {
504             m_xQuickLauncher.clear();
505             return;
506         }
507 
508         if( sImplementationName.equals(IMPLEMENTATIONNAME_SWTHREADMANAGER) )
509         {
510             m_xSWThreadManager.clear();
511             return;
512         }
513 
514         aWriteLock.unlock();
515         // <- SYCNHRONIZED
516     }
517 
518     // No lock required ... container is threadsafe by itself.
519     m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ), xListener );
520 }
521 
522 /*-************************************************************************************************************//**
523     @interface  XDesktop
524     @short      get access to create enumerations of all current components
525     @descr      You will be the owner of the returned object and must delete it if you don't use it again.
526 
527     @seealso    class TasksAccess
528     @seealso    class TasksEnumeration
529 
530     @param      -
531     @return     A reference to an XEnumerationAccess-object.
532 
533     @onerror    We return a null-reference.
534     @threadsafe yes
535 *//*-*************************************************************************************************************/
536 css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL Desktop::getComponents() throw( css::uno::RuntimeException )
537 {
538 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
539     // Register transaction and reject wrong calls.
540     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
541 
542 	// We use a helper class OComponentAccess to have access on all child components.
543     // Create it on demand and return it as a reference.
544     OComponentAccess* pAccess = new OComponentAccess( this );
545     css::uno::Reference< css::container::XEnumerationAccess > xAccess( static_cast< ::cppu::OWeakObject* >(pAccess), css::uno::UNO_QUERY );
546     return xAccess;
547 }
548 
549 /*-************************************************************************************************************//**
550     @interface  XDesktop
551     @short      return the current active component
552     @descr      The most current component is the window, model or the controller of the current active frame.
553 
554     @seealso    method getCurrentFrame()
555     @seealso    method impl_getFrameComponent()
556 
557     @param      -
558     @return     A reference to the component.
559 
560     @onerror    We return a null-reference.
561     @threadsafe yes
562 *//*-*************************************************************************************************************/
563 css::uno::Reference< css::lang::XComponent > SAL_CALL Desktop::getCurrentComponent() throw( css::uno::RuntimeException )
564 {
565 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
566     // Register transaction and reject wrong calls.
567     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
568 
569 	// Set return value if method failed.
570     css::uno::Reference< css::lang::XComponent > xComponent;
571 
572 	// Get reference to current frame ...
573 	// ... get component of this frame ... (It can be the window, the model or the controller.)
574     // ... and return the result.
575     css::uno::Reference< css::frame::XFrame > xCurrentFrame = getCurrentFrame();
576 	if( xCurrentFrame.is() == sal_True )
577 	{
578 		xComponent = impl_getFrameComponent( xCurrentFrame );
579 	}
580 	return xComponent;
581 }
582 
583 /*-************************************************************************************************************//**
584     @interface  XDesktop
585     @short      return the current active frame in hierarchy
586     @descr      There can be more then one different active pathes in our frame hierarchy. But only one of them
587                 could be the most active frame (normal he has the focus).
588                 Don't mix it with getActiveFrame()! That will return our current active frame, which must be
589                 a direct child of us and should be a part(!) of an active path.
590 
591     @seealso    method getActiveFrame()
592 
593     @param      -
594     @return     A valid reference, if there is an active frame.
595                 A null reference , otherwise.
596 
597     @onerror    We return a null reference.
598     @threadsafe yes
599 *//*-*************************************************************************************************************/
600 css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::getCurrentFrame() throw( css::uno::RuntimeException )
601 {
602 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
603     // Register transaction and reject wrong calls.
604     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
605 
606 	// Start search with ouer direct active frame (if it exist!).
607     // Search on his children for other active frames too.
608     // Stop if no one could be found and return last of found ones.
609     css::uno::Reference< css::frame::XFramesSupplier > xLast = css::uno::Reference< css::frame::XFramesSupplier >( getActiveFrame(), css::uno::UNO_QUERY );
610     if( xLast.is() == sal_True )
611 	{
612         css::uno::Reference< css::frame::XFramesSupplier > xNext = css::uno::Reference< css::frame::XFramesSupplier >( xLast->getActiveFrame(), css::uno::UNO_QUERY );
613         while( xNext.is() == sal_True )
614 		{
615             xLast = xNext;
616             xNext = css::uno::Reference< css::frame::XFramesSupplier >( xNext->getActiveFrame(), css::uno::UNO_QUERY );
617 		}
618 	}
619     return css::uno::Reference< css::frame::XFrame >( xLast, css::uno::UNO_QUERY );
620 }
621 
622 /*-************************************************************************************************************//**
623     @interface  XComponentLoader
624     @short      try to load given URL into a task
625     @descr      You can give us some informations about the content, which you will load into a frame.
626                 We search or create this target for you, make a type detection of given URL and try to load it.
627                 As result of this operation we return the new created component or nothing, if loading failed.
628 
629     @seealso    -
630 
631     @param      "sURL"              , URL, which represant the content
632     @param      "sTargetFrameName"  , name of target frame or special value like "_self", "_blank" ...
633     @param      "nSearchFlags"      , optional arguments for frame search, if target isn't a special one
634     @param      "lArguments"        , optional arguments for loading
635     @return     A valid component reference, if loading was successfully.
636                 A null reference otherwise.
637 
638     @onerror    We return a null reference.
639     @threadsafe yes
640 *//*-*************************************************************************************************************/
641 css::uno::Reference< css::lang::XComponent > SAL_CALL Desktop::loadComponentFromURL( const ::rtl::OUString&                                 sURL            ,
642                                                                                      const ::rtl::OUString&                                 sTargetFrameName,
643                                                                                            sal_Int32                                        nSearchFlags    ,
644                                                                                      const css::uno::Sequence< css::beans::PropertyValue >& lArguments      ) throw(    css::io::IOException                ,
645                                                                                                                                                                         css::lang::IllegalArgumentException ,
646                                                                                                                                                                         css::uno::RuntimeException          )
647 {
648     /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
649     // Register transaction and reject wrong calls.
650     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
651     RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::Desktop::loadComponentFromURL" );
652 
653     ReadGuard aReadLock(m_aLock);
654     css::uno::Reference< css::frame::XComponentLoader > xThis(static_cast< css::frame::XComponentLoader* >(this), css::uno::UNO_QUERY);
655     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xFactory;
656     aReadLock.unlock();
657 
658     RTL_LOGFILE_PRODUCT_CONTEXT( aLog2, "PERFORMANCE - Desktop::loadComponentFromURL()" );
659     return LoadEnv::loadComponentFromURL(xThis, xSMGR, sURL, sTargetFrameName, nSearchFlags, lArguments);
660 }
661 
662 /*-************************************************************************************************************//**
663     @interface  XTasksSupplier
664     @short      get access to create enumerations of ouer taskchilds
665     @descr      Direct childs of desktop are tasks everytime.
666                 Call these method to could create enumerations of it.
667 
668 But; Don't forget - you will be the owner of returned object and must release it!
669                 We use a helper class to implement the access interface. They hold a weakreference to us.
670                 It can be, that the desktop is dead - but not your tasksaccess-object! Then they will do nothing!
671                 You can't create enumerations then.
672 
673     @attention  Normaly we don't need any lock here. We don't work on internal member!
674 
675     @seealso    class TasksAccess
676 
677     @param      -
678     @return     A reference to an accessobject, which can create enumerations of ouer childtasks.
679 
680     @onerror    A null reference is returned.
681     @threadsafe yes
682 *//*-*************************************************************************************************************/
683 css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL Desktop::getTasks() throw( css::uno::RuntimeException )
684 {
685     LOG_WARNING("Desktop::getTasks()", "Use of obsolete interface XTaskSupplier")
686     return NULL;
687     /*
688     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
689 
690     OTasksAccess* pTasksAccess = new OTasksAccess( this, &m_aChildTaskContainer );
691     css::uno::Reference< css::container::XEnumerationAccess > xAccess( static_cast< ::cppu::OWeakObject* >(pTasksAccess), css::uno::UNO_QUERY );
692 	return xAccess;
693     */
694 }
695 
696 /*-************************************************************************************************************//**
697     @interface  XTasksSupplier
698     @short      return current active task of ouer direct childs
699     @descr      Desktop childs are tasks only ! If we have an active path from desktop
700                 as top to any frame on bottom, we must have an active direct child. His reference is returned here.
701 
702     @attention  a)  Do not confuse it with getCurrentFrame()! The current frame don't must one of ouer direct childs.
703                     It can be every frame in subtree and must have the focus (Is the last one of an active path!).
704                 b)  We don't need any lock here. Our container is threadsafe himself and live, if we live!
705 
706     @seealso    method getCurrentFrame()
707 
708     @param      -
709     @return     A reference to ouer current active taskchild.
710 
711     @onerror    A null reference is returned.
712     @threadsafe yes
713 *//*-*************************************************************************************************************/
714 css::uno::Reference< css::frame::XTask > SAL_CALL Desktop::getActiveTask() throw( css::uno::RuntimeException )
715 {
716     /*
717     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
718 
719     return css::uno::Reference< css::frame::XTask >( m_aChildTaskContainer.getActive(), css::uno::UNO_QUERY );
720     */
721     LOG_WARNING("Desktop::getActiveTask()", "Use of obsolete interface XTaskSupplier")
722     return NULL;
723 }
724 
725 /*-************************************************************************************************************//**
726     @interface  XDispatchProvider
727     @short      search a dispatcher for given URL
728     @descr      We use a helper implementation (class DispatchProvider) to do so.
729                 So we don't must implement this algorithm twice!
730 
731     @attention  We don't need any lock here. Our helper is threadsafe himself and live, if we live!
732 
733     @seealso    class DispatchProvider
734 
735     @param      "aURL"              , URL to dispatch
736     @param      "sTargetFrameName"  , name of target frame, who should dispatch these URL
737     @param      "nSearchFlags"      , flags to regulate the search
738     @param      "lQueries"          , list of queryDispatch() calls!
739     @return     A reference or list of founded dispatch objects for these URL.
740 
741     @onerror    A null reference is returned.
742     @threadsafe yes
743 *//*-*************************************************************************************************************/
744 css::uno::Reference< css::frame::XDispatch > SAL_CALL Desktop::queryDispatch( const css::util::URL&  aURL             ,
745                                                                               const ::rtl::OUString& sTargetFrameName ,
746                                                                                     sal_Int32        nSearchFlags     ) throw( css::uno::RuntimeException )
747 {
748 	const char UNO_PROTOCOL[] = ".uno:";
749 
750 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
751     // Register transaction and reject wrong calls.
752     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
753 
754 	// Remove uno and cmd protocol part as we want to support both of them. We store only the command part
755 	// in our hash map. All other protocols are stored with the protocol part.
756 	String aCommand( aURL.Main );
757 	if ( aURL.Protocol.equalsIgnoreAsciiCaseAsciiL( UNO_PROTOCOL, sizeof( UNO_PROTOCOL )-1 ))
758 		aCommand = aURL.Path;
759 
760 	// Make hash_map lookup if the current URL is in the disabled list
761 	if ( m_aCommandOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aCommand ) )
762 		return css::uno::Reference< css::frame::XDispatch >();
763 	else
764 	{
765 		// We use a helper to support these interface and an interceptor mechanism.
766 		// Our helper is threadsafe by himself!
767 		return m_xDispatchHelper->queryDispatch( aURL, sTargetFrameName, nSearchFlags );
768 	}
769 }
770 
771 //*****************************************************************************************************************
772 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL Desktop::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lQueries ) throw( css::uno::RuntimeException )
773 {
774 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
775     // Register transaction and reject wrong calls.
776     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
777 
778     return m_xDispatchHelper->queryDispatches( lQueries );
779 }
780 
781 /*-************************************************************************************************************//**
782     @interface  XDipsatchProviderInterception
783     @short      supports registration/deregistration of interception objects, which
784                 are interested on special dispatches.
785 
786     @descr      Its realy provided by an internal helper, which is used inside the dispatch api too.
787     @param      xInterceptor
788                 the interceptor object, which wish to be (de)registered.
789 
790     @threadsafe yes
791 *//*-*************************************************************************************************************/
792 void SAL_CALL Desktop::registerDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
793     throw( css::uno::RuntimeException)
794 {
795     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
796 
797     css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY );
798     xInterceptionHelper->registerDispatchProviderInterceptor( xInterceptor );
799 }
800 
801 //*****************************************************************************************************************
802 void SAL_CALL Desktop::releaseDispatchProviderInterceptor ( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
803     throw( css::uno::RuntimeException)
804 {
805     TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
806 
807     css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY );
808     xInterceptionHelper->releaseDispatchProviderInterceptor( xInterceptor );
809 }
810 
811 /*-************************************************************************************************************//**
812     @interface  XFramesSupplier
813     @short      return access to append or remove childs on desktop
814     @descr      We don't implement these interface directly. We use a helper class to do this.
815                 If you wish to add or delete childs to/from the container, call these method to get
816                 a reference to the helper.
817 
818     @attention  Helper is threadsafe himself. So we don't need any lock here.
819 
820     @seealso    class OFrames
821 
822     @param      -
823     @return     A reference to the helper.
824 
825     @onerror    A null reference is returned.
826     @threadsafe yes
827 *//*-*************************************************************************************************************/
828 css::uno::Reference< css::frame::XFrames > SAL_CALL Desktop::getFrames() throw( css::uno::RuntimeException )
829 {
830 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
831     // Register transaction and reject wrong calls.
832     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
833 
834     return m_xFramesHelper;
835 }
836 
837 /*-************************************************************************************************************//**
838     @interface  XFramesSupplier
839     @short      set/get the current active child frame
840     @descr      It must be a task. Direct childs of desktop are tasks only! No frames are accepted.
841                 We don't save this information directly in this class. We use ouer container-helper
842                 to do that.
843 
844     @attention  Helper is threadsafe himself. So we don't need any lock here.
845 
846     @seealso    class OFrameContainer
847 
848     @param      "xFrame", new active frame (must be valid!)
849     @return     A reference to ouer current active childtask, if anyone exist.
850 
851     @onerror    A null reference is returned.
852     @threadsafe yes
853 *//*-*************************************************************************************************************/
854 void SAL_CALL Desktop::setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) throw( css::uno::RuntimeException )
855 {
856 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
857     // Register transaction and reject wrong calls.
858     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
859 
860     // Get old active frame first.
861     // If nothing will change - do nothing!
862     // Otherwise set new active frame ...
863     // and deactivate last frame.
864     // It's neccessary for our FrameActionEvent listener on a frame!
865     css::uno::Reference< css::frame::XFrame > xLastActiveChild = m_aChildTaskContainer.getActive();
866     if( xLastActiveChild != xFrame )
867 	{
868         m_aChildTaskContainer.setActive( xFrame );
869         if( xLastActiveChild.is() == sal_True )
870         {
871             xLastActiveChild->deactivate();
872         }
873     }
874 }
875 
876 //*****************************************************************************************************************
877 css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::getActiveFrame() throw( css::uno::RuntimeException )
878 {
879 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
880     // Register transaction and reject wrong calls.
881     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
882 
883 	return m_aChildTaskContainer.getActive();
884 }
885 
886 /*-************************************************************************************************************//**
887     @interface  XFrame
888     @short      non implemented methods!
889     @descr      Some method make no sense for our desktop! He has no window or parent or ...
890                 So we should implement it empty and warn programmer, if he use it!
891 
892     @seealso    -
893 
894     @param      -
895     @return     -
896 
897     @onerror    -
898     @threadsafe -
899 *//*-*************************************************************************************************************/
900 void SAL_CALL Desktop::initialize( const css::uno::Reference< css::awt::XWindow >& ) throw( css::uno::RuntimeException )
901 {
902 }
903 
904 //*****************************************************************************************************************
905 css::uno::Reference< css::awt::XWindow > SAL_CALL Desktop::getContainerWindow() throw( css::uno::RuntimeException )
906 {
907     return css::uno::Reference< css::awt::XWindow >();
908 }
909 
910 //*****************************************************************************************************************
911 void SAL_CALL Desktop::setCreator( const css::uno::Reference< css::frame::XFramesSupplier >& /*xCreator*/ ) throw( css::uno::RuntimeException )
912 {
913 }
914 
915 //*****************************************************************************************************************
916 css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL Desktop::getCreator() throw( css::uno::RuntimeException )
917 {
918     return css::uno::Reference< css::frame::XFramesSupplier >();
919 }
920 
921 //*****************************************************************************************************************
922 ::rtl::OUString SAL_CALL Desktop::getName() throw( css::uno::RuntimeException )
923 {
924     /* SAFE { */
925     ReadGuard aReadLock( m_aLock );
926     return m_sName;
927     /* } SAFE */
928 }
929 
930 //*****************************************************************************************************************
931 void SAL_CALL Desktop::setName( const ::rtl::OUString& sName ) throw( css::uno::RuntimeException )
932 {
933     /* SAFE { */
934     WriteGuard aWriteLock( m_aLock );
935     m_sName = sName;
936     aWriteLock.unlock();
937     /* } SAFE */
938 }
939 
940 //*****************************************************************************************************************
941 sal_Bool SAL_CALL Desktop::isTop() throw( css::uno::RuntimeException )
942 {
943 	return sal_True;
944 }
945 
946 //*****************************************************************************************************************
947 void SAL_CALL Desktop::activate() throw( css::uno::RuntimeException )
948 {
949     // Desktop is activae always ... but sometimes our frames try to activate
950     // the complete path from bottom to top ... And our desktop is the topest frame :-(
951     // So - please don't show any assertions here. Do nothing!
952 }
953 
954 //*****************************************************************************************************************
955 void SAL_CALL Desktop::deactivate() throw( css::uno::RuntimeException )
956 {
957     // Desktop is activae always ... but sometimes our frames try to deactivate
958     // the complete path from bottom to top ... And our desktop is the topest frame :-(
959     // So - please don't show any assertions here. Do nothing!
960 }
961 
962 //*****************************************************************************************************************
963 sal_Bool SAL_CALL Desktop::isActive() throw( css::uno::RuntimeException )
964 {
965 	return sal_True;
966 }
967 
968 //*****************************************************************************************************************
969 sal_Bool SAL_CALL Desktop::setComponent( const css::uno::Reference< css::awt::XWindow >&       /*xComponentWindow*/ ,
970                                          const css::uno::Reference< css::frame::XController >& /*xController*/      ) throw( css::uno::RuntimeException )
971 {
972 	return sal_False;
973 }
974 
975 //*****************************************************************************************************************
976 css::uno::Reference< css::awt::XWindow > SAL_CALL Desktop::getComponentWindow() throw( css::uno::RuntimeException )
977 {
978     return css::uno::Reference< css::awt::XWindow >();
979 }
980 
981 //*****************************************************************************************************************
982 css::uno::Reference< css::frame::XController > SAL_CALL Desktop::getController() throw( css::uno::RuntimeException )
983 {
984     return css::uno::Reference< css::frame::XController >();
985 }
986 
987 //*****************************************************************************************************************
988 void SAL_CALL Desktop::contextChanged() throw( css::uno::RuntimeException )
989 {
990 }
991 
992 //*****************************************************************************************************************
993 void SAL_CALL Desktop::addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& ) throw( css::uno::RuntimeException )
994 {
995 }
996 
997 //*****************************************************************************************************************
998 //   css::frame::XFrame
999 //*****************************************************************************************************************
1000 void SAL_CALL Desktop::removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& ) throw( css::uno::RuntimeException )
1001 {
1002 }
1003 
1004 /*-************************************************************************************************************//**
1005     @interface  XFrame
1006     @short      try to find a frame with special parameters
1007     @descr      This method searches for a frame with the specified name.
1008                 Frames may contain other frames (e.g. a frameset) and may
1009                 be contained in other frames. This hierarchie ist searched by
1010                 this method.
1011                 First some special names are taken into account, i.e. "",
1012                 "_self", "_top", "_parent" etc. The FrameSearchFlags are ignored
1013                 when comparing these names with aTargetFrameName, further steps are
1014                 controlled by the FrameSearchFlags. If allowed, the name of the frame
1015                 itself is compared with the desired one, then ( again if allowed )
1016                 the method findFrame is called for all children of the frame.
1017                 If no Frame with the given name is found until the top frames container,
1018                 a new top Frame is created, if this is allowed by a special
1019                 FrameSearchFlag. The new Frame also gets the desired name.
1020                 We use a helper to get right search direction and react in a right manner.
1021 
1022     @seealso    class TargetFinder
1023 
1024     @param      "sTargetFrameName"  , name of searched frame
1025     @param      "nSearchFlags"      , flags to regulate search
1026     @return     A reference to an existing frame in hierarchy, if it exist.
1027 
1028     @onerror    A null reference is returned.
1029     @threadsafe yes
1030 *//*-*************************************************************************************************************/
1031 css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::findFrame( const ::rtl::OUString& sTargetFrameName ,
1032                                                                              sal_Int32        nSearchFlags     ) throw( css::uno::RuntimeException )
1033 {
1034     css::uno::Reference< css::frame::XFrame > xTarget;
1035 
1036     //-----------------------------------------------------------------------------------------------------
1037     // 0) Ignore wrong parameter!
1038     //    We doesn't support search for following special targets.
1039     //    If we reject this requests - we mustnt check for such names
1040     //    in following code again and again. If we do not so -wrong
1041     //    search results can occure!
1042     //-----------------------------------------------------------------------------------------------------
1043     if (
1044         (sTargetFrameName==SPECIALTARGET_DEFAULT  )   ||    // valid for dispatches - not for findFrame()!
1045         (sTargetFrameName==SPECIALTARGET_MENUBAR  )   ||    // valid for dispatches - not for findFrame()!
1046         (sTargetFrameName==SPECIALTARGET_HELPAGENT)   ||    // valid for dispatches - not for findFrame()!
1047         (sTargetFrameName==SPECIALTARGET_PARENT   )   ||    // we have no parent by definition
1048         (sTargetFrameName==SPECIALTARGET_BEAMER   )         // beamer frames are allowed as child of tasks only -
1049                                                             // and they exist more then ones. We have no idea which our sub tasks is the right one
1050        )
1051     {
1052         return NULL;
1053     }
1054 
1055     //-----------------------------------------------------------------------------------------------------
1056     // I) check for special defined targets first which must be handled exclusive.
1057     //    force using of "if() else if() ..."
1058     //-----------------------------------------------------------------------------------------------------
1059 
1060     // get threadsafe some neccessary member which are neccessary for following functionality
1061     /* SAFE { */
1062     ReadGuard aReadLock( m_aLock );
1063     css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
1064     aReadLock.unlock();
1065     /* } SAFE */
1066 
1067     //-----------------------------------------------------------------------------------------------------
1068     // I.I) "_blank"
1069     //  create a new task as child of this desktop instance
1070     //  Note: Used helper TaskCreator use us automaticly ...
1071     //-----------------------------------------------------------------------------------------------------
1072     if ( sTargetFrameName==SPECIALTARGET_BLANK )
1073     {
1074         TaskCreator aCreator(xFactory);
1075         xTarget = aCreator.createTask(sTargetFrameName,sal_False);
1076     }
1077 
1078     //-----------------------------------------------------------------------------------------------------
1079     // I.II) "_top"
1080     //  We are top by definition
1081     //-----------------------------------------------------------------------------------------------------
1082     else
1083     if ( sTargetFrameName==SPECIALTARGET_TOP )
1084     {
1085         xTarget = this;
1086     }
1087 
1088     //-----------------------------------------------------------------------------------------------------
1089     // I.III) "_self", ""
1090     //  This mean this "frame" in every case.
1091     //-----------------------------------------------------------------------------------------------------
1092     else
1093     if (
1094         ( sTargetFrameName==SPECIALTARGET_SELF ) ||
1095         ( sTargetFrameName.getLength()<1       )
1096        )
1097     {
1098         xTarget = this;
1099     }
1100 
1101     else
1102     {
1103         //-------------------------------------------------------------------------------------------------
1104         // II) otherwhise use optional given search flags
1105         //  force using of combinations of such flags. means no "else" part of use if() statements.
1106         //  But we ust break further searches if target was already found.
1107         //  Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT
1108         //  TASK and CREATE are handled special.
1109         //  But note: Such flags are not valid for the desktop - especialy SIBLINGS or PARENT.
1110         //-------------------------------------------------------------------------------------------------
1111 
1112         // get threadsafe some neccessary member which are neccessary for following functionality
1113         /* SAFE { */
1114         aReadLock.lock();
1115         ::rtl::OUString sOwnName = m_sName;
1116         aReadLock.unlock();
1117         /* } SAFE */
1118 
1119         //-------------------------------------------------------------------------------------------------
1120         // II.I) SELF
1121         //  Check for right name. If it's the searched one return ourself - otherwhise
1122         //  ignore this flag.
1123         //-------------------------------------------------------------------------------------------------
1124         if (
1125             (nSearchFlags &  css::frame::FrameSearchFlag::SELF)  &&
1126             (sOwnName     == sTargetFrameName                 )
1127            )
1128         {
1129             xTarget = this;
1130         }
1131 
1132         //-------------------------------------------------------------------------------------------------
1133         // II.II) TASKS
1134         //  This is a special flag. Normaly it regulate search inside tasks and forbid access to parent trees.
1135         //  But the desktop exists outside such task trees. They are our sub trees. So the desktop implement
1136         //  a special feature: We use it to start search on our direct childrens only. That means we supress
1137         //  search on ALL child frames. May that can be usefull to get access on opened document tasks
1138         //  only without filter out all non realy required sub frames ...
1139         //  Used helper method on our container doesn't create any frame - its a search only.
1140         //-------------------------------------------------------------------------------------------------
1141         if (
1142             ( ! xTarget.is()                                  ) &&
1143             (nSearchFlags & css::frame::FrameSearchFlag::TASKS)
1144            )
1145         {
1146             xTarget = m_aChildTaskContainer.searchOnDirectChildrens(sTargetFrameName);
1147         }
1148 
1149         //-------------------------------------------------------------------------------------------------
1150         // II.III) CHILDREN
1151         //  Search on all children for the given target name.
1152         //  An empty name value can't occure here - because it must be already handled as "_self"
1153         //  before. Used helper function of container doesn't create any frame.
1154         //  It makes a deep search only.
1155         //-------------------------------------------------------------------------------------------------
1156         if (
1157             ( ! xTarget.is()                                     ) &&
1158             (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
1159            )
1160         {
1161             xTarget = m_aChildTaskContainer.searchOnAllChildrens(sTargetFrameName);
1162         }
1163 
1164         //-------------------------------------------------------------------------------------------------
1165         // II.IV) CREATE
1166         //  If we haven't found any valid target frame by using normal flags - but user allowed us to create
1167         //  a new one ... we should do that. Used TaskCreator use us automaticly as parent!
1168         //-------------------------------------------------------------------------------------------------
1169         if (
1170             ( ! xTarget.is()                                   )    &&
1171             (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
1172            )
1173         {
1174             TaskCreator aCreator(xFactory);
1175             xTarget = aCreator.createTask(sTargetFrameName,sal_False);
1176         }
1177     }
1178 
1179     return xTarget;
1180 }
1181 
1182 //=============================================================================
1183 void SAL_CALL Desktop::dispose()
1184     throw( css::uno::RuntimeException )
1185 {
1186 	// Safe impossible cases
1187 	// It's an programming error if dispose is called before terminate!
1188     LOG_ASSERT2( m_bIsTerminated==sal_False, "Desktop::dispose()", "It's not allowed to dispose the desktop before terminate() is called!" )
1189 
1190     SYNCHRONIZED_START
1191         WriteGuard aWriteLock( m_aLock );
1192 
1193         // Look for multiple calls of this method!
1194         // If somewhere call dispose() twice - he will be stopped here realy!!!
1195         TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1196 
1197         // Now - we are alone and its the first call of this method ...
1198         // otherwise call before had thrown a DisposedException / hopefully .-)
1199         // But we dont use the transaction object created before ... we reset it immediatly ...
1200         // two lines of code ... for what ?
1201         // The answer: We wished to synchronize concurrent dispose() calls -> OK
1202         // But next line will wait for all currently running transaction (even if they
1203         // are running within the same thread!) So we would block ourself there if aTransaction
1204         // will stay registered .-)
1205         aTransaction.stop();
1206 
1207         // Disable this instance for further work.
1208         // This will wait for all current running transactions ...
1209         // and reject all new incoming requests!
1210         m_aTransactionManager.setWorkingMode( E_BEFORECLOSE );
1211 
1212         aWriteLock.unlock();
1213     SYNCHRONIZED_END
1214 
1215     // Following lines of code can be called outside a synchronized block ...
1216     // Because our transaction manager will block all new requests to this object.
1217     // So nobody can use us any longer.
1218     // Exception: Only removing of listener will work ... and this code cant be dangerous.
1219 
1220     // First we has to kill all listener connections.
1221     // They might rely on our member and can hinder us on releasing them.
1222     css::uno::Reference< css::uno::XInterface > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
1223     css::lang::EventObject                      aEvent( xThis );
1224     m_aListenerContainer.disposeAndClear( aEvent );
1225 
1226     // Clear our child task container and forget all task references hardly.
1227     // Normaly all open document was already closed by our terminate() function before ...
1228     // New opened frames will have a problem now .-)
1229     m_aChildTaskContainer.clear();
1230 
1231     // Dispose our helper too.
1232     css::uno::Reference< css::lang::XEventListener > xFramesHelper( m_xFramesHelper, css::uno::UNO_QUERY );
1233     if( xFramesHelper.is() )
1234         xFramesHelper->disposing( aEvent );
1235 
1236     // At least clean up other member references.
1237     m_xDispatchHelper.clear();
1238     m_xFramesHelper.clear();
1239     m_xLastFrame.clear();
1240     m_xFactory.clear();
1241 
1242     m_xPipeTerminator.clear();
1243     m_xQuickLauncher.clear();
1244     m_xSWThreadManager.clear();
1245     m_xSfxTerminator.clear();
1246 
1247     // From this point nothing will work further on this object ...
1248     // excepting our dtor() .-)
1249     m_aTransactionManager.setWorkingMode( E_CLOSE );
1250 }
1251 
1252 /*-************************************************************************************************************//**
1253     @interface  XComponent
1254     @short      add/remove listener for dispose events
1255     @descr      Add an event listener to this object, if you whish to get informations
1256                 about our dieing!
1257                 You must releas ethis listener reference during your own disposing() method.
1258 
1259     @attention  Our container is threadsafe himeslf. So we doesn't need any lock here.
1260 
1261     @seealso    -
1262 
1263     @param      "xListener", reference to valid listener. We don't accept invalid values!
1264     @return     -
1265 
1266     @onerror    -
1267     @threadsafe yes
1268 *//*-*************************************************************************************************************/
1269 void SAL_CALL Desktop::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException )
1270 {
1271 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1272 	// Safe impossible cases
1273 	// Method not defined for all incoming parameter.
1274     LOG_ASSERT2( implcp_addEventListener( xListener ), "Desktop::addEventListener()", "Invalid parameter detected!" )
1275     // Register transaction and reject wrong calls.
1276     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1277 
1278     m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >*) NULL ), xListener );
1279 }
1280 
1281 //*****************************************************************************************************************
1282 void SAL_CALL Desktop::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException )
1283 {
1284 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1285 	// Safe impossible cases
1286 	// Method not defined for all incoming parameter.
1287     LOG_ASSERT2( implcp_removeEventListener( xListener ), "Desktop::removeEventListener()", "Invalid parameter detected!" )
1288     // Register transaction and reject wrong calls.
1289     TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS );
1290 
1291     m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >*) NULL ), xListener );
1292 }
1293 
1294 /*-************************************************************************************************************//**
1295     @interface  XDispatchResultListener
1296     @short      callback for dispatches
1297     @descr      To support our method "loadComponentFromURL()" we are listener on temp. created dispatcher.
1298                 They call us back in this method "statusChanged()". As source of given state event, they give us a
1299                 reference to the target frame, in which dispatch was loaded! So we can use it to return his component
1300                 to caller! If no target exist ... ??!!
1301 
1302     @seealso    method loadComponentFromURL()
1303 
1304     @param      "aEvent", state event which (hopefully) valid informations
1305     @return     -
1306 
1307     @onerror    -
1308     @threadsafe yes
1309 *//*-*************************************************************************************************************/
1310 void SAL_CALL Desktop::dispatchFinished( const css::frame::DispatchResultEvent& aEvent ) throw( css::uno::RuntimeException )
1311 {
1312 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1313     // Register transaction and reject wrong calls.
1314     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1315 
1316     /* SAFE AREA ------------------------------------------------------------------------------------------- */
1317     WriteGuard aWriteLock( m_aLock );
1318     if( m_eLoadState != E_INTERACTION )
1319     {
1320         m_xLastFrame = css::uno::Reference< css::frame::XFrame >();
1321         m_eLoadState = E_FAILED                                   ;
1322         if( aEvent.State == css::frame::DispatchResultState::SUCCESS )
1323         {
1324             css::uno::Reference < css::frame::XFrame > xFrame;
1325             if ( aEvent.Result >>= m_xLastFrame )
1326                 m_eLoadState = E_SUCCESSFUL;
1327         }
1328     }
1329     /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
1330 }
1331 
1332 /*-************************************************************************************************************//**
1333     @interface  XEventListener
1334     @short      not implemented!
1335     @descr      We are a status listener ... and so we must be an event listener too ... But we doesn't need it realy!
1336                 We are a temp. listener only and our lifetime isn't smaller then of our temp. used dispatcher.
1337 
1338     @seealso    method loadComponentFromURL()
1339 
1340     @param      -
1341     @return     -
1342 
1343     @onerror    -
1344     @threadsafe -
1345 *//*-*************************************************************************************************************/
1346 void SAL_CALL Desktop::disposing( const css::lang::EventObject& ) throw( css::uno::RuntimeException )
1347 {
1348     LOG_ERROR( "Desktop::disposing()", "Algorithm error! Normaly desktop is temp. listener ... not all the time. So this method shouldn't be called." )
1349 }
1350 
1351 /*-************************************************************************************************************//**
1352     @interface  XInteractionHandler
1353     @short      callback for loadComponentFromURL for detected exceptions during load proccess
1354     @descr      In this case we must cancel loading and throw these detected exception again as result
1355                 of our own called method.
1356 
1357     @attention  a)
1358                 Normal loop in loadComponentFromURL() breaks on setted member m_eLoadState during callback statusChanged().
1359                 But these interaction feature implements second way to do so! So we must look on different callbacks
1360                 for same operation ... and live with it.
1361                 b)
1362                 Search for given continuations too. If any XInteractionAbort exist ... use it to abort further operations
1363                 for currently running operation!
1364 
1365     @seealso    method loadComponentFromURL()
1366     @seealso    member m_eLoadState
1367 
1368     @param      "xRequest", request for interaction - normal a wrapped target exception from bottom services
1369     @return     -
1370 
1371     @onerror    -
1372     @threadsafe yes
1373 *//*-*************************************************************************************************************/
1374 void SAL_CALL Desktop::handle( const css::uno::Reference< css::task::XInteractionRequest >& xRequest ) throw( css::uno::RuntimeException )
1375 {
1376 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1377     // Register transaction and reject wrong calls.
1378     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1379 
1380     // Don't check incoming request!
1381     // If somewhere starts interaction without right parameter - he maked something wrong.
1382     // loadComponentFromURL() waits for thjese event - otherwise it yield for ever!
1383 
1384     // get packed request and work on it first
1385     // Attention: Don't set it on internal member BEFORE interaction is finished - because
1386     // "loadComponentFromURL()" yield tills this member is changed. If we do it before
1387     // interaction finish we can't guarantee right functionality. May be we cancel load process to erliear ...
1388     css::uno::Any aRequest = xRequest->getRequest();
1389 
1390     // extract continuations from request
1391     css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations();
1392     css::uno::Reference< css::task::XInteractionAbort >                              xAbort         ;
1393     css::uno::Reference< css::task::XInteractionApprove >                            xApprove       ;
1394     css::uno::Reference< css::document::XInteractionFilterSelect >                   xFilterSelect  ;
1395     sal_Bool                                                                         bAbort         = sal_False;
1396 
1397     sal_Int32 nCount=lContinuations.getLength();
1398     for( sal_Int32 nStep=0; nStep<nCount; ++nStep )
1399     {
1400         if( ! xAbort.is() )
1401             xAbort  = css::uno::Reference< css::task::XInteractionAbort >( lContinuations[nStep], css::uno::UNO_QUERY );
1402 
1403         if( ! xApprove.is() )
1404             xApprove  = css::uno::Reference< css::task::XInteractionApprove >( lContinuations[nStep], css::uno::UNO_QUERY );
1405 
1406         if( ! xFilterSelect.is() )
1407             xFilterSelect = css::uno::Reference< css::document::XInteractionFilterSelect >( lContinuations[nStep], css::uno::UNO_QUERY );
1408     }
1409 
1410     // differ between abortable interactions (error, unknown filter ...)
1411     // and other ones (ambigous but not unknown filter ...)
1412     css::task::ErrorCodeRequest          aErrorCodeRequest     ;
1413     css::document::AmbigousFilterRequest aAmbigousFilterRequest;
1414     if( aRequest >>= aAmbigousFilterRequest )
1415     {
1416         if( xFilterSelect.is() )
1417         {
1418             xFilterSelect->setFilter( aAmbigousFilterRequest.SelectedFilter ); // user selected filter wins!
1419             xFilterSelect->select();
1420         }
1421     }
1422     else
1423     if( aRequest >>= aErrorCodeRequest )
1424     {
1425         sal_Bool bWarning = ((aErrorCodeRequest.ErrCode & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK);
1426         if (xApprove.is() && bWarning)
1427             xApprove->select();
1428         else
1429         if (xAbort.is())
1430         {
1431             xAbort->select();
1432             bAbort = sal_True;
1433         }
1434     }
1435     else
1436     if( xAbort.is() )
1437     {
1438         xAbort->select();
1439         bAbort = sal_True;
1440     }
1441 
1442     /* SAFE AREA ------------------------------------------------------------------------------------------- */
1443     // Ok now it's time to break yield loop of loadComponentFromURL().
1444     // But only for realy aborted requests!
1445     // For example warnings will be approved and we wait for any success story ...
1446     if (bAbort)
1447     {
1448         WriteGuard aWriteLock( m_aLock );
1449         m_eLoadState          = E_INTERACTION;
1450         m_aInteractionRequest = aRequest     ;
1451         aWriteLock.unlock();
1452     }
1453     /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
1454 }
1455 
1456 //-----------------------------------------------------------------------------
1457 ::sal_Int32 SAL_CALL Desktop::leaseNumber( const css::uno::Reference< css::uno::XInterface >& xComponent )
1458     throw (css::lang::IllegalArgumentException,
1459            css::uno::RuntimeException         )
1460 {
1461     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1462     return m_xTitleNumberGenerator->leaseNumber (xComponent);
1463 }
1464 
1465 //-----------------------------------------------------------------------------
1466 void SAL_CALL Desktop::releaseNumber( ::sal_Int32 nNumber )
1467     throw (css::lang::IllegalArgumentException,
1468            css::uno::RuntimeException         )
1469 {
1470     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1471     m_xTitleNumberGenerator->releaseNumber (nNumber);
1472 }
1473 
1474 //-----------------------------------------------------------------------------
1475 void SAL_CALL Desktop::releaseNumberForComponent( const css::uno::Reference< css::uno::XInterface >& xComponent )
1476     throw (css::lang::IllegalArgumentException,
1477            css::uno::RuntimeException         )
1478 {
1479     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1480     m_xTitleNumberGenerator->releaseNumberForComponent (xComponent);
1481 }
1482 
1483 //-----------------------------------------------------------------------------
1484 ::rtl::OUString SAL_CALL Desktop::getUntitledPrefix()
1485     throw (css::uno::RuntimeException)
1486 {
1487     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1488     return m_xTitleNumberGenerator->getUntitledPrefix ();
1489 }
1490 
1491 /*-************************************************************************************************************//**
1492     @short      try to convert a property value
1493     @descr      This method is called from helperclass "OPropertySetHelper".
1494                 Don't use this directly!
1495                 You must try to convert the value of given DESKTOP_PROPHANDLE and
1496                 return results of this operation. This will be used to ask vetoable
1497                 listener. If no listener has a veto, we will change value realy!
1498                 ( in method setFastPropertyValue_NoBroadcast(...) )
1499 
1500     @attention  Methods of OPropertySethelper are safed by using our shared osl mutex! (see ctor!)
1501                 So we must use different locks to make our implementation threadsafe.
1502 
1503     @seealso    class OPropertySetHelper
1504     @seealso    method setFastPropertyValue_NoBroadcast()
1505 
1506     @param      "aConvertedValue"   new converted value of property
1507     @param      "aOldValue"         old value of property
1508     @param      "nHandle"           handle of property
1509     @param      "aValue"            new value of property
1510     @return     sal_True if value will be changed, sal_FALSE otherway
1511 
1512     @onerror    IllegalArgumentException, if you call this with an invalid argument
1513     @threadsafe yes
1514 *//*-*************************************************************************************************************/
1515 sal_Bool SAL_CALL Desktop::convertFastPropertyValue(       css::uno::Any&   aConvertedValue ,
1516                                                            css::uno::Any&   aOldValue       ,
1517                                                            sal_Int32        nHandle         ,
1518                                                      const css::uno::Any&   aValue          ) throw( css::lang::IllegalArgumentException )
1519 {
1520 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1521     // Register transaction and reject wrong calls.
1522     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1523 
1524 	//	Initialize state with sal_False !!!
1525 	//	(Handle can be invalid)
1526 	sal_Bool bReturn = sal_False;
1527 
1528     switch( nHandle )
1529 	{
1530         case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO:
1531                 bReturn = PropHelper::willPropertyBeChanged(
1532                     css::uno::makeAny(m_bSuspendQuickstartVeto),
1533                     aValue,
1534                     aOldValue,
1535                     aConvertedValue);
1536                 break;
1537         case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
1538                 bReturn = PropHelper::willPropertyBeChanged(
1539                     css::uno::makeAny(m_xDispatchRecorderSupplier),
1540                     aValue,
1541                     aOldValue,
1542                     aConvertedValue);
1543                 break;
1544         case DESKTOP_PROPHANDLE_TITLE :
1545                 bReturn = PropHelper::willPropertyBeChanged(
1546                     css::uno::makeAny(m_sTitle),
1547                     aValue,
1548                     aOldValue,
1549                     aConvertedValue);
1550                 break;
1551 	}
1552 
1553 	// Return state of operation.
1554 	return bReturn ;
1555 }
1556 
1557 /*-************************************************************************************************************//**
1558     @short      set value of a transient property
1559     @descr      This method is calling from helperclass "OPropertySetHelper".
1560                 Don't use this directly!
1561                 Handle and value are valid everyway! You must set the new value only.
1562                 After this, baseclass send messages to all listener automaticly.
1563 
1564     @seealso    class OPropertySetHelper
1565 
1566     @param      "nHandle"   handle of property to change
1567     @param      "aValue"    new value of property
1568     @return     -
1569 
1570     @onerror    An exception is thrown.
1571     @threadsafe yes
1572 *//*-*************************************************************************************************************/
1573 void SAL_CALL Desktop::setFastPropertyValue_NoBroadcast(       sal_Int32        nHandle ,
1574                                                          const css::uno::Any&   aValue  ) throw( css::uno::Exception )
1575 {
1576 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1577     // Register transaction and reject wrong calls.
1578     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1579 
1580     switch( nHandle )
1581 	{
1582         case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO:    aValue >>= m_bSuspendQuickstartVeto;
1583 													break;
1584         case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER:    aValue >>= m_xDispatchRecorderSupplier;
1585                                                     break;
1586         case DESKTOP_PROPHANDLE_TITLE:    aValue >>= m_sTitle;
1587                                                     break;
1588 	}
1589 }
1590 
1591 /*-************************************************************************************************************//**
1592     @short      get value of a transient property
1593     @descr      This method is calling from helperclass "OPropertySetHelper".
1594                 Don't use this directly!
1595 
1596     @attention  We don't need any mutex or lock here ... We use threadsafe container or methods here only!
1597 
1598     @seealso    class OPropertySetHelper
1599 
1600     @param      "nHandle"   handle of property to change
1601     @param      "aValue"    current value of property
1602     @return     -
1603 
1604     @onerror    -
1605     @threadsafe yes
1606 *//*-*************************************************************************************************************/
1607 void SAL_CALL Desktop::getFastPropertyValue( css::uno::Any& aValue  ,
1608                                              sal_Int32      nHandle ) const
1609 {
1610 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1611     // Register transaction and reject wrong calls.
1612     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1613 
1614     switch( nHandle )
1615 	{
1616         case DESKTOP_PROPHANDLE_ACTIVEFRAME           :   aValue <<= m_aChildTaskContainer.getActive();
1617 													break;
1618         case DESKTOP_PROPHANDLE_ISPLUGGED           :   aValue <<= sal_False;
1619 													break;
1620         case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO:    aValue <<= m_bSuspendQuickstartVeto;
1621 													break;
1622         case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER:    aValue <<= m_xDispatchRecorderSupplier;
1623                                                     break;
1624         case DESKTOP_PROPHANDLE_TITLE:    aValue <<= m_sTitle;
1625                                                     break;
1626 	}
1627 }
1628 
1629 /*-************************************************************************************************************//**
1630     @short      return structure and information about transient properties
1631     @descr      This method is calling from helperclass "OPropertySetHelper".
1632                 Don't use this directly!
1633 
1634     @attention  You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it.
1635                 Because; our baseclass use this mutex to make his code threadsafe. We use our lock!
1636                 So we could have two different mutex/lock mechanism at the same object.
1637 
1638     @seealso    class OPropertySetHelper
1639 
1640     @param      -
1641     @return     structure with property-informations
1642 
1643     @onerror    -
1644     @threadsafe yes
1645 *//*-*************************************************************************************************************/
1646 ::cppu::IPropertyArrayHelper& SAL_CALL Desktop::getInfoHelper()
1647 {
1648 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1649     // Register transaction and reject wrong calls.
1650     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1651 
1652 	// Optimize this method !
1653 	// We initialize a static variable only one time. And we don't must use a mutex at every call!
1654 	// For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL!
1655     static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL;
1656 
1657     if( pInfoHelper == NULL )
1658 	{
1659 		// Ready for multithreading
1660         ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() );
1661 		// Control this pointer again, another instance can be faster then these!
1662         if( pInfoHelper == NULL )
1663 		{
1664 			// Define static member to give structure of properties to baseclass "OPropertySetHelper".
1665 			// "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable.
1666 			// "sal_True" say: Table is sorted by name.
1667             static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True );
1668 			pInfoHelper = &aInfoHelper;
1669 		}
1670 	}
1671 
1672     return(*pInfoHelper);
1673 }
1674 
1675 /*-************************************************************************************************************//**
1676     @short      return propertysetinfo
1677     @descr      You can call this method to get information about transient properties
1678                 of this object.
1679 
1680     @attention  You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it.
1681                 Because; our baseclass use this mutex to make his code threadsafe. We use our lock!
1682                 So we could have two different mutex/lock mechanism at the same object.
1683 
1684     @seealso    class OPropertySetHelper
1685     @seealso    interface XPropertySet
1686     @seealso    interface XMultiPropertySet
1687 
1688     @param      -
1689     @return     reference to object with information [XPropertySetInfo]
1690 
1691     @onerror    -
1692     @threadsafe yes
1693 *//*-*************************************************************************************************************/
1694 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL Desktop::getPropertySetInfo() throw (::com::sun::star::uno::RuntimeException)
1695 {
1696 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1697     // Register transaction and reject wrong calls.
1698     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1699 
1700 	// Optimize this method !
1701 	// We initialize a static variable only one time. And we don't must use a mutex at every call!
1702 	// For the first call; pInfo is NULL - for the second call pInfo is different from NULL!
1703     static css::uno::Reference< css::beans::XPropertySetInfo >* pInfo = NULL;
1704 
1705     if( pInfo == NULL )
1706 	{
1707 		// Ready for multithreading
1708         ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() );
1709 		// Control this pointer again, another instance can be faster then these!
1710         if( pInfo == NULL )
1711 		{
1712 			// Create structure of propertysetinfo for baseclass "OPropertySetHelper".
1713 			// (Use method "getInfoHelper()".)
1714             static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
1715 			pInfo = &xInfo;
1716 		}
1717 	}
1718 
1719 	return (*pInfo);
1720 }
1721 
1722 /*-************************************************************************************************************//**
1723     @short      return current component of current frame
1724     @descr      The desktop himself has no component. But every frame in subtree.
1725                 If somewhere call getCurrentComponent() at this class, we try to find the right frame and
1726                 then we try to become his component. It can be a VCL-component, the model or the controller
1727                 of founded frame.
1728 
1729     @attention  We don't work on internal member ... so we doesn't need any lock here.
1730 
1731     @seealso    method getCurrentComponent();
1732 
1733     @param      "xFrame", reference to valid frame in hierarchy. Method is not defined for invalid values.
1734                 But we don't check these. Its an IMPL-method and caller must use it right!
1735     @return     A reference to found component.
1736 
1737     @onerror    A null reference is returned.
1738     @threadsafe yes
1739 *//*-*************************************************************************************************************/
1740 css::uno::Reference< css::lang::XComponent > Desktop::impl_getFrameComponent( const css::uno::Reference< css::frame::XFrame >& xFrame ) const
1741 {
1742 	/* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1743     // Register transaction and reject wrong calls.
1744     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1745 
1746 	// Set default return value, if method failed.
1747     css::uno::Reference< css::lang::XComponent > xComponent;
1748 	// Does no controller exists?
1749     css::uno::Reference< css::frame::XController > xController = xFrame->getController();
1750     if( xController.is() == sal_False )
1751 	{
1752 		// Controller not exist - use the VCL-component.
1753         xComponent = css::uno::Reference< css::lang::XComponent >( xFrame->getComponentWindow(), css::uno::UNO_QUERY );
1754 	}
1755 	else
1756 	{
1757 		// Does no model exists?
1758         css::uno::Reference< css::frame::XModel > xModel( xController->getModel(), css::uno::UNO_QUERY );
1759         if( xModel.is() == sal_True )
1760 		{
1761 			// Model exist - use the model as component.
1762             xComponent = css::uno::Reference< css::lang::XComponent >( xModel, css::uno::UNO_QUERY );
1763 		}
1764 		else
1765 		{
1766 			// Model not exist - use the controller as component.
1767             xComponent = css::uno::Reference< css::lang::XComponent >( xController, css::uno::UNO_QUERY );
1768 		}
1769 	}
1770 
1771 	return xComponent;
1772 }
1773 
1774 /*-************************************************************************************************************//**
1775     @short      create table with information about properties
1776     @descr      We use a helper class to support properties. These class need some information about this.
1777                 These method create a new static description table with name, type, r/w-flags and so on ...
1778 
1779     @seealso    class OPropertySetHelper
1780     @seealso    method getInfoHelper()
1781 
1782     @param      -
1783     @return     Static table with information about properties.
1784 
1785     @onerror    -
1786     @threadsafe yes
1787 *//*-*************************************************************************************************************/
1788 const css::uno::Sequence< css::beans::Property > Desktop::impl_getStaticPropertyDescriptor()
1789 {
1790 	// Create a new static property array to initialize sequence!
1791 	// Table of all predefined properties of this class. Its used from OPropertySetHelper-class!
1792 	// Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!!
1793 	// It's necessary for methods of OPropertySetHelper.
1794 	// ATTENTION:
1795     //      YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!!
1796 
1797     static const css::beans::Property pProperties[] =
1798 	{
1799         css::beans::Property( DESKTOP_PROPNAME_ACTIVEFRAME              , DESKTOP_PROPHANDLE_ACTIVEFRAME             , ::getCppuType((const css::uno::Reference< css::lang::XComponent >*)NULL)                , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
1800         css::beans::Property( DESKTOP_PROPNAME_DISPATCHRECORDERSUPPLIER , DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER, ::getCppuType((const css::uno::Reference< css::frame::XDispatchRecorderSupplier >*)NULL), css::beans::PropertyAttribute::TRANSIENT ),
1801         css::beans::Property( DESKTOP_PROPNAME_ISPLUGGED                , DESKTOP_PROPHANDLE_ISPLUGGED               , ::getBooleanCppuType()                                                                  , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ),
1802         css::beans::Property( DESKTOP_PROPNAME_SUSPENDQUICKSTARTVETO    , DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO   , ::getBooleanCppuType()                                                                  , css::beans::PropertyAttribute::TRANSIENT ),
1803         css::beans::Property( DESKTOP_PROPNAME_TITLE                    , DESKTOP_PROPHANDLE_TITLE                   , ::getCppuType((const ::rtl::OUString*)NULL)                                             , css::beans::PropertyAttribute::TRANSIENT ),
1804 	};
1805 	// Use it to initialize sequence!
1806     static const css::uno::Sequence< css::beans::Property > lPropertyDescriptor( pProperties, DESKTOP_PROPCOUNT );
1807 	// Return static "PropertyDescriptor"
1808     return lPropertyDescriptor;
1809 }
1810 
1811 //=============================================================================
1812 void Desktop::impl_sendQueryTerminationEvent(Desktop::TTerminateListenerList& lCalledListener,
1813                                              ::sal_Bool&                      bVeto          )
1814 {
1815     bVeto = sal_False;
1816 
1817     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1818 
1819     ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ) );
1820 	if ( ! pContainer )
1821         return;
1822 
1823     css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) );
1824 
1825     ::cppu::OInterfaceIteratorHelper aIterator( *pContainer );
1826     while ( aIterator.hasMoreElements() )
1827     {
1828         try
1829         {
1830             css::uno::Reference< css::frame::XTerminateListener > xListener(aIterator.next(), css::uno::UNO_QUERY);
1831             if ( ! xListener.is() )
1832                 continue;
1833             xListener->queryTermination( aEvent );
1834             lCalledListener.push_back(xListener);
1835         }
1836         catch( const css::frame::TerminationVetoException& )
1837         {
1838             // first veto will stop notification loop.
1839             bVeto = sal_True;
1840             return;
1841         }
1842         catch( const css::uno::Exception& )
1843         {
1844             // clean up container.
1845             // E.g. dead remote listener objects can make trouble otherwise.
1846             // Iterator implementation allows removing objects during it's used !
1847             aIterator.remove();
1848         }
1849     }
1850 }
1851 
1852 //=============================================================================
1853 void Desktop::impl_sendCancelTerminationEvent(const Desktop::TTerminateListenerList& lCalledListener)
1854 {
1855     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1856 
1857     css::lang::EventObject                          aEvent( static_cast< ::cppu::OWeakObject* >(this) );
1858     Desktop::TTerminateListenerList::const_iterator pIt;
1859     for (  pIt  = lCalledListener.begin();
1860            pIt != lCalledListener.end  ();
1861          ++pIt                           )
1862     {
1863         try
1864         {
1865             // Note: cancelTermination() is a new and optional interface method !
1866             css::uno::Reference< css::frame::XTerminateListener  > xListener           = *pIt;
1867             css::uno::Reference< css::frame::XTerminateListener2 > xListenerGeneration2(xListener, css::uno::UNO_QUERY);
1868             if ( ! xListenerGeneration2.is() )
1869                 continue;
1870             xListenerGeneration2->cancelTermination( aEvent );
1871         }
1872         catch( const css::uno::Exception& )
1873         {}
1874     }
1875 }
1876 
1877 //=============================================================================
1878 void Desktop::impl_sendNotifyTerminationEvent()
1879 {
1880     TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1881 
1882     ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ) );
1883 	if ( ! pContainer )
1884         return;
1885 
1886     css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) );
1887 
1888     ::cppu::OInterfaceIteratorHelper aIterator( *pContainer );
1889     while ( aIterator.hasMoreElements() )
1890     {
1891         try
1892         {
1893             css::uno::Reference< css::frame::XTerminateListener > xListener(aIterator.next(), css::uno::UNO_QUERY);
1894             if ( ! xListener.is() )
1895                 continue;
1896             xListener->notifyTermination( aEvent );
1897         }
1898         catch( const css::uno::Exception& )
1899         {
1900             // clean up container.
1901             // E.g. dead remote listener objects can make trouble otherwise.
1902             // Iterator implementation allows removing objects during it's used !
1903             aIterator.remove();
1904         }
1905     }
1906 }
1907 
1908 //=============================================================================
1909 ::sal_Bool Desktop::impl_closeFrames(::sal_Bool bAllowUI)
1910 {
1911     SYNCHRONIZED_START
1912         ReadGuard aReadLock( m_aLock );
1913         css::uno::Sequence< css::uno::Reference< css::frame::XFrame > > lFrames = m_aChildTaskContainer.getAllElements();
1914         aReadLock.unlock();
1915     SYNCHRONIZED_END
1916 
1917     ::sal_Int32 c                = lFrames.getLength();
1918     ::sal_Int32 i                = 0;
1919     ::sal_Int32 nNonClosedFrames = 0;
1920 
1921     for( i=0; i<c; ++i )
1922     {
1923         try
1924         {
1925             css::uno::Reference< css::frame::XFrame > xFrame = lFrames[i];
1926 
1927             // XController.suspend() will show an UI ...
1928             // Use it in case it was allowed from outside only.
1929             sal_Bool                                       bSuspended = sal_False;
1930             css::uno::Reference< css::frame::XController > xController( xFrame->getController(), css::uno::UNO_QUERY );
1931             if (
1932                 ( bAllowUI         ) &&
1933                 ( xController.is() )
1934                )
1935             {
1936                 bSuspended = xController->suspend( sal_True );
1937                 if ( ! bSuspended )
1938                 {
1939                     ++nNonClosedFrames;
1940                     continue;
1941                 }
1942             }
1943 
1944             // Try to close frame (in case no UI was allowed without calling XController->suspend() before!)
1945             // But don't deliver ownership to any other one!
1946             // This method can be called again.
1947             css::uno::Reference< css::util::XCloseable > xClose( xFrame, css::uno::UNO_QUERY );
1948             if ( xClose.is() )
1949             {
1950                 try
1951                 {
1952                     xClose->close(sal_False);
1953                 }
1954                 catch(const css::util::CloseVetoException&)
1955                 {
1956                     // Any internal process of this frame disagree with our request.
1957                     // Safe this state but dont break these loop. Other frames has to be closed!
1958                     ++nNonClosedFrames;
1959 
1960                     // Reactivate controller.
1961                     // It can happen that XController.suspend() returned true ... but a registered close listener
1962                     // throwed these veto exception. Then the controller has to be reactivated. Otherwise
1963                     // these document doesnt work any more.
1964                     if (
1965                         (bSuspended      ) &&
1966                         (xController.is())
1967                        )
1968                         xController->suspend(sal_False);
1969                 }
1970 
1971                 // If interface XClosable interface exists and was used ...
1972                 // it's not allowed to use XComponent->dispose() also !
1973                 continue;
1974             }
1975 
1976             // XClosable not supported ?
1977             // Then we have to dispose these frame hardly.
1978             css::uno::Reference< css::lang::XComponent > xDispose( xFrame, css::uno::UNO_QUERY );
1979             if ( xDispose.is() )
1980                 xDispose->dispose();
1981 
1982             // Don't remove these frame from our child container!
1983             // A frame do it by itself inside close()/dispose() method.
1984         }
1985         catch(const css::lang::DisposedException&)
1986         {
1987             // Dispose frames are closed frames.
1988             // So we can count it here .-)
1989         }
1990     }
1991 
1992     return (nNonClosedFrames < 1);
1993 }
1994 
1995 //_________________________________________________________________________________________________________________
1996 //	debug methods
1997 //_________________________________________________________________________________________________________________
1998 
1999 /*-----------------------------------------------------------------------------------------------------------------
2000 	The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
2001     we return "sal_True". (otherwise sal_False) This mechanism is used to throw an ASSERT!
2002 -----------------------------------------------------------------------------------------------------------------*/
2003 
2004 #ifdef ENABLE_ASSERTIONS
2005 
2006 //*****************************************************************************************************************
2007 //	We work with valid servicemanager only.
2008 sal_Bool Desktop::implcp_ctor( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
2009 {
2010     return(
2011 			( &xFactory		==	NULL		)	||
2012 			( xFactory.is()	==	sal_False	)
2013           );
2014 }
2015 
2016 //*****************************************************************************************************************
2017 //	We work with valid listener only.
2018 sal_Bool Desktop::implcp_addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
2019 {
2020     return(
2021 			( &xListener		==	NULL		)	||
2022 			( xListener.is()	==	sal_False	)
2023           );
2024 }
2025 
2026 //*****************************************************************************************************************
2027 //	We work with valid listener only.
2028 sal_Bool Desktop::implcp_removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
2029 {
2030     return(
2031 			( &xListener		==	NULL		)	||
2032 			( xListener.is()	==	sal_False	)
2033           );
2034 }
2035 
2036 #endif	// #ifdef ENABLE_ASSERTIONS
2037 
2038 }	// namespace framework
2039