/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
*
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include // for xmlValidateNCName
#include
#include
#include
#include
#include
#include
N.B.: must not be called before DMA is fully initalized!
@returns true iff caller should retry
*/
static bool
handleError( ucb::InteractiveAugmentedIOException const & i_rException,
const uno::Reference & i_xHandler)
{
if (!i_xHandler.is()) {
throw lang::WrappedTargetException(::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromStorage: exception"),
/* *this*/ 0, uno::makeAny(i_rException));
}
::rtl::Reference< ::comphelper::OInteractionRequest > pRequest(
new ::comphelper::OInteractionRequest(uno::makeAny(i_rException)) );
::rtl::Reference< ::comphelper::OInteractionRetry > pRetry(
new ::comphelper::OInteractionRetry );
::rtl::Reference< ::comphelper::OInteractionApprove > pApprove(
new ::comphelper::OInteractionApprove );
::rtl::Reference< ::comphelper::OInteractionAbort > pAbort(
new ::comphelper::OInteractionAbort );
pRequest->addContinuation( pApprove.get() );
pRequest->addContinuation( pAbort.get() );
// actually call the handler
i_xHandler->handle( pRequest.get() );
if (pRetry->wasSelected()) {
return true;
} else if (pApprove->wasSelected()) {
return false;
} else {
OSL_ENSURE(pAbort->wasSelected(), "no continuation selected?");
throw lang::WrappedTargetException(::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromStorage: exception"),
/* *this*/ 0, uno::makeAny(i_rException));
}
}
/** check if storage has content.xml/styles.xml;
e.g. ODB files seem to only have content.xml */
static void
collectFilesFromStorage(uno::Reference const& i_xStorage,
::rtl::OUString i_Path,
std::set< ::rtl::OUString > & o_rFiles)
{
static ::rtl::OUString content(s_content);
static ::rtl::OUString styles(s_styles );
try {
if (i_xStorage->hasByName(content) &&
i_xStorage->isStreamElement(content))
{
o_rFiles.insert(i_Path + content);
}
if (i_xStorage->hasByName(styles) &&
i_xStorage->isStreamElement(styles))
{
o_rFiles.insert(i_Path + styles);
}
} catch (const uno::Exception &) {
OSL_TRACE("collectFilesFromStorage: exception?");
}
}
/** import a metadata file into repository */
static void
readStream(struct DocumentMetadataAccess_Impl & i_rImpl,
uno::Reference< embed::XStorage > const & i_xStorage,
::rtl::OUString const & i_rPath,
::rtl::OUString const & i_rBaseURI)
{
::rtl::OUString dir;
::rtl::OUString rest;
try {
if (!splitPath(i_rPath, dir, rest)) throw uno::RuntimeException();
if (dir.isEmpty()) {
if (i_xStorage->isStreamElement(i_rPath)) {
const uno::Reference xStream(
i_xStorage->openStreamElement(i_rPath,
embed::ElementModes::READ), uno::UNO_SET_THROW);
const uno::Reference xInStream(
xStream->getInputStream(), uno::UNO_SET_THROW );
const uno::Reference xBaseURI(
rdf::URI::create(i_rImpl.m_xContext, i_rBaseURI));
const uno::Reference xURI(
rdf::URI::createNS(i_rImpl.m_xContext,
i_rBaseURI, i_rPath));
i_rImpl.m_xRepository->importGraph(rdf::FileFormat::RDF_XML,
xInStream, xURI, xBaseURI);
} else {
throw mkException(::rtl::OUString(
"readStream: is not a stream"),
ucb::IOErrorCode_NO_FILE, i_rBaseURI + i_rPath, i_rPath);
}
} else {
if (i_xStorage->isStorageElement(dir)) {
const uno::Reference xDir(
i_xStorage->openStorageElement(dir,
embed::ElementModes::READ));
const uno::Reference< beans::XPropertySet > xDirProps(xDir,
uno::UNO_QUERY_THROW);
try {
::rtl::OUString mimeType;
xDirProps->getPropertyValue(
::comphelper::MediaDescriptor::PROP_MEDIATYPE() )
>>= mimeType;
if (mimeType.matchAsciiL(s_odfmime, sizeof(s_odfmime) - 1))
{
OSL_TRACE("readStream: "
"refusing to recurse into embedded document");
return;
}
} catch (const uno::Exception &) { }
::rtl::OUStringBuffer buf(i_rBaseURI);
buf.append(dir).append(static_cast('/'));
readStream(i_rImpl, xDir, rest, buf.makeStringAndClear() );
} else {
throw mkException(::rtl::OUString(
"readStream: is not a directory"),
ucb::IOErrorCode_NO_DIRECTORY, i_rBaseURI + dir, dir);
}
}
} catch (const container::NoSuchElementException & e) {
throw mkException(e.Message, ucb::IOErrorCode_NOT_EXISTING_PATH,
i_rBaseURI + i_rPath, i_rPath);
} catch (const io::IOException & e) {
throw mkException(e.Message, ucb::IOErrorCode_CANT_READ,
i_rBaseURI + i_rPath, i_rPath);
} catch (const rdf::ParseException & e) {
throw mkException(e.Message, ucb::IOErrorCode_WRONG_FORMAT,
i_rBaseURI + i_rPath, i_rPath);
}
}
/** import a metadata file into repository */
static void
importFile(struct DocumentMetadataAccess_Impl & i_rImpl,
uno::Reference const & i_xStorage,
::rtl::OUString const & i_rBaseURI,
uno::Reference const & i_xHandler,
::rtl::OUString i_rPath)
{
retry:
try {
readStream(i_rImpl, i_xStorage, i_rPath, i_rBaseURI);
} catch (const ucb::InteractiveAugmentedIOException & e) {
if (handleError(e, i_xHandler)) goto retry;
} catch (const uno::RuntimeException &) {
throw;
} catch (const uno::Exception & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString("importFile: exception"),
0, uno::makeAny(e));
}
}
/** actually write a metadata file to the storage */
static void
exportStream(struct DocumentMetadataAccess_Impl & i_rImpl,
uno::Reference< embed::XStorage > const & i_xStorage,
uno::Reference const & i_xGraphName,
::rtl::OUString const & i_rFileName,
::rtl::OUString const & i_rBaseURI)
{
const uno::Reference xStream(
i_xStorage->openStreamElement(i_rFileName,
embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE),
uno::UNO_SET_THROW);
const uno::Reference< beans::XPropertySet > xStreamProps(xStream,
uno::UNO_QUERY);
if (xStreamProps.is()) { // this is NOT supported in FileSystemStorage
xStreamProps->setPropertyValue(
::rtl::OUString("MediaType"),
uno::makeAny(::rtl::OUString(s_rdfxml)));
}
const uno::Reference xOutStream(
xStream->getOutputStream(), uno::UNO_SET_THROW );
const uno::Reference xBaseURI(
rdf::URI::create(i_rImpl.m_xContext, i_rBaseURI));
i_rImpl.m_xRepository->exportGraph(rdf::FileFormat::RDF_XML,
xOutStream, i_xGraphName, xBaseURI);
}
/** write a metadata file to the storage */
static void
writeStream(struct DocumentMetadataAccess_Impl & i_rImpl,
uno::Reference< embed::XStorage > const & i_xStorage,
uno::Reference const & i_xGraphName,
::rtl::OUString const & i_rPath,
::rtl::OUString const & i_rBaseURI)
{
::rtl::OUString dir;
::rtl::OUString rest;
if (!splitPath(i_rPath, dir, rest)) throw uno::RuntimeException();
try {
if (dir.isEmpty()) {
exportStream(i_rImpl, i_xStorage, i_xGraphName, i_rPath,
i_rBaseURI);
} else {
const uno::Reference xDir(
i_xStorage->openStorageElement(dir,
embed::ElementModes::WRITE));
const uno::Reference< beans::XPropertySet > xDirProps(xDir,
uno::UNO_QUERY_THROW);
try {
::rtl::OUString mimeType;
xDirProps->getPropertyValue(
::comphelper::MediaDescriptor::PROP_MEDIATYPE() )
>>= mimeType;
if (mimeType.matchAsciiL(s_odfmime, sizeof(s_odfmime) - 1)) {
OSL_TRACE("writeStream: "
"refusing to recurse into embedded document");
return;
}
} catch (const uno::Exception &) { }
::rtl::OUStringBuffer buf(i_rBaseURI);
buf.append(dir).append(static_cast('/'));
writeStream(i_rImpl, xDir, i_xGraphName, rest,
buf.makeStringAndClear());
uno::Reference const xTransaction(
xDir, uno::UNO_QUERY);
if (xTransaction.is()) {
xTransaction->commit();
}
}
} catch (const uno::RuntimeException &) {
throw;
} catch (const io::IOException &) {
throw;
}
}
static void
initLoading(struct DocumentMetadataAccess_Impl & i_rImpl,
const uno::Reference< embed::XStorage > & i_xStorage,
const uno::Reference & i_xBaseURI,
const uno::Reference & i_xHandler)
{
retry:
// clear old data
i_rImpl.m_xManifest.clear();
// init BaseURI
i_rImpl.m_xBaseURI = i_xBaseURI;
// create repository
i_rImpl.m_xRepository.clear();
i_rImpl.m_xRepository.set(rdf::Repository::create(i_rImpl.m_xContext),
uno::UNO_SET_THROW);
const ::rtl::OUString manifest (
::rtl::OUString::createFromAscii(s_manifest));
const ::rtl::OUString baseURI( i_xBaseURI->getStringValue() );
// try to delay raising errors until after initialization is done
uno::Any rterr;
ucb::InteractiveAugmentedIOException iaioe;
bool err(false);
const uno::Reference xManifest(
getURIForStream(i_rImpl, manifest));
try {
readStream(i_rImpl, i_xStorage, manifest, baseURI);
} catch (const ucb::InteractiveAugmentedIOException & e) {
// no manifest.rdf: this is not an error in ODF < 1.2
if (!(ucb::IOErrorCode_NOT_EXISTING_PATH == e.Code)) {
iaioe = e;
err = true;
}
} catch (const uno::Exception & e) {
rterr <<= e;
}
// init manifest graph
const uno::Reference xManifestGraph(
i_rImpl.m_xRepository->getGraph(xManifest));
i_rImpl.m_xManifest.set(xManifestGraph.is() ? xManifestGraph :
i_rImpl.m_xRepository->createGraph(xManifest), uno::UNO_SET_THROW);
const uno::Reference xEnum(
i_rImpl.m_xManifest->getStatements(0,
getURI(i_rImpl.m_xContext),
getURI(i_rImpl.m_xContext).get()));
// document statement
i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
getURI(i_rImpl.m_xContext),
getURI(i_rImpl.m_xContext).get());
OSL_ENSURE(i_rImpl.m_xBaseURI.is(), "base URI is null");
OSL_ENSURE(i_rImpl.m_xRepository.is(), "repository is null");
OSL_ENSURE(i_rImpl.m_xManifest.is(), "manifest is null");
if (rterr.hasValue()) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromStorage: "
"exception"), 0, rterr);
}
if (err) {
if (handleError(iaioe, i_xHandler)) goto retry;
}
}
/** init Impl struct */
static void init(struct DocumentMetadataAccess_Impl & i_rImpl)
{
try {
i_rImpl.m_xManifest.set(i_rImpl.m_xRepository->createGraph(
getURIForStream(i_rImpl,
::rtl::OUString::createFromAscii(s_manifest))),
uno::UNO_SET_THROW);
// insert the document statement
i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
getURI(i_rImpl.m_xContext),
getURI(i_rImpl.m_xContext).get());
} catch (const uno::Exception & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString("init: unexpected exception"), 0,
uno::makeAny(e));
}
// add top-level content files
if (!addContentOrStylesFileImpl(i_rImpl,
::rtl::OUString::createFromAscii(s_content))) {
throw uno::RuntimeException();
}
if (!addContentOrStylesFileImpl(i_rImpl,
::rtl::OUString::createFromAscii(s_styles))) {
throw uno::RuntimeException();
}
}
DocumentMetadataAccess::DocumentMetadataAccess(
uno::Reference< uno::XComponentContext > const & i_xContext,
const IXmlIdRegistrySupplier & i_rRegistrySupplier)
: m_pImpl(new DocumentMetadataAccess_Impl(i_xContext, i_rRegistrySupplier))
{
// no initalization: must call loadFrom...
}
DocumentMetadataAccess::DocumentMetadataAccess(
uno::Reference< uno::XComponentContext > const & i_xContext,
const IXmlIdRegistrySupplier & i_rRegistrySupplier,
::rtl::OUString const & i_rURI)
: m_pImpl(new DocumentMetadataAccess_Impl(i_xContext, i_rRegistrySupplier))
{
OSL_ENSURE(!i_rURI.isEmpty(), "DMA::DMA: no URI given!");
OSL_ENSURE(i_rURI.endsWithAsciiL("/", 1), "DMA::DMA: URI without / given!");
if (!i_rURI.endsWithAsciiL("/", 1)) throw uno::RuntimeException();
m_pImpl->m_xBaseURI.set(rdf::URI::create(m_pImpl->m_xContext, i_rURI));
m_pImpl->m_xRepository.set(rdf::Repository::create(m_pImpl->m_xContext),
uno::UNO_SET_THROW);
// init repository
init(*m_pImpl);
OSL_ENSURE(m_pImpl->m_xBaseURI.is(), "base URI is null");
OSL_ENSURE(m_pImpl->m_xRepository.is(), "repository is null");
OSL_ENSURE(m_pImpl->m_xManifest.is(), "manifest is null");
}
DocumentMetadataAccess::~DocumentMetadataAccess()
{
}
// ::com::sun::star::rdf::XRepositorySupplier:
uno::Reference< rdf::XRepository > SAL_CALL
DocumentMetadataAccess::getRDFRepository() throw (uno::RuntimeException)
{
OSL_ENSURE(m_pImpl->m_xRepository.is(), "repository not initialized");
return m_pImpl->m_xRepository;
}
// ::com::sun::star::rdf::XNode:
::rtl::OUString SAL_CALL
DocumentMetadataAccess::getStringValue() throw (uno::RuntimeException)
{
return m_pImpl->m_xBaseURI->getStringValue();
}
// ::com::sun::star::rdf::XURI:
::rtl::OUString SAL_CALL
DocumentMetadataAccess::getNamespace() throw (uno::RuntimeException)
{
return m_pImpl->m_xBaseURI->getNamespace();
}
::rtl::OUString SAL_CALL
DocumentMetadataAccess::getLocalName() throw (uno::RuntimeException)
{
return m_pImpl->m_xBaseURI->getLocalName();
}
// ::com::sun::star::rdf::XDocumentMetadataAccess:
uno::Reference< rdf::XMetadatable > SAL_CALL
DocumentMetadataAccess::getElementByMetadataReference(
const ::com::sun::star::beans::StringPair & i_rReference)
throw (uno::RuntimeException)
{
const IXmlIdRegistry * pReg(
m_pImpl->m_rXmlIdRegistrySupplier.GetXmlIdRegistry() );
if (!pReg) {
throw uno::RuntimeException(::rtl::OUString(
"DocumentMetadataAccess::getElementByXmlId: no registry"), *this);
}
return pReg->GetElementByMetadataReference(i_rReference);
}
uno::Reference< rdf::XMetadatable > SAL_CALL
DocumentMetadataAccess::getElementByURI(
const uno::Reference< rdf::XURI > & i_xURI )
throw (uno::RuntimeException, lang::IllegalArgumentException)
{
if (!i_xURI.is()) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::getElementByURI: URI is null"), *this, 0);
}
const ::rtl::OUString baseURI( m_pImpl->m_xBaseURI->getStringValue() );
const ::rtl::OUString name( i_xURI->getStringValue() );
if (!name.match(baseURI)) {
return 0;
}
const ::rtl::OUString relName( name.copy(baseURI.getLength()) );
::rtl::OUString path;
::rtl::OUString idref;
if (!splitXmlId(relName, path, idref)) {
return 0;
}
return getElementByMetadataReference( beans::StringPair(path, idref) );
}
uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
DocumentMetadataAccess::getMetadataGraphsWithType(
const uno::Reference & i_xType)
throw (uno::RuntimeException, lang::IllegalArgumentException)
{
if (!i_xType.is()) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::getMetadataGraphsWithType: "
"type is null"), *this, 0);
}
::comphelper::SequenceAsVector< uno::Reference< rdf::XURI > > ret;
const ::std::vector< uno::Reference< rdf::XURI > > parts(
getAllParts(*m_pImpl) );
::std::remove_copy_if(parts.begin(), parts.end(),
::std::back_inserter(ret),
::boost::bind(
::std::logical_not(),
::boost::bind(&isPartOfType, ::boost::ref(*m_pImpl), _1, i_xType) ));
return ret.getAsConstList();
}
uno::Reference SAL_CALL
DocumentMetadataAccess::addMetadataFile(const ::rtl::OUString & i_rFileName,
const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
throw (uno::RuntimeException, lang::IllegalArgumentException,
container::ElementExistException)
{
if (!isFileNameValid(i_rFileName)) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::addMetadataFile: invalid FileName"),
*this, 0);
}
if (isReservedFile(i_rFileName)) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::addMetadataFile:"
"invalid FileName: reserved"), *this, 0);
}
for (sal_Int32 i = 0; i < i_rTypes.getLength(); ++i) {
if (!i_rTypes[i].is()) {
throw lang::IllegalArgumentException(
::rtl::OUString(
"DocumentMetadataAccess::addMetadataFile: "
"null type"), *this, 2);
}
}
const uno::Reference xGraphName(
getURIForStream(*m_pImpl, i_rFileName) );
try {
m_pImpl->m_xRepository->createGraph(xGraphName);
} catch (const rdf::RepositoryException & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"DocumentMetadataAccess::addMetadataFile: exception"),
*this, uno::makeAny(e));
// note: all other exceptions are propagated
}
addMetadataFileImpl(*m_pImpl, i_rFileName, i_rTypes);
return xGraphName;
}
uno::Reference SAL_CALL
DocumentMetadataAccess::importMetadataFile(::sal_Int16 i_Format,
const uno::Reference< io::XInputStream > & i_xInStream,
const ::rtl::OUString & i_rFileName,
const uno::Reference< rdf::XURI > & i_xBaseURI,
const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
throw (uno::RuntimeException, lang::IllegalArgumentException,
datatransfer::UnsupportedFlavorException,
container::ElementExistException, rdf::ParseException, io::IOException)
{
if (!isFileNameValid(i_rFileName)) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::importMetadataFile: invalid FileName"),
*this, 0);
}
if (isReservedFile(i_rFileName)) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::importMetadataFile:"
"invalid FileName: reserved"), *this, 0);
}
for (sal_Int32 i = 0; i < i_rTypes.getLength(); ++i) {
if (!i_rTypes[i].is()) {
throw lang::IllegalArgumentException(
::rtl::OUString(
"DocumentMetadataAccess::importMetadataFile: null type"),
*this, 5);
}
}
const uno::Reference xGraphName(
getURIForStream(*m_pImpl, i_rFileName) );
try {
m_pImpl->m_xRepository->importGraph(
i_Format, i_xInStream, xGraphName, i_xBaseURI);
} catch (const rdf::RepositoryException & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"DocumentMetadataAccess::importMetadataFile: "
"RepositoryException"), *this, uno::makeAny(e));
// note: all other exceptions are propagated
}
// add to manifest
addMetadataFileImpl(*m_pImpl, i_rFileName, i_rTypes);
return xGraphName;
}
void SAL_CALL
DocumentMetadataAccess::removeMetadataFile(
const uno::Reference< rdf::XURI > & i_xGraphName)
throw (uno::RuntimeException, lang::IllegalArgumentException,
container::NoSuchElementException)
{
try {
m_pImpl->m_xRepository->destroyGraph(i_xGraphName);
} catch (const rdf::RepositoryException & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"DocumentMetadataAccess::removeMetadataFile: "
"RepositoryException"), *this, uno::makeAny(e));
// note: all other exceptions are propagated
}
// remove file from manifest
removeFile(*m_pImpl, i_xGraphName.get());
}
void SAL_CALL
DocumentMetadataAccess::addContentOrStylesFile(
const ::rtl::OUString & i_rFileName)
throw (uno::RuntimeException, lang::IllegalArgumentException,
container::ElementExistException)
{
if (!isFileNameValid(i_rFileName)) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::addContentOrStylesFile: "
"invalid FileName"), *this, 0);
}
if (!addContentOrStylesFileImpl(*m_pImpl, i_rFileName)) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::addContentOrStylesFile: "
"invalid FileName: must end with content.xml or styles.xml"),
*this, 0);
}
}
void SAL_CALL
DocumentMetadataAccess::removeContentOrStylesFile(
const ::rtl::OUString & i_rFileName)
throw (uno::RuntimeException, lang::IllegalArgumentException,
container::NoSuchElementException)
{
if (!isFileNameValid(i_rFileName)) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::removeContentOrStylesFile: "
"invalid FileName"), *this, 0);
}
try {
const uno::Reference xPart(
getURIForStream(*m_pImpl, i_rFileName) );
const uno::Reference xEnum(
m_pImpl->m_xManifest->getStatements( m_pImpl->m_xBaseURI.get(),
getURI(m_pImpl->m_xContext),
xPart.get()),
uno::UNO_SET_THROW);
if (!xEnum->hasMoreElements()) {
throw container::NoSuchElementException(
::rtl::OUString(
"DocumentMetadataAccess::removeContentOrStylesFile: "
"cannot find stream in manifest graph: ") + i_rFileName,
*this);
}
// remove file from manifest
removeFile(*m_pImpl, xPart);
} catch (const uno::RuntimeException &) {
throw;
} catch (const uno::Exception & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"DocumentMetadataAccess::removeContentOrStylesFile: exception"),
*this, uno::makeAny(e));
}
}
void SAL_CALL DocumentMetadataAccess::loadMetadataFromStorage(
const uno::Reference< embed::XStorage > & i_xStorage,
const uno::Reference & i_xBaseURI,
const uno::Reference & i_xHandler)
throw (uno::RuntimeException, lang::IllegalArgumentException,
lang::WrappedTargetException)
{
if (!i_xStorage.is()) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromStorage: "
"storage is null"), *this, 0);
}
if (!i_xBaseURI.is()) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromStorage: "
"base URI is null"), *this, 1);
}
const ::rtl::OUString baseURI( i_xBaseURI->getStringValue());
if (baseURI.indexOf('#') >= 0) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromStorage: "
"base URI not absolute"), *this, 1);
}
if (baseURI.isEmpty() || !baseURI.endsWithAsciiL("/", 1)) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromStorage: "
"base URI does not end with slash"), *this, 1);
}
initLoading(*m_pImpl, i_xStorage, i_xBaseURI, i_xHandler);
std::set< ::rtl::OUString > StgFiles;
collectFilesFromStorage(i_xStorage,
::rtl::OUString(""), StgFiles);
std::vector< ::rtl::OUString > MfstMetadataFiles;
try {
const ::std::vector< uno::Reference< rdf::XURI > > parts(
getAllParts(*m_pImpl) );
const uno::Reference xContentFile(
getURI(m_pImpl->m_xContext));
const uno::Reference xStylesFile(
getURI(m_pImpl->m_xContext));
const uno::Reference xMetadataFile(
getURI(m_pImpl->m_xContext));
const sal_Int32 len( baseURI.getLength() );
const ::rtl::OUString manifest (
::rtl::OUString::createFromAscii(s_manifest));
for (::std::vector< uno::Reference< rdf::XURI > >::const_iterator it
= parts.begin();
it != parts.end(); ++it) {
const ::rtl::OUString name((*it)->getStringValue());
if (!name.match(baseURI)) {
OSL_TRACE("loadMetadataFromStorage: graph not in document: %s",
::rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)
.getStr());
continue;
}
const ::rtl::OUString relName( name.copy(len) );
if (relName == manifest) {
OSL_TRACE("loadMetadataFromStorage: "
"found ourselves a recursive manifest!");
continue;
}
// remove found items from StgFiles
StgFiles.erase(relName);
if (isContentFile(relName)) {
if (!isPartOfType(*m_pImpl, *it, xContentFile)) {
const uno::Reference xName(
getURIForStream(*m_pImpl, relName) );
// add missing type statement
m_pImpl->m_xManifest->addStatement(xName.get(),
getURI(m_pImpl->m_xContext),
xContentFile.get());
}
} else if (isStylesFile(relName)) {
if (!isPartOfType(*m_pImpl, *it, xStylesFile)) {
const uno::Reference xName(
getURIForStream(*m_pImpl, relName) );
// add missing type statement
m_pImpl->m_xManifest->addStatement(xName.get(),
getURI(m_pImpl->m_xContext),
xStylesFile.get());
}
} else if (isReservedFile(relName)) {
OSL_TRACE("loadMetadataFromStorage: "
"reserved file name in manifest");
} else {
if (isPartOfType(*m_pImpl, *it, xMetadataFile)) {
MfstMetadataFiles.push_back(relName);
}
// do not add statement for MetadataFile; it could be
// something else! just ignore it...
}
}
} catch (const uno::RuntimeException &) {
throw;
} catch (const uno::Exception & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromStorage: "
"exception"), *this, uno::makeAny(e));
}
std::for_each(StgFiles.begin(), StgFiles.end(),
boost::bind(addContentOrStylesFileImpl, boost::ref(*m_pImpl), _1));
std::for_each(MfstMetadataFiles.begin(), MfstMetadataFiles.end(),
boost::bind(importFile, boost::ref(*m_pImpl),
i_xStorage, baseURI, i_xHandler, _1));
}
void SAL_CALL DocumentMetadataAccess::storeMetadataToStorage(
const uno::Reference< embed::XStorage > & i_xStorage)
throw (uno::RuntimeException, lang::IllegalArgumentException,
lang::WrappedTargetException)
{
if (!i_xStorage.is()) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::storeMetadataToStorage: "
"storage is null"), *this, 0);
}
// export manifest
const ::rtl::OUString manifest (
::rtl::OUString::createFromAscii(s_manifest));
const uno::Reference xManifest(
getURIForStream(*m_pImpl, manifest) );
const ::rtl::OUString baseURI( m_pImpl->m_xBaseURI->getStringValue() );
try {
writeStream(*m_pImpl, i_xStorage, xManifest, manifest, baseURI);
} catch (const uno::RuntimeException &) {
throw;
} catch (const io::IOException & e) {
throw lang::WrappedTargetException( ::rtl::OUString(
"storeMetadataToStorage: IO exception"), *this, uno::makeAny(e));
} catch (const uno::Exception & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"storeMetadataToStorage: exception"), *this, uno::makeAny(e));
}
// export metadata streams
try {
const uno::Sequence > graphs(
m_pImpl->m_xRepository->getGraphNames());
const sal_Int32 len( baseURI.getLength() );
for (sal_Int32 i = 0; i < graphs.getLength(); ++i) {
const uno::Reference xName(graphs[i]);
const ::rtl::OUString name(xName->getStringValue());
if (!name.match(baseURI)) {
OSL_TRACE("storeMetadataToStorage: graph not in document: %s",
::rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)
.getStr());
continue;
}
const ::rtl::OUString relName( name.copy(len) );
if (relName == manifest) {
continue;
}
if (!isFileNameValid(relName) || isReservedFile(relName)) {
OSL_TRACE("storeMetadataToStorage: invalid file name: %s",
::rtl::OUStringToOString(relName, RTL_TEXTENCODING_UTF8)
.getStr());
continue;
}
try {
writeStream(*m_pImpl, i_xStorage, xName, relName, baseURI);
} catch (const uno::RuntimeException &) {
throw;
} catch (const io::IOException & e) {
throw lang::WrappedTargetException(
::rtl::OUString(
"storeMetadataToStorage: IO exception"),
*this, uno::makeAny(e));
} catch (const uno::Exception & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"storeMetadataToStorage: exception"),
*this, uno::makeAny(e));
}
}
} catch (const rdf::RepositoryException & e) {
throw lang::WrappedTargetRuntimeException(
::rtl::OUString(
"storeMetadataToStorage: exception"), *this, uno::makeAny(e));
}
}
void SAL_CALL
DocumentMetadataAccess::loadMetadataFromMedium(
const uno::Sequence< beans::PropertyValue > & i_rMedium)
throw (uno::RuntimeException, lang::IllegalArgumentException,
lang::WrappedTargetException)
{
uno::Reference xIn;
::comphelper::MediaDescriptor md(i_rMedium);
::rtl::OUString URL;
md[ ::comphelper::MediaDescriptor::PROP_URL() ] >>= URL;
::rtl::OUString BaseURL;
md[ ::comphelper::MediaDescriptor::PROP_DOCUMENTBASEURL() ] >>= BaseURL;
if (md.addInputStream()) {
md[ ::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] >>= xIn;
}
if (!xIn.is() && URL.isEmpty()) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromMedium: "
"inalid medium: no URL, no input stream"), *this, 0);
}
uno::Reference xStorage;
try {
const uno::Reference xMsf (
m_pImpl->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
if (xIn.is()) {
xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream(
xIn, xMsf);
} else { // fallback to url
xStorage = ::comphelper::OStorageHelper::GetStorageFromURL2(
URL, embed::ElementModes::READ, xMsf);
}
} catch (const uno::RuntimeException &) {
throw;
} catch (const io::IOException &) {
throw;
} catch (const uno::Exception & e) {
throw lang::WrappedTargetException(
::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromMedium: "
"exception"), *this, uno::makeAny(e));
}
if (!xStorage.is()) {
throw uno::RuntimeException(::rtl::OUString(
"DocumentMetadataAccess::loadMetadataFromMedium: "
"cannot get Storage"), *this);
}
uno::Reference xBaseURI;
try {
xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, BaseURL);
} catch (const uno::Exception &) {
// fall back to URL
try {
xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, URL);
} catch (const uno::Exception &) {
OSL_FAIL("cannot create base URI");
}
}
uno::Reference xIH;
md[ ::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER() ] >>= xIH;
loadMetadataFromStorage(xStorage, xBaseURI, xIH);
}
void SAL_CALL
DocumentMetadataAccess::storeMetadataToMedium(
const uno::Sequence< beans::PropertyValue > & i_rMedium)
throw (uno::RuntimeException, lang::IllegalArgumentException,
lang::WrappedTargetException)
{
::comphelper::MediaDescriptor md(i_rMedium);
::rtl::OUString URL;
md[ ::comphelper::MediaDescriptor::PROP_URL() ] >>= URL;
if (URL.isEmpty()) {
throw lang::IllegalArgumentException(::rtl::OUString(
"DocumentMetadataAccess::storeMetadataToMedium: "
"invalid medium: no URL"), *this, 0);
}
SfxMedium aMedium(i_rMedium);
uno::Reference xStorage(aMedium.GetOutputStorage());
bool sfx(false);
if (xStorage.is()) {
sfx = true;
} else {
const uno::Reference xMsf (
m_pImpl->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
xStorage = ::comphelper::OStorageHelper::GetStorageFromURL2(
URL, embed::ElementModes::WRITE, xMsf);
}
if (!xStorage.is()) {
throw uno::RuntimeException(::rtl::OUString(
"DocumentMetadataAccess::storeMetadataToMedium: "
"cannot get Storage"), *this);
}
// set MIME type of the storage
::comphelper::MediaDescriptor::const_iterator iter
= md.find(::comphelper::MediaDescriptor::PROP_MEDIATYPE());
if (iter != md.end()) {
uno::Reference< beans::XPropertySet > xProps(xStorage,
uno::UNO_QUERY_THROW);
try {
// this is NOT supported in FileSystemStorage
xProps->setPropertyValue(
::comphelper::MediaDescriptor::PROP_MEDIATYPE(),
iter->second);
} catch (const uno::Exception &) { }
}
storeMetadataToStorage(xStorage);
if (sfx) {
const sal_Bool bOk = aMedium.Commit();
aMedium.Close();
if ( !bOk ) {
sal_uInt32 nError = aMedium.GetError();
if ( nError == ERRCODE_NONE ) {
nError = ERRCODE_IO_GENERAL;
}
task::ErrorCodeIOException ex( ::rtl::OUString(),
uno::Reference< uno::XInterface >(), nError);
throw lang::WrappedTargetException(::rtl::OUString(), *this,
uno::makeAny(ex));
}
}
}
} // namespace sfx2
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */