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/.
10 #include "WpftLoader.hxx"
12 #include <com/sun/star/beans/PropertyValue.hpp>
13 #include <com/sun/star/container/NoSuchElementException.hpp>
14 #include <com/sun/star/container/XNameAccess.hpp>
15 #include <com/sun/star/document/XExtendedFilterDetection.hpp>
16 #include <com/sun/star/document/XFilter.hpp>
17 #include <com/sun/star/document/XImporter.hpp>
18 #include <com/sun/star/frame/XController.hpp>
19 #include <com/sun/star/frame/XDesktop2.hpp>
20 #include <com/sun/star/frame/XModel.hpp>
21 #include <com/sun/star/io/XInputStream.hpp>
22 #include <com/sun/star/lang/IllegalArgumentException.hpp>
23 #include <com/sun/star/lang/XComponent.hpp>
24 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
25 #include <com/sun/star/ucb/XContent.hpp>
26 #include <com/sun/star/uno/XComponentContext.hpp>
27 #include <com/sun/star/util/XCloseable.hpp>
29 #include <ucbhelper/content.hxx>
31 namespace beans
= com::sun::star::beans
;
32 namespace container
= com::sun::star::container
;
33 namespace document
= com::sun::star::document
;
34 namespace frame
= com::sun::star::frame
;
35 namespace lang
= com::sun::star::lang
;
36 namespace ucb
= com::sun::star::ucb
;
37 namespace uno
= com::sun::star::uno
;
38 namespace util
= com::sun::star::util
;
40 namespace writerperfect::test
42 WpftLoader::WpftLoader(const OUString
& rURL
,
43 const css::uno::Reference
<css::document::XFilter
>& rxFilter
,
44 const OUString
& rFactoryURL
,
45 const css::uno::Reference
<css::frame::XDesktop2
>& rxDesktop
,
46 const css::uno::Reference
<css::container::XNameAccess
>& rxTypeMap
,
47 const css::uno::Reference
<css::uno::XComponentContext
>& rxContext
)
49 , m_aFactoryURL(rFactoryURL
)
51 , m_xDesktop(rxDesktop
)
52 , m_xTypeMap(rxTypeMap
)
53 , m_xContext(rxContext
)
59 WpftLoader::WpftLoader(const css::uno::Reference
<css::io::XInputStream
>& rxInputStream
,
60 const css::uno::Reference
<css::document::XFilter
>& rxFilter
,
61 const OUString
& rFactoryURL
,
62 const css::uno::Reference
<css::frame::XDesktop2
>& rxDesktop
,
63 const css::uno::Reference
<css::uno::XComponentContext
>& rxContext
)
64 : m_xInputStream(rxInputStream
)
65 , m_aFactoryURL(rFactoryURL
)
67 , m_xDesktop(rxDesktop
)
68 , m_xContext(rxContext
)
74 WpftLoader::~WpftLoader()
85 const css::uno::Reference
<css::lang::XComponent
>& WpftLoader::getDocument() const { return m_xDoc
; }
87 bool WpftLoader::impl_load()
89 // create an empty frame
90 m_xDoc
.set(m_xDesktop
->loadComponentFromURL(m_aFactoryURL
, "_blank", 0,
91 uno::Sequence
<beans::PropertyValue
>()),
94 // Find the model and frame. We need them later.
95 m_xFrame
.set(m_xDoc
, uno::UNO_QUERY
);
96 uno::Reference
<frame::XModel
> xModel(m_xDoc
, uno::UNO_QUERY
);
97 uno::Reference
<frame::XController
> xController(m_xDoc
, uno::UNO_QUERY
);
101 xController
= m_xFrame
->getController();
102 xModel
= xController
->getModel();
104 else if (xModel
.is())
106 xController
= xModel
->getCurrentController();
107 m_xFrame
= xController
->getFrame();
109 else if (xController
.is())
111 m_xFrame
= xController
->getFrame();
112 xModel
= xController
->getModel();
115 if (!m_xFrame
.is() || !xModel
.is())
116 throw uno::RuntimeException();
118 // try to import the document (and load it into the prepared frame)
121 const uno::Reference
<document::XImporter
> xImporter(m_xFilter
, uno::UNO_QUERY_THROW
);
123 xImporter
->setTargetDocument(m_xDoc
);
125 uno::Sequence
<beans::PropertyValue
> aDescriptor(3);
126 auto pDescriptor
= aDescriptor
.getArray();
127 pDescriptor
[0].Name
= "URL";
128 pDescriptor
[0].Value
<<= m_aURL
;
129 if (m_xInputStream
.is())
131 pDescriptor
[1].Name
= "InputStream";
132 pDescriptor
[1].Value
<<= m_xInputStream
;
136 ucbhelper::Content
aContent(m_aURL
, uno::Reference
<ucb::XCommandEnvironment
>(),
138 pDescriptor
[1].Name
= "InputStream";
139 pDescriptor
[1].Value
<<= aContent
.openStream();
140 pDescriptor
[2].Name
= "UCBContent";
141 pDescriptor
[2].Value
<<= aContent
.get();
144 const uno::Reference
<document::XExtendedFilterDetection
> xDetector(m_xFilter
,
145 uno::UNO_QUERY_THROW
);
147 const OUString
aTypeName(xDetector
->detect(aDescriptor
));
148 if (aTypeName
.isEmpty())
149 throw lang::IllegalArgumentException();
152 impl_detectFilterName(aDescriptor
, aTypeName
);
154 xModel
->lockControllers();
155 const bool bLoaded
= m_xFilter
->filter(aDescriptor
);
156 xModel
->unlockControllers();
159 catch (const uno::Exception
&)
167 void WpftLoader::impl_dispose()
169 // close the opened document
170 uno::Reference
<util::XCloseable
> xCloseable(m_xFrame
, uno::UNO_QUERY
);
172 xCloseable
->close(true);
173 else if (m_xDoc
.is())
179 void WpftLoader::impl_detectFilterName(uno::Sequence
<beans::PropertyValue
>& rDescriptor
,
180 const OUString
& rTypeName
)
183 = std::any_of(std::cbegin(rDescriptor
), std::cend(rDescriptor
),
184 [](const beans::PropertyValue
& rProp
) { return "FilterName" == rProp
.Name
; });
188 uno::Sequence
<beans::PropertyValue
> aTypes
;
189 if (m_xTypeMap
->getByName(rTypeName
) >>= aTypes
)
191 for (const auto& rType
: std::as_const(aTypes
))
193 OUString aFilterName
;
194 if (("PreferredFilter" == rType
.Name
) && (rType
.Value
>>= aFilterName
))
196 const sal_Int32 nDescriptorLen
= rDescriptor
.getLength();
197 rDescriptor
.realloc(nDescriptorLen
+ 1);
198 auto& el
= rDescriptor
.getArray()[nDescriptorLen
];
199 el
.Name
= "FilterName";
200 el
.Value
<<= aFilterName
;
206 throw container::NoSuchElementException();
210 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */