LCOV - code coverage report
Current view: top level - sfx2/source/doc - DocumentMetadataAccess.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 451 591 76.3 %
Date: 2012-08-25 Functions: 52 55 94.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 621 1500 41.4 %

           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: */

Generated by: LCOV version 1.10