summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2019-02-15 17:50:38 +0100
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2019-08-13 11:06:55 +0200
commitde6355afa4bf89199c7281ddb43a141e192d43d6 (patch)
tree7c349d3e4249c8fa82e4d7b1374f1403507dc221
parent44a40b38d881fd2b9cfbedfc630290d1927fd72f (diff)
tdf#123293 sfx2: fix metadata loss when loading from stream
The problem is that when loading from a stream, there is no BaseURL and also no storage for the document. Due to the lack of BaseURL, the sfx2::createBaseURI() throws and loading RDF metadata fails, which also pops up an annoying warning dialog. Try to handle this in a similar way than a newly created document (see GetDMA()), by using the vnd.sun.star.tdoc scheme URL for the document; this however currently requires that the document has a XStorage, which is also not the case here. So add another UNO method to tdoc UCP's tdoc_ucp::ContentProvider, to split out the creation of the tdoc schema URL from the creation of the ucb Content, to get rid of the XStorage requirement. Change-Id: Ica62743f9d21db0b1464b70db1a62ebc61989ef8 Reviewed-on: https://gerrit.libreoffice.org/67882 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt@cib.de> (cherry picked from commit 0a5ca5768f56db481dd3b947b3dddaab7ed96450) Reviewed-on: https://gerrit.libreoffice.org/69101 Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de> (cherry picked from commit 98b99ef61c6d725962cdbaa05ff90c9d1aa72d57) Reviewed-on: https://gerrit.libreoffice.org/75963 Reviewed-by: Michael Stahl <Michael.Stahl@cib.de> Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
-rw-r--r--include/sfx2/DocumentMetadataAccess.hxx9
-rw-r--r--offapi/UnoApi_offapi.mk1
-rw-r--r--offapi/com/sun/star/frame/XTransientDocumentsDocumentContentIdentifierFactory.idl59
-rw-r--r--sc/source/filter/xml/xmlwrap.cxx4
-rw-r--r--sfx2/source/doc/DocumentMetadataAccess.cxx39
-rw-r--r--sw/source/filter/ww8/ww8par.cxx5
-rw-r--r--sw/source/filter/xml/swxml.cxx4
-rw-r--r--ucb/source/ucp/tdoc/tdoc_provider.cxx27
-rw-r--r--ucb/source/ucp/tdoc/tdoc_provider.hxx13
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx4
10 files changed, 141 insertions, 24 deletions
diff --git a/include/sfx2/DocumentMetadataAccess.hxx b/include/sfx2/DocumentMetadataAccess.hxx
index 31a61adebb01..cf5a2ddbcbac 100644
--- a/include/sfx2/DocumentMetadataAccess.hxx
+++ b/include/sfx2/DocumentMetadataAccess.hxx
@@ -44,6 +44,9 @@
namespace com { namespace sun { namespace star { namespace embed {
class XStorage;
} } } }
+namespace com { namespace sun { namespace star { namespace frame {
+ class XModel;
+} } } }
class SfxObjectShell;
namespace sfx2 {
@@ -52,7 +55,7 @@ namespace sfx2 {
/** create a base URI for loading metadata from an ODF (sub)document.
@param i_xContext component context
- @param i_xStorage storage for the document; FileSystemStorage is allowed
+ @param i_xModel model of the document (required if no URI is provided)
@param i_rPkgURI the URI for the package
@param i_rSubDocument (optional) path of the subdocument in package
@@ -60,8 +63,8 @@ namespace sfx2 {
*/
css::uno::Reference< css::rdf::XURI> SFX2_DLLPUBLIC
createBaseURI(
- css::uno::Reference< css::uno::XComponentContext> const & i_xContext,
- css::uno::Reference< css::embed::XStorage> const & i_xStorage,
+ css::uno::Reference<css::uno::XComponentContext> const & i_xContext,
+ css::uno::Reference<css::frame::XModel> const & i_xModel,
OUString const & i_rPkgURI,
OUString const & i_rSubDocument = OUString());
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 93a76c5908a2..f95f390777d2 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -2656,6 +2656,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/frame,\
XToolbarController \
XToolbarControllerListener \
XTransientDocumentsDocumentContentFactory \
+ XTransientDocumentsDocumentContentIdentifierFactory \
XUIControllerFactory \
XUIControllerRegistration \
XUntitledNumbers \
diff --git a/offapi/com/sun/star/frame/XTransientDocumentsDocumentContentIdentifierFactory.idl b/offapi/com/sun/star/frame/XTransientDocumentsDocumentContentIdentifierFactory.idl
new file mode 100644
index 000000000000..26359db3eec5
--- /dev/null
+++ b/offapi/com/sun/star/frame/XTransientDocumentsDocumentContentIdentifierFactory.idl
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+#ifndef __com_sun_star_frame_XTransientDocumentsDocumentContentIdentifierFactory_idl__
+#define __com_sun_star_frame_XTransientDocumentsDocumentContentIdentifierFactory_idl__
+
+#include <com/sun/star/uno/XInterface.idl>
+#include <com/sun/star/ucb/XContentIdentifier.idl>
+#include <com/sun/star/frame/XModel.idl>
+#include <com/sun/star/lang/IllegalArgumentException.idl>
+
+
+module com { module sun { module star { module frame {
+
+/** a factory for identifiers of
+ com::sun::star::ucb::TransientDocumentsDocumentContents.
+
+ @see com::sun::star::document::OfficeDocument
+ @see com::sun::star::ucb::XContentIdentifier
+
+ @since LibreOffice 6.3
+*/
+interface XTransientDocumentsDocumentContentIdentifierFactory
+ : com::sun::star::uno::XInterface
+{
+ /** creates a com::sun::star::ucb::XContentIdentifier
+ based on a given com::sun::star::document::OfficeDocument.
+
+ @param Model
+ the document model for which a
+ com::sun::star::ucb::XContentIdentifier
+ is requested. The model must be an implementation of service
+ com::sun::star::document::OfficeDocument.
+
+ @returns
+ a content identifier based on the given document model.
+
+ @throws com::sun::star::lang::IllegalArgumentException
+ if the document model cannot be associated with content for any reason.
+ */
+ com::sun::star::ucb::XContentIdentifier
+ createDocumentContentIdentifier(
+ [in] com::sun::star::frame::XModel Model )
+ raises ( com::sun::star::lang::IllegalArgumentException );
+
+};
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx
index 2217a4a07838..ce5d7f360b55 100644
--- a/sc/source/filter/xml/xmlwrap.cxx
+++ b/sc/source/filter/xml/xmlwrap.cxx
@@ -37,6 +37,7 @@
#include <sfx2/sfxsids.hrc>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp>
#include <com/sun/star/xml/sax/InputSource.hpp>
#include <com/sun/star/xml/sax/Parser.hpp>
#include <com/sun/star/xml/sax/XFastParser.hpp>
@@ -74,6 +75,7 @@
#include <unonames.hxx>
using namespace com::sun::star;
+using namespace css::uno;
ScXMLImportWrapper::ScXMLImportWrapper( ScDocShell& rDocSh, SfxMedium* pM, const uno::Reference < embed::XStorage >& xStor ) :
mrDocShell(rDocSh),
@@ -393,7 +395,7 @@ bool ScXMLImportWrapper::Import( ImportFlags nMode, ErrCode& rError )
const uno::Reference< rdf::XDocumentMetadataAccess > xDMA(
xModel, uno::UNO_QUERY_THROW );
const uno::Reference< rdf::XURI > xBaseURI(
- ::sfx2::createBaseURI( xContext, xStorage, aBaseURL, aName ) );
+ ::sfx2::createBaseURI( xContext, xModel, aBaseURL, aName ) );
uno::Reference<task::XInteractionHandler> xHandler =
mrDocShell.GetMedium()->GetInteractionHandler();
xDMA->loadMetadataFromStorage( xStorage, xBaseURI, xHandler );
diff --git a/sfx2/source/doc/DocumentMetadataAccess.cxx b/sfx2/source/doc/DocumentMetadataAccess.cxx
index ff6ad06ea6a7..9e8c2a2bf601 100644
--- a/sfx2/source/doc/DocumentMetadataAccess.cxx
+++ b/sfx2/source/doc/DocumentMetadataAccess.cxx
@@ -25,6 +25,7 @@
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/frame/XTransientDocumentsDocumentContentIdentifierFactory.hpp>
#include <com/sun/star/task/ErrorCodeIOException.hpp>
#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
#include <com/sun/star/rdf/FileFormat.hpp>
@@ -114,16 +115,44 @@ static bool isReservedFile(OUString const & i_rPath)
uno::Reference<rdf::XURI> createBaseURI(
uno::Reference<uno::XComponentContext> const & i_xContext,
- uno::Reference<embed::XStorage> const & i_xStorage,
+ uno::Reference<frame::XModel> const & i_xModel,
OUString const & i_rPkgURI, OUString const & i_rSubDocument)
{
- if (!i_xContext.is() || !i_xStorage.is() || i_rPkgURI.isEmpty()) {
+ if (!i_xContext.is() || (!i_xModel.is() && i_rPkgURI.isEmpty())) {
throw uno::RuntimeException();
}
+ OUString pkgURI(i_rPkgURI);
+
+ // tdf#123293 chicken/egg problem when loading from stream: there is no URI,
+ // and also the model doesn't have a storage yet, so we need to get the
+ // tdoc URI without a storage...
+ if (pkgURI.isEmpty())
+ {
+ assert(i_xModel.is());
+ uno::Reference<frame::XTransientDocumentsDocumentContentIdentifierFactory>
+ const xTDDCIF(
+ i_xContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.ucb.TransientDocumentsContentProvider",
+ i_xContext),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<ucb::XContentIdentifier> const xContentId(
+ xTDDCIF->createDocumentContentIdentifier(i_xModel));
+ SAL_WARN_IF(!xContentId.is(), "sfx", "createBaseURI: cannot create ContentIdentifier");
+ if (!xContentId.is())
+ {
+ throw uno::RuntimeException("createBaseURI: cannot create ContentIdentifier");
+ }
+ pkgURI = xContentId->getContentIdentifier();
+ assert(!pkgURI.isEmpty());
+ if (!pkgURI.isEmpty() && !pkgURI.endsWith("/"))
+ {
+ pkgURI = pkgURI + "/";
+ }
+ }
+
// #i108078# workaround non-hierarchical vnd.sun.star.expand URIs
// this really should be done somewhere else, not here.
- OUString pkgURI(i_rPkgURI);
if (pkgURI.matchIgnoreAsciiCase("vnd.sun.star.expand:"))
{
// expand it here (makeAbsolute requires hierarchical URI)
@@ -1234,11 +1263,11 @@ DocumentMetadataAccess::loadMetadataFromMedium(
}
uno::Reference<rdf::XURI> xBaseURI;
try {
- xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, BaseURL);
+ xBaseURI = createBaseURI(m_pImpl->m_xContext, nullptr, BaseURL);
} catch (const uno::Exception &) {
// fall back to URL
try {
- xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, URL);
+ xBaseURI = createBaseURI(m_pImpl->m_xContext, nullptr, URL);
} catch (const uno::Exception &) {
OSL_FAIL("cannot create base URI");
}
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index bcc16adc2d98..5df28f764002 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -4925,10 +4925,11 @@ ErrCode SwWW8ImplReader::CoreLoad(WW8Glossary const *pGloss)
// Initialize RDF metadata, to be able to add statements during the import.
try
{
- uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<frame::XModel> const xModel(m_rDoc.GetDocShell()->GetBaseModel());
+ uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY_THROW);
uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
uno::Reference<embed::XStorage> xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
- const uno::Reference<rdf::XURI> xBaseURI(sfx2::createBaseURI(xComponentContext, xStorage, m_sBaseURL));
+ const uno::Reference<rdf::XURI> xBaseURI(sfx2::createBaseURI(xComponentContext, xModel, m_sBaseURL));
uno::Reference<task::XInteractionHandler> xHandler;
xDocumentMetadataAccess->loadMetadataFromStorage(xStorage, xBaseURI, xHandler);
}
diff --git a/sw/source/filter/xml/swxml.cxx b/sw/source/filter/xml/swxml.cxx
index cdeee03a3a96..faf4f4b4be91 100644
--- a/sw/source/filter/xml/swxml.cxx
+++ b/sw/source/filter/xml/swxml.cxx
@@ -791,8 +791,10 @@ ErrCode XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, con
{
const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(xModelComp,
uno::UNO_QUERY_THROW);
+ const uno::Reference<frame::XModel> xModel(xModelComp,
+ uno::UNO_QUERY_THROW);
const uno::Reference<rdf::XURI> xBaseURI( ::sfx2::createBaseURI(
- xContext, xStorage, rBaseURL, StreamPath) );
+ xContext, xModel, rBaseURL, StreamPath) );
const uno::Reference<task::XInteractionHandler> xHandler(
pDocSh->GetMedium()->GetInteractionHandler() );
xDMA->loadMetadataFromStorage(xStorage, xBaseURI, xHandler);
diff --git a/ucb/source/ucp/tdoc/tdoc_provider.cxx b/ucb/source/ucp/tdoc/tdoc_provider.cxx
index 58f2652a4dc0..08590131231a 100644
--- a/ucb/source/ucp/tdoc/tdoc_provider.cxx
+++ b/ucb/source/ucp/tdoc/tdoc_provider.cxx
@@ -85,6 +85,7 @@ css::uno::Any SAL_CALL ContentProvider::queryInterface( const css::uno::Type & r
static_cast< lang::XTypeProvider* >(this),
static_cast< lang::XServiceInfo* >(this),
static_cast< ucb::XContentProvider* >(this),
+ static_cast< frame::XTransientDocumentsDocumentContentIdentifierFactory* >(this),
static_cast< frame::XTransientDocumentsDocumentContentFactory* >(this)
);
return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
@@ -93,10 +94,11 @@ css::uno::Any SAL_CALL ContentProvider::queryInterface( const css::uno::Type & r
// XTypeProvider methods.
-XTYPEPROVIDER_IMPL_4( ContentProvider,
+XTYPEPROVIDER_IMPL_5( ContentProvider,
lang::XTypeProvider,
lang::XServiceInfo,
ucb::XContentProvider,
+ frame::XTransientDocumentsDocumentContentIdentifierFactory,
frame::XTransientDocumentsDocumentContentFactory );
@@ -161,13 +163,11 @@ ContentProvider::queryContent(
}
-// XTransientDocumentsDocumentContentFactory methods.
-
+// XTransientDocumentsDocumentContentIdentifierFactory methods.
-// virtual
-uno::Reference< ucb::XContent > SAL_CALL
-ContentProvider::createDocumentContent(
- const uno::Reference< frame::XModel >& Model )
+uno::Reference<ucb::XContentIdentifier> SAL_CALL
+ContentProvider::createDocumentContentIdentifier(
+ uno::Reference<frame::XModel> const& xModel)
{
// model -> id -> content identifier -> queryContent
if ( !m_xDocsMgr.is() )
@@ -178,7 +178,7 @@ ContentProvider::createDocumentContent(
1 );
}
- OUString aDocId = tdoc_ucp::OfficeDocumentsManager::queryDocumentId( Model );
+ OUString aDocId = tdoc_ucp::OfficeDocumentsManager::queryDocumentId(xModel);
if ( aDocId.isEmpty() )
{
throw lang::IllegalArgumentException(
@@ -193,6 +193,17 @@ ContentProvider::createDocumentContent(
uno::Reference< ucb::XContentIdentifier > xId
= new ::ucbhelper::ContentIdentifier( aBuffer.makeStringAndClear() );
+ return xId;
+}
+
+// XTransientDocumentsDocumentContentFactory methods.
+
+uno::Reference< ucb::XContent > SAL_CALL
+ContentProvider::createDocumentContent(
+ uno::Reference<frame::XModel> const& xModel)
+{
+ uno::Reference<ucb::XContentIdentifier> const xId(
+ createDocumentContentIdentifier(xModel));
osl::MutexGuard aGuard( m_aMutex );
diff --git a/ucb/source/ucp/tdoc/tdoc_provider.hxx b/ucb/source/ucp/tdoc/tdoc_provider.hxx
index 3501bd4d8ec9..f8c2fb701e83 100644
--- a/ucb/source/ucp/tdoc/tdoc_provider.hxx
+++ b/ucb/source/ucp/tdoc/tdoc_provider.hxx
@@ -22,6 +22,7 @@
#include <rtl/ref.hxx>
#include <com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp>
+#include <com/sun/star/frame/XTransientDocumentsDocumentContentIdentifierFactory.hpp>
#include <com/sun/star/packages/WrongPasswordException.hpp>
#include <ucbhelper/providerhelper.hxx>
#include "tdoc_uri.hxx"
@@ -51,9 +52,10 @@ namespace tdoc_ucp {
class StorageElementFactory;
-class ContentProvider :
- public ::ucbhelper::ContentProviderImplHelper,
- public css::frame::XTransientDocumentsDocumentContentFactory
+class ContentProvider
+ : public ::ucbhelper::ContentProviderImplHelper
+ , public css::frame::XTransientDocumentsDocumentContentIdentifierFactory
+ , public css::frame::XTransientDocumentsDocumentContentFactory
{
public:
explicit ContentProvider( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
@@ -86,6 +88,11 @@ public:
virtual css::uno::Reference< css::ucb::XContent > SAL_CALL
queryContent( const css::uno::Reference< css::ucb::XContentIdentifier >& Identifier ) override;
+ // XTransientDocumentsDocumentContentIdentifierFactory
+ virtual css::uno::Reference<css::ucb::XContentIdentifier> SAL_CALL
+ createDocumentContentIdentifier(
+ css::uno::Reference<css::frame::XModel> const& xModel) override;
+
// XTransientDocumentsDocumentContentFactory
virtual css::uno::Reference< css::ucb::XContent > SAL_CALL
createDocumentContent( const css::uno::Reference<
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index b14db3d28767..7c53493e6f66 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -126,7 +126,9 @@ DomainMapper::DomainMapper( const uno::Reference< uno::XComponentContext >& xCon
uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY_THROW);
uno::Reference<embed::XStorage> xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
OUString aBaseURL = rMediaDesc.getUnpackedValueOrDefault("URL", OUString());
- const uno::Reference<rdf::XURI> xBaseURI(sfx2::createBaseURI(xContext, xStorage, aBaseURL, OUString()));
+ const uno::Reference<frame::XModel> xModel_(xModel,
+ uno::UNO_QUERY_THROW);
+ const uno::Reference<rdf::XURI> xBaseURI(sfx2::createBaseURI(xContext, xModel_, aBaseURL, OUString()));
const uno::Reference<task::XInteractionHandler> xHandler;
xDocumentMetadataAccess->loadMetadataFromStorage(xStorage, xBaseURI, xHandler);
}