Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include <sfx2/DocumentMetadataAccess.hxx>
22 : :
23 : : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
24 : : #include <com/sun/star/beans/XPropertySet.hpp>
25 : : #include <com/sun/star/embed/ElementModes.hpp>
26 : : #include <com/sun/star/embed/XStorage.hpp>
27 : : #include <com/sun/star/embed/XTransactedObject.hpp>
28 : : #include <com/sun/star/task/ErrorCodeIOException.hpp>
29 : : #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
30 : : #include <com/sun/star/rdf/FileFormat.hpp>
31 : : #include <com/sun/star/rdf/URIs.hpp>
32 : : #include <com/sun/star/rdf/Statement.hpp>
33 : : #include <com/sun/star/rdf/Literal.hpp>
34 : : #include <com/sun/star/rdf/URI.hpp>
35 : : #include <com/sun/star/rdf/Repository.hpp>
36 : :
37 : : #include <rtl/ustrbuf.hxx>
38 : : #include <rtl/uri.hxx>
39 : : #include <rtl/bootstrap.hxx>
40 : :
41 : : #include <comphelper/interaction.hxx>
42 : : #include <comphelper/makesequence.hxx>
43 : : #include <comphelper/mediadescriptor.hxx>
44 : : #include <comphelper/sequenceasvector.hxx>
45 : : #include <comphelper/storagehelper.hxx>
46 : :
47 : : #include <sfx2/docfile.hxx>
48 : : #include <sfx2/XmlIdRegistry.hxx>
49 : :
50 : : #include <libxml/tree.h> // for xmlValidateNCName
51 : :
52 : : #include <boost/bind.hpp>
53 : : #include <boost/shared_array.hpp>
54 : : #include <boost/tuple/tuple.hpp>
55 : :
56 : : #include <vector>
57 : : #include <set>
58 : : #include <map>
59 : : #include <functional>
60 : : #include <algorithm>
61 : :
62 : : #include <unotools/ucbhelper.hxx>
63 : : #include <com/sun/star/uri/XUriReference.hpp>
64 : : #include <com/sun/star/uri/XUriReferenceFactory.hpp>
65 : : #include <com/sun/star/uri/XVndSunStarPkgUrlReferenceFactory.hpp>
66 : :
67 : :
68 : : /*
69 : : Note: in the context of this implementation, all rdf.QueryExceptions and
70 : : rdf.RepositoryExceptions are RuntimeExceptions, and will be reported as such.
71 : :
72 : : This implementation assumes that it is only used with ODF documents, not mere
73 : : ODF packages. In other words, we enforce that metadata files must not be
74 : : called reserved names.
75 : : */
76 : :
77 : : using namespace ::com::sun::star;
78 : :
79 : : namespace sfx2 {
80 : :
81 : :
82 : 1813 : bool isValidNCName(::rtl::OUString const & i_rIdref)
83 : : {
84 : : const ::rtl::OString id(
85 [ + - ]: 1813 : ::rtl::OUStringToOString(i_rIdref, RTL_TEXTENCODING_UTF8) );
86 : : return !(xmlValidateNCName(
87 [ + - ]: 1813 : reinterpret_cast<const unsigned char*>(id.getStr()), 0));
88 : : }
89 : :
90 : :
91 : : static const char s_content [] = "content.xml";
92 : : static const char s_styles [] = "styles.xml";
93 : : static const char s_meta [] = "meta.xml";
94 : : static const char s_settings[] = "settings.xml";
95 : : static const char s_manifest[] = "manifest.rdf";
96 : : static const char s_rdfxml [] = "application/rdf+xml";
97 : : static const char s_odfmime [] = "application/vnd.oasis.opendocument.";
98 : :
99 : :
100 : 1955 : static bool isContentFile(::rtl::OUString const & i_rPath)
101 : : {
102 : 1955 : return i_rPath == s_content;
103 : : }
104 : :
105 : 92 : static bool isStylesFile (::rtl::OUString const & i_rPath)
106 : : {
107 : 92 : return i_rPath == s_styles;
108 : : }
109 : :
110 : 1813 : bool isValidXmlId(::rtl::OUString const & i_rStreamName,
111 : : ::rtl::OUString const & i_rIdref)
112 : : {
113 : 1813 : return isValidNCName(i_rIdref)
114 [ + + ][ + - ]: 1813 : && (isContentFile(i_rStreamName) || isStylesFile(i_rStreamName));
[ + - ]
115 : : }
116 : :
117 : 28 : static bool isReservedFile(::rtl::OUString const & i_rPath)
118 : : {
119 [ + + ][ + + ]: 28 : return isContentFile(i_rPath) || isStylesFile(i_rPath) || i_rPath == s_meta || i_rPath == s_settings;
[ + + ][ + + ]
120 : : }
121 : :
122 : :
123 : 75 : uno::Reference<rdf::XURI> createBaseURI(
124 : : uno::Reference<uno::XComponentContext> const & i_xContext,
125 : : uno::Reference<embed::XStorage> const & i_xStorage,
126 : : ::rtl::OUString const & i_rPkgURI, ::rtl::OUString const & i_rSubDocument)
127 : : {
128 [ + - ][ + - ]: 75 : if (!i_xContext.is() || !i_xStorage.is() || i_rPkgURI.isEmpty()) {
[ + + ][ + + ]
129 [ + - ]: 6 : throw uno::RuntimeException();
130 : : }
131 : :
132 : : // #i108078# workaround non-hierarchical vnd.sun.star.expand URIs
133 : : // this really should be done somewhere else, not here.
134 : 69 : ::rtl::OUString pkgURI(i_rPkgURI);
135 [ - + ]: 69 : if (pkgURI.matchIgnoreAsciiCaseAsciiL(
136 : 69 : RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:")))
137 : : {
138 : : // expand it here (makeAbsolute requires hierarchical URI)
139 : 0 : pkgURI = pkgURI.copy( RTL_CONSTASCII_LENGTH("vnd.sun.star.expand:") );
140 [ # # ]: 0 : if (!pkgURI.isEmpty()) {
141 : : pkgURI = ::rtl::Uri::decode(
142 : 0 : pkgURI, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
143 [ # # ]: 0 : if (pkgURI.isEmpty()) {
144 [ # # ]: 0 : throw uno::RuntimeException();
145 : : }
146 : 0 : ::rtl::Bootstrap::expandMacros(pkgURI);
147 : : }
148 : : }
149 : :
150 : : const uno::Reference<lang::XMultiComponentFactory> xServiceFactory(
151 [ + - ][ + - ]: 69 : i_xContext->getServiceManager(), uno::UNO_SET_THROW);
[ + - ]
152 : : const uno::Reference<uri::XUriReferenceFactory> xUriFactory(
153 [ + - ]: 69 : xServiceFactory->createInstanceWithContext(
154 : : ::rtl::OUString(
155 : 69 : "com.sun.star.uri.UriReferenceFactory"), i_xContext),
156 [ + - ][ + - ]: 69 : uno::UNO_QUERY_THROW);
157 : 69 : uno::Reference< uri::XUriReference > xBaseURI;
158 : :
159 : : const uno::Reference< uri::XUriReference > xPkgURI(
160 [ + - ][ + - ]: 69 : xUriFactory->parse(pkgURI), uno::UNO_SET_THROW );
[ + - ]
161 [ + - ][ + - ]: 69 : xPkgURI->clearFragment();
162 : :
163 : : // need to know whether the storage is a FileSystemStorage
164 : : // XServiceInfo would be better, but it is not implemented
165 : : // if ( pkgURI.getLength() && ::utl::UCBContentHelper::IsFolder(pkgURI) )
166 : : if (true) {
167 [ + - ]: 69 : xBaseURI.set( xPkgURI, uno::UNO_SET_THROW );
168 : : }
169 : 69 : ::rtl::OUStringBuffer buf;
170 [ + - ][ + - ]: 69 : if (!xBaseURI->getUriReference().endsWithAsciiL("/", 1))
[ + - ]
171 : : {
172 [ + - ][ + - ]: 69 : const sal_Int32 count( xBaseURI->getPathSegmentCount() );
173 [ + - ]: 69 : if (count > 0)
174 : : {
175 [ + - ][ + - ]: 69 : const ::rtl::OUString last( xBaseURI->getPathSegment(count - 1) );
176 [ + - ]: 69 : buf.append(last);
177 : : }
178 [ + - ]: 69 : buf.append(static_cast<sal_Unicode>('/'));
179 : : }
180 [ - + ]: 69 : if (!i_rSubDocument.isEmpty())
181 : : {
182 [ # # ]: 0 : buf.append(i_rSubDocument);
183 [ # # ]: 0 : buf.append(static_cast<sal_Unicode>('/'));
184 : : }
185 [ + - ]: 69 : const ::rtl::OUString Path(buf.makeStringAndClear());
186 [ + - ]: 69 : if (!Path.isEmpty())
187 : : {
188 : : const uno::Reference< uri::XUriReference > xPathURI(
189 [ + - ][ + - ]: 69 : xUriFactory->parse(Path), uno::UNO_SET_THROW );
[ + - ]
190 : : xBaseURI.set(
191 [ + - ]: 69 : xUriFactory->makeAbsolute(xBaseURI, xPathURI,
192 : 69 : true, uri::RelativeUriExcessParentSegments_ERROR),
193 [ + - ][ + - ]: 69 : uno::UNO_SET_THROW);
194 : : }
195 : :
196 [ + - ][ + - ]: 75 : return rdf::URI::create(i_xContext, xBaseURI->getUriReference());
[ + + ]
197 : : }
198 : :
199 : :
200 : 58 : struct DocumentMetadataAccess_Impl
201 : : {
202 : : // note: these are all initialized in constructor, and loadFromStorage
203 : : const uno::Reference<uno::XComponentContext> m_xContext;
204 : : const IXmlIdRegistrySupplier & m_rXmlIdRegistrySupplier;
205 : : uno::Reference<rdf::XURI> m_xBaseURI;
206 : : uno::Reference<rdf::XRepository> m_xRepository;
207 : : uno::Reference<rdf::XNamedGraph> m_xManifest;
208 : 58 : DocumentMetadataAccess_Impl(
209 : : uno::Reference<uno::XComponentContext> const& i_xContext,
210 : : IXmlIdRegistrySupplier const & i_rRegistrySupplier)
211 : : : m_xContext(i_xContext)
212 : : , m_rXmlIdRegistrySupplier(i_rRegistrySupplier)
213 : : , m_xBaseURI()
214 : : , m_xRepository()
215 : 58 : , m_xManifest()
216 : : {
217 : : OSL_ENSURE(m_xContext.is(), "context null");
218 : 58 : }
219 : : };
220 : :
221 : : // this is... a hack.
222 : : template<sal_Int16 Constant>
223 : : /*static*/ uno::Reference<rdf::XURI>
224 : 610 : getURI(uno::Reference< uno::XComponentContext > const & i_xContext)
225 : : {
226 : : static uno::Reference< rdf::XURI > xURI(
227 [ + + ][ + - ]: 610 : rdf::URI::createKnown(i_xContext, Constant), uno::UNO_QUERY_THROW);
[ + - ][ + - ]
[ # # ][ + + ]
[ + - ][ + - ]
[ + - ][ # # ]
[ + + ][ + - ]
[ + - ][ + - ]
[ # # ][ + + ]
[ + - ][ + - ]
[ + - ][ # # ]
[ + + ][ + - ]
[ + - ][ + - ]
[ # # ][ + + ]
[ + - ][ + - ]
[ + - ][ # # ]
228 : 610 : return xURI;
229 : : }
230 : :
231 : :
232 : : /** would storing the file to a XStorage succeed? */
233 : 54 : static bool isFileNameValid(const ::rtl::OUString & i_rFileName)
234 : : {
235 [ + + ]: 54 : if (i_rFileName.isEmpty()) return false;
236 [ + + ]: 46 : if (i_rFileName[0] == '/') return false; // no absolute paths!
237 : 42 : sal_Int32 idx(0);
238 [ + + ]: 58 : do {
239 : : const ::rtl::OUString segment(
240 : 58 : i_rFileName.getToken(0, static_cast<sal_Unicode> ('/'), idx) );
241 [ + + ][ + + ]: 224 : if (segment.isEmpty() || // no empty segments
[ + - + +
+ + ]
242 : 58 : segment == "." || // no . segments
243 : 56 : segment == ".." || // no .. segments
244 : : !::comphelper::OStorageHelper::IsValidZipEntryFileName(
245 [ + - ]: 52 : segment, sal_False)) // no invalid characters
246 [ + + ]: 58 : return false;
247 : : } while (idx >= 0);
248 : 54 : return true;
249 : : }
250 : :
251 : : /** split a uri hierarchy into first segment and rest */
252 : : static bool
253 : 76 : splitPath(::rtl::OUString const & i_rPath,
254 : : ::rtl::OUString & o_rDir, ::rtl::OUString& o_rRest)
255 : : {
256 : 76 : const sal_Int32 idx(i_rPath.indexOf(static_cast<sal_Unicode>('/')));
257 [ - + ][ + + ]: 76 : if (idx < 0 || idx >= i_rPath.getLength()) {
[ + + ]
258 : 60 : o_rDir = ::rtl::OUString();
259 : 60 : o_rRest = i_rPath;
260 : 60 : return true;
261 [ + - ][ - + ]: 16 : } else if (idx == 0 || idx == i_rPath.getLength() - 1) {
[ - + ]
262 : : // input must not start or end with '/'
263 : 0 : return false;
264 : : } else {
265 : 16 : o_rDir = (i_rPath.copy(0, idx));
266 : 16 : o_rRest = (i_rPath.copy(idx+1));
267 : 76 : return true;
268 : : }
269 : : }
270 : :
271 : : static bool
272 : 2 : splitXmlId(::rtl::OUString const & i_XmlId,
273 : : ::rtl::OUString & o_StreamName, ::rtl::OUString& o_Idref )
274 : : {
275 : 2 : const sal_Int32 idx(i_XmlId.indexOf(static_cast<sal_Unicode>('#')));
276 [ - + ][ - + ]: 2 : if ((idx <= 0) || (idx >= i_XmlId.getLength() - 1)) {
[ + - ]
277 : 0 : return false;
278 : : } else {
279 : 2 : o_StreamName = (i_XmlId.copy(0, idx));
280 : 2 : o_Idref = (i_XmlId.copy(idx+1));
281 : 2 : return isValidXmlId(o_StreamName, o_Idref);
282 : : }
283 : : }
284 : :
285 : :
286 : : static uno::Reference<rdf::XURI>
287 : 156 : getURIForStream(struct DocumentMetadataAccess_Impl& i_rImpl,
288 : : ::rtl::OUString const& i_rPath)
289 : : {
290 : : const uno::Reference<rdf::XURI> xURI(
291 : : rdf::URI::createNS( i_rImpl.m_xContext,
292 : 156 : i_rImpl.m_xBaseURI->getStringValue(), i_rPath),
293 [ + - ][ + - ]: 156 : uno::UNO_SET_THROW);
294 : 156 : return xURI;
295 : : }
296 : :
297 : : /** add statements declaring i_xResource to be a file of type i_xType with
298 : : path i_rPath to manifest, with optional additional types i_pTypes */
299 : : static void
300 : 72 : addFile(struct DocumentMetadataAccess_Impl & i_rImpl,
301 : : uno::Reference<rdf::XURI> const& i_xType,
302 : : ::rtl::OUString const & i_rPath,
303 : : const uno::Sequence < uno::Reference< rdf::XURI > > * i_pTypes = 0)
304 : : {
305 : : try {
306 : : const uno::Reference<rdf::XURI> xURI( getURIForStream(
307 [ + - ]: 72 : i_rImpl, i_rPath) );
308 : :
309 [ + - ][ + - ]: 144 : i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
310 : : getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext),
311 [ + - ][ + - ]: 144 : xURI.get());
[ + - ][ + - ]
[ + - ]
312 [ + - ][ + - ]: 144 : i_rImpl.m_xManifest->addStatement(xURI.get(),
313 : : getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
314 [ + - ][ + - ]: 144 : i_xType.get());
[ + - ][ + - ]
[ + - ]
315 [ + + ]: 72 : if (i_pTypes) {
316 [ + + ]: 6 : for (sal_Int32 i = 0; i < i_pTypes->getLength(); ++i) {
317 [ + - ][ + - ]: 4 : i_rImpl.m_xManifest->addStatement(xURI.get(),
318 : : getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
319 [ + - ][ + - ]: 4 : (*i_pTypes)[i].get());
[ + - ][ + - ]
[ + - ]
320 : : }
321 : 72 : }
322 : 0 : } catch (const uno::RuntimeException &) {
323 : 0 : throw;
324 [ # # # ]: 0 : } catch (const uno::Exception & e) {
325 : : throw lang::WrappedTargetRuntimeException(
326 : : ::rtl::OUString(
327 [ # # # # : 0 : "addFile: exception"), /*this*/0, uno::makeAny(e));
# # ]
328 : : }
329 : 72 : }
330 : :
331 : : /** add content.xml or styles.xml to manifest */
332 : : static bool
333 : 70 : addContentOrStylesFileImpl(struct DocumentMetadataAccess_Impl & i_rImpl,
334 : : const ::rtl::OUString & i_rPath)
335 : : {
336 : 70 : uno::Reference<rdf::XURI> xType;
337 [ + + ][ + - ]: 70 : if (isContentFile(i_rPath)) {
338 [ + - ][ + - ]: 34 : xType.set(getURI<rdf::URIs::ODF_CONTENTFILE>(i_rImpl.m_xContext));
339 [ + - ][ + + ]: 36 : } else if (isStylesFile(i_rPath)) {
340 [ + - ][ + - ]: 34 : xType.set(getURI<rdf::URIs::ODF_STYLESFILE>(i_rImpl.m_xContext));
341 : : } else {
342 : 2 : return false;
343 : : }
344 [ + - ][ + - ]: 68 : addFile(i_rImpl, xType.get(), i_rPath);
[ + - ]
345 : 70 : return true;
346 : : }
347 : :
348 : : /** add metadata file to manifest */
349 : : static void
350 : 4 : addMetadataFileImpl(struct DocumentMetadataAccess_Impl & i_rImpl,
351 : : const ::rtl::OUString & i_rPath,
352 : : const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
353 : : {
354 : : addFile(i_rImpl,
355 : : getURI<rdf::URIs::PKG_METADATAFILE>(i_rImpl.m_xContext),
356 [ + - ]: 4 : i_rPath, &i_rTypes);
357 : 4 : }
358 : :
359 : : /** remove a file from the manifest */
360 : : static void
361 : 6 : removeFile(struct DocumentMetadataAccess_Impl & i_rImpl,
362 : : uno::Reference<rdf::XURI> const& i_xPart)
363 : : {
364 [ - + ][ # # ]: 6 : if (!i_xPart.is()) throw uno::RuntimeException();
365 : : try {
366 [ + - ][ + - ]: 12 : i_rImpl.m_xManifest->removeStatements(i_rImpl.m_xBaseURI.get(),
367 : : getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext),
368 [ + - ][ + - ]: 12 : i_xPart.get());
[ + - ][ + - ]
[ + - ]
369 [ + - ][ + - ]: 12 : i_rImpl.m_xManifest->removeStatements(i_xPart.get(),
370 [ + - ][ + - ]: 12 : getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext), 0);
[ + - ][ + - ]
371 : 0 : } catch (const uno::RuntimeException &) {
372 : 0 : throw;
373 [ # # # ]: 0 : } catch (const uno::Exception & e) {
374 : : throw lang::WrappedTargetRuntimeException(
375 : : ::rtl::OUString("removeFile: exception"),
376 [ # # # # : 0 : 0, uno::makeAny(e));
# # ]
377 : : }
378 : 6 : }
379 : :
380 : : static ::std::vector< uno::Reference< rdf::XURI > >
381 : 38 : getAllParts(struct DocumentMetadataAccess_Impl & i_rImpl)
382 : : {
383 : 38 : ::std::vector< uno::Reference< rdf::XURI > > ret;
384 : : try {
385 : : const uno::Reference<container::XEnumeration> xEnum(
386 [ + - ][ + - ]: 76 : i_rImpl.m_xManifest->getStatements( i_rImpl.m_xBaseURI.get(),
387 : 38 : getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext), 0),
388 [ + - ][ + - ]: 76 : uno::UNO_SET_THROW);
[ + - ][ + - ]
[ + - ]
389 [ + - ][ + - ]: 88 : while (xEnum->hasMoreElements()) {
[ + + ]
390 [ + - ]: 50 : rdf::Statement stmt;
391 [ + - ][ + - ]: 50 : if (!(xEnum->nextElement() >>= stmt)) {
[ + - ][ - + ]
392 [ # # ]: 0 : throw uno::RuntimeException();
393 : : }
394 : : const uno::Reference<rdf::XURI> xPart(stmt.Object,
395 [ + - ]: 50 : uno::UNO_QUERY);
396 [ - + ]: 50 : if (!xPart.is()) continue;
397 [ + - ][ - + ]: 100 : ret.push_back(xPart);
398 [ + - ][ + - ]: 100 : }
399 : 38 : return ret;
400 : 0 : } catch (const uno::RuntimeException &) {
401 : 0 : throw;
402 [ # # # ]: 0 : } catch (const uno::Exception & e) {
403 : : throw lang::WrappedTargetRuntimeException(
404 : : ::rtl::OUString("getAllParts: exception"),
405 [ # # # # : 0 : 0, uno::makeAny(e));
# # ]
406 : 0 : }
407 : : }
408 : :
409 : : static bool
410 : 50 : isPartOfType(struct DocumentMetadataAccess_Impl & i_rImpl,
411 : : uno::Reference<rdf::XURI> const & i_xPart,
412 : : uno::Reference<rdf::XURI> const & i_xType)
413 : : {
414 [ + - ][ - + ]: 50 : if (!i_xPart.is() || !i_xType.is()) throw uno::RuntimeException();
[ - + ][ # # ]
415 : : try {
416 : : const uno::Reference<container::XEnumeration> xEnum(
417 [ + - ][ + - ]: 100 : i_rImpl.m_xManifest->getStatements(i_xPart.get(),
418 : : getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
419 [ + - ]: 50 : i_xType.get()),
420 [ + - ][ + - ]: 100 : uno::UNO_SET_THROW);
[ + - ][ + - ]
[ + - ]
421 [ + - ][ + - ]: 50 : return (xEnum->hasMoreElements());
422 : 0 : } catch (const uno::RuntimeException &) {
423 : 0 : throw;
424 [ # # # ]: 0 : } catch (const uno::Exception & e) {
425 : : throw lang::WrappedTargetRuntimeException(
426 : : ::rtl::OUString("isPartOfType: exception"),
427 [ # # # # : 0 : 0, uno::makeAny(e));
# # ]
428 : : }
429 : : }
430 : :
431 : :
432 : : static ucb::InteractiveAugmentedIOException
433 : 16 : mkException( ::rtl::OUString const & i_rMessage,
434 : : ucb::IOErrorCode const i_ErrorCode,
435 : : ::rtl::OUString const & i_rUri, ::rtl::OUString const & i_rResource)
436 : : {
437 [ + - ]: 16 : ucb::InteractiveAugmentedIOException iaioe;
438 : 16 : iaioe.Message = i_rMessage;
439 : 16 : iaioe.Classification = task::InteractionClassification_ERROR;
440 : 16 : iaioe.Code = i_ErrorCode;
441 : :
442 : : const beans::PropertyValue uriProp(::rtl::OUString("Uri"),
443 [ + - ]: 16 : -1, uno::makeAny(i_rUri), static_cast<beans::PropertyState>(0));
444 : : const beans::PropertyValue rnProp(
445 : : ::rtl::OUString("ResourceName"),
446 [ + - ]: 16 : -1, uno::makeAny(i_rResource), static_cast<beans::PropertyState>(0));
447 : : iaioe.Arguments = ::comphelper::makeSequence(
448 [ + - ][ + - ]: 16 : uno::makeAny(uriProp), uno::makeAny(rnProp));
[ + - ][ + - ]
[ + - ]
449 : 16 : return iaioe;
450 : : }
451 : :
452 : : /** error handling policy.
453 : : <p>If a handler is given, ask it how to proceed:
454 : : <ul><li>(default:) cancel import, raise exception</li>
455 : : <li>ignore the error and continue</li>
456 : : <li>retry the action that led to the error</li></ul></p>
457 : : N.B.: must not be called before DMA is fully initalized!
458 : : @returns true iff caller should retry
459 : : */
460 : : static bool
461 : 0 : handleError( ucb::InteractiveAugmentedIOException const & i_rException,
462 : : const uno::Reference<task::XInteractionHandler> & i_xHandler)
463 : : {
464 [ # # ]: 0 : if (!i_xHandler.is()) {
465 : : throw lang::WrappedTargetException(::rtl::OUString(
466 : : "DocumentMetadataAccess::loadMetadataFromStorage: exception"),
467 [ # # ][ # # ]: 0 : /* *this*/ 0, uno::makeAny(i_rException));
[ # # ]
468 : : }
469 : :
470 : : ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest(
471 [ # # ][ # # ]: 0 : new ::comphelper::OInteractionRequest(uno::makeAny(i_rException)) );
472 : : ::rtl::Reference< ::comphelper::OInteractionRetry > pRetry(
473 [ # # ]: 0 : new ::comphelper::OInteractionRetry );
474 : : ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove(
475 [ # # ]: 0 : new ::comphelper::OInteractionApprove );
476 : : ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort(
477 [ # # ]: 0 : new ::comphelper::OInteractionAbort );
478 : :
479 [ # # ][ # # ]: 0 : pRequest->addContinuation( pApprove.get() );
[ # # ]
480 [ # # ][ # # ]: 0 : pRequest->addContinuation( pAbort.get() );
[ # # ]
481 : : // actually call the handler
482 [ # # ][ # # ]: 0 : i_xHandler->handle( pRequest.get() );
[ # # ][ # # ]
483 [ # # ]: 0 : if (pRetry->wasSelected()) {
484 : 0 : return true;
485 [ # # ]: 0 : } else if (pApprove->wasSelected()) {
486 : 0 : return false;
487 : : } else {
488 : : OSL_ENSURE(pAbort->wasSelected(), "no continuation selected?");
489 : : throw lang::WrappedTargetException(::rtl::OUString(
490 : : "DocumentMetadataAccess::loadMetadataFromStorage: exception"),
491 [ # # ][ # # ]: 0 : /* *this*/ 0, uno::makeAny(i_rException));
[ # # ]
492 : 0 : }
493 : : }
494 : :
495 : : /** check if storage has content.xml/styles.xml;
496 : : e.g. ODB files seem to only have content.xml */
497 : : static void
498 : 36 : collectFilesFromStorage(uno::Reference<embed::XStorage> const& i_xStorage,
499 : : ::rtl::OUString i_Path,
500 : : std::set< ::rtl::OUString > & o_rFiles)
501 : : {
502 [ + + ][ + - ]: 36 : static ::rtl::OUString content(s_content);
503 [ + + ][ + - ]: 36 : static ::rtl::OUString styles(s_styles );
504 : : try {
505 [ + - ][ + - ]: 68 : if (i_xStorage->hasByName(content) &&
[ + + ][ + - ]
[ + + ]
506 [ + - ][ + - ]: 32 : i_xStorage->isStreamElement(content))
507 : : {
508 [ + - ]: 32 : o_rFiles.insert(i_Path + content);
509 : : }
510 [ + - ][ + - ]: 68 : if (i_xStorage->hasByName(styles) &&
[ + + ][ + - ]
[ + + ]
511 [ + - ][ + - ]: 32 : i_xStorage->isStreamElement(styles))
512 : : {
513 [ + - ][ # # ]: 32 : o_rFiles.insert(i_Path + styles);
514 : : }
515 : 0 : } catch (const uno::Exception &) {
516 : : OSL_TRACE("collectFilesFromStorage: exception?");
517 : : }
518 : 36 : }
519 : :
520 : : /** import a metadata file into repository */
521 : : static void
522 : 48 : readStream(struct DocumentMetadataAccess_Impl & i_rImpl,
523 : : uno::Reference< embed::XStorage > const & i_xStorage,
524 : : ::rtl::OUString const & i_rPath,
525 : : ::rtl::OUString const & i_rBaseURI)
526 : : {
527 : 48 : ::rtl::OUString dir;
528 : 48 : ::rtl::OUString rest;
529 : : try {
530 [ # # ][ - + ]: 48 : if (!splitPath(i_rPath, dir, rest)) throw uno::RuntimeException();
531 [ + + ]: 48 : if (dir.isEmpty()) {
532 [ + - ][ + + ]: 40 : if (i_xStorage->isStreamElement(i_rPath)) {
[ + - ]
533 : : const uno::Reference<io::XStream> xStream(
534 [ + - ]: 24 : i_xStorage->openStreamElement(i_rPath,
535 [ + - ][ + - ]: 24 : embed::ElementModes::READ), uno::UNO_SET_THROW);
536 : : const uno::Reference<io::XInputStream> xInStream(
537 [ + - ][ + - ]: 24 : xStream->getInputStream(), uno::UNO_SET_THROW );
[ + - ]
538 : : const uno::Reference<rdf::XURI> xBaseURI(
539 [ + - ]: 24 : rdf::URI::create(i_rImpl.m_xContext, i_rBaseURI));
540 : : const uno::Reference<rdf::XURI> xURI(
541 : : rdf::URI::createNS(i_rImpl.m_xContext,
542 [ + - ]: 24 : i_rBaseURI, i_rPath));
543 [ + - ]: 24 : i_rImpl.m_xRepository->importGraph(rdf::FileFormat::RDF_XML,
544 [ + - ]: 24 : xInStream, xURI, xBaseURI);
545 : : } else {
546 : : throw mkException(::rtl::OUString(
547 : : "readStream: is not a stream"),
548 [ # # ]: 0 : ucb::IOErrorCode_NO_FILE, i_rBaseURI + i_rPath, i_rPath);
549 : : }
550 : : } else {
551 [ + - ][ + - ]: 8 : if (i_xStorage->isStorageElement(dir)) {
[ + - ]
552 : : const uno::Reference<embed::XStorage> xDir(
553 [ + - ]: 8 : i_xStorage->openStorageElement(dir,
554 [ + - ]: 8 : embed::ElementModes::READ));
555 : : const uno::Reference< beans::XPropertySet > xDirProps(xDir,
556 [ + - ]: 8 : uno::UNO_QUERY_THROW);
557 : : try {
558 : 8 : ::rtl::OUString mimeType;
559 [ + - ]: 8 : xDirProps->getPropertyValue(
560 [ + - ]: 8 : ::comphelper::MediaDescriptor::PROP_MEDIATYPE() )
561 [ + - ]: 8 : >>= mimeType;
562 [ - + ]: 8 : if (mimeType.matchAsciiL(s_odfmime, sizeof(s_odfmime) - 1))
563 : : {
564 : : OSL_TRACE("readStream: "
565 : : "refusing to recurse into embedded document");
566 : 32 : return;
567 [ + - ][ # # ]: 8 : }
568 [ # # ]: 0 : } catch (const uno::Exception &) { }
569 [ + - ]: 8 : ::rtl::OUStringBuffer buf(i_rBaseURI);
570 [ + - ][ + - ]: 8 : buf.append(dir).append(static_cast<sal_Unicode>('/'));
571 [ + - ][ + - ]: 8 : readStream(i_rImpl, xDir, rest, buf.makeStringAndClear() );
[ - + ][ + - ]
572 : : } else {
573 : : throw mkException(::rtl::OUString(
574 : : "readStream: is not a directory"),
575 [ # # ]: 32 : ucb::IOErrorCode_NO_DIRECTORY, i_rBaseURI + dir, dir);
576 : : }
577 : : }
578 : 32 : } catch (const container::NoSuchElementException & e) {
579 : : throw mkException(e.Message, ucb::IOErrorCode_NOT_EXISTING_PATH,
580 [ - + ]: 16 : i_rBaseURI + i_rPath, i_rPath);
581 : 0 : } catch (const io::IOException & e) {
582 : : throw mkException(e.Message, ucb::IOErrorCode_CANT_READ,
583 [ # # ]: 0 : i_rBaseURI + i_rPath, i_rPath);
584 [ - + - - ]: 16 : } catch (const rdf::ParseException & e) {
585 : : throw mkException(e.Message, ucb::IOErrorCode_WRONG_FORMAT,
586 [ # # ]: 0 : i_rBaseURI + i_rPath, i_rPath);
587 [ - + ][ + - ]: 48 : }
588 : : }
589 : :
590 : : /** import a metadata file into repository */
591 : : static void
592 : 4 : importFile(struct DocumentMetadataAccess_Impl & i_rImpl,
593 : : uno::Reference<embed::XStorage> const & i_xStorage,
594 : : ::rtl::OUString const & i_rBaseURI,
595 : : uno::Reference<task::XInteractionHandler> const & i_xHandler,
596 : : ::rtl::OUString i_rPath)
597 : : {
598 : : retry:
599 : : try {
600 [ + - ]: 4 : readStream(i_rImpl, i_xStorage, i_rPath, i_rBaseURI);
601 [ # # ]: 0 : } catch (const ucb::InteractiveAugmentedIOException & e) {
602 [ # # # # ]: 0 : if (handleError(e, i_xHandler)) goto retry;
603 : 0 : } catch (const uno::RuntimeException &) {
604 : 0 : throw;
605 [ # # # # ]: 0 : } catch (const uno::Exception & e) {
606 : : throw lang::WrappedTargetRuntimeException(
607 : : ::rtl::OUString("importFile: exception"),
608 [ # # # # : 0 : 0, uno::makeAny(e));
# # ]
609 : : }
610 : 4 : }
611 : :
612 : : /** actually write a metadata file to the storage */
613 : : static void
614 : 20 : exportStream(struct DocumentMetadataAccess_Impl & i_rImpl,
615 : : uno::Reference< embed::XStorage > const & i_xStorage,
616 : : uno::Reference<rdf::XURI> const & i_xGraphName,
617 : : ::rtl::OUString const & i_rFileName,
618 : : ::rtl::OUString const & i_rBaseURI)
619 : : {
620 : : const uno::Reference<io::XStream> xStream(
621 [ + - ]: 20 : i_xStorage->openStreamElement(i_rFileName,
622 : 20 : embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE),
623 [ + - ][ + - ]: 20 : uno::UNO_SET_THROW);
624 : : const uno::Reference< beans::XPropertySet > xStreamProps(xStream,
625 [ + - ]: 20 : uno::UNO_QUERY);
626 [ + - ]: 20 : if (xStreamProps.is()) { // this is NOT supported in FileSystemStorage
627 [ + - ]: 20 : xStreamProps->setPropertyValue(
628 : : ::rtl::OUString("MediaType"),
629 [ + - ][ + - ]: 20 : uno::makeAny(::rtl::OUString(s_rdfxml)));
630 : : }
631 : : const uno::Reference<io::XOutputStream> xOutStream(
632 [ + - ][ + - ]: 20 : xStream->getOutputStream(), uno::UNO_SET_THROW );
[ + - ]
633 : : const uno::Reference<rdf::XURI> xBaseURI(
634 [ + - ]: 20 : rdf::URI::create(i_rImpl.m_xContext, i_rBaseURI));
635 [ + - ]: 20 : i_rImpl.m_xRepository->exportGraph(rdf::FileFormat::RDF_XML,
636 [ + - ]: 20 : xOutStream, i_xGraphName, xBaseURI);
637 : 20 : }
638 : :
639 : : /** write a metadata file to the storage */
640 : : static void
641 : 28 : writeStream(struct DocumentMetadataAccess_Impl & i_rImpl,
642 : : uno::Reference< embed::XStorage > const & i_xStorage,
643 : : uno::Reference<rdf::XURI> const & i_xGraphName,
644 : : ::rtl::OUString const & i_rPath,
645 : : ::rtl::OUString const & i_rBaseURI)
646 : : {
647 : 28 : ::rtl::OUString dir;
648 : 28 : ::rtl::OUString rest;
649 [ # # ][ - + ]: 28 : if (!splitPath(i_rPath, dir, rest)) throw uno::RuntimeException();
650 : : try {
651 [ + + ]: 28 : if (dir.isEmpty()) {
652 : : exportStream(i_rImpl, i_xStorage, i_xGraphName, i_rPath,
653 [ + - ]: 20 : i_rBaseURI);
654 : : } else {
655 : : const uno::Reference<embed::XStorage> xDir(
656 [ + - ]: 8 : i_xStorage->openStorageElement(dir,
657 [ + - ]: 8 : embed::ElementModes::WRITE));
658 : : const uno::Reference< beans::XPropertySet > xDirProps(xDir,
659 [ + - ]: 8 : uno::UNO_QUERY_THROW);
660 : : try {
661 : 8 : ::rtl::OUString mimeType;
662 [ + - ]: 8 : xDirProps->getPropertyValue(
663 [ + - ]: 8 : ::comphelper::MediaDescriptor::PROP_MEDIATYPE() )
664 [ + - ]: 8 : >>= mimeType;
665 [ - + ]: 8 : if (mimeType.matchAsciiL(s_odfmime, sizeof(s_odfmime) - 1)) {
666 : : OSL_TRACE("writeStream: "
667 : : "refusing to recurse into embedded document");
668 : 28 : return;
669 [ + - ][ # # ]: 8 : }
670 [ # # ]: 0 : } catch (const uno::Exception &) { }
671 [ + - ]: 8 : ::rtl::OUStringBuffer buf(i_rBaseURI);
672 [ + - ][ + - ]: 8 : buf.append(dir).append(static_cast<sal_Unicode>('/'));
673 : : writeStream(i_rImpl, xDir, i_xGraphName, rest,
674 [ + - ][ + - ]: 8 : buf.makeStringAndClear());
675 : : uno::Reference<embed::XTransactedObject> const xTransaction(
676 [ + - ]: 8 : xDir, uno::UNO_QUERY);
677 [ + - ]: 8 : if (xTransaction.is()) {
678 [ + - ][ + - ]: 8 : xTransaction->commit();
679 [ - + ][ + - ]: 28 : }
680 : : }
681 : 0 : } catch (const uno::RuntimeException &) {
682 : 0 : throw;
683 [ # # # ]: 0 : } catch (const io::IOException &) {
684 : 0 : throw;
685 [ - + ][ + - ]: 28 : }
686 : : }
687 : :
688 : : static void
689 : 36 : initLoading(struct DocumentMetadataAccess_Impl & i_rImpl,
690 : : const uno::Reference< embed::XStorage > & i_xStorage,
691 : : const uno::Reference<rdf::XURI> & i_xBaseURI,
692 : : const uno::Reference<task::XInteractionHandler> & i_xHandler)
693 : : {
694 : : retry:
695 : : // clear old data
696 : 36 : i_rImpl.m_xManifest.clear();
697 : : // init BaseURI
698 [ + - ]: 36 : i_rImpl.m_xBaseURI = i_xBaseURI;
699 : :
700 : : // create repository
701 : 36 : i_rImpl.m_xRepository.clear();
702 : : i_rImpl.m_xRepository.set(rdf::Repository::create(i_rImpl.m_xContext),
703 [ + - ][ + - ]: 36 : uno::UNO_SET_THROW);
704 : :
705 : : const ::rtl::OUString manifest (
706 : 36 : ::rtl::OUString::createFromAscii(s_manifest));
707 [ + - ][ + - ]: 36 : const ::rtl::OUString baseURI( i_xBaseURI->getStringValue() );
708 : : // try to delay raising errors until after initialization is done
709 : 36 : uno::Any rterr;
710 [ + - ]: 36 : ucb::InteractiveAugmentedIOException iaioe;
711 : 36 : bool err(false);
712 : :
713 : : const uno::Reference <rdf::XURI> xManifest(
714 [ + - ]: 36 : getURIForStream(i_rImpl, manifest));
715 : : try {
716 [ + + ]: 36 : readStream(i_rImpl, i_xStorage, manifest, baseURI);
717 [ + - ]: 32 : } catch (const ucb::InteractiveAugmentedIOException & e) {
718 : : // no manifest.rdf: this is not an error in ODF < 1.2
719 [ - + ]: 16 : if (!(ucb::IOErrorCode_NOT_EXISTING_PATH == e.Code)) {
720 [ # # ]: 0 : iaioe = e;
721 : 0 : err = true;
722 : : }
723 [ - + - # : 16 : } catch (const uno::Exception & e) {
# ]
724 [ # # ]: 0 : rterr <<= e;
725 : : }
726 : :
727 : : // init manifest graph
728 : : const uno::Reference<rdf::XNamedGraph> xManifestGraph(
729 [ + - ][ + - ]: 36 : i_rImpl.m_xRepository->getGraph(xManifest));
730 : 36 : i_rImpl.m_xManifest.set(xManifestGraph.is() ? xManifestGraph :
731 [ + - ][ + - ]: 36 : i_rImpl.m_xRepository->createGraph(xManifest), uno::UNO_SET_THROW);
[ + - ][ + + ]
732 : : const uno::Reference<container::XEnumeration> xEnum(
733 [ + - ]: 36 : i_rImpl.m_xManifest->getStatements(0,
734 : : getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
735 [ + - ][ + - ]: 36 : getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get()));
[ + - ][ + - ]
[ + - ][ + - ]
736 : :
737 : : // document statement
738 [ + - ][ + - ]: 72 : i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
739 : : getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
740 [ + - ][ + - ]: 72 : getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get());
[ + - ][ + - ]
[ + - ][ + - ]
741 : :
742 : : OSL_ENSURE(i_rImpl.m_xBaseURI.is(), "base URI is null");
743 : : OSL_ENSURE(i_rImpl.m_xRepository.is(), "repository is null");
744 : : OSL_ENSURE(i_rImpl.m_xManifest.is(), "manifest is null");
745 : :
746 [ - + ]: 36 : if (rterr.hasValue()) {
747 : : throw lang::WrappedTargetRuntimeException(
748 : : ::rtl::OUString(
749 : : "DocumentMetadataAccess::loadMetadataFromStorage: "
750 [ # # ][ # # ]: 0 : "exception"), 0, rterr);
751 : : }
752 : :
753 [ - + ]: 36 : if (err) {
754 [ # # ][ # # ]: 36 : if (handleError(iaioe, i_xHandler)) goto retry;
755 [ - + ][ - + ]: 36 : }
[ - + ][ + - ]
[ - + ][ - + ]
[ - + ][ + - ]
756 : 36 : }
757 : :
758 : : /** init Impl struct */
759 : 18 : static void init(struct DocumentMetadataAccess_Impl & i_rImpl)
760 : : {
761 : : try {
762 : :
763 [ + - ]: 18 : i_rImpl.m_xManifest.set(i_rImpl.m_xRepository->createGraph(
764 : : getURIForStream(i_rImpl,
765 : 18 : ::rtl::OUString::createFromAscii(s_manifest))),
766 [ + - ][ + - ]: 18 : uno::UNO_SET_THROW);
[ + - ]
767 : :
768 : : // insert the document statement
769 [ + - ][ + - ]: 36 : i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
770 : : getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
771 [ + - ][ + - ]: 36 : getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get());
[ + - ][ + - ]
[ + - ][ + - ]
772 [ # # ]: 0 : } catch (const uno::Exception & e) {
773 : : throw lang::WrappedTargetRuntimeException(
774 : : ::rtl::OUString("init: unexpected exception"), 0,
775 [ # # # # : 0 : uno::makeAny(e));
# # ]
776 : : }
777 : :
778 : : // add top-level content files
779 [ - + ]: 18 : if (!addContentOrStylesFileImpl(i_rImpl,
780 [ + - ]: 18 : ::rtl::OUString::createFromAscii(s_content))) {
781 [ # # ]: 0 : throw uno::RuntimeException();
782 : : }
783 [ - + ]: 18 : if (!addContentOrStylesFileImpl(i_rImpl,
784 [ + - ]: 18 : ::rtl::OUString::createFromAscii(s_styles))) {
785 [ # # ]: 0 : throw uno::RuntimeException();
786 : : }
787 : 18 : }
788 : :
789 : :
790 : :
791 : 40 : DocumentMetadataAccess::DocumentMetadataAccess(
792 : : uno::Reference< uno::XComponentContext > const & i_xContext,
793 : : const IXmlIdRegistrySupplier & i_rRegistrySupplier)
794 [ + - ][ + - ]: 40 : : m_pImpl(new DocumentMetadataAccess_Impl(i_xContext, i_rRegistrySupplier))
[ + - ]
795 : : {
796 : : // no initalization: must call loadFrom...
797 : 40 : }
798 : :
799 : 18 : DocumentMetadataAccess::DocumentMetadataAccess(
800 : : uno::Reference< uno::XComponentContext > const & i_xContext,
801 : : const IXmlIdRegistrySupplier & i_rRegistrySupplier,
802 : : ::rtl::OUString const & i_rURI)
803 [ + - ][ + - ]: 18 : : m_pImpl(new DocumentMetadataAccess_Impl(i_xContext, i_rRegistrySupplier))
[ + - ]
804 : : {
805 : : OSL_ENSURE(!i_rURI.isEmpty(), "DMA::DMA: no URI given!");
806 : : OSL_ENSURE(i_rURI.endsWithAsciiL("/", 1), "DMA::DMA: URI without / given!");
807 [ # # ][ - + ]: 18 : if (!i_rURI.endsWithAsciiL("/", 1)) throw uno::RuntimeException();
808 [ + - ][ + - ]: 18 : m_pImpl->m_xBaseURI.set(rdf::URI::create(m_pImpl->m_xContext, i_rURI));
809 : 36 : m_pImpl->m_xRepository.set(rdf::Repository::create(m_pImpl->m_xContext),
810 [ + - + - ]: 36 : uno::UNO_SET_THROW);
811 : :
812 : : // init repository
813 [ + - ]: 18 : init(*m_pImpl);
814 : :
815 : : OSL_ENSURE(m_pImpl->m_xBaseURI.is(), "base URI is null");
816 : : OSL_ENSURE(m_pImpl->m_xRepository.is(), "repository is null");
817 : : OSL_ENSURE(m_pImpl->m_xManifest.is(), "manifest is null");
818 : 18 : }
819 : :
820 [ + - ]: 58 : DocumentMetadataAccess::~DocumentMetadataAccess()
821 : : {
822 [ - + ]: 116 : }
823 : :
824 : : // ::com::sun::star::rdf::XRepositorySupplier:
825 : : uno::Reference< rdf::XRepository > SAL_CALL
826 : 190 : DocumentMetadataAccess::getRDFRepository() throw (uno::RuntimeException)
827 : : {
828 : : OSL_ENSURE(m_pImpl->m_xRepository.is(), "repository not initialized");
829 : 190 : return m_pImpl->m_xRepository;
830 : : }
831 : :
832 : : // ::com::sun::star::rdf::XNode:
833 : : ::rtl::OUString SAL_CALL
834 : 670 : DocumentMetadataAccess::getStringValue() throw (uno::RuntimeException)
835 : : {
836 : 670 : return m_pImpl->m_xBaseURI->getStringValue();
837 : : }
838 : :
839 : : // ::com::sun::star::rdf::XURI:
840 : : ::rtl::OUString SAL_CALL
841 : 0 : DocumentMetadataAccess::getNamespace() throw (uno::RuntimeException)
842 : : {
843 : 0 : return m_pImpl->m_xBaseURI->getNamespace();
844 : : }
845 : :
846 : : ::rtl::OUString SAL_CALL
847 : 0 : DocumentMetadataAccess::getLocalName() throw (uno::RuntimeException)
848 : : {
849 : 0 : return m_pImpl->m_xBaseURI->getLocalName();
850 : : }
851 : :
852 : : // ::com::sun::star::rdf::XDocumentMetadataAccess:
853 : : uno::Reference< rdf::XMetadatable > SAL_CALL
854 : 2 : DocumentMetadataAccess::getElementByMetadataReference(
855 : : const ::com::sun::star::beans::StringPair & i_rReference)
856 : : throw (uno::RuntimeException)
857 : : {
858 : : const IXmlIdRegistry * pReg(
859 : 2 : m_pImpl->m_rXmlIdRegistrySupplier.GetXmlIdRegistry() );
860 [ - + ]: 2 : if (!pReg) {
861 : : throw uno::RuntimeException(::rtl::OUString(
862 [ # # ][ # # ]: 0 : "DocumentMetadataAccess::getElementByXmlId: no registry"), *this);
863 : : }
864 : 2 : return pReg->GetElementByMetadataReference(i_rReference);
865 : : }
866 : :
867 : : uno::Reference< rdf::XMetadatable > SAL_CALL
868 : 4 : DocumentMetadataAccess::getElementByURI(
869 : : const uno::Reference< rdf::XURI > & i_xURI )
870 : : throw (uno::RuntimeException, lang::IllegalArgumentException)
871 : : {
872 [ + + ]: 4 : if (!i_xURI.is()) {
873 : : throw lang::IllegalArgumentException(::rtl::OUString(
874 [ + - ][ + - ]: 2 : "DocumentMetadataAccess::getElementByURI: URI is null"), *this, 0);
875 : : }
876 : :
877 [ + - ][ + - ]: 2 : const ::rtl::OUString baseURI( m_pImpl->m_xBaseURI->getStringValue() );
878 [ + - ][ + - ]: 2 : const ::rtl::OUString name( i_xURI->getStringValue() );
879 [ - + ]: 2 : if (!name.match(baseURI)) {
880 [ # # ]: 0 : return 0;
881 : : }
882 : 2 : const ::rtl::OUString relName( name.copy(baseURI.getLength()) );
883 : 2 : ::rtl::OUString path;
884 : 2 : ::rtl::OUString idref;
885 [ - + ][ + - ]: 2 : if (!splitXmlId(relName, path, idref)) {
886 [ # # ]: 0 : return 0;
887 : : }
888 : :
889 [ + - ]: 4 : return getElementByMetadataReference( beans::StringPair(path, idref) );
890 : : }
891 : :
892 : :
893 : : uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
894 : 4 : DocumentMetadataAccess::getMetadataGraphsWithType(
895 : : const uno::Reference<rdf::XURI> & i_xType)
896 : : throw (uno::RuntimeException, lang::IllegalArgumentException)
897 : : {
898 [ + + ]: 4 : if (!i_xType.is()) {
899 : : throw lang::IllegalArgumentException(::rtl::OUString(
900 : : "DocumentMetadataAccess::getMetadataGraphsWithType: "
901 [ + - ][ + - ]: 2 : "type is null"), *this, 0);
902 : : }
903 : :
904 [ + - ]: 2 : ::comphelper::SequenceAsVector< uno::Reference< rdf::XURI > > ret;
905 : : const ::std::vector< uno::Reference< rdf::XURI > > parts(
906 [ + - ]: 2 : getAllParts(*m_pImpl) );
907 : : ::std::remove_copy_if(parts.begin(), parts.end(),
908 : : ::std::back_inserter(ret),
909 : : ::boost::bind(
910 : : ::std::logical_not<bool>(),
911 [ + - ][ + - ]: 2 : ::boost::bind(&isPartOfType, ::boost::ref(*m_pImpl), _1, i_xType) ));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
912 [ + - ]: 4 : return ret.getAsConstList();
913 : : }
914 : :
915 : : uno::Reference<rdf::XURI> SAL_CALL
916 : 24 : DocumentMetadataAccess::addMetadataFile(const ::rtl::OUString & i_rFileName,
917 : : const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
918 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
919 : : container::ElementExistException)
920 : : {
921 [ + + ]: 24 : if (!isFileNameValid(i_rFileName)) {
922 : : throw lang::IllegalArgumentException(::rtl::OUString(
923 : : "DocumentMetadataAccess::addMetadataFile: invalid FileName"),
924 [ + - ][ + - ]: 12 : *this, 0);
925 : : }
926 [ + + ]: 12 : if (isReservedFile(i_rFileName)) {
927 : : throw lang::IllegalArgumentException(::rtl::OUString(
928 : : "DocumentMetadataAccess::addMetadataFile:"
929 [ + - ][ + - ]: 8 : "invalid FileName: reserved"), *this, 0);
930 : : }
931 [ + + ]: 6 : for (sal_Int32 i = 0; i < i_rTypes.getLength(); ++i) {
932 [ - + ]: 2 : if (!i_rTypes[i].is()) {
933 : : throw lang::IllegalArgumentException(
934 : : ::rtl::OUString(
935 : : "DocumentMetadataAccess::addMetadataFile: "
936 [ # # ][ # # ]: 0 : "null type"), *this, 2);
937 : : }
938 : : }
939 : :
940 : : const uno::Reference<rdf::XURI> xGraphName(
941 : 4 : getURIForStream(*m_pImpl, i_rFileName) );
942 : :
943 : : try {
944 [ + - ][ + - ]: 4 : m_pImpl->m_xRepository->createGraph(xGraphName);
945 [ # # ]: 0 : } catch (const rdf::RepositoryException & e) {
946 : : throw lang::WrappedTargetRuntimeException(
947 : : ::rtl::OUString(
948 : : "DocumentMetadataAccess::addMetadataFile: exception"),
949 [ # # # # : 0 : *this, uno::makeAny(e));
# # ]
950 : : // note: all other exceptions are propagated
951 : : }
952 : :
953 [ + - ]: 4 : addMetadataFileImpl(*m_pImpl, i_rFileName, i_rTypes);
954 : 4 : return xGraphName;
955 : : }
956 : :
957 : : uno::Reference<rdf::XURI> SAL_CALL
958 : 10 : DocumentMetadataAccess::importMetadataFile(::sal_Int16 i_Format,
959 : : const uno::Reference< io::XInputStream > & i_xInStream,
960 : : const ::rtl::OUString & i_rFileName,
961 : : const uno::Reference< rdf::XURI > & i_xBaseURI,
962 : : const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
963 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
964 : : datatransfer::UnsupportedFlavorException,
965 : : container::ElementExistException, rdf::ParseException, io::IOException)
966 : : {
967 [ + + ]: 10 : if (!isFileNameValid(i_rFileName)) {
968 : : throw lang::IllegalArgumentException(::rtl::OUString(
969 : : "DocumentMetadataAccess::importMetadataFile: invalid FileName"),
970 [ + - ][ + - ]: 2 : *this, 0);
971 : : }
972 [ + + ]: 8 : if (isReservedFile(i_rFileName)) {
973 : : throw lang::IllegalArgumentException(::rtl::OUString(
974 : : "DocumentMetadataAccess::importMetadataFile:"
975 [ + - ][ + - ]: 2 : "invalid FileName: reserved"), *this, 0);
976 : : }
977 [ - + ]: 6 : for (sal_Int32 i = 0; i < i_rTypes.getLength(); ++i) {
978 [ # # ]: 0 : if (!i_rTypes[i].is()) {
979 : : throw lang::IllegalArgumentException(
980 : : ::rtl::OUString(
981 : : "DocumentMetadataAccess::importMetadataFile: null type"),
982 [ # # ][ # # ]: 0 : *this, 5);
983 : : }
984 : : }
985 : :
986 : : const uno::Reference<rdf::XURI> xGraphName(
987 : 6 : getURIForStream(*m_pImpl, i_rFileName) );
988 : :
989 : : try {
990 [ + - ]: 6 : m_pImpl->m_xRepository->importGraph(
991 [ - + ]: 6 : i_Format, i_xInStream, xGraphName, i_xBaseURI);
992 [ + - ]: 6 : } catch (const rdf::RepositoryException & e) {
993 : : throw lang::WrappedTargetRuntimeException(
994 : : ::rtl::OUString(
995 : : "DocumentMetadataAccess::importMetadataFile: "
996 [ # # # # : 0 : "RepositoryException"), *this, uno::makeAny(e));
# # ]
997 : : // note: all other exceptions are propagated
998 : : }
999 : :
1000 : : // add to manifest
1001 [ # # ]: 0 : addMetadataFileImpl(*m_pImpl, i_rFileName, i_rTypes);
1002 : 6 : return xGraphName;
1003 : : }
1004 : :
1005 : : void SAL_CALL
1006 : 4 : DocumentMetadataAccess::removeMetadataFile(
1007 : : const uno::Reference< rdf::XURI > & i_xGraphName)
1008 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
1009 : : container::NoSuchElementException)
1010 : : {
1011 : : try {
1012 [ + - ][ + - ]: 4 : m_pImpl->m_xRepository->destroyGraph(i_xGraphName);
1013 [ # # ]: 0 : } catch (const rdf::RepositoryException & e) {
1014 : : throw lang::WrappedTargetRuntimeException(
1015 : : ::rtl::OUString(
1016 : : "DocumentMetadataAccess::removeMetadataFile: "
1017 [ # # # # : 0 : "RepositoryException"), *this, uno::makeAny(e));
# # ]
1018 : : // note: all other exceptions are propagated
1019 : : }
1020 : :
1021 : : // remove file from manifest
1022 [ + - ]: 2 : removeFile(*m_pImpl, i_xGraphName.get());
1023 : 2 : }
1024 : :
1025 : : void SAL_CALL
1026 : 10 : DocumentMetadataAccess::addContentOrStylesFile(
1027 : : const ::rtl::OUString & i_rFileName)
1028 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
1029 : : container::ElementExistException)
1030 : : {
1031 [ + + ]: 10 : if (!isFileNameValid(i_rFileName)) {
1032 : : throw lang::IllegalArgumentException(::rtl::OUString(
1033 : : "DocumentMetadataAccess::addContentOrStylesFile: "
1034 [ + - ][ + - ]: 4 : "invalid FileName"), *this, 0);
1035 : : }
1036 : :
1037 [ + + ]: 6 : if (!addContentOrStylesFileImpl(*m_pImpl, i_rFileName)) {
1038 : : throw lang::IllegalArgumentException(::rtl::OUString(
1039 : : "DocumentMetadataAccess::addContentOrStylesFile: "
1040 : : "invalid FileName: must end with content.xml or styles.xml"),
1041 [ + - ][ + - ]: 2 : *this, 0);
1042 : : }
1043 : 4 : }
1044 : :
1045 : : void SAL_CALL
1046 : 6 : DocumentMetadataAccess::removeContentOrStylesFile(
1047 : : const ::rtl::OUString & i_rFileName)
1048 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
1049 : : container::NoSuchElementException)
1050 : : {
1051 [ + + ]: 6 : if (!isFileNameValid(i_rFileName)) {
1052 : : throw lang::IllegalArgumentException(::rtl::OUString(
1053 : : "DocumentMetadataAccess::removeContentOrStylesFile: "
1054 [ + - ][ + - ]: 2 : "invalid FileName"), *this, 0);
1055 : : }
1056 : :
1057 : : try {
1058 : : const uno::Reference<rdf::XURI> xPart(
1059 [ + - ]: 4 : getURIForStream(*m_pImpl, i_rFileName) );
1060 : : const uno::Reference<container::XEnumeration> xEnum(
1061 [ + - ][ + - ]: 8 : m_pImpl->m_xManifest->getStatements( m_pImpl->m_xBaseURI.get(),
1062 : 4 : getURI<rdf::URIs::PKG_HASPART>(m_pImpl->m_xContext),
1063 [ + - ]: 4 : xPart.get()),
1064 [ + - + - ]: 12 : uno::UNO_SET_THROW);
[ + - ][ + - ]
[ + - ]
1065 [ + - ][ - + ]: 4 : if (!xEnum->hasMoreElements()) {
[ + - ]
1066 : : throw container::NoSuchElementException(
1067 : : ::rtl::OUString(
1068 : : "DocumentMetadataAccess::removeContentOrStylesFile: "
1069 : : "cannot find stream in manifest graph: ") + i_rFileName,
1070 [ # # ][ # # ]: 0 : *this);
1071 : : }
1072 : :
1073 : : // remove file from manifest
1074 [ + - ]: 4 : removeFile(*m_pImpl, xPart);
1075 : :
1076 : 0 : } catch (const uno::RuntimeException &) {
1077 : 0 : throw;
1078 [ # # # ]: 0 : } catch (const uno::Exception & e) {
1079 : : throw lang::WrappedTargetRuntimeException(
1080 : : ::rtl::OUString(
1081 : : "DocumentMetadataAccess::removeContentOrStylesFile: exception"),
1082 [ # # # # : 0 : *this, uno::makeAny(e));
# # ]
1083 : : }
1084 : 4 : }
1085 : :
1086 : 38 : void SAL_CALL DocumentMetadataAccess::loadMetadataFromStorage(
1087 : : const uno::Reference< embed::XStorage > & i_xStorage,
1088 : : const uno::Reference<rdf::XURI> & i_xBaseURI,
1089 : : const uno::Reference<task::XInteractionHandler> & i_xHandler)
1090 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
1091 : : lang::WrappedTargetException)
1092 : : {
1093 [ + + ]: 38 : if (!i_xStorage.is()) {
1094 : : throw lang::IllegalArgumentException(::rtl::OUString(
1095 : : "DocumentMetadataAccess::loadMetadataFromStorage: "
1096 [ + - ][ + - ]: 2 : "storage is null"), *this, 0);
1097 : : }
1098 [ - + ]: 36 : if (!i_xBaseURI.is()) {
1099 : : throw lang::IllegalArgumentException(::rtl::OUString(
1100 : : "DocumentMetadataAccess::loadMetadataFromStorage: "
1101 [ # # ][ # # ]: 0 : "base URI is null"), *this, 1);
1102 : : }
1103 [ + - ][ + - ]: 36 : const ::rtl::OUString baseURI( i_xBaseURI->getStringValue());
1104 [ - + ]: 36 : if (baseURI.indexOf('#') >= 0) {
1105 : : throw lang::IllegalArgumentException(::rtl::OUString(
1106 : : "DocumentMetadataAccess::loadMetadataFromStorage: "
1107 [ # # ][ # # ]: 0 : "base URI not absolute"), *this, 1);
1108 : : }
1109 [ + - ][ - + ]: 36 : if (baseURI.isEmpty() || !baseURI.endsWithAsciiL("/", 1)) {
[ - + ]
1110 : : throw lang::IllegalArgumentException(::rtl::OUString(
1111 : : "DocumentMetadataAccess::loadMetadataFromStorage: "
1112 [ # # ][ # # ]: 0 : "base URI does not end with slash"), *this, 1);
1113 : : }
1114 : :
1115 [ + - ]: 36 : initLoading(*m_pImpl, i_xStorage, i_xBaseURI, i_xHandler);
1116 : :
1117 [ + - ]: 36 : std::set< ::rtl::OUString > StgFiles;
1118 : : collectFilesFromStorage(i_xStorage,
1119 [ + - ]: 36 : ::rtl::OUString(""), StgFiles);
1120 : :
1121 [ + - ]: 36 : std::vector< ::rtl::OUString > MfstMetadataFiles;
1122 : :
1123 : : try {
1124 : : const ::std::vector< uno::Reference< rdf::XURI > > parts(
1125 [ + - ]: 36 : getAllParts(*m_pImpl) );
1126 : : const uno::Reference<rdf::XURI> xContentFile(
1127 [ + - ]: 36 : getURI<rdf::URIs::ODF_CONTENTFILE>(m_pImpl->m_xContext));
1128 : : const uno::Reference<rdf::XURI> xStylesFile(
1129 [ + - ]: 36 : getURI<rdf::URIs::ODF_STYLESFILE>(m_pImpl->m_xContext));
1130 : : const uno::Reference<rdf::XURI> xMetadataFile(
1131 [ + - ]: 36 : getURI<rdf::URIs::PKG_METADATAFILE>(m_pImpl->m_xContext));
1132 : 36 : const sal_Int32 len( baseURI.getLength() );
1133 : : const ::rtl::OUString manifest (
1134 : 36 : ::rtl::OUString::createFromAscii(s_manifest));
1135 [ + - ][ + + ]: 160 : for (::std::vector< uno::Reference< rdf::XURI > >::const_iterator it
1136 : 36 : = parts.begin();
1137 : 80 : it != parts.end(); ++it) {
1138 [ + - ][ + - ]: 44 : const ::rtl::OUString name((*it)->getStringValue());
1139 [ - + ]: 44 : if (!name.match(baseURI)) {
1140 : : OSL_TRACE("loadMetadataFromStorage: graph not in document: %s",
1141 : : ::rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)
1142 : : .getStr());
1143 : 0 : continue;
1144 : : }
1145 : 44 : const ::rtl::OUString relName( name.copy(len) );
1146 [ - + ]: 44 : if (relName == manifest) {
1147 : : OSL_TRACE("loadMetadataFromStorage: "
1148 : : "found ourselves a recursive manifest!");
1149 : 0 : continue;
1150 : : }
1151 : : // remove found items from StgFiles
1152 [ + - ]: 44 : StgFiles.erase(relName);
1153 [ + - ][ + + ]: 44 : if (isContentFile(relName)) {
1154 [ + - ][ - + ]: 20 : if (!isPartOfType(*m_pImpl, *it, xContentFile)) {
1155 : : const uno::Reference <rdf::XURI> xName(
1156 [ # # ]: 0 : getURIForStream(*m_pImpl, relName) );
1157 : : // add missing type statement
1158 [ # # ][ # # ]: 0 : m_pImpl->m_xManifest->addStatement(xName.get(),
1159 : 0 : getURI<rdf::URIs::RDF_TYPE>(m_pImpl->m_xContext),
1160 [ # # ]: 0 : xContentFile.get());
[ # # # # ]
[ # # ][ # # ]
1161 : : }
1162 [ + - ][ + + ]: 24 : } else if (isStylesFile(relName)) {
1163 [ + - ][ - + ]: 20 : if (!isPartOfType(*m_pImpl, *it, xStylesFile)) {
1164 : : const uno::Reference <rdf::XURI> xName(
1165 [ # # ]: 0 : getURIForStream(*m_pImpl, relName) );
1166 : : // add missing type statement
1167 [ # # ][ # # ]: 0 : m_pImpl->m_xManifest->addStatement(xName.get(),
1168 : 0 : getURI<rdf::URIs::RDF_TYPE>(m_pImpl->m_xContext),
1169 [ # # ]: 0 : xStylesFile.get());
[ # # # # ]
[ # # ][ # # ]
1170 : : }
1171 [ + - ][ + - ]: 4 : } else if (isReservedFile(relName)) {
1172 : : OSL_TRACE("loadMetadataFromStorage: "
1173 : : "reserved file name in manifest");
1174 : : } else {
1175 [ + - ][ + - ]: 4 : if (isPartOfType(*m_pImpl, *it, xMetadataFile)) {
1176 [ + - ]: 44 : MfstMetadataFiles.push_back(relName);
1177 : : }
1178 : : // do not add statement for MetadataFile; it could be
1179 : : // something else! just ignore it...
1180 : : }
1181 [ - + ][ + - ]: 80 : }
1182 : 0 : } catch (const uno::RuntimeException &) {
1183 : 0 : throw;
1184 [ # # # ]: 0 : } catch (const uno::Exception & e) {
1185 : : throw lang::WrappedTargetRuntimeException(
1186 : : ::rtl::OUString(
1187 : : "DocumentMetadataAccess::loadMetadataFromStorage: "
1188 [ # # # # : 0 : "exception"), *this, uno::makeAny(e));
# # ]
1189 : : }
1190 : :
1191 : : std::for_each(StgFiles.begin(), StgFiles.end(),
1192 [ + - ][ + - ]: 36 : boost::bind(addContentOrStylesFileImpl, boost::ref(*m_pImpl), _1));
[ + - ]
1193 : :
1194 : : std::for_each(MfstMetadataFiles.begin(), MfstMetadataFiles.end(),
1195 : 36 : boost::bind(importFile, boost::ref(*m_pImpl),
1196 [ + - ][ + - ]: 74 : i_xStorage, baseURI, i_xHandler, _1));
[ + - ][ + - ]
[ + - ]
1197 : 36 : }
1198 : :
1199 : 18 : void SAL_CALL DocumentMetadataAccess::storeMetadataToStorage(
1200 : : const uno::Reference< embed::XStorage > & i_xStorage)
1201 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
1202 : : lang::WrappedTargetException)
1203 : : {
1204 [ + + ]: 18 : if (!i_xStorage.is()) {
1205 : : throw lang::IllegalArgumentException(::rtl::OUString(
1206 : : "DocumentMetadataAccess::storeMetadataToStorage: "
1207 [ + - ][ + - ]: 2 : "storage is null"), *this, 0);
1208 : : }
1209 : :
1210 : : // export manifest
1211 : : const ::rtl::OUString manifest (
1212 : 16 : ::rtl::OUString::createFromAscii(s_manifest));
1213 : : const uno::Reference <rdf::XURI> xManifest(
1214 [ + - ]: 16 : getURIForStream(*m_pImpl, manifest) );
1215 [ + - ][ + - ]: 16 : const ::rtl::OUString baseURI( m_pImpl->m_xBaseURI->getStringValue() );
1216 : : try {
1217 [ + - ]: 16 : writeStream(*m_pImpl, i_xStorage, xManifest, manifest, baseURI);
1218 : 0 : } catch (const uno::RuntimeException &) {
1219 : 0 : throw;
1220 : 0 : } catch (const io::IOException & e) {
1221 : : throw lang::WrappedTargetException( ::rtl::OUString(
1222 [ # # # # : 0 : "storeMetadataToStorage: IO exception"), *this, uno::makeAny(e));
# # ]
1223 [ # # # # ]: 0 : } catch (const uno::Exception & e) {
1224 : : throw lang::WrappedTargetRuntimeException(
1225 : : ::rtl::OUString(
1226 [ # # # # : 0 : "storeMetadataToStorage: exception"), *this, uno::makeAny(e));
# # ]
1227 : : }
1228 : :
1229 : : // export metadata streams
1230 : : try {
1231 : : const uno::Sequence<uno::Reference<rdf::XURI> > graphs(
1232 [ + - ][ + - ]: 16 : m_pImpl->m_xRepository->getGraphNames());
1233 : 16 : const sal_Int32 len( baseURI.getLength() );
1234 [ + + ]: 36 : for (sal_Int32 i = 0; i < graphs.getLength(); ++i) {
1235 : 20 : const uno::Reference<rdf::XURI> xName(graphs[i]);
1236 [ + - ][ + - ]: 20 : const ::rtl::OUString name(xName->getStringValue());
1237 [ - + ]: 20 : if (!name.match(baseURI)) {
1238 : : OSL_TRACE("storeMetadataToStorage: graph not in document: %s",
1239 : : ::rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)
1240 : : .getStr());
1241 : 0 : continue;
1242 : : }
1243 : 20 : const ::rtl::OUString relName( name.copy(len) );
1244 [ + + ]: 20 : if (relName == manifest) {
1245 : 16 : continue;
1246 : : }
1247 [ + - ][ + - ]: 4 : if (!isFileNameValid(relName) || isReservedFile(relName)) {
[ + - ][ - + ]
[ - + ]
1248 : : OSL_TRACE("storeMetadataToStorage: invalid file name: %s",
1249 : : ::rtl::OUStringToOString(relName, RTL_TEXTENCODING_UTF8)
1250 : : .getStr());
1251 : 0 : continue;
1252 : : }
1253 : : try {
1254 [ + - ][ + + ]: 24 : writeStream(*m_pImpl, i_xStorage, xName, relName, baseURI);
1255 : 0 : } catch (const uno::RuntimeException &) {
1256 : 0 : throw;
1257 : 0 : } catch (const io::IOException & e) {
1258 : : throw lang::WrappedTargetException(
1259 : : ::rtl::OUString(
1260 : : "storeMetadataToStorage: IO exception"),
1261 [ # # # # : 0 : *this, uno::makeAny(e));
# # ]
1262 [ # # # # ]: 0 : } catch (const uno::Exception & e) {
1263 : : throw lang::WrappedTargetRuntimeException(
1264 : : ::rtl::OUString(
1265 : : "storeMetadataToStorage: exception"),
1266 [ # # # # : 0 : *this, uno::makeAny(e));
# # ]
1267 : : }
1268 [ + + ][ + + ]: 56 : }
[ + - ]
1269 [ # # ]: 0 : } catch (const rdf::RepositoryException & e) {
1270 : : throw lang::WrappedTargetRuntimeException(
1271 : : ::rtl::OUString(
1272 [ # # # # : 0 : "storeMetadataToStorage: exception"), *this, uno::makeAny(e));
# # ]
1273 : 18 : }
1274 : 16 : }
1275 : :
1276 : : void SAL_CALL
1277 : 8 : DocumentMetadataAccess::loadMetadataFromMedium(
1278 : : const uno::Sequence< beans::PropertyValue > & i_rMedium)
1279 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
1280 : : lang::WrappedTargetException)
1281 : : {
1282 : 8 : uno::Reference<io::XInputStream> xIn;
1283 [ + - ]: 8 : ::comphelper::MediaDescriptor md(i_rMedium);
1284 : 8 : ::rtl::OUString URL;
1285 [ + - ][ + - ]: 8 : md[ ::comphelper::MediaDescriptor::PROP_URL() ] >>= URL;
1286 : 8 : ::rtl::OUString BaseURL;
1287 [ + - ][ + - ]: 8 : md[ ::comphelper::MediaDescriptor::PROP_DOCUMENTBASEURL() ] >>= BaseURL;
1288 [ + + ][ + - ]: 8 : if (md.addInputStream()) {
1289 [ + - ][ + - ]: 6 : md[ ::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] >>= xIn;
[ + - ]
1290 : : }
1291 [ + + ][ + - ]: 8 : if (!xIn.is() && URL.isEmpty()) {
[ + + ]
1292 : : throw lang::IllegalArgumentException(::rtl::OUString(
1293 : : "DocumentMetadataAccess::loadMetadataFromMedium: "
1294 [ + - ][ + - ]: 2 : "inalid medium: no URL, no input stream"), *this, 0);
1295 : : }
1296 : 6 : uno::Reference<embed::XStorage> xStorage;
1297 : : try {
1298 : : const uno::Reference<lang::XMultiServiceFactory> xMsf (
1299 [ + - ][ + - ]: 6 : m_pImpl->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
[ + - ]
1300 [ + - ]: 6 : if (xIn.is()) {
1301 : : xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream(
1302 [ + - ][ + - ]: 6 : xIn, xMsf);
1303 : : } else { // fallback to url
1304 : : xStorage = ::comphelper::OStorageHelper::GetStorageFromURL2(
1305 [ # # ][ # # ]: 0 : URL, embed::ElementModes::READ, xMsf);
1306 : 6 : }
1307 : 0 : } catch (const uno::RuntimeException &) {
1308 : 0 : throw;
1309 : 0 : } catch (const io::IOException &) {
1310 : 0 : throw;
1311 [ # # # # ]: 0 : } catch (const uno::Exception & e) {
1312 : : throw lang::WrappedTargetException(
1313 : : ::rtl::OUString(
1314 : : "DocumentMetadataAccess::loadMetadataFromMedium: "
1315 [ # # # # : 0 : "exception"), *this, uno::makeAny(e));
# # ]
1316 : : }
1317 [ - + ]: 6 : if (!xStorage.is()) {
1318 : : throw uno::RuntimeException(::rtl::OUString(
1319 : : "DocumentMetadataAccess::loadMetadataFromMedium: "
1320 [ # # ][ # # ]: 0 : "cannot get Storage"), *this);
1321 : : }
1322 : 6 : uno::Reference<rdf::XURI> xBaseURI;
1323 : : try {
1324 [ # # ][ - + ]: 6 : xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, BaseURL);
1325 [ - + ][ + - ]: 12 : } catch (const uno::Exception &) {
1326 : : // fall back to URL
1327 : : try {
1328 [ - + ]: 6 : xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, URL);
[ # # - + ]
1329 [ # # ]: 0 : } catch (const uno::Exception &) {
1330 : : OSL_FAIL("cannot create base URI");
1331 : : }
1332 : : }
1333 : 6 : uno::Reference<task::XInteractionHandler> xIH;
1334 [ + - ][ + - ]: 6 : md[ ::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER() ] >>= xIH;
[ + - ]
1335 [ + - ][ + - ]: 8 : loadMetadataFromStorage(xStorage, xBaseURI, xIH);
1336 : 6 : }
1337 : :
1338 : : void SAL_CALL
1339 : 4 : DocumentMetadataAccess::storeMetadataToMedium(
1340 : : const uno::Sequence< beans::PropertyValue > & i_rMedium)
1341 : : throw (uno::RuntimeException, lang::IllegalArgumentException,
1342 : : lang::WrappedTargetException)
1343 : : {
1344 [ + - ]: 4 : ::comphelper::MediaDescriptor md(i_rMedium);
1345 : 4 : ::rtl::OUString URL;
1346 [ + - ][ + - ]: 4 : md[ ::comphelper::MediaDescriptor::PROP_URL() ] >>= URL;
1347 [ + + ]: 4 : if (URL.isEmpty()) {
1348 : : throw lang::IllegalArgumentException(::rtl::OUString(
1349 : : "DocumentMetadataAccess::storeMetadataToMedium: "
1350 [ + - ][ + - ]: 2 : "invalid medium: no URL"), *this, 0);
1351 : : }
1352 : :
1353 [ + - ]: 2 : SfxMedium aMedium(i_rMedium);
1354 [ + - ]: 2 : uno::Reference<embed::XStorage> xStorage(aMedium.GetOutputStorage());
1355 : :
1356 : 2 : bool sfx(false);
1357 [ + - ]: 2 : if (xStorage.is()) {
1358 : 2 : sfx = true;
1359 : : } else {
1360 : : const uno::Reference<lang::XMultiServiceFactory> xMsf (
1361 [ # # ][ # # ]: 0 : m_pImpl->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
[ # # ]
1362 : : xStorage = ::comphelper::OStorageHelper::GetStorageFromURL2(
1363 [ # # ][ # # ]: 0 : URL, embed::ElementModes::WRITE, xMsf);
1364 : : }
1365 : :
1366 [ - + ]: 2 : if (!xStorage.is()) {
1367 : : throw uno::RuntimeException(::rtl::OUString(
1368 : : "DocumentMetadataAccess::storeMetadataToMedium: "
1369 [ # # ][ # # ]: 0 : "cannot get Storage"), *this);
[ # # ]
1370 : : }
1371 : : // set MIME type of the storage
1372 : : ::comphelper::MediaDescriptor::const_iterator iter
1373 [ + - ][ + - ]: 2 : = md.find(::comphelper::MediaDescriptor::PROP_MEDIATYPE());
1374 [ + - ][ + - ]: 2 : if (iter != md.end()) {
1375 : : uno::Reference< beans::XPropertySet > xProps(xStorage,
1376 [ + - ]: 2 : uno::UNO_QUERY_THROW);
1377 : : try {
1378 : : // this is NOT supported in FileSystemStorage
1379 [ + - ]: 2 : xProps->setPropertyValue(
1380 [ + - ]: 2 : ::comphelper::MediaDescriptor::PROP_MEDIATYPE(),
1381 [ + - ][ + - ]: 4 : iter->second);
1382 [ # # ]: 2 : } catch (const uno::Exception &) { }
1383 : : }
1384 [ + - ]: 2 : storeMetadataToStorage(xStorage);
1385 : :
1386 [ + - ]: 2 : if (sfx) {
1387 [ + - ]: 2 : const sal_Bool bOk = aMedium.Commit();
1388 [ + - ]: 2 : aMedium.Close();
1389 [ - + ]: 2 : if ( !bOk ) {
1390 [ # # ]: 0 : sal_uInt32 nError = aMedium.GetError();
1391 [ # # ]: 0 : if ( nError == ERRCODE_NONE ) {
1392 : 0 : nError = ERRCODE_IO_GENERAL;
1393 : : }
1394 : : task::ErrorCodeIOException ex( ::rtl::OUString(),
1395 [ # # ]: 0 : uno::Reference< uno::XInterface >(), nError);
1396 : : throw lang::WrappedTargetException(::rtl::OUString(), *this,
1397 [ # # ][ # # ]: 0 : uno::makeAny(ex));
[ # # ]
1398 : : }
1399 [ + - ][ + - ]: 4 : }
1400 : 2 : }
1401 : :
1402 [ + - ][ + - ]: 735 : } // namespace sfx2
1403 : :
1404 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|