1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 //_______________________________________________
27 // includes of own project
28 #include <loadenv/loadenv.hxx>
29 
30 #ifndef __FRAMEWORK_LOADENV_TARGETHELPER_HXX_
31 #include <loadenv/targethelper.hxx>
32 #endif
33 #include <framework/framelistanalyzer.hxx>
34 
35 #ifndef __FRAMEWORK_CONSTANT_FRAMELOADER_HXX_
36 #include <constant/frameloader.hxx>
37 #endif
38 
39 #ifndef __FRAMEWORK_CONSTANT_CONTENTHANDLER_HXX_
40 #include <constant/contenthandler.hxx>
41 #endif
42 
43 #ifndef __FRAMEWORK_CONSTANT_CONTAINERQUERY_HXX_
44 #include <constant/containerquery.hxx>
45 #endif
46 #include <interaction/quietinteraction.hxx>
47 #include <threadhelp/writeguard.hxx>
48 #include <threadhelp/readguard.hxx>
49 #include <threadhelp/resetableguard.hxx>
50 #include <properties.h>
51 #include <protocols.h>
52 #include <services.h>
53 #include <comphelper/interaction.hxx>
54 #include <framework/interaction.hxx>
55 
56 //_______________________________________________
57 // includes of uno interface
58 #include <com/sun/star/task/ErrorCodeRequest.hpp>
59 #include <com/sun/star/uno/RuntimeException.hpp>
60 #include <com/sun/star/frame/DispatchResultState.hpp>
61 #include <com/sun/star/frame/FrameSearchFlag.hpp>
62 #include <com/sun/star/util/XURLTransformer.hpp>
63 #include <com/sun/star/ucb/XContentProviderManager.hpp>
64 #include <com/sun/star/util/XCloseable.hpp>
65 #include <com/sun/star/lang/XComponent.hpp>
66 #include <com/sun/star/lang/XServiceInfo.hpp>
67 #include <com/sun/star/lang/DisposedException.hpp>
68 #include <com/sun/star/awt/XWindow.hpp>
69 #include <com/sun/star/awt/XWindow2.hpp>
70 #include <com/sun/star/awt/XTopWindow.hpp>
71 #include <com/sun/star/frame/XModel.hpp>
72 #include <com/sun/star/frame/XFrameLoader.hpp>
73 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
74 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
75 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
76 #include <com/sun/star/task/XStatusIndicator.hpp>
77 #include <com/sun/star/util/XModifiable.hpp>
78 #include <com/sun/star/frame/XDispatchProvider.hpp>
79 #include <com/sun/star/document/XTypeDetection.hpp>
80 #include <com/sun/star/document/XActionLockable.hpp>
81 #include <com/sun/star/io/XInputStream.hpp>
82 #include <com/sun/star/task/XInteractionHandler.hpp>
83 #include <com/sun/star/container/XNameAccess.hpp>
84 #include <com/sun/star/container/XContainerQuery.hpp>
85 #include <com/sun/star/container/XEnumeration.hpp>
86 #include <com/sun/star/document/MacroExecMode.hpp>
87 #include <com/sun/star/document/UpdateDocMode.hpp>
88 
89 //_______________________________________________
90 // includes of an other project
91 #include <vcl/window.hxx>
92 #include <vcl/wrkwin.hxx>
93 #include <vcl/syswin.hxx>
94 
95 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
96 #include <toolkit/unohlp.hxx>
97 #endif
98 #include <unotools/moduleoptions.hxx>
99 #include <svtools/sfxecode.hxx>
100 #include <unotools/processfactory.hxx>
101 #include <unotools/ucbhelper.hxx>
102 #include <comphelper/configurationhelper.hxx>
103 #include <rtl/ustrbuf.hxx>
104 #include <vcl/svapp.hxx>
105 
106 //_______________________________________________
107 // namespace
108 
109 namespace framework{
110 
111 // may there exist already a define .-(
112 #ifndef css
113 namespace css = ::com::sun::star;
114 #endif
115 
116 //_______________________________________________
117 // declarations
118 
119 class LoadEnvListener : private ThreadHelpBase
120                       , public ::cppu::WeakImplHelper2< css::frame::XLoadEventListener      ,
121                                                         css::frame::XDispatchResultListener >
122 {
123     private:
124 
125         void**   m_ppCheck ;
126         LoadEnv* m_pLoadEnv;
127 
128     public:
129 
130         //_______________________________________
131         LoadEnvListener(void*    pCheck  ,
132                         LoadEnv* pLoadEnv)
133         {
134             m_ppCheck  = &pCheck ;
135             m_pLoadEnv = pLoadEnv;
136         }
137 
138         //_______________________________________
139         // frame.XLoadEventListener
140         virtual void SAL_CALL loadFinished(const css::uno::Reference< css::frame::XFrameLoader >& xLoader)
141             throw(css::uno::RuntimeException);
142 
143         virtual void SAL_CALL loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >& xLoader)
144             throw(css::uno::RuntimeException);
145 
146         //_______________________________________
147         // frame.XDispatchResultListener
148         virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent& aEvent)
149             throw(css::uno::RuntimeException);
150 
151         //_______________________________________
152         // lang.XEventListener
153         virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent)
154             throw(css::uno::RuntimeException);
155 };
156 
157 /*-----------------------------------------------
158     14.10.2003 13:43
159 -----------------------------------------------*/
160 LoadEnv::LoadEnv(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
161     throw(LoadEnvException, css::uno::RuntimeException)
162     : ThreadHelpBase(     )
163     , m_xSMGR       (xSMGR)
164     , m_pCheck      (this )
165 	, m_pQuietInteraction( 0 )
166 {
167 }
168 
169 /*-----------------------------------------------
170     14.10.2003 13:43
171 -----------------------------------------------*/
172 LoadEnv::~LoadEnv()
173 {
174     m_pCheck = 0;
175 }
176 
177 /*-----------------------------------------------
178     10.09.2003 14:05
179 -----------------------------------------------*/
180 css::uno::Reference< css::lang::XComponent > LoadEnv::loadComponentFromURL(const css::uno::Reference< css::frame::XComponentLoader >&    xLoader,
181                                                                            const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR  ,
182                                                                            const ::rtl::OUString&                                        sURL   ,
183                                                                            const ::rtl::OUString&                                        sTarget,
184                                                                                  sal_Int32                                               nFlags ,
185                                                                            const css::uno::Sequence< css::beans::PropertyValue >&        lArgs  )
186     throw(css::lang::IllegalArgumentException,
187           css::io::IOException               ,
188           css::uno::RuntimeException         )
189 {
190     css::uno::Reference< css::lang::XComponent > xComponent;
191 
192     try
193     {
194         LoadEnv aEnv(xSMGR);
195 
196         aEnv.initializeLoading(sURL,
197                                lArgs,
198                                css::uno::Reference< css::frame::XFrame >(xLoader, css::uno::UNO_QUERY),
199                                sTarget,
200                                nFlags,
201                                LoadEnv::E_NO_FEATURE);
202         aEnv.startLoading();
203         aEnv.waitWhileLoading(); // wait for ever!
204 
205         xComponent = aEnv.getTargetComponent();
206     }
207     catch(const LoadEnvException& ex)
208     {
209         switch(ex.m_nID)
210         {
211             case LoadEnvException::ID_INVALID_MEDIADESCRIPTOR:
212                     throw css::lang::IllegalArgumentException(
213                             ::rtl::OUString::createFromAscii("Optional list of arguments seem to be corrupted."),
214                             xLoader,
215                             4);
216 
217             case LoadEnvException::ID_UNSUPPORTED_CONTENT:
218                     throw css::lang::IllegalArgumentException(
219                             ::rtl::OUString::createFromAscii("URL seems to be an unsupported one."),
220                             xLoader,
221                             1);
222 
223 			default: xComponent.clear();
224                     break;
225         }
226     }
227 
228     return xComponent;
229 }
230 
231 //-----------------------------------------------
232 ::comphelper::MediaDescriptor impl_mergeMediaDescriptorWithMightExistingModelArgs(const css::uno::Sequence< css::beans::PropertyValue >& lOutsideDescriptor)
233 {
234     ::comphelper::MediaDescriptor lDescriptor(lOutsideDescriptor);
235     css::uno::Reference< css::frame::XModel > xModel     = lDescriptor.getUnpackedValueOrDefault(
236                                                             ::comphelper::MediaDescriptor::PROP_MODEL (),
237                                                             css::uno::Reference< css::frame::XModel > ());
238     if (xModel.is ())
239     {
240         ::comphelper::MediaDescriptor lModelDescriptor(xModel->getArgs());
241         ::comphelper::MediaDescriptor::iterator pIt = lModelDescriptor.find( ::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE() );
242 		if ( pIt != lModelDescriptor.end() )
243 			lDescriptor[::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()] = pIt->second;
244     }
245 
246     return lDescriptor;
247 }
248 
249 /*-----------------------------------------------
250     20.08.2003 09:49
251 -----------------------------------------------*/
252 void LoadEnv::initializeLoading(const ::rtl::OUString&                                           sURL            ,
253                                 const css::uno::Sequence< css::beans::PropertyValue >&           lMediaDescriptor,
254                                 const css::uno::Reference< css::frame::XFrame >&                 xBaseFrame      ,
255                                 const ::rtl::OUString&                                           sTarget         ,
256                                       sal_Int32                                                  nSearchFlags    ,
257                                       EFeature                                                   eFeature        , // => use default ...
258                                       EContentType                                               eContentType    ) // => use default ...
259     throw(LoadEnvException, css::uno::RuntimeException)
260 {
261     // SAFE -> ----------------------------------
262     WriteGuard aWriteLock(m_aLock);
263 
264     // Handle still running processes!
265     if (m_xAsynchronousJob.is())
266         throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
267 
268     // take over all new parameters.
269     m_xTargetFrame.clear();
270     m_xBaseFrame                    = xBaseFrame        ;
271     m_lMediaDescriptor              = impl_mergeMediaDescriptorWithMightExistingModelArgs(lMediaDescriptor);
272     m_sTarget                       = sTarget           ;
273     m_nSearchFlags                  = nSearchFlags      ;
274     m_eFeature                      = eFeature          ;
275     m_eContentType                  = eContentType      ;
276     m_bCloseFrameOnError            = sal_False         ;
277     m_bReactivateControllerOnError  = sal_False         ;
278     m_bLoaded                       = sal_False         ;
279 
280     // try to find out, if its realy a content, which can be loaded or must be "handled"
281     // We use a default value for this in-parameter. Then we have to start a complex check method
282     // internaly. But if this check was already done outside it can be supressed to perform
283     // the load request. We take over the result then!
284     if (m_eContentType == E_UNSUPPORTED_CONTENT)
285     {
286         m_eContentType = LoadEnv::classifyContent(sURL, lMediaDescriptor);
287         if (m_eContentType == E_UNSUPPORTED_CONTENT)
288             throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
289     }
290 
291     // make URL part of the MediaDescriptor
292     // It doesnt mater, if its already an item of it.
293     // It must be the same value ... so we can overwrite it :-)
294     m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_URL()] <<= sURL;
295 
296     // parse it - because some following code require that
297     m_aURL.Complete = sURL;
298     css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY);
299     xParser->parseStrict(m_aURL);
300 
301     // BTW: Split URL and JumpMark ...
302     // Because such mark is an explicit value of the media descriptor!
303     if (m_aURL.Mark.getLength())
304         m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_JUMPMARK()] <<= m_aURL.Mark;
305 
306     // By the way: remove the old and deprecated value "FileName" from the descriptor!
307     ::comphelper::MediaDescriptor::iterator pIt = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_FILENAME());
308     if (pIt != m_lMediaDescriptor.end())
309         m_lMediaDescriptor.erase(pIt);
310 
311     // patch the MediaDescriptor, so it fullfill the outside requirements
312     // Means especialy items like e.g. UI InteractionHandler, Status Indicator,
313     // MacroExecutionMode etcpp.
314 
315     /*TODO progress is bound to a frame ... How can we set it here? */
316 
317     // UI mode
318     const bool bUIMode =
319         ( ( m_eFeature & E_WORK_WITH_UI )                                                                          == E_WORK_WITH_UI ) &&
320         ( m_lMediaDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_HIDDEN() , sal_False ) == sal_False      ) &&
321         ( m_lMediaDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_PREVIEW(), sal_False ) == sal_False      );
322 
323     initializeUIDefaults(
324         m_xSMGR,
325         m_lMediaDescriptor,
326         bUIMode,
327         &m_pQuietInteraction
328     );
329 
330     aWriteLock.unlock();
331     // <- SAFE ----------------------------------
332 }
333 
334 /*-----------------------------------------------
335     22.01.2010
336 -----------------------------------------------*/
337 void LoadEnv::initializeUIDefaults( const css::uno::Reference< css::lang::XMultiServiceFactory >& i_rSMGR,
338                                     ::comphelper::MediaDescriptor& io_lMediaDescriptor, const bool i_bUIMode,
339                                     QuietInteraction** o_ppQuietInteraction )
340 {
341     css::uno::Reference< css::task::XInteractionHandler > xInteractionHandler;
342     sal_Int16                                             nMacroMode         ;
343     sal_Int16                                             nUpdateMode        ;
344 
345     if ( i_bUIMode )
346     {
347         nMacroMode  = css::document::MacroExecMode::USE_CONFIG;
348         nUpdateMode = css::document::UpdateDocMode::ACCORDING_TO_CONFIG;
349         try
350         {
351             xInteractionHandler = css::uno::Reference< css::task::XInteractionHandler >(i_rSMGR->createInstance(IMPLEMENTATIONNAME_UIINTERACTIONHANDLER), css::uno::UNO_QUERY);
352         }
353         catch(const css::uno::RuntimeException&) {throw;}
354         catch(const css::uno::Exception&       ) {      }
355     }
356     // hidden mode
357     else
358     {
359         nMacroMode  = css::document::MacroExecMode::NEVER_EXECUTE;
360         nUpdateMode = css::document::UpdateDocMode::NO_UPDATE;
361         QuietInteraction* pQuietInteraction = new QuietInteraction();
362         xInteractionHandler = css::uno::Reference< css::task::XInteractionHandler >(static_cast< css::task::XInteractionHandler* >(pQuietInteraction), css::uno::UNO_QUERY);
363         if ( o_ppQuietInteraction != NULL )
364         {
365             *o_ppQuietInteraction = pQuietInteraction;
366             (*o_ppQuietInteraction)->acquire();
367         }
368     }
369 
370     if (
371         (xInteractionHandler.is()                                                                                       ) &&
372         (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()) == io_lMediaDescriptor.end())
373        )
374     {
375         io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()] <<= xInteractionHandler;
376     }
377 
378     if (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()) == io_lMediaDescriptor.end())
379         io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()] <<= nMacroMode;
380 
381     if (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_UPDATEDOCMODE()) == io_lMediaDescriptor.end())
382         io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_UPDATEDOCMODE()] <<= nUpdateMode;
383 }
384 
385 /*-----------------------------------------------
386     15.08.2003 08:16
387 -----------------------------------------------*/
388 void LoadEnv::startLoading()
389     throw(LoadEnvException, css::uno::RuntimeException)
390 {
391     // SAFE ->
392     ReadGuard aReadLock(m_aLock);
393 
394     // Handle still running processes!
395     if (m_xAsynchronousJob.is())
396         throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
397 
398     // content can not be loaded or handled
399     // check "classifyContent()" failed before ...
400     if (m_eContentType == E_UNSUPPORTED_CONTENT)
401         throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
402 
403     // <- SAFE
404     aReadLock.unlock();
405 
406     // detect its type/filter etcpp.
407     // These information will be available by the
408     // used descriptor member afterwards and is needed
409     // for all following operations!
410     // Note: An exception will be thrown, in case operation was not successfully ...
411     if (m_eContentType != E_CAN_BE_SET)/* Attention: special feature to set existing component on a frame must ignore type detection! */
412         impl_detectTypeAndFilter();
413 
414     // start loading the content ...
415     // Attention: Dont check m_eContentType deeper then UNSUPPORTED/SUPPORTED!
416     // Because it was made in th easiest way ... may a flat detection was made only.
417     // And such simple detection can fail some times .-)
418     // Use another strategy here. Try it and let it run into the case "loading not possible".
419     sal_Bool bStarted = sal_False;
420     if (
421         ((m_eFeature & E_ALLOW_CONTENTHANDLER) == E_ALLOW_CONTENTHANDLER) &&
422         (m_eContentType                        != E_CAN_BE_SET          )   /* Attention: special feature to set existing component on a frame must ignore type detection! */
423        )
424     {
425         bStarted = impl_handleContent();
426     }
427 
428     if (!bStarted)
429         bStarted = impl_loadContent();
430 
431     // not started => general error
432     // We cant say - what was the reason for.
433     if (!bStarted)
434         throw LoadEnvException(LoadEnvException::ID_GENERAL_ERROR);
435 }
436 
437 /*-----------------------------------------------
438     15.08.2003 09:50
439     TODO
440         First draft does not implement timeout using [ms].
441         Current implementation counts yield calls only ...
442 -----------------------------------------------*/
443 sal_Bool LoadEnv::waitWhileLoading(sal_uInt32 nTimeout)
444     throw(LoadEnvException, css::uno::RuntimeException)
445 {
446     // Because its not a good idea to block the main thread
447     // (and we cant be shure that we are currently not used inside the
448     // main thread!), we cant use conditions here realy. We must yield
449     // in an intellegent manner :-)
450 
451     sal_Int32 nTime = nTimeout;
452     while(true)
453     {
454         // SAFE -> ------------------------------
455         ReadGuard aReadLock1(m_aLock);
456         if (!m_xAsynchronousJob.is())
457             break;
458         aReadLock1.unlock();
459         // <- SAFE ------------------------------
460 
461         Application::Yield();
462 
463         // forever!
464         if (nTimeout==0)
465             continue;
466 
467         // timed out?
468         --nTime;
469         if (nTime<1)
470             break;
471     }
472 
473     // SAFE -> ----------------------------------
474     ReadGuard aReadLock2(m_aLock);
475     return !m_xAsynchronousJob.is();
476     // <- SAFE ----------------------------------
477 }
478 
479 /*-----------------------------------------------
480     20.08.2003 10:00
481 -----------------------------------------------*/
482 void LoadEnv::cancelLoading()
483     throw(LoadEnvException, css::uno::RuntimeException)
484 {
485     // PARTIAL(!) SAFE -> ------------------------------
486     ReadGuard aReadLock(m_aLock);
487 
488     // Still running? Might waitWhileLoading()
489     // runned into the timeout!
490     if (m_xAsynchronousJob.is())
491     {
492         // try to cancel it ... if its an asynchronous frame loader
493         css::uno::Reference< css::frame::XFrameLoader > xAsyncLoader(m_xAsynchronousJob, css::uno::UNO_QUERY);
494         if (xAsyncLoader.is())
495         {
496             aReadLock.unlock();
497             // <- BREAK SAFE ------------------------------
498             xAsyncLoader->cancel();
499             // <- RESTART SAFE ----------------------------
500             aReadLock.lock();
501             /* Attention:
502                 After returning from any cancel/dispose call, neither the frame nor weself
503                 may be called back. Because only we can cancel this job, we already know
504                 the result! => Thats why its not usefull nor neccessary to wait for any
505                 asynchronous listener notification.
506             */
507             m_bLoaded = sal_False;
508             m_xAsynchronousJob.clear();
509         }
510         // or may be its a content handler? Such handler cant be cancelled in its running
511         // operation :-( And we cant deregister us there again :-(
512         // => The only chance is an exception :-)
513         else
514             throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
515     }
516 
517     impl_reactForLoadingState();
518 
519     aReadLock.unlock();
520     // <- PARTIAL(!) SAFE ------------------------------
521 }
522 
523 /*-----------------------------------------------
524     14.08.2003 13:33
525 -----------------------------------------------*/
526 css::uno::Reference< css::frame::XFrame > LoadEnv::getTarget() const
527 {
528     // SAFE ->
529     ReadGuard aReadLock(m_aLock);
530     return m_xTargetFrame;
531     // <- SAFE
532 }
533 
534 /*-----------------------------------------------
535     14.08.2003 13:35
536 -----------------------------------------------*/
537 css::uno::Reference< css::lang::XComponent > LoadEnv::getTargetComponent() const
538 {
539     // SAFE ->
540     ReadGuard aReadLock(m_aLock);
541 
542     if (!m_xTargetFrame.is())
543         return css::uno::Reference< css::lang::XComponent >();
544 
545     css::uno::Reference< css::frame::XController > xController = m_xTargetFrame->getController();
546     if (!xController.is())
547         return css::uno::Reference< css::lang::XComponent >(m_xTargetFrame->getComponentWindow(), css::uno::UNO_QUERY);
548 
549     css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
550     if (!xModel.is())
551         return css::uno::Reference< css::lang::XComponent >(xController, css::uno::UNO_QUERY);
552 
553     return css::uno::Reference< css::lang::XComponent >(xModel, css::uno::UNO_QUERY);
554     // <- SAFE
555 }
556 
557 /*-----------------------------------------------
558     15.08.2003 11:15
559 -----------------------------------------------*/
560 void SAL_CALL LoadEnvListener::loadFinished(const css::uno::Reference< css::frame::XFrameLoader >&)
561     throw(css::uno::RuntimeException)
562 {
563     // SAFE -> ----------------------------------
564     WriteGuard aWriteLock(m_aLock);
565 
566     if (m_ppCheck && *m_ppCheck)
567         m_pLoadEnv->impl_setResult(sal_True);
568     m_ppCheck = NULL;
569 
570     aWriteLock.unlock();
571     // <- SAFE ----------------------------------
572 }
573 
574 /*-----------------------------------------------
575     14.10.2003 12:23
576 -----------------------------------------------*/
577 void SAL_CALL LoadEnvListener::loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >&)
578     throw(css::uno::RuntimeException)
579 {
580     // SAFE -> ----------------------------------
581     WriteGuard aWriteLock(m_aLock);
582 
583     if (m_ppCheck && *m_ppCheck)
584         m_pLoadEnv->impl_setResult(sal_False);
585     m_ppCheck = NULL;
586 
587     aWriteLock.unlock();
588     // <- SAFE ----------------------------------
589 }
590 
591 /*-----------------------------------------------
592     14.10.2003 12:23
593 -----------------------------------------------*/
594 void SAL_CALL LoadEnvListener::dispatchFinished(const css::frame::DispatchResultEvent& aEvent)
595     throw(css::uno::RuntimeException)
596 {
597     // SAFE -> ----------------------------------
598     WriteGuard aWriteLock(m_aLock);
599 
600     if (!m_ppCheck || !*m_ppCheck)
601         return;
602 
603     switch(aEvent.State)
604     {
605         case css::frame::DispatchResultState::FAILURE :
606             m_pLoadEnv->impl_setResult(sal_False);
607             break;
608 
609         case css::frame::DispatchResultState::SUCCESS :
610             m_pLoadEnv->impl_setResult(sal_False);
611             break;
612 
613         case css::frame::DispatchResultState::DONTKNOW :
614             m_pLoadEnv->impl_setResult(sal_False);
615             break;
616     }
617     m_ppCheck = NULL;
618 
619     aWriteLock.unlock();
620     // <- SAFE ----------------------------------
621 }
622 
623 /*-----------------------------------------------
624     14.10.2003 12:24
625 -----------------------------------------------*/
626 void SAL_CALL LoadEnvListener::disposing(const css::lang::EventObject&)
627     throw(css::uno::RuntimeException)
628 {
629     // SAFE -> ----------------------------------
630     WriteGuard aWriteLock(m_aLock);
631 
632     if (m_ppCheck && *m_ppCheck)
633         m_pLoadEnv->impl_setResult(sal_False);
634     m_ppCheck = NULL;
635 
636     aWriteLock.unlock();
637     // <- SAFE ----------------------------------
638 }
639 
640 /*-----------------------------------------------
641     14.10.2003 12:20
642 -----------------------------------------------*/
643 void LoadEnv::impl_setResult(sal_Bool bResult)
644 {
645     // SAFE -> ----------------------------------
646     WriteGuard aWriteLock(m_aLock);
647 
648     m_bLoaded = bResult;
649 
650     impl_reactForLoadingState();
651 
652     // clearing of this reference will unblock waitWhileLoading()!
653     // So we must be shure, that loading process was realy finished.
654     // => do it as last operation of this method ...
655     m_xAsynchronousJob.clear();
656 
657     aWriteLock.unlock();
658     // <- SAFE ----------------------------------
659 }
660 
661 /*-----------------------------------------------
662     06.02.2004 14:03
663     TODO: Is it a good idea to change Sequence<>
664           parameter to stl-adapter?
665 -----------------------------------------------*/
666 LoadEnv::EContentType LoadEnv::classifyContent(const ::rtl::OUString&                                 sURL            ,
667                                                const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor)
668 {
669     //-------------------------------------------
670     // (i) Filter some special well known URL protocols,
671     //     which can not be handled or loaded in general.
672     //     Of course an empty URL must be ignored here too.
673     //     Note: These URL schemata are fix and well known ...
674     //     But there can be some additional ones, which was not
675     //     defined at implementation time of this class :-(
676     //     So we have to make shure, that the following code
677     //     can detect such protocol schemata too :-)
678 
679     if(
680         (!sURL.getLength()                                       ) ||
681         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_UNO    )) ||
682         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_SLOT   )) ||
683         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_MACRO  )) ||
684         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_SERVICE)) ||
685         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_MAILTO )) ||
686         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_NEWS   ))
687       )
688     {
689         return E_UNSUPPORTED_CONTENT;
690     }
691 
692     //-------------------------------------------
693     // (ii) Some special URLs indicates a given input stream,
694     //      a full featured document model directly or
695     //      specify a request for opening an empty document.
696     //      Such contents are loadable in general.
697     //      But we have to check, if the media descriptor contains
698     //      all needed resources. If they are missing - the following
699     //      load request will fail.
700 
701     /* Attention: The following code cant work on such special URLs!
702                   It should not break the office .. but it make no sense
703                   to start expensive object creations and complex search
704                   algorithm if its clear, that such URLs must be handled
705                   in a special way .-)
706     */
707 
708     // creation of new documents
709     if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_FACTORY))
710         return E_CAN_BE_LOADED;
711 
712     // using of an existing input stream
713     ::comphelper::MediaDescriptor                 stlMediaDescriptor(lMediaDescriptor);
714     ::comphelper::MediaDescriptor::const_iterator pIt;
715     if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_STREAM))
716     {
717         pIt = stlMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_INPUTSTREAM());
718         css::uno::Reference< css::io::XInputStream > xStream;
719         if (pIt != stlMediaDescriptor.end())
720             pIt->second >>= xStream;
721         if (xStream.is())
722             return E_CAN_BE_LOADED;
723         LOG_WARNING("LoadEnv::classifyContent()", "loading from stream with right URL but invalid stream detected")
724         return E_UNSUPPORTED_CONTENT;
725     }
726 
727     // using of a full featured document
728     if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_OBJECT))
729     {
730         pIt = stlMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_MODEL());
731         css::uno::Reference< css::frame::XModel > xModel;
732         if (pIt != stlMediaDescriptor.end())
733             pIt->second >>= xModel;
734         if (xModel.is())
735             return E_CAN_BE_SET;
736         LOG_WARNING("LoadEnv::classifyContent()", "loading with object with right URL but invalid object detected")
737         return E_UNSUPPORTED_CONTENT;
738     }
739 
740     // following operatons can work on an internal type name only :-(
741     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::utl::getProcessServiceFactory();
742     css::uno::Reference< css::document::XTypeDetection > xDetect(xSMGR->createInstance(SERVICENAME_TYPEDETECTION), css::uno::UNO_QUERY);
743 
744     ::rtl::OUString sType = xDetect->queryTypeByURL(sURL);
745 
746     css::uno::Sequence< css::beans::NamedValue >           lQuery(1)   ;
747     css::uno::Reference< css::container::XContainerQuery > xContainer  ;
748     css::uno::Reference< css::container::XEnumeration >    xSet        ;
749     css::uno::Sequence< ::rtl::OUString >                  lTypesReg(1);
750 
751     /*
752     //-------------------------------------------
753     lQuery[0].Name    = ::framework::constant::Filter::PROP_TYPE;
754     lQuery[0].Value <<= sType;
755 
756     xContainer = css::uno::Reference< css::container::XContainerQuery >(xSMGR->createInstance(SERVICENAME_FILTERFACTORY), css::uno::UNO_QUERY);
757     xSet       = xContainer->createSubSetEnumerationByProperties(lQuery);
758     // at least one registered frame loader is enough!
759     if (xSet->hasMoreElements())
760         return E_CAN_BE_LOADED;
761     */
762 
763     //-------------------------------------------
764     // (iii) If a FrameLoader service (or at least
765     //      a Filter) can be found, which supports
766     //      this URL - it must be a loadable content.
767     //      Because both items are registered for types
768     //      its enough to check for frame loaders only.
769     //      Mos of our filters are handled by our global
770     //      default loader. But there exist some specialized
771     //      loader, which does not work on top of filters!
772     //      So its not enough to search on the filter configuration.
773     //      Further its not enough to search for types!
774     //      Because there exist some types, which are referenced by
775     //      other objects ... but not by filters nor frame loaders!
776 
777     lTypesReg[0]      = sType;
778     lQuery[0].Name    = ::framework::constant::FrameLoader::PROP_TYPES;
779     lQuery[0].Value <<= lTypesReg;
780 
781     xContainer = css::uno::Reference< css::container::XContainerQuery >(xSMGR->createInstance(SERVICENAME_FRAMELOADERFACTORY), css::uno::UNO_QUERY);
782     xSet       = xContainer->createSubSetEnumerationByProperties(lQuery);
783     // at least one registered frame loader is enough!
784     if (xSet->hasMoreElements())
785         return E_CAN_BE_LOADED;
786 
787     //-------------------------------------------
788     // (iv) Some URL protocols are supported by special services.
789     //      E.g. ContentHandler.
790     //      Such contents can be handled ... but not loaded.
791 
792     lTypesReg[0]      = sType;
793     lQuery[0].Name    = ::framework::constant::ContentHandler::PROP_TYPES;
794     lQuery[0].Value <<= lTypesReg;
795 
796     xContainer = css::uno::Reference< css::container::XContainerQuery >(xSMGR->createInstance(SERVICENAME_CONTENTHANDLERFACTORY), css::uno::UNO_QUERY);
797     xSet       = xContainer->createSubSetEnumerationByProperties(lQuery);
798     // at least one registered content handler is enough!
799     if (xSet->hasMoreElements())
800         return E_CAN_BE_HANDLED;
801 
802     //-------------------------------------------
803     // (v) Last but not least the UCB is used inside office to
804     //     load contents. He has a special configuration to know
805     //     which URL schemata can be used inside office.
806     css::uno::Reference< css::ucb::XContentProviderManager > xUCB(xSMGR->createInstance(SERVICENAME_UCBCONTENTBROKER), css::uno::UNO_QUERY);
807     if (xUCB->queryContentProvider(sURL).is())
808         return E_CAN_BE_LOADED;
809 
810     //-------------------------------------------
811     // (TODO) At this point, we have no idea .-)
812     //        But it seems to be better, to break all
813     //        further requests for this URL. Otherwhise
814     //        we can run into some trouble.
815     return E_UNSUPPORTED_CONTENT;
816 }
817 
818 /*-----------------------------------------------
819     03.11.2003 09:31
820 -----------------------------------------------*/
821 void LoadEnv::impl_detectTypeAndFilter()
822     throw(LoadEnvException, css::uno::RuntimeException)
823 {
824     static ::rtl::OUString TYPEPROP_PREFERREDFILTER = ::rtl::OUString::createFromAscii("PreferredFilter");
825     static ::rtl::OUString FILTERPROP_FLAGS         = ::rtl::OUString::createFromAscii("Flags"          );
826     static sal_Int32       FILTERFLAG_TEMPLATEPATH  = 16;
827 
828     // SAFE ->
829     ReadGuard aReadLock(m_aLock);
830 
831     // Attention: Because our stl media descriptor is a copy of an uno sequence
832     // we cant use as an in/out parameter here. Copy it before and dont forget to
833     // update structure afterwards again!
834     css::uno::Sequence< css::beans::PropertyValue >        lDescriptor = m_lMediaDescriptor.getAsConstPropertyValueList();
835     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR       = m_xSMGR;
836 
837     aReadLock.unlock();
838     // <- SAFE
839 
840     ::rtl::OUString sType;
841     css::uno::Reference< css::document::XTypeDetection > xDetect(xSMGR->createInstance(SERVICENAME_TYPEDETECTION), css::uno::UNO_QUERY);
842     if (xDetect.is())
843         sType = xDetect->queryTypeByDescriptor(lDescriptor, sal_True); /*TODO should deep detection be able for enable/disable it from outside? */
844 
845     // no valid content -> loading not possible
846     if (!sType.getLength())
847         throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
848 
849     // SAFE ->
850     WriteGuard aWriteLock(m_aLock);
851 
852     // detection was successfully => update the descriptor member of this class
853     m_lMediaDescriptor << lDescriptor;
854     m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType;
855     // Is there an already detected (may be preselected) filter?
856     // see below ...
857     ::rtl::OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), ::rtl::OUString());
858 
859     aWriteLock.unlock();
860     // <- SAFE
861 
862     // But the type isnt enough. For loading sometimes we need more informations.
863     // E.g. for our "_default" feature, where we recylce any frame which contains
864     // and "Untitled" document, we must know if the new document is based on a template!
865     // But this information is available as a filter property only.
866     // => We must try(!) to detect the right filter for this load request.
867     // On the other side ... if no filter is available .. ignore it.
868     // Then the type information must be enough.
869     if (!sFilter.getLength())
870     {
871         // no -> try to find a preferred filter for the detected type.
872         // Dont forget to updatet he media descriptor.
873         css::uno::Reference< css::container::XNameAccess > xTypeCont(xDetect, css::uno::UNO_QUERY_THROW);
874         try
875         {
876             ::comphelper::SequenceAsHashMap lTypeProps(xTypeCont->getByName(sType));
877             sFilter = lTypeProps.getUnpackedValueOrDefault(TYPEPROP_PREFERREDFILTER, ::rtl::OUString());
878             if (sFilter.getLength())
879             {
880                 // SAFE ->
881                 aWriteLock.lock();
882                 m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
883                 aWriteLock.unlock();
884                 // <- SAFE
885             }
886         }
887         catch(const css::container::NoSuchElementException&)
888             {}
889     }
890 
891     // check if the filter (if one exists) points to a template format filter.
892     // Then we have to add the property "AsTemplate".
893     // We need this information to decide afterwards if we can use a "recycle frame"
894     // for target "_default" or has to create a new one everytimes.
895     // On the other side we have to supress that, if this property already exists
896     // and should trigger a special handling. Then the outside calli of this method here,
897     // has to know, what he is doing .-)
898 
899     sal_Bool bIsOwnTemplate = sal_False;
900     if (sFilter.getLength())
901     {
902         css::uno::Reference< css::container::XNameAccess > xFilterCont(xSMGR->createInstance(SERVICENAME_FILTERFACTORY), css::uno::UNO_QUERY_THROW);
903         try
904         {
905             ::comphelper::SequenceAsHashMap lFilterProps(xFilterCont->getByName(sFilter));
906             sal_Int32 nFlags         = lFilterProps.getUnpackedValueOrDefault(FILTERPROP_FLAGS, (sal_Int32)0);
907                       bIsOwnTemplate = ((nFlags & FILTERFLAG_TEMPLATEPATH) == FILTERFLAG_TEMPLATEPATH);
908         }
909         catch(const css::container::NoSuchElementException&)
910             {}
911     }
912     if (bIsOwnTemplate)
913     {
914         // SAFE ->
915         aWriteLock.lock();
916         // Dont overwrite external decisions! See comments before ...
917         ::comphelper::MediaDescriptor::const_iterator pAsTemplateItem = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_ASTEMPLATE());
918         if (pAsTemplateItem == m_lMediaDescriptor.end())
919             m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_ASTEMPLATE()] <<= sal_True;
920         aWriteLock.unlock();
921         // <- SAFE
922     }
923 }
924 
925 /*-----------------------------------------------
926     15.08.2003 09:38
927 -----------------------------------------------*/
928 sal_Bool LoadEnv::impl_handleContent()
929     throw(LoadEnvException, css::uno::RuntimeException)
930 {
931     // SAFE -> -----------------------------------
932     ReadGuard aReadLock(m_aLock);
933 
934     // the type must exist inside the descriptor ... otherwhise this class is implemented wrong :-)
935     ::rtl::OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString());
936     if (!sType.getLength())
937         throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
938 
939     // convert media descriptor and URL to right format for later interface call!
940     css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
941     m_lMediaDescriptor >> lDescriptor;
942     css::util::URL aURL = m_aURL;
943 
944     // get neccessary container to query for a handler object
945     css::uno::Reference< css::lang::XMultiServiceFactory > xFactory(m_xSMGR->createInstance(SERVICENAME_CONTENTHANDLERFACTORY), css::uno::UNO_QUERY);
946     css::uno::Reference< css::container::XContainerQuery > xQuery  (xFactory                                                  , css::uno::UNO_QUERY);
947 
948     aReadLock.unlock();
949     // <- SAFE -----------------------------------
950 
951     // query
952     css::uno::Sequence< ::rtl::OUString > lTypeReg(1);
953     lTypeReg[0] = sType;
954 
955     css::uno::Sequence< css::beans::NamedValue > lQuery(1);
956     lQuery[0].Name    = ::framework::constant::ContentHandler::PROP_TYPES;
957     lQuery[0].Value <<= lTypeReg;
958 
959     css::uno::Reference< css::container::XEnumeration > xSet = xQuery->createSubSetEnumerationByProperties(lQuery);
960     while(xSet->hasMoreElements())
961     {
962         ::comphelper::SequenceAsHashMap lProps   (xSet->nextElement());
963         ::rtl::OUString                 sHandler = lProps.getUnpackedValueOrDefault(::framework::constant::ContentHandler::PROP_NAME, ::rtl::OUString());
964 
965         css::uno::Reference< css::frame::XNotifyingDispatch > xHandler;
966         try
967         {
968             xHandler = css::uno::Reference< css::frame::XNotifyingDispatch >(xFactory->createInstance(sHandler), css::uno::UNO_QUERY);
969             if (!xHandler.is())
970                 continue;
971         }
972         catch(const css::uno::RuntimeException&)
973             { throw; }
974         catch(const css::uno::Exception&)
975             { continue; }
976 
977         // SAFE -> -----------------------------------
978         WriteGuard aWriteLock(m_aLock);
979         m_xAsynchronousJob = xHandler;
980         m_pCheck           = this;
981         LoadEnvListener* pListener = new LoadEnvListener(m_pCheck, this);
982         aWriteLock.unlock();
983         // <- SAFE -----------------------------------
984 
985         css::uno::Reference< css::frame::XDispatchResultListener > xListener(static_cast< css::frame::XDispatchResultListener* >(pListener), css::uno::UNO_QUERY);
986         xHandler->dispatchWithNotification(aURL, lDescriptor, xListener);
987 
988         return sal_True;
989     }
990 
991     return sal_False;
992 }
993 
994 //-----------------------------------------------
995 sal_Bool LoadEnv::impl_furtherDocsAllowed()
996 {
997     // SAFE ->
998     ReadGuard aReadLock(m_aLock);
999     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1000     aReadLock.unlock();
1001     // <- SAFE
1002 
1003     sal_Bool bAllowed = sal_True;
1004 
1005     try
1006     {
1007         css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
1008                                 xSMGR,
1009                                 ::rtl::OUString::createFromAscii("org.openoffice.Office.Common/"),
1010                                 ::rtl::OUString::createFromAscii("Misc"),
1011                                 ::rtl::OUString::createFromAscii("MaxOpenDocuments"),
1012                                 ::comphelper::ConfigurationHelper::E_READONLY);
1013 
1014         // NIL means: count of allowed documents = infinite !
1015         //     => return sal_True
1016         if ( ! aVal.hasValue())
1017             bAllowed = sal_True;
1018         else
1019         {
1020             sal_Int32 nMaxOpenDocuments = 0;
1021             aVal >>= nMaxOpenDocuments;
1022 
1023             css::uno::Reference< css::frame::XFramesSupplier > xDesktop(
1024                 xSMGR->createInstance(SERVICENAME_DESKTOP),
1025                 css::uno::UNO_QUERY_THROW);
1026 
1027             FrameListAnalyzer aAnalyzer(xDesktop,
1028                                         css::uno::Reference< css::frame::XFrame >(),
1029                                         FrameListAnalyzer::E_HELP |
1030                                         FrameListAnalyzer::E_BACKINGCOMPONENT |
1031                                         FrameListAnalyzer::E_HIDDEN);
1032 
1033             sal_Int32 nOpenDocuments = aAnalyzer.m_lOtherVisibleFrames.getLength();
1034                       bAllowed       = (nOpenDocuments < nMaxOpenDocuments);
1035         }
1036     }
1037     catch(const css::uno::Exception&)
1038         { bAllowed = sal_True; } // !! internal errors are no reason to disturb the office from opening documents .-)
1039 
1040     if ( ! bAllowed )
1041     {
1042         // SAFE ->
1043         aReadLock.lock();
1044         css::uno::Reference< css::task::XInteractionHandler > xInteraction = m_lMediaDescriptor.getUnpackedValueOrDefault(
1045                                                                                 ::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER(),
1046                                                                                 css::uno::Reference< css::task::XInteractionHandler >());
1047         aReadLock.unlock();
1048         // <- SAFE
1049 
1050         if (xInteraction.is())
1051         {
1052             css::uno::Any                                                                    aInteraction;
1053             css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations(2);
1054 
1055             comphelper::OInteractionAbort*   pAbort   = new comphelper::OInteractionAbort();
1056             comphelper::OInteractionApprove* pApprove = new comphelper::OInteractionApprove();
1057 
1058             lContinuations[0] = css::uno::Reference< css::task::XInteractionContinuation >(
1059                                     static_cast< css::task::XInteractionContinuation* >(pAbort),
1060                                     css::uno::UNO_QUERY_THROW);
1061             lContinuations[1] = css::uno::Reference< css::task::XInteractionContinuation >(
1062                                     static_cast< css::task::XInteractionContinuation* >(pApprove),
1063                                     css::uno::UNO_QUERY_THROW);
1064 
1065             css::task::ErrorCodeRequest aErrorCode;
1066             aErrorCode.ErrCode = ERRCODE_SFX_NOMOREDOCUMENTSALLOWED;
1067             aInteraction <<= aErrorCode;
1068             xInteraction->handle( InteractionRequest::CreateRequest(aInteraction, lContinuations) );
1069         }
1070     }
1071 
1072     return bAllowed;
1073 }
1074 
1075 //-----------------------------------------------
1076 sal_Bool LoadEnv::impl_loadContent()
1077     throw(LoadEnvException, css::uno::RuntimeException)
1078 {
1079     // SAFE -> -----------------------------------
1080     WriteGuard aWriteLock(m_aLock);
1081 
1082     // search or create right target frame
1083     ::rtl::OUString sTarget = m_sTarget;
1084     if (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_DEFAULT))
1085     {
1086         m_xTargetFrame = impl_searchAlreadyLoaded();
1087         if (m_xTargetFrame.is())
1088 		{
1089 			impl_setResult(sal_True);
1090 			return sal_True;
1091 		}
1092         m_xTargetFrame = impl_searchRecycleTarget();
1093     }
1094 
1095     if (! m_xTargetFrame.is())
1096     {
1097         if (
1098             (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_BLANK  )) ||
1099             (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_DEFAULT))
1100            )
1101         {
1102             if (! impl_furtherDocsAllowed())
1103                 return sal_False;
1104             m_xTargetFrame       = m_xBaseFrame->findFrame(SPECIALTARGET_BLANK, 0);
1105             m_bCloseFrameOnError = m_xTargetFrame.is();
1106         }
1107         else
1108         {
1109             sal_Int32 nFlags = m_nSearchFlags & ~css::frame::FrameSearchFlag::CREATE;
1110             m_xTargetFrame   = m_xBaseFrame->findFrame(sTarget, nFlags);
1111             if (! m_xTargetFrame.is())
1112             {
1113                 if (! impl_furtherDocsAllowed())
1114                     return sal_False;
1115                 m_xTargetFrame       = m_xBaseFrame->findFrame(SPECIALTARGET_BLANK, 0);
1116                 m_bCloseFrameOnError = m_xTargetFrame.is();
1117             }
1118         }
1119     }
1120 
1121     // If we couldn't find a valid frame or the frame has no container window
1122     // we have to throw an exception.
1123     if (
1124         ( ! m_xTargetFrame.is()                       ) ||
1125         ( ! m_xTargetFrame->getContainerWindow().is() )
1126        )
1127         throw LoadEnvException(LoadEnvException::ID_NO_TARGET_FOUND);
1128 
1129     css::uno::Reference< css::frame::XFrame > xTargetFrame = m_xTargetFrame;
1130 
1131     // Now we have a valid frame ... and type detection was already done.
1132     // We should apply the module dependend window position and size to the
1133     // frame window.
1134     impl_applyPersistentWindowState(xTargetFrame->getContainerWindow());
1135 
1136     // Don't forget to lock task for following load process. Otherwise it could die
1137     // during this operation runs by terminating the office or closing this task via api.
1138     // If we set this lock "close()" will return false and closing will be broken.
1139     // Attention: Don't forget to reset this lock again after finishing operation.
1140     // Otherwise task AND office couldn't die!!!
1141     // This includes gracefully handling of Exceptions (Runtime!) too ...
1142     // Thats why we use a specialized guard, which will reset the lock
1143     // if it will be run out of scope.
1144 
1145     // Note further: ignore if this internal guard already contains a resource.
1146     // Might impl_searchRecylcTarget() set it before. But incase this impl-method wasnt used
1147     // and the target frame was new created ... this lock here must be set!
1148     css::uno::Reference< css::document::XActionLockable > xTargetLock(xTargetFrame, css::uno::UNO_QUERY);
1149     m_aTargetLock.setResource(xTargetLock);
1150 
1151     // Add status indicator to descriptor. Loader can show an progresses then.
1152     // But don't do it, if loading should be hidden or preview is used ...!
1153     // So we prevent our code against wrong using. Why?
1154     // It could be, that using of this progress could make trouble. e.g. He make window visible ...
1155     // but shouldn't do that. But if no indicator is available ... nobody has a chance to do that!
1156     sal_Bool                                           bHidden    = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN()         , sal_False                                           );
1157     sal_Bool                                           bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_MINIMIZED()      , sal_False                                           );
1158     sal_Bool                                           bPreview   = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_PREVIEW()        , sal_False                                           );
1159     css::uno::Reference< css::task::XStatusIndicator > xProgress  = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), css::uno::Reference< css::task::XStatusIndicator >());
1160 
1161     if (!bHidden && !bMinimized && !bPreview && !xProgress.is())
1162     {
1163         // Note: its an optional interface!
1164         css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xTargetFrame, css::uno::UNO_QUERY);
1165         if (xProgressFactory.is())
1166         {
1167             xProgress = xProgressFactory->createStatusIndicator();
1168             if (xProgress.is())
1169                 m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= xProgress;
1170         }
1171     }
1172 
1173     // convert media descriptor and URL to right format for later interface call!
1174     css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
1175     m_lMediaDescriptor >> lDescriptor;
1176     ::rtl::OUString sURL = m_aURL.Complete;
1177 
1178     // try to locate any interested frame loader
1179     css::uno::Reference< css::uno::XInterface >                xLoader     = impl_searchLoader();
1180     css::uno::Reference< css::frame::XFrameLoader >            xAsyncLoader(xLoader, css::uno::UNO_QUERY);
1181     css::uno::Reference< css::frame::XSynchronousFrameLoader > xSyncLoader (xLoader, css::uno::UNO_QUERY);
1182 
1183     if (xAsyncLoader.is())
1184     {
1185         // SAFE -> -----------------------------------
1186         aWriteLock.lock();
1187         m_xAsynchronousJob = xAsyncLoader;
1188         m_pCheck           = this;
1189         LoadEnvListener* pListener = new LoadEnvListener(m_pCheck, this);
1190         aWriteLock.unlock();
1191         // <- SAFE -----------------------------------
1192 
1193         css::uno::Reference< css::frame::XLoadEventListener > xListener(static_cast< css::frame::XLoadEventListener* >(pListener), css::uno::UNO_QUERY);
1194         xAsyncLoader->load(xTargetFrame, sURL, lDescriptor, xListener);
1195 
1196         return sal_True;
1197     }
1198     else
1199     if (xSyncLoader.is())
1200     {
1201         sal_Bool bResult = xSyncLoader->load(lDescriptor, xTargetFrame);
1202         // react for the result here, so the outside waiting
1203         // code can ask for it later.
1204         impl_setResult(bResult);
1205         // But the return value indicates a valid started(!) operation.
1206         // And thats true everxtimes, we reach this line :-)
1207         return sal_True;
1208     }
1209 
1210     aWriteLock.unlock();
1211     // <- SAFE
1212 
1213     return sal_False;
1214 }
1215 
1216 /*-----------------------------------------------
1217     06.02.2004 14:40
1218 -----------------------------------------------*/
1219 css::uno::Reference< css::uno::XInterface > LoadEnv::impl_searchLoader()
1220 {
1221     // SAFE -> -----------------------------------
1222     ReadGuard aReadLock(m_aLock);
1223 
1224     // special mode to set an existing component on this frame
1225     // In such case the laoder is fix. It must be the SFX based implementation,
1226     // which can create a view on top of such xModel components :-)
1227     if (m_eContentType == E_CAN_BE_SET)
1228     {
1229         try
1230         {
1231             return m_xSMGR->createInstance(IMPLEMENTATIONNAME_GENERICFRAMELOADER);
1232         }
1233         catch(const css::uno::RuntimeException&)
1234             { throw; }
1235         catch(const css::uno::Exception&)
1236             {}
1237         throw LoadEnvException(LoadEnvException::ID_INVALID_ENVIRONMENT);
1238     }
1239 
1240     // Otherwhise ...
1241     // We need this type information to locate an registered frame loader
1242     // Without such information we cant work!
1243     ::rtl::OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString());
1244     if (!sType.getLength())
1245         throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
1246 
1247     // try to locate any interested frame loader
1248     css::uno::Reference< css::lang::XMultiServiceFactory > xLoaderFactory(m_xSMGR->createInstance(SERVICENAME_FRAMELOADERFACTORY), css::uno::UNO_QUERY);
1249     css::uno::Reference< css::container::XContainerQuery > xQuery        (xLoaderFactory                                         , css::uno::UNO_QUERY);
1250 
1251     aReadLock.unlock();
1252     // <- SAFE -----------------------------------
1253 
1254     css::uno::Sequence< ::rtl::OUString > lTypesReg(1);
1255     lTypesReg[0] = sType;
1256 
1257     css::uno::Sequence< css::beans::NamedValue > lQuery(1);
1258     lQuery[0].Name    = ::framework::constant::FrameLoader::PROP_TYPES;
1259     lQuery[0].Value <<= lTypesReg;
1260 
1261     css::uno::Reference< css::container::XEnumeration > xSet = xQuery->createSubSetEnumerationByProperties(lQuery);
1262     while(xSet->hasMoreElements())
1263     {
1264         // try everyone ...
1265         // Ignore any loader, which makes trouble :-)
1266         ::comphelper::SequenceAsHashMap             lLoaderProps(xSet->nextElement());
1267         ::rtl::OUString                             sLoader     = lLoaderProps.getUnpackedValueOrDefault(::framework::constant::FrameLoader::PROP_NAME, ::rtl::OUString());
1268         css::uno::Reference< css::uno::XInterface > xLoader     ;
1269         try
1270         {
1271             xLoader = xLoaderFactory->createInstance(sLoader);
1272             if (xLoader.is())
1273                 return xLoader;
1274         }
1275         catch(const css::uno::RuntimeException&)
1276             { throw; }
1277         catch(const css::uno::Exception&)
1278             { continue; }
1279     }
1280 
1281     return css::uno::Reference< css::uno::XInterface >();
1282 }
1283 
1284 /*-----------------------------------------------
1285     24.01.2006 15:11
1286 -----------------------------------------------*/
1287 void LoadEnv::impl_jumpToMark(const css::uno::Reference< css::frame::XFrame >& xFrame,
1288                               const css::util::URL&                            aURL  )
1289 {
1290     if (! aURL.Mark.getLength())
1291         return;
1292 
1293     css::uno::Reference< css::frame::XDispatchProvider > xProvider(xFrame, css::uno::UNO_QUERY);
1294     if (! xProvider.is())
1295         return;
1296 
1297     // SAFE ->
1298     ReadGuard aReadLock(m_aLock);
1299     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1300     aReadLock.unlock();
1301     // <- SAFE
1302 
1303     css::util::URL aCmd;
1304     aCmd.Complete = ::rtl::OUString::createFromAscii(".uno:JumpToMark");
1305 
1306     css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
1307     xParser->parseStrict(aCmd);
1308 
1309     css::uno::Reference< css::frame::XDispatch > xDispatcher = xProvider->queryDispatch(aCmd, SPECIALTARGET_SELF, 0);
1310     if (! xDispatcher.is())
1311         return;
1312 
1313     ::comphelper::SequenceAsHashMap lArgs;
1314     lArgs[::rtl::OUString::createFromAscii("Bookmark")] <<= aURL.Mark;
1315     xDispatcher->dispatch(aCmd, lArgs.getAsConstPropertyValueList());
1316 }
1317 
1318 /*-----------------------------------------------
1319     31.07.2003 09:02
1320 -----------------------------------------------*/
1321 css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchAlreadyLoaded()
1322     throw(LoadEnvException, css::uno::RuntimeException)
1323 {
1324     // SAFE ->
1325     ReadGuard aReadLock(m_aLock);
1326 
1327     // such search is allowed for special requests only ...
1328     // or better its not allowed for some requests in general :-)
1329     if (
1330         ( ! TargetHelper::matchSpecialTarget(m_sTarget, TargetHelper::E_DEFAULT)                                               ) ||
1331         (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_ASTEMPLATE() , sal_False) == sal_True) ||
1332 //      (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN()     , sal_False) == sal_True) ||
1333         (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_OPENNEWVIEW(), sal_False) == sal_True)
1334        )
1335     {
1336         return css::uno::Reference< css::frame::XFrame >();
1337     }
1338 
1339     // check URL
1340     // May its not usefull to start expensive document search, if it
1341     // can fail only .. because we load from a stream or model directly!
1342     if (
1343         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_STREAM )) ||
1344         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_OBJECT ))
1345         /*TODO should be private:factory here tested too? */
1346        )
1347     {
1348         return css::uno::Reference< css::frame::XFrame >();
1349     }
1350 
1351     // otherwhise - iterate through the tasks of the desktop container
1352     // to find out, which of them might contains the requested document
1353     css::uno::Reference< css::frame::XFramesSupplier >  xSupplier(m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
1354     css::uno::Reference< css::container::XIndexAccess > xTaskList(xSupplier->getFrames()                      , css::uno::UNO_QUERY);
1355 
1356     if (!xTaskList.is())
1357         return css::uno::Reference< css::frame::XFrame >(); // task list can be empty!
1358 
1359     // Note: To detect if a document was alrady loaded before
1360     // we check URLs here only. But might the existing and the requred
1361     // document has different versions! Then its URLs are the same ...
1362     sal_Int16 nNewVersion = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_VERSION(), (sal_Int16)(-1));
1363 
1364     // will be used to save the first hidden frame referring the searched model
1365     // Normaly we are interested on visible frames ... but if there is no such visible
1366     // frame we referr to any hidden frame also (but as fallback only).
1367     css::uno::Reference< css::frame::XFrame > xHiddenTask;
1368     css::uno::Reference< css::frame::XFrame > xTask;
1369 
1370     sal_Int32 count = xTaskList->getCount();
1371     for (sal_Int32 i=0; i<count; ++i)
1372     {
1373         try
1374         {
1375             // locate model of task
1376             // Note: Without a model there is no chance to decide if
1377             // this task contains the searched document or not!
1378             xTaskList->getByIndex(i) >>= xTask;
1379             if (!xTask.is())
1380                 continue;
1381 
1382             css::uno::Reference< css::frame::XController > xController = xTask->getController();
1383             if (!xController.is())
1384 			{
1385 				xTask.clear ();
1386                 continue;
1387 			}
1388 
1389             css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
1390             if (!xModel.is())
1391 			{
1392 				xTask.clear ();
1393                 continue;
1394 			}
1395 
1396             // don't check the complete URL here.
1397             // use its main part - ignore optional jumpmarks!
1398 			const ::rtl::OUString sURL = xModel->getURL();
1399             if (!::utl::UCBContentHelper::EqualURLs( m_aURL.Main, sURL ))
1400 			{
1401 				xTask.clear ();
1402                 continue;
1403 			}
1404 
1405             // get the original load arguments from the current document
1406             // and decide if its realy the same then the one will be.
1407             // It must be visible and must use the same file revision ...
1408             // or must not have any file revision set (-1 == -1!)
1409             ::comphelper::MediaDescriptor lOldDocDescriptor(xModel->getArgs());
1410 
1411             if (lOldDocDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_VERSION(), (sal_Int32)(-1)) != nNewVersion)
1412 			{
1413 				xTask.clear ();
1414                 continue;
1415 			}
1416 
1417             // Hidden frames are special.
1418             // They will be used as "last chance" if there is no visible frame pointing to the same model.
1419             // Safe the result but continue with current loop might be looking for other visible frames.
1420             ::sal_Bool bIsHidden = lOldDocDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False);
1421             if (
1422                 (   bIsHidden       ) &&
1423                 ( ! xHiddenTask.is())
1424                )
1425             {
1426                 xHiddenTask = xTask;
1427                 xTask.clear ();
1428                 continue;
1429             }
1430 
1431             // We found a visible task pointing to the right model ...
1432             // Break search.
1433             break;
1434         }
1435         catch(const css::uno::RuntimeException& exRun)
1436             { throw exRun; }
1437         catch(const css::uno::Exception&)
1438             { continue; }
1439     }
1440 
1441     css::uno::Reference< css::frame::XFrame > xResult;
1442     if (xTask.is())
1443         xResult = xTask;
1444     else
1445     if (xHiddenTask.is())
1446         xResult = xHiddenTask;
1447 
1448     if (xResult.is())
1449     {
1450         // Now we are shure, that this task includes the searched document.
1451         // It's time to activate it. As special feature we try to jump internaly
1452         // if an optional jumpmark is given too.
1453         if (m_aURL.Mark.getLength())
1454             impl_jumpToMark(xResult, m_aURL);
1455 
1456         // bring it to front and make sure it's visible...
1457         impl_makeFrameWindowVisible(xResult->getContainerWindow(), sal_True);
1458     }
1459 
1460     aReadLock.unlock();
1461     // <- SAFE
1462 
1463     return xResult;
1464 }
1465 
1466 /*-----------------------------------------------
1467     30.03.2004 09:12
1468 -----------------------------------------------*/
1469 sal_Bool LoadEnv::impl_isFrameAlreadyUsedForLoading(const css::uno::Reference< css::frame::XFrame >& xFrame) const
1470 {
1471     css::uno::Reference< css::document::XActionLockable > xLock(xFrame, css::uno::UNO_QUERY);
1472 
1473     // ? no lock interface ?
1474     // Might its an external written frame implementation :-(
1475     // Allowing using of it ... but it can fail if its not synchronized with our processes !
1476     if (!xLock.is())
1477         return sal_False;
1478 
1479     // Otherwhise we have to look for any other existing lock.
1480     return xLock->isActionLocked();
1481 }
1482 
1483 /*-----------------------------------------------
1484     30.03.2004 09:12
1485 -----------------------------------------------*/
1486 css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchRecycleTarget()
1487     throw(LoadEnvException, css::uno::RuntimeException)
1488 {
1489     // SAFE -> ..................................
1490     ReadGuard aReadLock(m_aLock);
1491 
1492     // The special backing mode frame will be recycled by definition!
1493     // It does'nt matter if somehwere whish to create a new view
1494     // or open a new untitled document ...
1495     // The only exception form that - hidden frames!
1496     if (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False) == sal_True)
1497         return css::uno::Reference< css::frame::XFrame >();
1498 
1499     css::uno::Reference< css::frame::XFramesSupplier > xSupplier(m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
1500     FrameListAnalyzer aTasksAnalyzer(xSupplier, css::uno::Reference< css::frame::XFrame >(), FrameListAnalyzer::E_BACKINGCOMPONENT);
1501     if (aTasksAnalyzer.m_xBackingComponent.is())
1502     {
1503         if (!impl_isFrameAlreadyUsedForLoading(aTasksAnalyzer.m_xBackingComponent))
1504         {
1505             // bring it to front ...
1506             impl_makeFrameWindowVisible(aTasksAnalyzer.m_xBackingComponent->getContainerWindow(), sal_True);
1507             return aTasksAnalyzer.m_xBackingComponent;
1508         }
1509     }
1510 
1511     // These states indicates the wishing for creation of a new view in general.
1512     if (
1513         (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_ASTEMPLATE() , sal_False) == sal_True) ||
1514         (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_OPENNEWVIEW(), sal_False) == sal_True)
1515        )
1516     {
1517         return css::uno::Reference< css::frame::XFrame >();
1518     }
1519 
1520 	// On the other side some special URLs will open a new frame everytimes (expecting
1521 	// they can use the backing-mode frame!)
1522     if (
1523         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_FACTORY )) ||
1524         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_STREAM  )) ||
1525         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_OBJECT  ))
1526        )
1527     {
1528         return css::uno::Reference< css::frame::XFrame >();
1529     }
1530 
1531 	// No backing frame! No special URL => recycle active task - if possible.
1532 	// Means - if it does not already contains a modified document, or
1533 	// use another office module.
1534     css::uno::Reference< css::frame::XFrame > xTask = xSupplier->getActiveFrame();
1535 
1536     // not a real error - but might a focus problem!
1537     if (!xTask.is())
1538         return css::uno::Reference< css::frame::XFrame >();
1539 
1540     // not a real error - may its a view only
1541     css::uno::Reference< css::frame::XController > xController = xTask->getController();
1542     if (!xController.is())
1543         return css::uno::Reference< css::frame::XFrame >();
1544 
1545     // not a real error - may its a db component instead of a full feartured office document
1546     css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
1547     if (!xModel.is())
1548         return css::uno::Reference< css::frame::XFrame >();
1549 
1550     // get some more informations ...
1551 
1552     // A valid set URL means: there is already a location for this document.
1553     // => it was saved there or opened from there. Such Documents can not be used here.
1554     // We search for empty document ... created by a private:factory/ URL!
1555     if (xModel->getURL().getLength()>0)
1556         return css::uno::Reference< css::frame::XFrame >();
1557 
1558     // The old document must be unmodified ...
1559     css::uno::Reference< css::util::XModifiable > xModified(xModel, css::uno::UNO_QUERY);
1560     if (xModified->isModified())
1561         return css::uno::Reference< css::frame::XFrame >();
1562 
1563     Window* pWindow = VCLUnoHelper::GetWindow(xTask->getContainerWindow());
1564     if (pWindow && pWindow->IsInModalMode())
1565         return css::uno::Reference< css::frame::XFrame >();
1566 
1567     // find out the application type of this document
1568     // We can recycle only documents, which uses the same application
1569     // then the new one.
1570     SvtModuleOptions::EFactory eOldApp = SvtModuleOptions::ClassifyFactoryByModel(xModel);
1571     SvtModuleOptions::EFactory eNewApp = SvtModuleOptions::ClassifyFactoryByURL  (m_aURL.Complete, m_lMediaDescriptor.getAsConstPropertyValueList());
1572 
1573     aReadLock.unlock();
1574     // <- SAFE ..................................
1575 
1576     if (eOldApp != eNewApp)
1577         return css::uno::Reference< css::frame::XFrame >();
1578 
1579     // OK this task seams to be useable for recycling
1580     // But we should mark it as such - means set an action lock.
1581     // Otherwhise it would be used more then ones or will be destroyed
1582     // by a close() or terminate() request.
1583     // But if such lock already exist ... it means this task is used for
1584     // any other operation already. Don't use it then.
1585     if (impl_isFrameAlreadyUsedForLoading(xTask))
1586         return css::uno::Reference< css::frame::XFrame >();
1587 
1588     // OK - there is a valid target frame.
1589     // But may be it contains already a document.
1590     // Then we have to ask it, if it allows recylcing of this frame .-)
1591     sal_Bool bReactivateOldControllerOnError = sal_False;
1592     css::uno::Reference< css::frame::XController > xOldDoc = xTask->getController();
1593     if (xOldDoc.is())
1594     {
1595         bReactivateOldControllerOnError = xOldDoc->suspend(sal_True);
1596         if (! bReactivateOldControllerOnError)
1597             return css::uno::Reference< css::frame::XFrame >();
1598     }
1599 
1600     // SAFE -> ..................................
1601     WriteGuard aWriteLock(m_aLock);
1602 
1603     css::uno::Reference< css::document::XActionLockable > xLock(xTask, css::uno::UNO_QUERY);
1604     if (!m_aTargetLock.setResource(xLock))
1605         return css::uno::Reference< css::frame::XFrame >();
1606 
1607     m_bReactivateControllerOnError = bReactivateOldControllerOnError;
1608     aWriteLock.unlock();
1609     // <- SAFE ..................................
1610 
1611     // bring it to front ...
1612     impl_makeFrameWindowVisible(xTask->getContainerWindow(), sal_True);
1613 
1614     return xTask;
1615 }
1616 
1617 /*-----------------------------------------------
1618     15.08.2003 12:39
1619 -----------------------------------------------*/
1620 void LoadEnv::impl_reactForLoadingState()
1621     throw(LoadEnvException, css::uno::RuntimeException)
1622 {
1623     /*TODO reset action locks */
1624 
1625     // SAFE -> ----------------------------------
1626     ReadGuard aReadLock(m_aLock);
1627 
1628     if (m_bLoaded)
1629     {
1630         // Bring the new loaded document to front (if allowed!).
1631         // Note: We show new created frames here only.
1632         // We dont hide already visible frames here ...
1633         css::uno::Reference< css::awt::XWindow > xWindow      = m_xTargetFrame->getContainerWindow();
1634         sal_Bool                                 bHidden      = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False);
1635         sal_Bool                                 bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_MINIMIZED(), sal_False);
1636 
1637         if (bMinimized)
1638         {
1639             ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex());
1640             Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
1641             // check for system window is neccessary to guarantee correct pointer cast!
1642             if (pWindow && pWindow->IsSystemWindow())
1643                 ((WorkWindow*)pWindow)->Minimize();
1644         }
1645         else
1646         if (!bHidden)
1647         {
1648             // show frame ... if it's not still visible ...
1649             // But do nothing if it's already visible!
1650             impl_makeFrameWindowVisible(xWindow, sal_False);
1651         }
1652 
1653         // Note: Only if an existing property "FrameName" is given by this media descriptor,
1654         // it should be used. Otherwhise we should do nothing. May be the outside code has already
1655         // set a frame name on the target!
1656         ::comphelper::MediaDescriptor::const_iterator pFrameName = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_FRAMENAME());
1657         if (pFrameName != m_lMediaDescriptor.end())
1658         {
1659             ::rtl::OUString sFrameName;
1660             pFrameName->second >>= sFrameName;
1661             // Check the name again. e.g. "_default" isnt allowed.
1662             // On the other side "_beamer" is a valid name :-)
1663             if (TargetHelper::isValidNameForFrame(sFrameName))
1664                 m_xTargetFrame->setName(sFrameName);
1665         }
1666     }
1667     else if (m_bReactivateControllerOnError)
1668 	{
1669 		// Try to reactivate the old document (if any exists!)
1670 		css::uno::Reference< css::frame::XController > xOldDoc = m_xTargetFrame->getController();
1671 		// clear does not depend from reactivation state of a might existing old document!
1672 		// We must make shure, that a might following getTargetComponent() call does not return
1673 		// the old document!
1674 		m_xTargetFrame.clear();
1675 		if (xOldDoc.is())
1676 		{
1677 			sal_Bool bReactivated = xOldDoc->suspend(sal_False);
1678 			if (!bReactivated)
1679 				throw LoadEnvException(LoadEnvException::ID_COULD_NOT_REACTIVATE_CONTROLLER);
1680 			m_bReactivateControllerOnError = sal_False;
1681 		}
1682 	}
1683 	else if (m_bCloseFrameOnError)
1684 	{
1685 		// close empty frames
1686 		css::uno::Reference< css::util::XCloseable > xCloseable (m_xTargetFrame, css::uno::UNO_QUERY);
1687 		css::uno::Reference< css::lang::XComponent > xDisposable(m_xTargetFrame, css::uno::UNO_QUERY);
1688 
1689 		try
1690 		{
1691 			if (xCloseable.is())
1692 				xCloseable->close(sal_True);
1693 			else
1694 			if (xDisposable.is())
1695 				xDisposable->dispose();
1696 		}
1697 		catch(const css::util::CloseVetoException&)
1698 		{}
1699 		catch(const css::lang::DisposedException&)
1700 		{}
1701 		m_xTargetFrame.clear();
1702 	}
1703 
1704     // This max force an implicit closing of our target frame ...
1705     // e.g. in case close(sal_True) was called before and the frame
1706     // kill itself if our external use-lock is released here!
1707     // Thats why we releas this lock AFTER ALL OPERATIONS on this frame
1708     // are finished. The frame itslef must handle then
1709     // this situation gracefully.
1710     m_aTargetLock.freeResource();
1711 
1712     // Last but not least :-)
1713     // We have to clear the current media descriptor.
1714     // Otherwhise it hold a might existing stream open!
1715     m_lMediaDescriptor.clear();
1716 
1717 	css::uno::Any aRequest;
1718 	bool bThrow = false;
1719 	if ( !m_bLoaded && m_pQuietInteraction && m_pQuietInteraction->wasUsed() )
1720 	{
1721 		aRequest = m_pQuietInteraction->getRequest();
1722 		m_pQuietInteraction->release();
1723 		m_pQuietInteraction = 0;
1724 		bThrow = true;
1725 	}
1726 
1727     aReadLock.unlock();
1728 
1729 	if (bThrow)
1730 	{
1731         if  ( aRequest.isExtractableTo( ::cppu::UnoType< css::uno::Exception >::get() ) )
1732 			throw LoadEnvException( LoadEnvException::ID_GENERAL_ERROR, aRequest );
1733 	}
1734 
1735     // <- SAFE ----------------------------------
1736 }
1737 
1738 /*-----------------------------------------------
1739     16.01.2005 13:04
1740 -----------------------------------------------*/
1741 void LoadEnv::impl_makeFrameWindowVisible(const css::uno::Reference< css::awt::XWindow >& xWindow      ,
1742                                                 sal_Bool bForceToFront)
1743 {
1744     // SAFE -> ----------------------------------
1745     ReadGuard aReadLock(m_aLock);
1746     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR( m_xSMGR.get(), css::uno::UNO_QUERY );
1747     aReadLock.unlock();
1748     // <- SAFE ----------------------------------
1749 
1750     ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex());
1751     Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
1752     if ( pWindow )
1753     {
1754         bool bForceFrontAndFocus(false);
1755         css::uno::Any a = ::comphelper::ConfigurationHelper::readDirectKey(
1756             xSMGR,
1757             ::rtl::OUString::createFromAscii("org.openoffice.Office.Common/View"),
1758             ::rtl::OUString::createFromAscii("NewDocumentHandling"),
1759             ::rtl::OUString::createFromAscii("ForceFocusAndToFront"),
1760             ::comphelper::ConfigurationHelper::E_READONLY);
1761         a >>= bForceFrontAndFocus;
1762 
1763         if( pWindow->IsVisible() && (bForceFrontAndFocus || bForceToFront) )
1764             pWindow->ToTop();
1765         else
1766             pWindow->Show(sal_True, (bForceFrontAndFocus || bForceToFront) ? SHOW_FOREGROUNDTASK : 0 );
1767     }
1768 
1769 /* #i19976#
1770     We tried to prevent a toFront() call in case the user putted the
1771     loading document into the background ..
1772     But we had several errors trying that. So we decided to
1773     rollback these changes and bring the new loaded document to front hardly !
1774 
1775     css::uno::Reference< css::awt::XWindow2 > xWindow2(xWindow, css::uno::UNO_QUERY);
1776 
1777     sal_Bool bIsVisible = sal_False;
1778     if (xWindow2.is())
1779         bIsVisible = xWindow2->isVisible(); // TODO is parent visible too ? .-)
1780 
1781     if (!bIsVisible)
1782     {
1783         xWindow->setVisible(sal_True);
1784         bForceToFront = sal_True;
1785     }
1786 
1787     if (
1788         (bForceToFront  ) &&
1789         (xTopWindow.is())
1790        )
1791     {
1792         xTopWindow->toFront();
1793     }
1794 */
1795 }
1796 
1797 /*-----------------------------------------------
1798     15.03.2005 11:12
1799 -----------------------------------------------*/
1800 void LoadEnv::impl_applyPersistentWindowState(const css::uno::Reference< css::awt::XWindow >& xWindow)
1801 {
1802     static ::rtl::OUString PACKAGE_SETUP_MODULES = ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Office/Factories");
1803 
1804     // no window -> action not possible
1805     if (!xWindow.is())
1806         return;
1807 
1808     // window already visible -> do nothing! If we use a "recycle frame" for loading ...
1809     // the current position and size must be used.
1810     css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(xWindow, css::uno::UNO_QUERY);
1811     if (
1812         (xVisibleCheck.is()        ) &&
1813         (xVisibleCheck->isVisible())
1814        )
1815        return;
1816 
1817     // SOLAR SAFE ->
1818     ::vos::OClearableGuard aSolarLock1(Application::GetSolarMutex());
1819 
1820     Window*  pWindow       = VCLUnoHelper::GetWindow(xWindow);
1821     sal_Bool bSystemWindow = pWindow->IsSystemWindow();
1822     sal_Bool bWorkWindow   = (pWindow->GetType() == WINDOW_WORKWINDOW);
1823 
1824     if (!bSystemWindow && !bWorkWindow)
1825         return;
1826 
1827     // dont overwrite this special state!
1828     WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
1829     if (pWorkWindow->IsMinimized())
1830         return;
1831 
1832     aSolarLock1.clear();
1833     // <- SOLAR SAFE
1834 
1835     // SAFE ->
1836     ReadGuard aReadLock(m_aLock);
1837 
1838     // no filter -> no module -> no persistent window state
1839     ::rtl::OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(
1840                                     ::comphelper::MediaDescriptor::PROP_FILTERNAME(),
1841                                     ::rtl::OUString());
1842     if (!sFilter.getLength())
1843         return;
1844 
1845     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1846 
1847     aReadLock.unlock();
1848     // <- SAFE
1849 
1850     try
1851     {
1852         // retrieve the module name from the filter configuration
1853         css::uno::Reference< css::container::XNameAccess > xFilterCfg(
1854             xSMGR->createInstance(SERVICENAME_FILTERFACTORY),
1855             css::uno::UNO_QUERY_THROW);
1856         ::comphelper::SequenceAsHashMap lProps (xFilterCfg->getByName(sFilter));
1857         ::rtl::OUString                 sModule = lProps.getUnpackedValueOrDefault(FILTER_PROPNAME_DOCUMENTSERVICE, ::rtl::OUString());
1858 
1859         // get access to the configuration of this office module
1860         css::uno::Reference< css::container::XNameAccess > xModuleCfg(::comphelper::ConfigurationHelper::openConfig(
1861                                                                         xSMGR,
1862                                                                         PACKAGE_SETUP_MODULES,
1863                                                                         ::comphelper::ConfigurationHelper::E_READONLY),
1864                                                                       css::uno::UNO_QUERY_THROW);
1865 
1866         // read window state from the configuration
1867         // and apply it on the window.
1868         // Do nothing, if no configuration entry exists!
1869         ::rtl::OUString sWindowState ;
1870         ::comphelper::ConfigurationHelper::readRelativeKey(xModuleCfg, sModule, OFFICEFACTORY_PROPNAME_WINDOWATTRIBUTES) >>= sWindowState;
1871         if (sWindowState.getLength())
1872         {
1873             // SOLAR SAFE ->
1874             ::vos::OClearableGuard aSolarLock2(Application::GetSolarMutex());
1875 
1876             // We have to retrieve the window pointer again. Because nobody can guarantee
1877             // that the XWindow was not disposed inbetween .-)
1878             // But if we get a valid pointer we can be sure, that it's the system window pointer
1879             // we already checked and used before. Because nobody recylce the same uno reference for
1880             // a new internal c++ implementation ... hopefully .-))
1881             Window* pWindowCheck  = VCLUnoHelper::GetWindow(xWindow);
1882             if (! pWindowCheck)
1883                 return;
1884 
1885             SystemWindow* pSystemWindow = (SystemWindow*)pWindowCheck;
1886             pSystemWindow->SetWindowState(U2B_ENC(sWindowState,RTL_TEXTENCODING_UTF8));
1887 
1888             aSolarLock2.clear();
1889             // <- SOLAR SAFE
1890         }
1891     }
1892     catch(const css::uno::RuntimeException& exRun)
1893         { throw exRun; }
1894     catch(const css::uno::Exception&)
1895         {}
1896 }
1897 
1898 } // namespace framework
1899 
1900