diff options
Diffstat (limited to 'chart2/source/model/filter/XMLFilter.cxx')
-rw-r--r-- | chart2/source/model/filter/XMLFilter.cxx | 773 |
1 files changed, 773 insertions, 0 deletions
diff --git a/chart2/source/model/filter/XMLFilter.cxx b/chart2/source/model/filter/XMLFilter.cxx new file mode 100644 index 000000000..a31f1d9f6 --- /dev/null +++ b/chart2/source/model/filter/XMLFilter.cxx @@ -0,0 +1,773 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <XMLFilter.hxx> +#include <MediaDescriptorHelper.hxx> + +#include <officecfg/Office/Common.hxx> +#include <svtools/sfxecode.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <comphelper/documentconstants.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/sequence.hxx> + +#include <osl/diagnose.h> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/Writer.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/StorageFactory.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/xml/sax/Parser.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XFastParser.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/document/GraphicStorageHandler.hpp> +#include <tools/diagnose_ex.h> +#include <sal/log.hxx> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::osl::MutexGuard; + +namespace +{ +constexpr OUStringLiteral sXML_metaStreamName = u"meta.xml"; +constexpr OUStringLiteral sXML_styleStreamName = u"styles.xml"; +constexpr OUStringLiteral sXML_contentStreamName = u"content.xml"; + + +uno::Reference< embed::XStorage > lcl_getWriteStorage( + const Sequence< beans::PropertyValue >& rMediaDescriptor, + const uno::Reference< uno::XComponentContext >& xContext,const OUString& _sMediaType) +{ + uno::Reference< embed::XStorage > xStorage; + try + { + apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor ); + if( aMDHelper.ISSET_Storage ) + { + xStorage = aMDHelper.Storage; + } + else + { + Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) ); + + std::vector< beans::PropertyValue > aPropertiesForStorage; + + for( sal_Int32 i=rMediaDescriptor.getLength(); i--; ) + { + // properties understood by storage factory + // (see package/source/xstor/xfactory.cxx for details) + if ( rMediaDescriptor[i].Name == "InteractionHandler" || rMediaDescriptor[i].Name == "Password" || rMediaDescriptor[i].Name == "RepairPackage" ) + { + aPropertiesForStorage.push_back( rMediaDescriptor[i] ); + } + } + + if( aMDHelper.ISSET_Storage ) + xStorage.set( aMDHelper.Storage ); + else + { + Sequence< uno::Any > aStorageArgs{ + aMDHelper.ISSET_OutputStream ? uno::Any(aMDHelper.OutputStream) + : uno::Any(aMDHelper.URL), + uno::Any(embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE), + uno::Any(comphelper::containerToSequence( aPropertiesForStorage )) + }; + + xStorage.set( + xStorageFact->createInstanceWithArguments( aStorageArgs ), + uno::UNO_QUERY_THROW ); + } + } + + // set correct media type at storage + uno::Reference<beans::XPropertySet> xProp(xStorage,uno::UNO_QUERY); + OUString aMediaType; + if ( ! xProp.is() || + ! ( xProp->getPropertyValue( "MediaType") >>= aMediaType ) || + ( aMediaType.isEmpty() )) + { + xProp->setPropertyValue( "MediaType", uno::Any( _sMediaType )); + } + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xStorage; +} + +uno::Reference< embed::XStorage > lcl_getReadStorage( + const Sequence< beans::PropertyValue >& rMediaDescriptor, + const uno::Reference< uno::XComponentContext >& xContext) +{ + uno::Reference< embed::XStorage > xStorage; + + try + { + apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor ); + if( aMDHelper.ISSET_Storage ) + { + xStorage = aMDHelper.Storage; + } + else + { + // get XStream from MediaDescriptor + uno::Reference< io::XInputStream > xStream; + std::vector< beans::PropertyValue > aPropertiesForStorage; + for( sal_Int32 i=rMediaDescriptor.getLength(); i--; ) + { + if( rMediaDescriptor[i].Name == "InputStream" ) + xStream.set( rMediaDescriptor[i].Value, uno::UNO_QUERY ); + + // properties understood by storage factory + // (see package/source/xstor/xfactory.cxx for details) + if ( rMediaDescriptor[i].Name == "InteractionHandler" || rMediaDescriptor[i].Name == "Password" || rMediaDescriptor[i].Name == "RepairPackage" ) + { + aPropertiesForStorage.push_back( rMediaDescriptor[i] ); + } + } + OSL_ENSURE( xStream.is(), "No Stream" ); + if( ! xStream.is()) + return xStorage; + + // convert XInputStream to XStorage via the storage factory + Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) ); + Sequence< uno::Any > aStorageArgs{ + uno::Any(xStream), + uno::Any(embed::ElementModes::READ | embed::ElementModes::NOCREATE), + uno::Any(comphelper::containerToSequence( aPropertiesForStorage )) + }; + xStorage.set( + xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW ); + } + + OSL_ENSURE( xStorage.is(), "No Storage" ); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xStorage; +} + +} // anonymous namespace + +namespace chart +{ + +XMLFilter::XMLFilter( Reference< uno::XComponentContext > const & xContext ) : + m_xContext( xContext ), + m_bCancelOperation( false ) +{} + +XMLFilter::~XMLFilter() +{} + +// ____ XFilter ____ +sal_Bool SAL_CALL XMLFilter::filter( + const Sequence< beans::PropertyValue >& aDescriptor ) +{ + bool bResult = false; + + MutexGuard aGuard( m_aMutex ); + + // ignore cancel flag at start of function + // note: is currently ignored during import/export + if( m_bCancelOperation ) + m_bCancelOperation = false; + + if( m_xSourceDoc.is()) + { + OSL_ENSURE( ! m_xTargetDoc.is(), "source doc is set -> target document should not be set" ); + if( impl_Export( m_xSourceDoc, + aDescriptor ) == ERRCODE_NONE ) + { + m_xSourceDoc = nullptr; + bResult = true; + } + } + else if( m_xTargetDoc.is()) + { + if( impl_Import( m_xTargetDoc, + aDescriptor ) == ERRCODE_NONE ) + { + m_xTargetDoc = nullptr; + bResult = true; + } + } + else + { + OSL_FAIL( "filter() called with no document set" ); + } + + return bResult; +} + +void SAL_CALL XMLFilter::cancel() +{ + // if mutex is locked set "cancel state" + // note: is currently ignored in filter-method + if( ! m_aMutex.tryToAcquire()) + { + m_bCancelOperation = true; + } +} + +// ____ XImporter ____ +void SAL_CALL XMLFilter::setTargetDocument( + const Reference< lang::XComponent >& Document ) +{ + MutexGuard aGuard( m_aMutex ); + OSL_ENSURE( ! m_xSourceDoc.is(), "Setting target doc while source doc is set" ); + + m_xTargetDoc = Document; +} + +// ____ XExporter ____ +void SAL_CALL XMLFilter::setSourceDocument( + const Reference< lang::XComponent >& Document ) +{ + MutexGuard aGuard( m_aMutex ); + OSL_ENSURE( ! m_xTargetDoc.is(), "Setting source doc while target doc is set" ); + + m_xSourceDoc = Document; +} + +ErrCode XMLFilter::impl_Import( + const Reference< lang::XComponent > & xDocumentComp, + const Sequence< beans::PropertyValue > & rMediaDescriptor ) +{ + ErrCode nWarning = ERRCODE_NONE; + + OSL_ENSURE( xDocumentComp.is(), "Import: No Model" ); + OSL_ENSURE( m_xContext.is(), "Import: No ComponentContext" ); + + if( ! (xDocumentComp.is() && + m_xContext.is())) + return nWarning; + + try + { + Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW ); + if( ! xServInfo->supportsService( "com.sun.star.chart2.ChartDocument")) + { + OSL_FAIL( "Import: No ChartDocument" ); + return ERRCODE_SFX_GENERAL; + } + + Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager()); + OSL_ENSURE( xFactory.is(), "Import: No Factory" ); + if( ! xFactory.is()) + return ERRCODE_SFX_GENERAL; + + bool bOasis = true; + isOasisFormat( rMediaDescriptor, bOasis ); + Reference< embed::XStorage > xStorage( lcl_getReadStorage( rMediaDescriptor, m_xContext)); + if( ! xStorage.is()) + return ERRCODE_SFX_GENERAL; + + uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler; + uno::Reference<lang::XMultiServiceFactory> xServiceFactory(xFactory, uno::UNO_QUERY); + if (xServiceFactory.is()) + { + uno::Sequence<uno::Any> aArgs{ uno::Any(xStorage) }; + xGraphicStorageHandler.set( + xServiceFactory->createInstanceWithArguments( + "com.sun.star.comp.Svx.GraphicImportHelper", aArgs), uno::UNO_QUERY); + } + + // create XPropertySet with extra information for the filter + /** property map for import info set */ + static comphelper::PropertyMapEntry const aImportInfoMap[] = + { + // necessary properties for XML progress bar at load time + { OUString("ProgressRange"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("ProgressMax"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("ProgressCurrent"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("PrivateData"), 0, cppu::UnoType<XInterface>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BaseURI"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BuildId"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + }; + uno::Reference< beans::XPropertySet > xImportInfo( + comphelper::GenericPropertySet_CreateInstance( + new comphelper::PropertySetInfo( aImportInfoMap ) ) ); + + // Set base URI and Hierarchical Name + OUString aHierarchName, aBaseUri; + // why retrieve this from the model when it's available as rMediaDescriptor? + uno::Reference<frame::XModel> const xModel(m_xTargetDoc, uno::UNO_QUERY); + if( xModel.is() ) + { + const uno::Sequence< beans::PropertyValue > aModProps = xModel->getArgs(); + for( beans::PropertyValue const & prop : aModProps ) + { + if( prop.Name == "HierarchicalDocumentName" ) + { + // Actually this argument only has meaning for embedded documents + prop.Value >>= aHierarchName; + } + else if( prop.Name == "DocumentBaseURL" ) + { + prop.Value >>= aBaseUri; + } + } + } + + // needed for relative URLs, but in clipboard copy/paste there may be none + SAL_INFO_IF(aBaseUri.isEmpty(), "chart2", "chart::XMLFilter: no base URL"); + if( !aBaseUri.isEmpty() ) + xImportInfo->setPropertyValue( "BaseURI", uno::Any( aBaseUri ) ); + + if( !aHierarchName.isEmpty() ) + xImportInfo->setPropertyValue( "StreamRelPath", uno::Any( aHierarchName ) ); + + // import meta information + if( bOasis ) + nWarning = impl_ImportStream( + sXML_metaStreamName, + "com.sun.star.comp.Chart.XMLOasisMetaImporter", + xStorage, xFactory, xGraphicStorageHandler, xImportInfo ); + + // import styles + ErrCode nTmpErr = impl_ImportStream( + sXML_styleStreamName, + bOasis + ? OUString("com.sun.star.comp.Chart.XMLOasisStylesImporter") + : OUString("com.sun.star.comp.Chart.XMLStylesImporter"), + xStorage, xFactory, xGraphicStorageHandler, xImportInfo ); + nWarning = nWarning != ERRCODE_NONE ? nWarning : nTmpErr; + + // import content + ErrCode nContentWarning = impl_ImportStream( + sXML_contentStreamName, + bOasis + ? OUString("com.sun.star.comp.Chart.XMLOasisContentImporter") + : OUString("com.sun.star.comp.Chart.XMLContentImporter"), + xStorage, xFactory, xGraphicStorageHandler, xImportInfo ); + nWarning = nWarning != ERRCODE_NONE ? nWarning : nContentWarning; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + + // something went awry + nWarning = ERRCODE_SFX_GENERAL; + } + + return nWarning; +} + +ErrCode XMLFilter::impl_ImportStream( + const OUString & rStreamName, + const OUString & rServiceName, + const Reference< embed::XStorage > & xStorage, + const Reference< lang::XMultiComponentFactory > & xFactory, + const Reference< document::XGraphicStorageHandler > & xGraphicStorageHandler, + uno::Reference< beans::XPropertySet > const & xImportInfo ) +{ + ErrCode nWarning = ERRCODE_SFX_GENERAL; + + if( ! (xStorage.is() && + xStorage->hasByName( rStreamName ))) + return ERRCODE_NONE; + + if( xImportInfo.is() ) + xImportInfo->setPropertyValue( "StreamName", uno::Any( rStreamName ) ); + + if( xStorage.is() && + xStorage->isStreamElement( rStreamName ) ) + { + try + { + auto xInputStream = + xStorage->openStreamElement( + rStreamName, + embed::ElementModes::READ | embed::ElementModes::NOCREATE ); + + // todo: encryption + + if( xInputStream.is()) + { + sal_Int32 nArgs = 0; + if( xGraphicStorageHandler.is()) + nArgs++; + if( xImportInfo.is()) + nArgs++; + + uno::Sequence< uno::Any > aFilterCompArgs( nArgs ); + auto aFilterCompArgsRange = asNonConstRange(aFilterCompArgs); + + nArgs = 0; + if( xGraphicStorageHandler.is()) + aFilterCompArgsRange[nArgs++] <<= xGraphicStorageHandler; + if( xImportInfo.is()) + aFilterCompArgsRange[ nArgs++ ] <<= xImportInfo; + + // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler + Reference< XInterface > xFilter = + xFactory->createInstanceWithArgumentsAndContext( rServiceName, aFilterCompArgs, m_xContext ); + assert(xFilter); + Reference< document::XImporter > xImporter( xFilter, uno::UNO_QUERY ); + assert(xImporter); + xImporter->setTargetDocument( Reference< lang::XComponent >( m_xTargetDoc, uno::UNO_SET_THROW )); + + if ( !m_sDocumentHandler.isEmpty() ) + { + try + { + uno::Sequence< uno::Any > aArgs{ + uno::Any(beans::NamedValue("DocumentHandler", uno::Any(xFilter))), + uno::Any(beans::NamedValue("Model", uno::Any(m_xTargetDoc))) + }; + + xFilter = xFactory->createInstanceWithArgumentsAndContext(m_sDocumentHandler,aArgs,m_xContext); + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("chart2", "failed to instantiate " << m_sDocumentHandler); + } + } + xml::sax::InputSource aParserInput; + aParserInput.aInputStream.set(xInputStream, uno::UNO_QUERY_THROW); + + // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler + Reference< xml::sax::XFastParser > xFastParser(xFilter, uno::UNO_QUERY); + if (xFastParser.is()) + xFastParser->parseStream(aParserInput); + else + { + Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(m_xContext); + xParser->setDocumentHandler( uno::Reference<xml::sax::XDocumentHandler>(xFilter, uno::UNO_QUERY_THROW) ); + xParser->parseStream(aParserInput); + } + } + + // load was successful + nWarning = ERRCODE_NONE; + } + catch (const xml::sax::SAXParseException&) + { + // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD + } + catch (const xml::sax::SAXException&) + { + // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD + } + catch (const packages::zip::ZipIOException&) + { + nWarning = ERRCODE_IO_BROKENPACKAGE; + } + catch (const io::IOException&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return nWarning; +} + +ErrCode XMLFilter::impl_Export( + const Reference< lang::XComponent > & xDocumentComp, + const Sequence< beans::PropertyValue > & rMediaDescriptor ) +{ + m_aMediaDescriptor = rMediaDescriptor; + //save + + ErrCode nWarning = ERRCODE_NONE; + + OSL_ENSURE( xDocumentComp.is(), "Export: No Model" ); + OSL_ENSURE( m_xContext.is(), "Export: No ComponentContext" ); + + if( !xDocumentComp.is() || !m_xContext.is() ) + return nWarning; + + try + { + Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW ); + if( ! xServInfo->supportsService( "com.sun.star.chart2.ChartDocument")) + { + OSL_FAIL( "Export: No ChartDocument" ); + return ERRCODE_SFX_GENERAL; + } + + Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager()); + OSL_ENSURE( xFactory.is(), "Export: No Factory" ); + if( ! xFactory.is()) + return ERRCODE_SFX_GENERAL; + uno::Reference< lang::XMultiServiceFactory > xServiceFactory( m_xContext->getServiceManager(), uno::UNO_QUERY); + if( ! xServiceFactory.is()) + return ERRCODE_SFX_GENERAL; + + uno::Reference< xml::sax::XWriter > xSaxWriter = xml::sax::Writer::create(m_xContext); + + bool bOasis = true; + isOasisFormat( rMediaDescriptor, bOasis ); + + uno::Reference< embed::XStorage > xStorage( lcl_getWriteStorage( rMediaDescriptor, m_xContext, getMediaType(bOasis) ) ); + OSL_ENSURE( xStorage.is(), "No Storage" ); + if( ! xStorage.is()) + return ERRCODE_SFX_GENERAL; + + uno::Reference< xml::sax::XDocumentHandler> xDocHandler = xSaxWriter; + + if ( !m_sDocumentHandler.isEmpty() ) + { + try + { + uno::Sequence< uno::Any > aArgs{ + uno::Any(beans::NamedValue("DocumentHandler", uno::Any(xDocHandler))), + uno::Any(beans::NamedValue("Model", uno::Any(xDocumentComp))) + }; + + xDocHandler.set(xServiceFactory->createInstanceWithArguments(m_sDocumentHandler,aArgs), uno::UNO_QUERY ); + xSaxWriter.set(xDocHandler,uno::UNO_QUERY); + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "chart2", "Exception caught!"); + } + } + + Reference<document::XGraphicStorageHandler> xGraphicStorageHandler; + xGraphicStorageHandler.set(document::GraphicStorageHandler::createWithStorage(m_xContext, xStorage)); + + // property map for export info set + static comphelper::PropertyMapEntry const aExportInfoMap[] = + { + { OUString("UsePrettyPrinting"), 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("ExportTableNumberList"), 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + }; + + uno::Reference< beans::XPropertySet > xInfoSet = + comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ); + + bool bUsePrettyPrinting( officecfg::Office::Common::Save::Document::PrettyPrinting::get() ); + xInfoSet->setPropertyValue( "UsePrettyPrinting", uno::Any( bUsePrettyPrinting ) ); + if( ! bOasis ) + xInfoSet->setPropertyValue( "ExportTableNumberList", uno::Any( true )); + + sal_Int32 nArgs = 2; + if( xGraphicStorageHandler.is()) + nArgs++; + + uno::Sequence< uno::Any > aFilterProperties( nArgs ); + { + auto pFilterProperties = aFilterProperties.getArray(); + nArgs = 0; + pFilterProperties[ nArgs++ ] <<= xInfoSet; + pFilterProperties[ nArgs++ ] <<= xDocHandler; + if( xGraphicStorageHandler.is()) + pFilterProperties[ nArgs++ ] <<= xGraphicStorageHandler; + } + + // export meta information + if( bOasis ) + nWarning = impl_ExportStream( + sXML_metaStreamName, + "com.sun.star.comp.Chart.XMLOasisMetaExporter", + xStorage, xSaxWriter, xServiceFactory, aFilterProperties ); + + // export styles + ErrCode nTmp = impl_ExportStream( + sXML_styleStreamName, + bOasis + ? OUString("com.sun.star.comp.Chart.XMLOasisStylesExporter") + : OUString("com.sun.star.comp.Chart.XMLStylesExporter"), // soffice 6/7 + xStorage, xSaxWriter, xServiceFactory, aFilterProperties ); + nWarning = nWarning != ERRCODE_NONE ? nWarning : nTmp; + + // export content + ErrCode nContentWarning = impl_ExportStream( + sXML_contentStreamName, + bOasis + ? OUString("com.sun.star.comp.Chart.XMLOasisContentExporter") + : OUString("com.sun.star.comp.Chart.XMLContentExporter"), + xStorage, xSaxWriter, xServiceFactory, aFilterProperties ); + nWarning = nWarning != ERRCODE_NONE ? nWarning : nContentWarning; + + Reference< lang::XComponent > xComp(xGraphicStorageHandler, uno::UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + + uno::Reference<embed::XTransactedObject> xTransact( xStorage ,uno::UNO_QUERY); + if ( xTransact.is() ) + xTransact->commit(); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + + // something went awry + nWarning = ERRCODE_SFX_GENERAL; + } + + return nWarning; +} + +ErrCode XMLFilter::impl_ExportStream( + const OUString & rStreamName, + const OUString & rServiceName, + const Reference< embed::XStorage > & xStorage, + const uno::Reference< xml::sax::XWriter >& xActiveDataSource, + const Reference< lang::XMultiServiceFactory >& xServiceFactory, + const Sequence< uno::Any > & rFilterProperties ) +{ + try + { + if( !xServiceFactory.is() ) + return ERRCODE_SFX_GENERAL; + if( !xStorage.is() ) + return ERRCODE_SFX_GENERAL; + if ( !xActiveDataSource.is() ) + return ERRCODE_SFX_GENERAL; + + uno::Reference< io::XStream > xStream( xStorage->openStreamElement( + rStreamName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ) ); + if ( !xStream.is() ) + return ERRCODE_SFX_GENERAL; + uno::Reference< io::XOutputStream > xOutputStream( xStream->getOutputStream() ); + if ( !xOutputStream.is() ) + return ERRCODE_SFX_GENERAL; + + uno::Reference< beans::XPropertySet > xStreamProp( xOutputStream, uno::UNO_QUERY ); + if(xStreamProp.is()) try + { + xStreamProp->setPropertyValue( "MediaType", uno::Any( OUString("text/xml") ) ); + xStreamProp->setPropertyValue( "Compressed", uno::Any( true ) );//@todo? + xStreamProp->setPropertyValue( "UseCommonStoragePasswordEncryption", uno::Any( true ) ); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + xActiveDataSource->setOutputStream(xOutputStream); + + // set Base URL + { + uno::Reference< beans::XPropertySet > xInfoSet; + if( rFilterProperties.hasElements() ) + rFilterProperties.getConstArray()[0] >>= xInfoSet; + OSL_ENSURE( xInfoSet.is(), "missing infoset for export" ); + if( xInfoSet.is() ) + xInfoSet->setPropertyValue( "StreamName", uno::Any( rStreamName ) ); + } + + Reference< XExporter > xExporter( xServiceFactory->createInstanceWithArguments( + rServiceName, rFilterProperties ), uno::UNO_QUERY); + if ( !xExporter.is() ) + return ERRCODE_SFX_GENERAL; + + xExporter->setSourceDocument( m_xSourceDoc ); + + uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY ); + if ( !xFilter.is() ) + return ERRCODE_SFX_GENERAL; + + xFilter->filter(m_aMediaDescriptor); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return ERRCODE_NONE; +} + +void XMLFilter::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS ) +{ + apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor ); + if( aMDHelper.ISSET_FilterName ) + rOutOASIS = aMDHelper.FilterName == "chart8"; +} +OUString XMLFilter::getMediaType(bool _bOasis) +{ + return _bOasis ? OUString(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII) : OUString(MIMETYPE_VND_SUN_XML_CHART_ASCII); +} + +OUString SAL_CALL XMLFilter::getImplementationName() +{ + return "com.sun.star.comp.chart2.XMLFilter"; +} + +sal_Bool SAL_CALL XMLFilter::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL XMLFilter::getSupportedServiceNames() +{ + return { + "com.sun.star.document.ImportFilter", + "com.sun.star.document.ExportFilter" + }; + // todo: services are incomplete. Missing: + // XInitialization, XNamed +} + +void XMLReportFilterHelper::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS ) +{ + apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor ); + if( aMDHelper.ISSET_FilterName ) + rOutOASIS = aMDHelper.FilterName == "StarOffice XML (Base) Report Chart"; +} +OUString XMLReportFilterHelper::getMediaType(bool ) +{ + return MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_XMLFilter_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::XMLFilter(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_report_XMLFilter_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ::chart::XMLReportFilterHelper(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |