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