1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <loadenv/loadenv.hxx>
22 #include <loadenv/targethelper.hxx>
23 #include <framework/framelistanalyzer.hxx>
25 #include <constant/containerquery.hxx>
26 #include <interaction/quietinteraction.hxx>
27 #include <threadhelp/writeguard.hxx>
28 #include <threadhelp/readguard.hxx>
29 #include <threadhelp/resetableguard.hxx>
30 #include <properties.h>
31 #include <protocols.h>
33 #include <comphelper/interaction.hxx>
34 #include <framework/interaction.hxx>
35 #include <comphelper/processfactory.hxx>
36 #include <comphelper/configuration.hxx>
37 #include "officecfg/Office/Common.hxx"
39 #include <com/sun/star/task/ErrorCodeRequest.hpp>
40 #include <com/sun/star/task/InteractionHandler.hpp>
41 #include <com/sun/star/uno/RuntimeException.hpp>
42 #include <com/sun/star/frame/DispatchResultState.hpp>
43 #include <com/sun/star/frame/FrameSearchFlag.hpp>
44 #include <com/sun/star/util/URLTransformer.hpp>
45 #include <com/sun/star/util/XURLTransformer.hpp>
46 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
47 #include <com/sun/star/util/XCloseable.hpp>
48 #include <com/sun/star/lang/XComponent.hpp>
49 #include <com/sun/star/lang/XServiceInfo.hpp>
50 #include <com/sun/star/lang/DisposedException.hpp>
51 #include <com/sun/star/awt/XWindow.hpp>
52 #include <com/sun/star/awt/XWindow2.hpp>
53 #include <com/sun/star/awt/XTopWindow.hpp>
54 #include <com/sun/star/frame/Desktop.hpp>
55 #include <com/sun/star/frame/XModel.hpp>
56 #include <com/sun/star/frame/XFrameLoader.hpp>
57 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
58 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
59 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
60 #include <com/sun/star/task/XStatusIndicator.hpp>
61 #include <com/sun/star/util/XModifiable.hpp>
62 #include <com/sun/star/frame/XDispatchProvider.hpp>
63 #include <com/sun/star/document/XTypeDetection.hpp>
64 #include <com/sun/star/document/XActionLockable.hpp>
65 #include <com/sun/star/io/XInputStream.hpp>
66 #include <com/sun/star/task/XInteractionHandler.hpp>
67 #include <com/sun/star/container/XNameAccess.hpp>
68 #include <com/sun/star/container/XContainerQuery.hpp>
69 #include <com/sun/star/container/XEnumeration.hpp>
70 #include <com/sun/star/document/MacroExecMode.hpp>
71 #include <com/sun/star/document/UpdateDocMode.hpp>
73 #include <vcl/window.hxx>
74 #include <vcl/wrkwin.hxx>
75 #include <vcl/syswin.hxx>
77 #include <toolkit/unohlp.hxx>
78 #include <unotools/moduleoptions.hxx>
79 #include <svtools/sfxecode.hxx>
80 #include <unotools/ucbhelper.hxx>
81 #include <comphelper/configurationhelper.hxx>
82 #include <rtl/ustrbuf.hxx>
83 #include "rtl/bootstrap.hxx"
84 #include <vcl/svapp.hxx>
86 const char PROP_TYPES
[] = "Types";
87 const char PROP_NAME
[] = "Name";
91 using namespace com::sun::star
;
94 class LoadEnvListener
: private ThreadHelpBase
95 , public ::cppu::WeakImplHelper2
< css::frame::XLoadEventListener
,
96 css::frame::XDispatchResultListener
>
100 bool m_bWaitingResult
;
105 //_______________________________________
106 LoadEnvListener(LoadEnv
* pLoadEnv
)
107 : m_bWaitingResult(true)
108 , m_pLoadEnv(pLoadEnv
)
112 //_______________________________________
113 // frame.XLoadEventListener
114 virtual void SAL_CALL
loadFinished(const css::uno::Reference
< css::frame::XFrameLoader
>& xLoader
)
115 throw(css::uno::RuntimeException
);
117 virtual void SAL_CALL
loadCancelled(const css::uno::Reference
< css::frame::XFrameLoader
>& xLoader
)
118 throw(css::uno::RuntimeException
);
120 //_______________________________________
121 // frame.XDispatchResultListener
122 virtual void SAL_CALL
dispatchFinished(const css::frame::DispatchResultEvent
& aEvent
)
123 throw(css::uno::RuntimeException
);
125 //_______________________________________
126 // lang.XEventListener
127 virtual void SAL_CALL
disposing(const css::lang::EventObject
& aEvent
)
128 throw(css::uno::RuntimeException
);
132 LoadEnv::LoadEnv(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
133 throw(LoadEnvException
, css::uno::RuntimeException
)
136 , m_pQuietInteraction( 0 )
146 css::uno::Reference
< css::lang::XComponent
> LoadEnv::loadComponentFromURL(const css::uno::Reference
< css::frame::XComponentLoader
>& xLoader
,
147 const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
,
148 const OUString
& sURL
,
149 const OUString
& sTarget
,
151 const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
)
152 throw(css::lang::IllegalArgumentException
,
153 css::io::IOException
,
154 css::uno::RuntimeException
)
156 css::uno::Reference
< css::lang::XComponent
> xComponent
;
162 aEnv
.initializeLoading(sURL
,
164 css::uno::Reference
< css::frame::XFrame
>(xLoader
, css::uno::UNO_QUERY
),
167 LoadEnv::E_NO_FEATURE
);
169 aEnv
.waitWhileLoading(); // wait for ever!
171 xComponent
= aEnv
.getTargetComponent();
173 catch(const LoadEnvException
& ex
)
177 case LoadEnvException::ID_INVALID_MEDIADESCRIPTOR
:
178 throw css::lang::IllegalArgumentException(
179 "Optional list of arguments seem to be corrupted.", xLoader
, 4);
181 case LoadEnvException::ID_UNSUPPORTED_CONTENT
:
184 aMsg
.appendAscii("Unsupported URL <").append(sURL
).append('>');
186 if (!ex
.m_sMessage
.isEmpty())
188 aMsg
.appendAscii(": \"").
189 append(OStringToOUString(
190 ex
.m_sMessage
, RTL_TEXTENCODING_UTF8
)).
194 throw css::lang::IllegalArgumentException(aMsg
.makeStringAndClear(),
207 //-----------------------------------------------
208 ::comphelper::MediaDescriptor
impl_mergeMediaDescriptorWithMightExistingModelArgs(const css::uno::Sequence
< css::beans::PropertyValue
>& lOutsideDescriptor
)
210 ::comphelper::MediaDescriptor
lDescriptor(lOutsideDescriptor
);
211 css::uno::Reference
< css::frame::XModel
> xModel
= lDescriptor
.getUnpackedValueOrDefault(
212 ::comphelper::MediaDescriptor::PROP_MODEL (),
213 css::uno::Reference
< css::frame::XModel
> ());
216 ::comphelper::MediaDescriptor
lModelDescriptor(xModel
->getArgs());
217 ::comphelper::MediaDescriptor::iterator pIt
= lModelDescriptor
.find( ::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE() );
218 if ( pIt
!= lModelDescriptor
.end() )
219 lDescriptor
[::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()] = pIt
->second
;
226 void LoadEnv::initializeLoading(const OUString
& sURL
,
227 const css::uno::Sequence
< css::beans::PropertyValue
>& lMediaDescriptor
,
228 const css::uno::Reference
< css::frame::XFrame
>& xBaseFrame
,
229 const OUString
& sTarget
,
230 sal_Int32 nSearchFlags
,
231 EFeature eFeature
, // => use default ...
232 EContentType eContentType
) // => use default ...
234 // SAFE -> ----------------------------------
235 WriteGuard
aWriteLock(m_aLock
);
237 // Handle still running processes!
238 if (m_xAsynchronousJob
.is())
239 throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING
);
241 // take over all new parameters.
242 m_xTargetFrame
.clear();
243 m_xBaseFrame
= xBaseFrame
;
244 m_lMediaDescriptor
= impl_mergeMediaDescriptorWithMightExistingModelArgs(lMediaDescriptor
);
245 m_sTarget
= sTarget
;
246 m_nSearchFlags
= nSearchFlags
;
247 m_eFeature
= eFeature
;
248 m_eContentType
= eContentType
;
249 m_bCloseFrameOnError
= sal_False
;
250 m_bReactivateControllerOnError
= sal_False
;
251 m_bLoaded
= sal_False
;
253 // try to find out, if its really a content, which can be loaded or must be "handled"
254 // We use a default value for this in-parameter. Then we have to start a complex check method
255 // internally. But if this check was already done outside it can be supressed to perform
256 // the load request. We take over the result then!
257 if (m_eContentType
== E_UNSUPPORTED_CONTENT
)
259 m_eContentType
= LoadEnv::classifyContent(sURL
, lMediaDescriptor
);
260 if (m_eContentType
== E_UNSUPPORTED_CONTENT
)
261 throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT
);
264 // make URL part of the MediaDescriptor
265 // It doesn't mater, if it is already an item of it.
266 // It must be the same value ... so we can overwrite it :-)
267 m_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_URL()] <<= sURL
;
269 // parse it - because some following code require that
270 m_aURL
.Complete
= sURL
;
271 css::uno::Reference
< css::util::XURLTransformer
> xParser(css::util::URLTransformer::create(::comphelper::getComponentContext(m_xSMGR
)));
272 xParser
->parseStrict(m_aURL
);
274 // BTW: Split URL and JumpMark ...
275 // Because such mark is an explicit value of the media descriptor!
276 if (!m_aURL
.Mark
.isEmpty())
277 m_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_JUMPMARK()] <<= m_aURL
.Mark
;
279 // By the way: remove the old and deprecated value "FileName" from the descriptor!
280 ::comphelper::MediaDescriptor::iterator pIt
= m_lMediaDescriptor
.find(::comphelper::MediaDescriptor::PROP_FILENAME());
281 if (pIt
!= m_lMediaDescriptor
.end())
282 m_lMediaDescriptor
.erase(pIt
);
284 // patch the MediaDescriptor, so it fullfill the outside requirements
285 // Means especially items like e.g. UI InteractionHandler, Status Indicator,
286 // MacroExecutionMode etcpp.
288 /*TODO progress is bound to a frame ... How can we set it here? */
292 ( ( m_eFeature
& E_WORK_WITH_UI
) == E_WORK_WITH_UI
) &&
293 ( m_lMediaDescriptor
.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_HIDDEN() , sal_False
) == sal_False
) &&
294 ( m_lMediaDescriptor
.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_PREVIEW(), sal_False
) == sal_False
);
296 initializeUIDefaults(
297 comphelper::getComponentContext(m_xSMGR
),
304 // <- SAFE ----------------------------------
308 void LoadEnv::initializeUIDefaults( const css::uno::Reference
< css::uno::XComponentContext
>& i_rxContext
,
309 ::comphelper::MediaDescriptor
& io_lMediaDescriptor
, const bool i_bUIMode
,
310 QuietInteraction
** o_ppQuietInteraction
)
312 css::uno::Reference
< css::task::XInteractionHandler
> xInteractionHandler
;
313 sal_Int16 nMacroMode
;
314 sal_Int16 nUpdateMode
;
318 nMacroMode
= css::document::MacroExecMode::USE_CONFIG
;
319 nUpdateMode
= css::document::UpdateDocMode::ACCORDING_TO_CONFIG
;
322 xInteractionHandler
.set( css::task::InteractionHandler::createWithParent( i_rxContext
, 0 ), css::uno::UNO_QUERY_THROW
);
324 catch(const css::uno::RuntimeException
&) {throw;}
325 catch(const css::uno::Exception
& ) { }
330 nMacroMode
= css::document::MacroExecMode::NEVER_EXECUTE
;
331 nUpdateMode
= css::document::UpdateDocMode::NO_UPDATE
;
332 QuietInteraction
* pQuietInteraction
= new QuietInteraction();
333 xInteractionHandler
= css::uno::Reference
< css::task::XInteractionHandler
>(static_cast< css::task::XInteractionHandler
* >(pQuietInteraction
), css::uno::UNO_QUERY
);
334 if ( o_ppQuietInteraction
!= NULL
)
336 *o_ppQuietInteraction
= pQuietInteraction
;
337 (*o_ppQuietInteraction
)->acquire();
342 (xInteractionHandler
.is() ) &&
343 (io_lMediaDescriptor
.find(::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()) == io_lMediaDescriptor
.end())
346 io_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()] <<= xInteractionHandler
;
349 if (io_lMediaDescriptor
.find(::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()) == io_lMediaDescriptor
.end())
350 io_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()] <<= nMacroMode
;
352 if (io_lMediaDescriptor
.find(::comphelper::MediaDescriptor::PROP_UPDATEDOCMODE()) == io_lMediaDescriptor
.end())
353 io_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_UPDATEDOCMODE()] <<= nUpdateMode
;
357 void LoadEnv::startLoading()
360 ReadGuard
aReadLock(m_aLock
);
362 // Handle still running processes!
363 if (m_xAsynchronousJob
.is())
364 throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING
);
366 // content can not be loaded or handled
367 // check "classifyContent()" failed before ...
368 if (m_eContentType
== E_UNSUPPORTED_CONTENT
)
369 throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT
);
374 // detect its type/filter etcpp.
375 // These information will be available by the
376 // used descriptor member afterwards and is needed
377 // for all following operations!
378 // Note: An exception will be thrown, in case operation was not successfully ...
379 if (m_eContentType
!= E_CAN_BE_SET
)/* Attention: special feature to set existing component on a frame must ignore type detection! */
380 impl_detectTypeAndFilter();
382 // start loading the content ...
383 // Attention: Dont check m_eContentType deeper then UNSUPPORTED/SUPPORTED!
384 // Because it was made in th easiest way ... may a flat detection was made only.
385 // And such simple detection can fail some times .-)
386 // Use another strategy here. Try it and let it run into the case "loading not possible".
387 sal_Bool bStarted
= sal_False
;
389 ((m_eFeature
& E_ALLOW_CONTENTHANDLER
) == E_ALLOW_CONTENTHANDLER
) &&
390 (m_eContentType
!= E_CAN_BE_SET
) /* Attention: special feature to set existing component on a frame must ignore type detection! */
393 bStarted
= impl_handleContent();
397 bStarted
= impl_loadContent();
399 // not started => general error
400 // We can't say - what was the reason for.
402 throw LoadEnvException(LoadEnvException::ID_GENERAL_ERROR
);
405 /*-----------------------------------------------
407 First draft does not implement timeout using [ms].
408 Current implementation counts yield calls only ...
409 -----------------------------------------------*/
410 sal_Bool
LoadEnv::waitWhileLoading(sal_uInt32 nTimeout
)
412 // Because its not a good idea to block the main thread
413 // (and we can't be sure that we are currently not used inside the
414 // main thread!), we can't use conditions here really. We must yield
415 // in an intellegent manner :-)
417 sal_Int32 nTime
= nTimeout
;
420 // SAFE -> ------------------------------
421 ReadGuard
aReadLock1(m_aLock
);
422 if (!m_xAsynchronousJob
.is())
425 // <- SAFE ------------------------------
427 Application::Yield();
439 // SAFE -> ----------------------------------
440 ReadGuard
aReadLock2(m_aLock
);
441 return !m_xAsynchronousJob
.is();
442 // <- SAFE ----------------------------------
445 css::uno::Reference
< css::lang::XComponent
> LoadEnv::getTargetComponent() const
448 ReadGuard
aReadLock(m_aLock
);
450 if (!m_xTargetFrame
.is())
451 return css::uno::Reference
< css::lang::XComponent
>();
453 css::uno::Reference
< css::frame::XController
> xController
= m_xTargetFrame
->getController();
454 if (!xController
.is())
455 return css::uno::Reference
< css::lang::XComponent
>(m_xTargetFrame
->getComponentWindow(), css::uno::UNO_QUERY
);
457 css::uno::Reference
< css::frame::XModel
> xModel
= xController
->getModel();
459 return css::uno::Reference
< css::lang::XComponent
>(xController
, css::uno::UNO_QUERY
);
461 return css::uno::Reference
< css::lang::XComponent
>(xModel
, css::uno::UNO_QUERY
);
466 void SAL_CALL
LoadEnvListener::loadFinished(const css::uno::Reference
< css::frame::XFrameLoader
>&)
467 throw(css::uno::RuntimeException
)
469 // SAFE -> ----------------------------------
470 WriteGuard
aWriteLock(m_aLock
);
472 if (m_bWaitingResult
)
473 m_pLoadEnv
->impl_setResult(sal_True
);
474 m_bWaitingResult
= false;
477 // <- SAFE ----------------------------------
481 void SAL_CALL
LoadEnvListener::loadCancelled(const css::uno::Reference
< css::frame::XFrameLoader
>&)
482 throw(css::uno::RuntimeException
)
484 // SAFE -> ----------------------------------
485 WriteGuard
aWriteLock(m_aLock
);
487 if (m_bWaitingResult
)
488 m_pLoadEnv
->impl_setResult(sal_False
);
489 m_bWaitingResult
= false;
492 // <- SAFE ----------------------------------
496 void SAL_CALL
LoadEnvListener::dispatchFinished(const css::frame::DispatchResultEvent
& aEvent
)
497 throw(css::uno::RuntimeException
)
499 // SAFE -> ----------------------------------
500 WriteGuard
aWriteLock(m_aLock
);
502 if (!m_bWaitingResult
)
507 case css::frame::DispatchResultState::FAILURE
:
508 m_pLoadEnv
->impl_setResult(sal_False
);
511 case css::frame::DispatchResultState::SUCCESS
:
512 m_pLoadEnv
->impl_setResult(sal_False
);
515 case css::frame::DispatchResultState::DONTKNOW
:
516 m_pLoadEnv
->impl_setResult(sal_False
);
519 m_bWaitingResult
= false;
522 // <- SAFE ----------------------------------
526 void SAL_CALL
LoadEnvListener::disposing(const css::lang::EventObject
&)
527 throw(css::uno::RuntimeException
)
529 // SAFE -> ----------------------------------
530 WriteGuard
aWriteLock(m_aLock
);
532 if (m_bWaitingResult
)
533 m_pLoadEnv
->impl_setResult(sal_False
);
534 m_bWaitingResult
= false;
537 // <- SAFE ----------------------------------
541 void LoadEnv::impl_setResult(sal_Bool bResult
)
543 // SAFE -> ----------------------------------
544 WriteGuard
aWriteLock(m_aLock
);
548 impl_reactForLoadingState();
550 // clearing of this reference will unblock waitWhileLoading()!
551 // So we must be sure, that loading process was really finished.
552 // => do it as last operation of this method ...
553 m_xAsynchronousJob
.clear();
556 // <- SAFE ----------------------------------
559 /*-----------------------------------------------
560 TODO: Is it a good idea to change Sequence<>
561 parameter to stl-adapter?
562 -----------------------------------------------*/
563 LoadEnv::EContentType
LoadEnv::classifyContent(const OUString
& sURL
,
564 const css::uno::Sequence
< css::beans::PropertyValue
>& lMediaDescriptor
)
566 //-------------------------------------------
567 // (i) Filter some special well known URL protocols,
568 // which can not be handled or loaded in general.
569 // Of course an empty URL must be ignored here too.
570 // Note: These URL schemata are fix and well known ...
571 // But there can be some additional ones, which was not
572 // defined at implementation time of this class :-(
573 // So we have to make sure, that the following code
574 // can detect such protocol schemata too :-)
578 (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_UNO
)) ||
579 (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_SLOT
)) ||
580 (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_MACRO
)) ||
581 (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_SERVICE
)) ||
582 (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_MAILTO
)) ||
583 (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_NEWS
))
586 return E_UNSUPPORTED_CONTENT
;
589 //-------------------------------------------
590 // (ii) Some special URLs indicates a given input stream,
591 // a full featured document model directly or
592 // specify a request for opening an empty document.
593 // Such contents are loadable in general.
594 // But we have to check, if the media descriptor contains
595 // all needed resources. If they are missing - the following
596 // load request will fail.
598 /* Attention: The following code can't work on such special URLs!
599 It should not break the office .. but it make no sense
600 to start expensive object creations and complex search
601 algorithm if its clear, that such URLs must be handled
605 // creation of new documents
606 if (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_PRIVATE_FACTORY
))
607 return E_CAN_BE_LOADED
;
609 // using of an existing input stream
610 ::comphelper::MediaDescriptor
stlMediaDescriptor(lMediaDescriptor
);
611 ::comphelper::MediaDescriptor::const_iterator pIt
;
612 if (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_PRIVATE_STREAM
))
614 pIt
= stlMediaDescriptor
.find(::comphelper::MediaDescriptor::PROP_INPUTSTREAM());
615 css::uno::Reference
< css::io::XInputStream
> xStream
;
616 if (pIt
!= stlMediaDescriptor
.end())
617 pIt
->second
>>= xStream
;
619 return E_CAN_BE_LOADED
;
620 LOG_WARNING("LoadEnv::classifyContent()", "loading from stream with right URL but invalid stream detected")
621 return E_UNSUPPORTED_CONTENT
;
624 // using of a full featured document
625 if (ProtocolCheck::isProtocol(sURL
,ProtocolCheck::E_PRIVATE_OBJECT
))
627 pIt
= stlMediaDescriptor
.find(::comphelper::MediaDescriptor::PROP_MODEL());
628 css::uno::Reference
< css::frame::XModel
> xModel
;
629 if (pIt
!= stlMediaDescriptor
.end())
630 pIt
->second
>>= xModel
;
633 LOG_WARNING("LoadEnv::classifyContent()", "loading with object with right URL but invalid object detected")
634 return E_UNSUPPORTED_CONTENT
;
637 // following operations can work on an internal type name only :-(
638 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
639 css::uno::Reference
< css::document::XTypeDetection
> xDetect(
640 xContext
->getServiceManager()->createInstanceWithContext(SERVICENAME_TYPEDETECTION
, xContext
),
641 css::uno::UNO_QUERY
);
643 OUString sType
= xDetect
->queryTypeByURL(sURL
);
645 css::uno::Sequence
< css::beans::NamedValue
> lQuery(1) ;
646 css::uno::Reference
< css::container::XContainerQuery
> xContainer
;
647 css::uno::Reference
< css::container::XEnumeration
> xSet
;
648 css::uno::Sequence
< OUString
> lTypesReg(1);
651 //-------------------------------------------
652 // (iii) If a FrameLoader service (or at least
653 // a Filter) can be found, which supports
654 // this URL - it must be a loadable content.
655 // Because both items are registered for types
656 // its enough to check for frame loaders only.
657 // Mos of our filters are handled by our global
658 // default loader. But there exist some specialized
659 // loader, which does not work on top of filters!
660 // So its not enough to search on the filter configuration.
661 // Further its not enough to search for types!
662 // Because there exist some types, which are referenced by
663 // other objects ... but not by filters nor frame loaders!
665 OUString
sPROP_TYPES(PROP_TYPES
);
667 lTypesReg
[0] = sType
;
668 lQuery
[0].Name
= sPROP_TYPES
;
669 lQuery
[0].Value
<<= lTypesReg
;
671 xContainer
= css::uno::Reference
< css::container::XContainerQuery
>(
672 xContext
->getServiceManager()->createInstanceWithContext(SERVICENAME_FRAMELOADERFACTORY
, xContext
),
673 css::uno::UNO_QUERY
);
674 xSet
= xContainer
->createSubSetEnumerationByProperties(lQuery
);
675 // at least one registered frame loader is enough!
676 if (xSet
->hasMoreElements())
677 return E_CAN_BE_LOADED
;
679 //-------------------------------------------
680 // (iv) Some URL protocols are supported by special services.
681 // E.g. ContentHandler.
682 // Such contents can be handled ... but not loaded.
684 lTypesReg
[0] = sType
;
685 lQuery
[0].Name
= sPROP_TYPES
;
686 lQuery
[0].Value
<<= lTypesReg
;
688 xContainer
= css::uno::Reference
< css::container::XContainerQuery
>(
689 xContext
->getServiceManager()->createInstanceWithContext(SERVICENAME_CONTENTHANDLERFACTORY
, xContext
),
690 css::uno::UNO_QUERY
);
691 xSet
= xContainer
->createSubSetEnumerationByProperties(lQuery
);
692 // at least one registered content handler is enough!
693 if (xSet
->hasMoreElements())
694 return E_CAN_BE_HANDLED
;
696 //-------------------------------------------
697 // (v) Last but not least the UCB is used inside office to
698 // load contents. He has a special configuration to know
699 // which URL schemata can be used inside office.
700 css::uno::Reference
< css::ucb::XUniversalContentBroker
> xUCB(css::ucb::UniversalContentBroker::create(xContext
));
701 if (xUCB
->queryContentProvider(sURL
).is())
702 return E_CAN_BE_LOADED
;
704 //-------------------------------------------
705 // (TODO) At this point, we have no idea .-)
706 // But it seems to be better, to break all
707 // further requests for this URL. Otherwhise
708 // we can run into some trouble.
709 return E_UNSUPPORTED_CONTENT
;
714 bool queryOrcusTypeAndFilter(const uno::Sequence
<beans::PropertyValue
>& rDescriptor
, OUString
& rType
, OUString
& rFilter
)
716 // depending on the experimental mode
717 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
718 if (!xContext
.is() || !officecfg::Office::Common::Misc::ExperimentalMode::get(xContext
))
724 sal_Int32 nSize
= rDescriptor
.getLength();
725 for (sal_Int32 i
= 0; i
< nSize
; ++i
)
727 const beans::PropertyValue
& rProp
= rDescriptor
[i
];
728 if (rProp
.Name
== "URL")
730 rProp
.Value
>>= aURL
;
735 if (aURL
.isEmpty() || aURL
.copy(0,8).equalsIgnoreAsciiCase("private:"))
739 rtl::Bootstrap::get("LIBO_USE_ORCUS", aUseOrcus
);
740 bool bUseOrcus
= (aUseOrcus
== "YES");
742 // TODO : Type must be set to be generic_Text (or any other type that
743 // exists) in order to find a usable loader. Exploit it as a temporary
746 if (aURL
.endsWith(".gnumeric"))
748 rType
= "generic_Text";
749 rFilter
= "gnumeric";
756 if (aURL
.endsWith(".xlsx"))
758 rType
= "generic_Text";
762 else if (aURL
.endsWith(".ods"))
764 rType
= "generic_Text";
768 else if (aURL
.endsWith(".csv"))
770 rType
= "generic_Text";
780 void LoadEnv::impl_detectTypeAndFilter()
781 throw(LoadEnvException
, css::uno::RuntimeException
)
783 static OUString
TYPEPROP_PREFERREDFILTER("PreferredFilter");
784 static OUString
FILTERPROP_FLAGS ("Flags");
785 static sal_Int32 FILTERFLAG_TEMPLATEPATH
= 16;
788 ReadGuard
aReadLock(m_aLock
);
790 // Attention: Because our stl media descriptor is a copy of an uno sequence
791 // we can't use as an in/out parameter here. Copy it before and dont forget to
792 // update structure afterwards again!
793 css::uno::Sequence
< css::beans::PropertyValue
> lDescriptor
= m_lMediaDescriptor
.getAsConstPropertyValueList();
794 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
799 OUString sType
, sFilter
;
801 if (queryOrcusTypeAndFilter(lDescriptor
, sType
, sFilter
) && !sType
.isEmpty() && !sFilter
.isEmpty())
803 // Orcus type detected. Skip the normal type detection process.
804 m_lMediaDescriptor
<< lDescriptor
;
805 m_lMediaDescriptor
[comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType
;
806 m_lMediaDescriptor
[comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter
;
807 m_lMediaDescriptor
[comphelper::MediaDescriptor::PROP_FILTERPROVIDER()] <<= OUString("orcus");
811 css::uno::Reference
< css::document::XTypeDetection
> xDetect(xSMGR
->createInstance(SERVICENAME_TYPEDETECTION
), css::uno::UNO_QUERY
);
813 sType
= xDetect
->queryTypeByDescriptor(lDescriptor
, sal_True
); /*TODO should deep detection be able for enable/disable it from outside? */
815 // no valid content -> loading not possible
817 throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT
);
820 WriteGuard
aWriteLock(m_aLock
);
822 // detection was successfully => update the descriptor member of this class
823 m_lMediaDescriptor
<< lDescriptor
;
824 m_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType
;
825 // Is there an already detected (may be preselected) filter?
827 sFilter
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), OUString());
832 // But the type isnt enough. For loading sometimes we need more information.
833 // E.g. for our "_default" feature, where we recylce any frame which contains
834 // and "Untitled" document, we must know if the new document is based on a template!
835 // But this information is available as a filter property only.
836 // => We must try(!) to detect the right filter for this load request.
837 // On the other side ... if no filter is available .. ignore it.
838 // Then the type information must be enough.
839 if (sFilter
.isEmpty())
841 // no -> try to find a preferred filter for the detected type.
842 // Dont forget to updatet he media descriptor.
843 css::uno::Reference
< css::container::XNameAccess
> xTypeCont(xDetect
, css::uno::UNO_QUERY_THROW
);
846 ::comphelper::SequenceAsHashMap
lTypeProps(xTypeCont
->getByName(sType
));
847 sFilter
= lTypeProps
.getUnpackedValueOrDefault(TYPEPROP_PREFERREDFILTER
, OUString());
848 if (!sFilter
.isEmpty())
852 m_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter
;
857 catch(const css::container::NoSuchElementException
&)
861 // check if the filter (if one exists) points to a template format filter.
862 // Then we have to add the property "AsTemplate".
863 // We need this information to decide afterwards if we can use a "recycle frame"
864 // for target "_default" or has to create a new one everytimes.
865 // On the other side we have to supress that, if this property already exists
866 // and should trigger a special handling. Then the outside calli of this method here,
867 // has to know, what he is doing .-)
869 sal_Bool bIsOwnTemplate
= sal_False
;
870 if (!sFilter
.isEmpty())
872 css::uno::Reference
< css::container::XNameAccess
> xFilterCont(xSMGR
->createInstance(SERVICENAME_FILTERFACTORY
), css::uno::UNO_QUERY_THROW
);
875 ::comphelper::SequenceAsHashMap
lFilterProps(xFilterCont
->getByName(sFilter
));
876 sal_Int32 nFlags
= lFilterProps
.getUnpackedValueOrDefault(FILTERPROP_FLAGS
, (sal_Int32
)0);
877 bIsOwnTemplate
= ((nFlags
& FILTERFLAG_TEMPLATEPATH
) == FILTERFLAG_TEMPLATEPATH
);
879 catch(const css::container::NoSuchElementException
&)
886 // Dont overwrite external decisions! See comments before ...
887 ::comphelper::MediaDescriptor::const_iterator pAsTemplateItem
= m_lMediaDescriptor
.find(::comphelper::MediaDescriptor::PROP_ASTEMPLATE());
888 if (pAsTemplateItem
== m_lMediaDescriptor
.end())
889 m_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_ASTEMPLATE()] <<= sal_True
;
896 sal_Bool
LoadEnv::impl_handleContent()
897 throw(LoadEnvException
, css::uno::RuntimeException
)
899 // SAFE -> -----------------------------------
900 ReadGuard
aReadLock(m_aLock
);
902 // the type must exist inside the descriptor ... otherwise this class is implemented wrong :-)
903 OUString sType
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), OUString());
905 throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR
);
907 // convert media descriptor and URL to right format for later interface call!
908 css::uno::Sequence
< css::beans::PropertyValue
> lDescriptor
;
909 m_lMediaDescriptor
>> lDescriptor
;
910 css::util::URL aURL
= m_aURL
;
912 // get necessary container to query for a handler object
913 css::uno::Reference
< css::lang::XMultiServiceFactory
> xFactory(m_xSMGR
->createInstance(SERVICENAME_CONTENTHANDLERFACTORY
), css::uno::UNO_QUERY
);
914 css::uno::Reference
< css::container::XContainerQuery
> xQuery (xFactory
, css::uno::UNO_QUERY
);
917 // <- SAFE -----------------------------------
920 css::uno::Sequence
< OUString
> lTypeReg(1);
923 css::uno::Sequence
< css::beans::NamedValue
> lQuery(1);
924 lQuery
[0].Name
= OUString(PROP_TYPES
);
925 lQuery
[0].Value
<<= lTypeReg
;
927 OUString
sPROP_NAME(PROP_NAME
);
929 css::uno::Reference
< css::container::XEnumeration
> xSet
= xQuery
->createSubSetEnumerationByProperties(lQuery
);
930 while(xSet
->hasMoreElements())
932 ::comphelper::SequenceAsHashMap
lProps (xSet
->nextElement());
933 OUString sHandler
= lProps
.getUnpackedValueOrDefault(sPROP_NAME
, OUString());
935 css::uno::Reference
< css::frame::XNotifyingDispatch
> xHandler
;
938 xHandler
= css::uno::Reference
< css::frame::XNotifyingDispatch
>(xFactory
->createInstance(sHandler
), css::uno::UNO_QUERY
);
942 catch(const css::uno::RuntimeException
&)
944 catch(const css::uno::Exception
&)
947 // SAFE -> -----------------------------------
948 WriteGuard
aWriteLock(m_aLock
);
949 m_xAsynchronousJob
= xHandler
;
950 LoadEnvListener
* pListener
= new LoadEnvListener(this);
952 // <- SAFE -----------------------------------
954 css::uno::Reference
< css::frame::XDispatchResultListener
> xListener(static_cast< css::frame::XDispatchResultListener
* >(pListener
), css::uno::UNO_QUERY
);
955 xHandler
->dispatchWithNotification(aURL
, lDescriptor
, xListener
);
963 //-----------------------------------------------
964 sal_Bool
LoadEnv::impl_furtherDocsAllowed()
967 ReadGuard
aReadLock(m_aLock
);
968 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
972 sal_Bool bAllowed
= sal_True
;
976 css::uno::Any aVal
= ::comphelper::ConfigurationHelper::readDirectKey(
977 comphelper::getComponentContext(xSMGR
),
978 OUString("org.openoffice.Office.Common/"),
980 OUString("MaxOpenDocuments"),
981 ::comphelper::ConfigurationHelper::E_READONLY
);
983 // NIL means: count of allowed documents = infinite !
984 // => return sal_True
985 if ( ! aVal
.hasValue())
989 sal_Int32 nMaxOpenDocuments
= 0;
990 aVal
>>= nMaxOpenDocuments
;
992 css::uno::Reference
< css::frame::XFramesSupplier
> xDesktop(
993 css::frame::Desktop::create( comphelper::getComponentContext(xSMGR
)),
994 css::uno::UNO_QUERY_THROW
);
996 FrameListAnalyzer
aAnalyzer(xDesktop
,
997 css::uno::Reference
< css::frame::XFrame
>(),
998 FrameListAnalyzer::E_HELP
|
999 FrameListAnalyzer::E_BACKINGCOMPONENT
|
1000 FrameListAnalyzer::E_HIDDEN
);
1002 sal_Int32 nOpenDocuments
= aAnalyzer
.m_lOtherVisibleFrames
.getLength();
1003 bAllowed
= (nOpenDocuments
< nMaxOpenDocuments
);
1006 catch(const css::uno::Exception
&)
1007 { bAllowed
= sal_True
; } // !! internal errors are no reason to disturb the office from opening documents .-)
1013 css::uno::Reference
< css::task::XInteractionHandler
> xInteraction
= m_lMediaDescriptor
.getUnpackedValueOrDefault(
1014 ::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER(),
1015 css::uno::Reference
< css::task::XInteractionHandler
>());
1019 if (xInteraction
.is())
1021 css::uno::Any aInteraction
;
1022 css::uno::Sequence
< css::uno::Reference
< css::task::XInteractionContinuation
> > lContinuations(2);
1024 comphelper::OInteractionAbort
* pAbort
= new comphelper::OInteractionAbort();
1025 comphelper::OInteractionApprove
* pApprove
= new comphelper::OInteractionApprove();
1027 lContinuations
[0] = css::uno::Reference
< css::task::XInteractionContinuation
>(
1028 static_cast< css::task::XInteractionContinuation
* >(pAbort
),
1029 css::uno::UNO_QUERY_THROW
);
1030 lContinuations
[1] = css::uno::Reference
< css::task::XInteractionContinuation
>(
1031 static_cast< css::task::XInteractionContinuation
* >(pApprove
),
1032 css::uno::UNO_QUERY_THROW
);
1034 css::task::ErrorCodeRequest aErrorCode
;
1035 aErrorCode
.ErrCode
= ERRCODE_SFX_NOMOREDOCUMENTSALLOWED
;
1036 aInteraction
<<= aErrorCode
;
1037 xInteraction
->handle( InteractionRequest::CreateRequest(aInteraction
, lContinuations
) );
1044 //-----------------------------------------------
1045 sal_Bool
LoadEnv::impl_loadContent()
1046 throw(LoadEnvException
, css::uno::RuntimeException
)
1048 // SAFE -> -----------------------------------
1049 WriteGuard
aWriteLock(m_aLock
);
1051 // search or create right target frame
1052 OUString sTarget
= m_sTarget
;
1053 if (TargetHelper::matchSpecialTarget(sTarget
, TargetHelper::E_DEFAULT
))
1055 m_xTargetFrame
= impl_searchAlreadyLoaded();
1056 if (m_xTargetFrame
.is())
1058 impl_setResult(sal_True
);
1061 m_xTargetFrame
= impl_searchRecycleTarget();
1064 if (! m_xTargetFrame
.is())
1067 (TargetHelper::matchSpecialTarget(sTarget
, TargetHelper::E_BLANK
)) ||
1068 (TargetHelper::matchSpecialTarget(sTarget
, TargetHelper::E_DEFAULT
))
1071 if (! impl_furtherDocsAllowed())
1073 m_xTargetFrame
= m_xBaseFrame
->findFrame(SPECIALTARGET_BLANK
, 0);
1074 m_bCloseFrameOnError
= m_xTargetFrame
.is();
1078 sal_Int32 nFlags
= m_nSearchFlags
& ~css::frame::FrameSearchFlag::CREATE
;
1079 m_xTargetFrame
= m_xBaseFrame
->findFrame(sTarget
, nFlags
);
1080 if (! m_xTargetFrame
.is())
1082 if (! impl_furtherDocsAllowed())
1084 m_xTargetFrame
= m_xBaseFrame
->findFrame(SPECIALTARGET_BLANK
, 0);
1085 m_bCloseFrameOnError
= m_xTargetFrame
.is();
1090 // If we couldn't find a valid frame or the frame has no container window
1091 // we have to throw an exception.
1093 ( ! m_xTargetFrame
.is() ) ||
1094 ( ! m_xTargetFrame
->getContainerWindow().is() )
1096 throw LoadEnvException(LoadEnvException::ID_NO_TARGET_FOUND
);
1098 css::uno::Reference
< css::frame::XFrame
> xTargetFrame
= m_xTargetFrame
;
1100 // Now we have a valid frame ... and type detection was already done.
1101 // We should apply the module dependend window position and size to the
1103 impl_applyPersistentWindowState(xTargetFrame
->getContainerWindow());
1105 // Don't forget to lock task for following load process. Otherwise it could die
1106 // during this operation runs by terminating the office or closing this task via api.
1107 // If we set this lock "close()" will return false and closing will be broken.
1108 // Attention: Don't forget to reset this lock again after finishing operation.
1109 // Otherwise task AND office couldn't die!!!
1110 // This includes gracefully handling of Exceptions (Runtime!) too ...
1111 // Thats why we use a specialized guard, which will reset the lock
1112 // if it will be run out of scope.
1114 // Note further: ignore if this internal guard already contains a resource.
1115 // Might impl_searchRecylcTarget() set it before. But incase this impl-method wasnt used
1116 // and the target frame was new created ... this lock here must be set!
1117 css::uno::Reference
< css::document::XActionLockable
> xTargetLock(xTargetFrame
, css::uno::UNO_QUERY
);
1118 m_aTargetLock
.setResource(xTargetLock
);
1120 // Add status indicator to descriptor. Loader can show an progresses then.
1121 // But don't do it, if loading should be hidden or preview is used ...!
1122 // So we prevent our code against wrong using. Why?
1123 // It could be, that using of this progress could make trouble. e.g. He make window visible ...
1124 // but shouldn't do that. But if no indicator is available ... nobody has a chance to do that!
1125 sal_Bool bHidden
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN() , sal_False
);
1126 sal_Bool bMinimized
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_MINIMIZED() , sal_False
);
1127 sal_Bool bPreview
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_PREVIEW() , sal_False
);
1128 css::uno::Reference
< css::task::XStatusIndicator
> xProgress
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), css::uno::Reference
< css::task::XStatusIndicator
>());
1130 if (!bHidden
&& !bMinimized
&& !bPreview
&& !xProgress
.is())
1132 // Note: its an optional interface!
1133 css::uno::Reference
< css::task::XStatusIndicatorFactory
> xProgressFactory(xTargetFrame
, css::uno::UNO_QUERY
);
1134 if (xProgressFactory
.is())
1136 xProgress
= xProgressFactory
->createStatusIndicator();
1138 m_lMediaDescriptor
[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= xProgress
;
1142 // convert media descriptor and URL to right format for later interface call!
1143 css::uno::Sequence
< css::beans::PropertyValue
> lDescriptor
;
1144 m_lMediaDescriptor
>> lDescriptor
;
1145 OUString sURL
= m_aURL
.Complete
;
1147 // try to locate any interested frame loader
1148 css::uno::Reference
< css::uno::XInterface
> xLoader
= impl_searchLoader();
1149 css::uno::Reference
< css::frame::XFrameLoader
> xAsyncLoader(xLoader
, css::uno::UNO_QUERY
);
1150 css::uno::Reference
< css::frame::XSynchronousFrameLoader
> xSyncLoader (xLoader
, css::uno::UNO_QUERY
);
1152 if (xAsyncLoader
.is())
1154 // SAFE -> -----------------------------------
1156 m_xAsynchronousJob
= xAsyncLoader
;
1157 LoadEnvListener
* pListener
= new LoadEnvListener(this);
1158 aWriteLock
.unlock();
1159 // <- SAFE -----------------------------------
1161 css::uno::Reference
< css::frame::XLoadEventListener
> xListener(static_cast< css::frame::XLoadEventListener
* >(pListener
), css::uno::UNO_QUERY
);
1162 xAsyncLoader
->load(xTargetFrame
, sURL
, lDescriptor
, xListener
);
1166 else if (xSyncLoader
.is())
1168 sal_Bool bResult
= xSyncLoader
->load(lDescriptor
, xTargetFrame
);
1169 // react for the result here, so the outside waiting
1170 // code can ask for it later.
1171 impl_setResult(bResult
);
1172 // But the return value indicates a valid started(!) operation.
1173 // And thats true everxtimes, we reach this line :-)
1177 aWriteLock
.unlock();
1184 css::uno::Reference
< css::uno::XInterface
> LoadEnv::impl_searchLoader()
1186 // SAFE -> -----------------------------------
1187 ReadGuard
aReadLock(m_aLock
);
1189 // special mode to set an existing component on this frame
1190 // In such case the laoder is fix. It must be the SFX based implementation,
1191 // which can create a view on top of such xModel components :-)
1192 if (m_eContentType
== E_CAN_BE_SET
)
1196 return m_xSMGR
->createInstance(IMPLEMENTATIONNAME_GENERICFRAMELOADER
);
1198 catch(const css::uno::RuntimeException
&)
1200 catch(const css::uno::Exception
&)
1202 throw LoadEnvException(LoadEnvException::ID_INVALID_ENVIRONMENT
);
1206 // We need this type information to locate an registered frame loader
1207 // Without such information we can't work!
1208 OUString sType
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), OUString());
1209 if (sType
.isEmpty())
1210 throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR
);
1212 // try to locate any interested frame loader
1213 css::uno::Reference
< css::lang::XMultiServiceFactory
> xLoaderFactory(m_xSMGR
->createInstance(SERVICENAME_FRAMELOADERFACTORY
), css::uno::UNO_QUERY
);
1214 css::uno::Reference
< css::container::XContainerQuery
> xQuery (xLoaderFactory
, css::uno::UNO_QUERY
);
1217 // <- SAFE -----------------------------------
1219 css::uno::Sequence
< OUString
> lTypesReg(1);
1220 lTypesReg
[0] = sType
;
1222 css::uno::Sequence
< css::beans::NamedValue
> lQuery(1);
1223 lQuery
[0].Name
= OUString(PROP_TYPES
);
1224 lQuery
[0].Value
<<= lTypesReg
;
1226 OUString
sPROP_NAME(PROP_NAME
);
1228 css::uno::Reference
< css::container::XEnumeration
> xSet
= xQuery
->createSubSetEnumerationByProperties(lQuery
);
1229 while(xSet
->hasMoreElements())
1232 // Ignore any loader, which makes trouble :-)
1233 ::comphelper::SequenceAsHashMap
lLoaderProps(xSet
->nextElement());
1234 OUString sLoader
= lLoaderProps
.getUnpackedValueOrDefault(sPROP_NAME
, OUString());
1235 css::uno::Reference
< css::uno::XInterface
> xLoader
;
1238 xLoader
= xLoaderFactory
->createInstance(sLoader
);
1242 catch(const css::uno::RuntimeException
&)
1244 catch(const css::uno::Exception
&)
1248 return css::uno::Reference
< css::uno::XInterface
>();
1252 void LoadEnv::impl_jumpToMark(const css::uno::Reference
< css::frame::XFrame
>& xFrame
,
1253 const css::util::URL
& aURL
)
1255 if (aURL
.Mark
.isEmpty())
1258 css::uno::Reference
< css::frame::XDispatchProvider
> xProvider(xFrame
, css::uno::UNO_QUERY
);
1259 if (! xProvider
.is())
1263 ReadGuard
aReadLock(m_aLock
);
1264 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
1268 css::util::URL aCmd
;
1269 aCmd
.Complete
= OUString(".uno:JumpToMark");
1271 css::uno::Reference
< css::util::XURLTransformer
> xParser(css::util::URLTransformer::create(::comphelper::getComponentContext(m_xSMGR
)));
1272 xParser
->parseStrict(aCmd
);
1274 css::uno::Reference
< css::frame::XDispatch
> xDispatcher
= xProvider
->queryDispatch(aCmd
, SPECIALTARGET_SELF
, 0);
1275 if (! xDispatcher
.is())
1278 ::comphelper::SequenceAsHashMap lArgs
;
1279 lArgs
[OUString("Bookmark")] <<= aURL
.Mark
;
1280 xDispatcher
->dispatch(aCmd
, lArgs
.getAsConstPropertyValueList());
1284 css::uno::Reference
< css::frame::XFrame
> LoadEnv::impl_searchAlreadyLoaded()
1285 throw(LoadEnvException
, css::uno::RuntimeException
)
1288 ReadGuard
aReadLock(m_aLock
);
1290 // such search is allowed for special requests only ...
1291 // or better its not allowed for some requests in general :-)
1293 ( ! TargetHelper::matchSpecialTarget(m_sTarget
, TargetHelper::E_DEFAULT
) ) ||
1294 (m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_ASTEMPLATE() , sal_False
) == sal_True
) ||
1295 // (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN() , sal_False) == sal_True) ||
1296 (m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_OPENNEWVIEW(), sal_False
) == sal_True
)
1299 return css::uno::Reference
< css::frame::XFrame
>();
1303 // May its not useful to start expensive document search, if it
1304 // can fail only .. because we load from a stream or model directly!
1306 (ProtocolCheck::isProtocol(m_aURL
.Complete
, ProtocolCheck::E_PRIVATE_STREAM
)) ||
1307 (ProtocolCheck::isProtocol(m_aURL
.Complete
, ProtocolCheck::E_PRIVATE_OBJECT
))
1308 /*TODO should be private:factory here tested too? */
1311 return css::uno::Reference
< css::frame::XFrame
>();
1314 // otherwise - iterate through the tasks of the desktop container
1315 // to find out, which of them might contains the requested document
1316 css::uno::Reference
< css::frame::XDesktop2
> xSupplier
= css::frame::Desktop::create( comphelper::getComponentContext(m_xSMGR
) );
1317 css::uno::Reference
< css::container::XIndexAccess
> xTaskList(xSupplier
->getFrames() , css::uno::UNO_QUERY
);
1319 if (!xTaskList
.is())
1320 return css::uno::Reference
< css::frame::XFrame
>(); // task list can be empty!
1322 // Note: To detect if a document was alrady loaded before
1323 // we check URLs here only. But might the existing and the required
1324 // document has different versions! Then its URLs are the same ...
1325 sal_Int16 nNewVersion
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_VERSION(), (sal_Int16
)(-1));
1327 // will be used to save the first hidden frame referring the searched model
1328 // Normally we are interested on visible frames ... but if there is no such visible
1329 // frame we referr to any hidden frame also (but as fallback only).
1330 css::uno::Reference
< css::frame::XFrame
> xHiddenTask
;
1331 css::uno::Reference
< css::frame::XFrame
> xTask
;
1333 sal_Int32 count
= xTaskList
->getCount();
1334 for (sal_Int32 i
=0; i
<count
; ++i
)
1338 // locate model of task
1339 // Note: Without a model there is no chance to decide if
1340 // this task contains the searched document or not!
1341 xTaskList
->getByIndex(i
) >>= xTask
;
1345 css::uno::Reference
< css::frame::XController
> xController
= xTask
->getController();
1346 if (!xController
.is())
1352 css::uno::Reference
< css::frame::XModel
> xModel
= xController
->getModel();
1359 // don't check the complete URL here.
1360 // use its main part - ignore optional jumpmarks!
1361 const OUString sURL
= xModel
->getURL();
1362 if (!::utl::UCBContentHelper::EqualURLs( m_aURL
.Main
, sURL
))
1368 // get the original load arguments from the current document
1369 // and decide if its really the same then the one will be.
1370 // It must be visible and must use the same file revision ...
1371 // or must not have any file revision set (-1 == -1!)
1372 ::comphelper::MediaDescriptor
lOldDocDescriptor(xModel
->getArgs());
1374 if (lOldDocDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_VERSION(), (sal_Int32
)(-1)) != nNewVersion
)
1380 // Hidden frames are special.
1381 // They will be used as "last chance" if there is no visible frame pointing to the same model.
1382 // Safe the result but continue with current loop might be looking for other visible frames.
1383 ::sal_Bool bIsHidden
= lOldDocDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False
);
1386 ( ! xHiddenTask
.is())
1389 xHiddenTask
= xTask
;
1394 // We found a visible task pointing to the right model ...
1398 catch(const css::uno::RuntimeException
&)
1400 catch(const css::uno::Exception
&)
1404 css::uno::Reference
< css::frame::XFrame
> xResult
;
1407 else if (xHiddenTask
.is())
1408 xResult
= xHiddenTask
;
1412 // Now we are sure, that this task includes the searched document.
1413 // It's time to activate it. As special feature we try to jump internally
1414 // if an optional jumpmark is given too.
1415 if (!m_aURL
.Mark
.isEmpty())
1416 impl_jumpToMark(xResult
, m_aURL
);
1418 // bring it to front and make sure it's visible...
1419 impl_makeFrameWindowVisible(xResult
->getContainerWindow(), sal_True
);
1429 sal_Bool
LoadEnv::impl_isFrameAlreadyUsedForLoading(const css::uno::Reference
< css::frame::XFrame
>& xFrame
) const
1431 css::uno::Reference
< css::document::XActionLockable
> xLock(xFrame
, css::uno::UNO_QUERY
);
1433 // ? no lock interface ?
1434 // Might its an external written frame implementation :-(
1435 // Allowing using of it ... but it can fail if its not synchronized with our processes !
1439 // Otherwise we have to look for any other existing lock.
1440 return xLock
->isActionLocked();
1444 css::uno::Reference
< css::frame::XFrame
> LoadEnv::impl_searchRecycleTarget()
1445 throw(LoadEnvException
, css::uno::RuntimeException
)
1447 // SAFE -> ..................................
1448 ReadGuard
aReadLock(m_aLock
);
1450 // The special backing mode frame will be recycled by definition!
1451 // It doesn't matter if somehwere whish to create a new view
1452 // or open a new untitled document ...
1453 // The only exception form that - hidden frames!
1454 if (m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False
) == sal_True
)
1455 return css::uno::Reference
< css::frame::XFrame
>();
1457 css::uno::Reference
< css::frame::XFramesSupplier
> xSupplier( css::frame::Desktop::create( comphelper::getComponentContext(m_xSMGR
) ), css::uno::UNO_QUERY
);
1458 FrameListAnalyzer
aTasksAnalyzer(xSupplier
, css::uno::Reference
< css::frame::XFrame
>(), FrameListAnalyzer::E_BACKINGCOMPONENT
);
1459 if (aTasksAnalyzer
.m_xBackingComponent
.is())
1461 if (!impl_isFrameAlreadyUsedForLoading(aTasksAnalyzer
.m_xBackingComponent
))
1463 // bring it to front ...
1464 impl_makeFrameWindowVisible(aTasksAnalyzer
.m_xBackingComponent
->getContainerWindow(), sal_True
);
1465 return aTasksAnalyzer
.m_xBackingComponent
;
1469 // These states indicates a wish for creation of a new view in general.
1471 (m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_ASTEMPLATE() , sal_False
) == sal_True
) ||
1472 (m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_OPENNEWVIEW(), sal_False
) == sal_True
)
1475 return css::uno::Reference
< css::frame::XFrame
>();
1478 // On the other side some special URLs will open a new frame everytimes (expecting
1479 // they can use the backing-mode frame!)
1481 (ProtocolCheck::isProtocol(m_aURL
.Complete
, ProtocolCheck::E_PRIVATE_FACTORY
)) ||
1482 (ProtocolCheck::isProtocol(m_aURL
.Complete
, ProtocolCheck::E_PRIVATE_STREAM
)) ||
1483 (ProtocolCheck::isProtocol(m_aURL
.Complete
, ProtocolCheck::E_PRIVATE_OBJECT
))
1486 return css::uno::Reference
< css::frame::XFrame
>();
1489 // No backing frame! No special URL => recycle active task - if possible.
1490 // Means - if it does not already contains a modified document, or
1491 // use another office module.
1492 css::uno::Reference
< css::frame::XFrame
> xTask
= xSupplier
->getActiveFrame();
1494 // not a real error - but might a focus problem!
1496 return css::uno::Reference
< css::frame::XFrame
>();
1498 // not a real error - may its a view only
1499 css::uno::Reference
< css::frame::XController
> xController
= xTask
->getController();
1500 if (!xController
.is())
1501 return css::uno::Reference
< css::frame::XFrame
>();
1503 // not a real error - may its a db component instead of a full feartured office document
1504 css::uno::Reference
< css::frame::XModel
> xModel
= xController
->getModel();
1506 return css::uno::Reference
< css::frame::XFrame
>();
1508 // get some more information ...
1510 // A valid set URL means: there is already a location for this document.
1511 // => it was saved there or opened from there. Such Documents can not be used here.
1512 // We search for empty document ... created by a private:factory/ URL!
1513 if (xModel
->getURL().getLength()>0)
1514 return css::uno::Reference
< css::frame::XFrame
>();
1516 // The old document must be unmodified ...
1517 css::uno::Reference
< css::util::XModifiable
> xModified(xModel
, css::uno::UNO_QUERY
);
1518 if (xModified
->isModified())
1519 return css::uno::Reference
< css::frame::XFrame
>();
1521 Window
* pWindow
= VCLUnoHelper::GetWindow(xTask
->getContainerWindow());
1522 if (pWindow
&& pWindow
->IsInModalMode())
1523 return css::uno::Reference
< css::frame::XFrame
>();
1525 // find out the application type of this document
1526 // We can recycle only documents, which uses the same application
1527 // then the new one.
1528 SvtModuleOptions::EFactory eOldApp
= SvtModuleOptions::ClassifyFactoryByModel(xModel
);
1529 SvtModuleOptions::EFactory eNewApp
= SvtModuleOptions::ClassifyFactoryByURL (m_aURL
.Complete
, m_lMediaDescriptor
.getAsConstPropertyValueList());
1532 // <- SAFE ..................................
1534 if (eOldApp
!= eNewApp
)
1535 return css::uno::Reference
< css::frame::XFrame
>();
1537 // OK this task seams to be useable for recycling
1538 // But we should mark it as such - means set an action lock.
1539 // Otherwhise it would be used more then ones or will be destroyed
1540 // by a close() or terminate() request.
1541 // But if such lock already exist ... it means this task is used for
1542 // any other operation already. Don't use it then.
1543 if (impl_isFrameAlreadyUsedForLoading(xTask
))
1544 return css::uno::Reference
< css::frame::XFrame
>();
1546 // OK - there is a valid target frame.
1547 // But may be it contains already a document.
1548 // Then we have to ask it, if it allows recylcing of this frame .-)
1549 sal_Bool bReactivateOldControllerOnError
= sal_False
;
1550 css::uno::Reference
< css::frame::XController
> xOldDoc
= xTask
->getController();
1553 bReactivateOldControllerOnError
= xOldDoc
->suspend(sal_True
);
1554 if (! bReactivateOldControllerOnError
)
1555 return css::uno::Reference
< css::frame::XFrame
>();
1558 // SAFE -> ..................................
1559 WriteGuard
aWriteLock(m_aLock
);
1561 css::uno::Reference
< css::document::XActionLockable
> xLock(xTask
, css::uno::UNO_QUERY
);
1562 if (!m_aTargetLock
.setResource(xLock
))
1563 return css::uno::Reference
< css::frame::XFrame
>();
1565 m_bReactivateControllerOnError
= bReactivateOldControllerOnError
;
1566 aWriteLock
.unlock();
1567 // <- SAFE ..................................
1569 // bring it to front ...
1570 impl_makeFrameWindowVisible(xTask
->getContainerWindow(), sal_True
);
1576 void LoadEnv::impl_reactForLoadingState()
1577 throw(LoadEnvException
, css::uno::RuntimeException
)
1579 /*TODO reset action locks */
1581 // SAFE -> ----------------------------------
1582 ReadGuard
aReadLock(m_aLock
);
1586 // Bring the new loaded document to front (if allowed!).
1587 // Note: We show new created frames here only.
1588 // We dont hide already visible frames here ...
1589 css::uno::Reference
< css::awt::XWindow
> xWindow
= m_xTargetFrame
->getContainerWindow();
1590 sal_Bool bHidden
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False
);
1591 sal_Bool bMinimized
= m_lMediaDescriptor
.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_MINIMIZED(), sal_False
);
1595 SolarMutexGuard aSolarGuard
;
1596 Window
* pWindow
= VCLUnoHelper::GetWindow(xWindow
);
1597 // check for system window is necessary to guarantee correct pointer cast!
1598 if (pWindow
&& pWindow
->IsSystemWindow())
1599 ((WorkWindow
*)pWindow
)->Minimize();
1603 // show frame ... if it's not still visible ...
1604 // But do nothing if it's already visible!
1605 impl_makeFrameWindowVisible(xWindow
, sal_False
);
1608 // Note: Only if an existing property "FrameName" is given by this media descriptor,
1609 // it should be used. Otherwhise we should do nothing. May be the outside code has already
1610 // set a frame name on the target!
1611 ::comphelper::MediaDescriptor::const_iterator pFrameName
= m_lMediaDescriptor
.find(::comphelper::MediaDescriptor::PROP_FRAMENAME());
1612 if (pFrameName
!= m_lMediaDescriptor
.end())
1614 OUString sFrameName
;
1615 pFrameName
->second
>>= sFrameName
;
1616 // Check the name again. e.g. "_default" isnt allowed.
1617 // On the other side "_beamer" is a valid name :-)
1618 if (TargetHelper::isValidNameForFrame(sFrameName
))
1619 m_xTargetFrame
->setName(sFrameName
);
1622 else if (m_bReactivateControllerOnError
)
1624 // Try to reactivate the old document (if any exists!)
1625 css::uno::Reference
< css::frame::XController
> xOldDoc
= m_xTargetFrame
->getController();
1626 // clear does not depend from reactivation state of a might existing old document!
1627 // We must make sure, that a might following getTargetComponent() call does not return
1628 // the old document!
1629 m_xTargetFrame
.clear();
1632 sal_Bool bReactivated
= xOldDoc
->suspend(sal_False
);
1634 throw LoadEnvException(LoadEnvException::ID_COULD_NOT_REACTIVATE_CONTROLLER
);
1635 m_bReactivateControllerOnError
= sal_False
;
1638 else if (m_bCloseFrameOnError
)
1640 // close empty frames
1641 css::uno::Reference
< css::util::XCloseable
> xCloseable (m_xTargetFrame
, css::uno::UNO_QUERY
);
1642 css::uno::Reference
< css::lang::XComponent
> xDisposable(m_xTargetFrame
, css::uno::UNO_QUERY
);
1646 if (xCloseable
.is())
1647 xCloseable
->close(sal_True
);
1649 if (xDisposable
.is())
1650 xDisposable
->dispose();
1652 catch(const css::util::CloseVetoException
&)
1654 catch(const css::lang::DisposedException
&)
1656 m_xTargetFrame
.clear();
1659 // This max force an implicit closing of our target frame ...
1660 // e.g. in case close(sal_True) was called before and the frame
1661 // kill itself if our external use-lock is released here!
1662 // Thats why we releas this lock AFTER ALL OPERATIONS on this frame
1663 // are finished. The frame itslef must handle then
1664 // this situation gracefully.
1665 m_aTargetLock
.freeResource();
1667 // Last but not least :-)
1668 // We have to clear the current media descriptor.
1669 // Otherwhise it hold a might existing stream open!
1670 m_lMediaDescriptor
.clear();
1672 css::uno::Any aRequest
;
1673 bool bThrow
= false;
1674 if ( !m_bLoaded
&& m_pQuietInteraction
&& m_pQuietInteraction
->wasUsed() )
1676 aRequest
= m_pQuietInteraction
->getRequest();
1677 m_pQuietInteraction
->release();
1678 m_pQuietInteraction
= 0;
1686 if ( aRequest
.isExtractableTo( ::cppu::UnoType
< css::uno::Exception
>::get() ) )
1687 throw LoadEnvException( LoadEnvException::ID_GENERAL_ERROR
, aRequest
);
1690 // <- SAFE ----------------------------------
1694 void LoadEnv::impl_makeFrameWindowVisible(const css::uno::Reference
< css::awt::XWindow
>& xWindow
,
1695 sal_Bool bForceToFront
)
1697 // SAFE -> ----------------------------------
1698 ReadGuard
aReadLock(m_aLock
);
1699 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR( m_xSMGR
.get(), css::uno::UNO_QUERY
);
1701 // <- SAFE ----------------------------------
1703 SolarMutexGuard aSolarGuard
;
1704 Window
* pWindow
= VCLUnoHelper::GetWindow(xWindow
);
1707 bool const preview( m_lMediaDescriptor
.getUnpackedValueOrDefault(
1708 ::comphelper::MediaDescriptor::PROP_PREVIEW(), sal_False
) );
1710 bool bForceFrontAndFocus(false);
1713 css::uno::Any
const a
=
1714 ::comphelper::ConfigurationHelper::readDirectKey(
1715 comphelper::getComponentContext(xSMGR
),
1716 OUString("org.openoffice.Office.Common/View"),
1717 OUString("NewDocumentHandling"),
1718 OUString("ForceFocusAndToFront"),
1719 ::comphelper::ConfigurationHelper::E_READONLY
);
1720 a
>>= bForceFrontAndFocus
;
1723 if( pWindow
->IsVisible() && (bForceFrontAndFocus
|| bForceToFront
) )
1726 pWindow
->Show(sal_True
, (bForceFrontAndFocus
|| bForceToFront
) ? SHOW_FOREGROUNDTASK
: 0 );
1731 void LoadEnv::impl_applyPersistentWindowState(const css::uno::Reference
< css::awt::XWindow
>& xWindow
)
1733 static OUString
PACKAGE_SETUP_MODULES("/org.openoffice.Setup/Office/Factories");
1735 // no window -> action not possible
1739 // window already visible -> do nothing! If we use a "recycle frame" for loading ...
1740 // the current position and size must be used.
1741 css::uno::Reference
< css::awt::XWindow2
> xVisibleCheck(xWindow
, css::uno::UNO_QUERY
);
1743 (xVisibleCheck
.is() ) &&
1744 (xVisibleCheck
->isVisible())
1749 SolarMutexClearableGuard aSolarGuard1
;
1751 Window
* pWindow
= VCLUnoHelper::GetWindow(xWindow
);
1755 sal_Bool bSystemWindow
= pWindow
->IsSystemWindow();
1756 sal_Bool bWorkWindow
= (pWindow
->GetType() == WINDOW_WORKWINDOW
);
1758 if (!bSystemWindow
&& !bWorkWindow
)
1761 // dont overwrite this special state!
1762 WorkWindow
* pWorkWindow
= (WorkWindow
*)pWindow
;
1763 if (pWorkWindow
->IsMinimized())
1766 aSolarGuard1
.clear();
1770 ReadGuard
aReadLock(m_aLock
);
1772 // no filter -> no module -> no persistent window state
1773 OUString sFilter
= m_lMediaDescriptor
.getUnpackedValueOrDefault(
1774 ::comphelper::MediaDescriptor::PROP_FILTERNAME(),
1776 if (sFilter
.isEmpty())
1779 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
1786 // retrieve the module name from the filter configuration
1787 css::uno::Reference
< css::container::XNameAccess
> xFilterCfg(
1788 xSMGR
->createInstance(SERVICENAME_FILTERFACTORY
),
1789 css::uno::UNO_QUERY_THROW
);
1790 ::comphelper::SequenceAsHashMap
lProps (xFilterCfg
->getByName(sFilter
));
1791 OUString sModule
= lProps
.getUnpackedValueOrDefault(FILTER_PROPNAME_DOCUMENTSERVICE
, OUString());
1793 // get access to the configuration of this office module
1794 css::uno::Reference
< css::container::XNameAccess
> xModuleCfg(::comphelper::ConfigurationHelper::openConfig(
1795 comphelper::getComponentContext(xSMGR
),
1796 PACKAGE_SETUP_MODULES
,
1797 ::comphelper::ConfigurationHelper::E_READONLY
),
1798 css::uno::UNO_QUERY_THROW
);
1800 // read window state from the configuration
1801 // and apply it on the window.
1802 // Do nothing, if no configuration entry exists!
1803 OUString sWindowState
;
1804 ::comphelper::ConfigurationHelper::readRelativeKey(xModuleCfg
, sModule
, OFFICEFACTORY_PROPNAME_WINDOWATTRIBUTES
) >>= sWindowState
;
1805 if (!sWindowState
.isEmpty())
1808 SolarMutexGuard aSolarGuard
;
1810 // We have to retrieve the window pointer again. Because nobody can guarantee
1811 // that the XWindow was not disposed inbetween .-)
1812 // But if we get a valid pointer we can be sure, that it's the system window pointer
1813 // we already checked and used before. Because nobody recylce the same uno reference for
1814 // a new internal c++ implementation ... hopefully .-))
1815 Window
* pWindowCheck
= VCLUnoHelper::GetWindow(xWindow
);
1819 SystemWindow
* pSystemWindow
= (SystemWindow
*)pWindowCheck
;
1820 pSystemWindow
->SetWindowState(OUStringToOString(sWindowState
,RTL_TEXTENCODING_UTF8
));
1824 catch(const css::uno::RuntimeException
&)
1826 catch(const css::uno::Exception
&)
1830 } // namespace framework
1832 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */