LCOV - code coverage report
Current view: top level - libreoffice/sfx2/source/doc - DocumentMetadataAccess.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 159 586 27.1 %
Date: 2012-12-17 Functions: 28 55 50.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10