package/inc/ZipPackage.hxx | 14 + package/source/zippackage/ZipPackage.cxx | 25 ++ writerperfect/source/common/WPXSvStream.cxx | 299 +++++++++++++++++++++++++++- 3 files changed, 326 insertions(+), 12 deletions(-)
New commits: commit 723863ff26f46e294adde61009b85f6f0e28b5b0 Author: David Tardon <dtar...@redhat.com> Date: Wed Jan 15 21:15:28 2014 +0100 finish zip support in WPXSvInputStream Change-Id: I48017873991abdc054e8be93912f2b2f5ae4383f diff --git a/writerperfect/source/common/WPXSvStream.cxx b/writerperfect/source/common/WPXSvStream.cxx index 9bc6984..0084ec3 100644 --- a/writerperfect/source/common/WPXSvStream.cxx +++ b/writerperfect/source/common/WPXSvStream.cxx @@ -9,7 +9,10 @@ #include "WPXSvStream.hxx" +#include <com/sun/star/container/XEnumerationAccess.hpp> #include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> #include <com/sun/star/uno/Any.hxx> #include <comphelper/processfactory.hxx> @@ -86,9 +89,9 @@ const rtl::OUString concatPath(const rtl::OUString &lhs, const rtl::OUString &rh return lhs + "/" + rhs; } -struct StreamData +struct OLEStreamData { - explicit StreamData(const rtl::OString &rName); + explicit OLEStreamData(const rtl::OString &rName); SotStorageStreamRefWrapper stream; @@ -136,12 +139,12 @@ private: public: SotStorageRefWrapper mxRootStorage; //< root storage of the OLE2 OLEStorageMap_t maStorageMap; //< map of all sub storages by name - ::std::vector< StreamData > maStreams; //< list of streams and their names + ::std::vector< OLEStreamData > maStreams; //< list of streams and their names NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams) bool mbInitialized; }; -StreamData::StreamData(const rtl::OString &rName) +OLEStreamData::OLEStreamData(const rtl::OString &rName) : stream() , name(rName) { @@ -202,7 +205,7 @@ void OLEStorageImpl::traverse(const SotStorageRef &rStorage, const rtl::OUString { if (aIt->IsStream()) { - maStreams.push_back(StreamData(rtl::OUStringToOString(aIt->GetName(), RTL_TEXTENCODING_UTF8))); + maStreams.push_back(OLEStreamData(rtl::OUStringToOString(aIt->GetName(), RTL_TEXTENCODING_UTF8))); maNameMap[concatPath(rPath, aIt->GetName())] = maStreams.size() - 1; } else if (aIt->IsStorage()) @@ -243,6 +246,162 @@ SotStorageStreamRef OLEStorageImpl::createStream(const rtl::OUString &rPath) } +namespace +{ + +struct ZipStreamData +{ + explicit ZipStreamData(const rtl::OString &rName); + + Reference<XInputStream> xStream; + + /** Name of the stream. + * + * This is not @c rtl::OUString, because we need to be able to + * produce const char* from it. + */ + rtl::OString aName; +}; + +typedef boost::unordered_map<rtl::OUString, Reference<XInputStream>, rtl::OUStringHash> ZipStorageMap_t; + +/** Representation of a Zip storage. + * + * This is quite similar to OLEStorageImpl, except that we do not need + * to keep all storages (folders) open. + */ +struct ZipStorageImpl +{ + ZipStorageImpl(const Reference<container::XHierarchicalNameAccess> &rxRoot); + + /** Initialize for access. + * + * This creates a bidirectional map of stream names to their + * indexes (index of a stream is determined by deep-first + * traversal). + */ + void initialize(); + + Reference<XInputStream> getStream(const rtl::OUString &rPath); + Reference<XInputStream> getStream(std::size_t nId); + +private: + void traverse(const Reference<container::XEnumeration> &rxEnum, const rtl::OUString &rPath); + + Reference<XInputStream> createStream(const rtl::OUString &rPath); + +public: + Reference<container::XHierarchicalNameAccess> mxRoot; //< root of the Zip + ::std::vector< ZipStreamData > maStreams; //< list of streams and their names + NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams) + bool mbInitialized; +}; + +ZipStreamData::ZipStreamData(const rtl::OString &rName) + : xStream() + , aName(rName) +{ +} + +ZipStorageImpl::ZipStorageImpl(const Reference<container::XHierarchicalNameAccess> &rxRoot) + : mxRoot(rxRoot) + , maStreams() + , maNameMap() + , mbInitialized(false) +{ + assert(mxRoot.is()); +} + +void ZipStorageImpl::initialize() +{ + const Reference<container::XEnumerationAccess> xEnum(mxRoot, UNO_QUERY); + + if (xEnum.is()) + traverse(xEnum->createEnumeration(), ""); + + mbInitialized = true; +} + +Reference<XInputStream> ZipStorageImpl::getStream(const rtl::OUString &rPath) +{ + NameMap_t::iterator aIt = maNameMap.find(rPath); + + // For the while don't return stream in this situation. + // Later, given how libcdr's zip stream implementation behaves, + // return the first stream in the storage if there is one. + if (maNameMap.end() == aIt) + return Reference<XInputStream>(); + + if (!maStreams[aIt->second].xStream.is()) + maStreams[aIt->second].xStream = createStream(rPath); + + return maStreams[aIt->second].xStream; +} + +Reference<XInputStream> ZipStorageImpl::getStream(const std::size_t nId) +{ + if (!maStreams[nId].xStream.is()) + maStreams[nId].xStream = createStream(rtl::OStringToOUString(maStreams[nId].aName, RTL_TEXTENCODING_UTF8)); + + return maStreams[nId].xStream; +} + +void ZipStorageImpl::traverse(const Reference<container::XEnumeration> &rxEnum, const rtl::OUString &rPath) +{ + while (rxEnum->hasMoreElements()) + { + Any aItem; + try + { + aItem = rxEnum->nextElement(); + } + catch (const Exception &) + { + continue; + } + + const Reference<container::XNamed> xNamed(aItem, UNO_QUERY); + const Reference<XActiveDataSink> xSink(aItem, UNO_QUERY); + const Reference<container::XEnumerationAccess> xEnum(aItem, UNO_QUERY); + + if (xSink.is() && xNamed.is()) + { + maStreams.push_back(ZipStreamData(rtl::OUStringToOString(xNamed->getName(), RTL_TEXTENCODING_UTF8))); + maNameMap[concatPath(rPath, xNamed->getName())] = maStreams.size() - 1; + } + else if (xEnum.is() && xNamed.is()) + { + const rtl::OUString aPath = concatPath(rPath, xNamed->getName()); + + // deep-first traversal + traverse(xEnum->createEnumeration(), aPath); + } + else + { + assert(0); + } + } +} + +Reference<XInputStream> ZipStorageImpl::createStream(const rtl::OUString &rPath) +{ + Reference<XInputStream> xStream; + + try + { + const Reference<XActiveDataSink> xSink(mxRoot->getByHierarchicalName(rPath), UNO_QUERY_THROW); + xStream.set(xSink->getInputStream(), UNO_QUERY_THROW); + } + catch (const Exception &) + { + // nothing needed + } + + return xStream; +} + +} + class WPXSvInputStreamImpl { public : @@ -269,6 +428,7 @@ private: void ensureOLEIsInitialized(); bool isZip(); + void ensureZipIsInitialized(); WPXInputStream *createWPXStream(const SotStorageStreamRef &rxStorage); @@ -277,10 +437,7 @@ private: ::com::sun::star::uno::Reference< ::com::sun::star::io::XSeekable > mxSeekable; ::com::sun::star::uno::Sequence< sal_Int8 > maData; boost::scoped_ptr< OLEStorageImpl > mpOLEStorage; - // TODO: this is not sufficient to implement RVNGInputStream, as - // packages::Package does not support any kind of enumeration of - // its content - ::com::sun::star::uno::Reference< container::XHierarchicalNameAccess > mxZipStorage; + boost::scoped_ptr< ZipStorageImpl > mpZipStorage; bool mbCheckedOLE; bool mbCheckedZip; public: @@ -295,7 +452,7 @@ WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference< XInputStream > xStream ) mxSeekable(xStream, UNO_QUERY), maData(0), mpOLEStorage(0), - mxZipStorage(), + mpZipStorage(0), mbCheckedOLE(false), mbCheckedZip(false), mnLength(0), @@ -391,7 +548,12 @@ bool WPXSvInputStreamImpl::isStructured() PositionHolder pos(mxSeekable); mxSeekable->seek(0); - return isOLE() || isZip(); + if (isOLE()) + return true; + + mxSeekable->seek(0); + + return isZip(); } unsigned WPXSvInputStreamImpl::subStreamCount() @@ -409,7 +571,14 @@ unsigned WPXSvInputStreamImpl::subStreamCount() return mpOLEStorage->maStreams.size(); } - // TODO: zip impl. + mxSeekable->seek(0); + + if (isZip()) + { + ensureZipIsInitialized(); + + return mpZipStorage->maStreams.size(); + } return 0; } @@ -432,7 +601,17 @@ const char *WPXSvInputStreamImpl::subStreamName(const unsigned id) return mpOLEStorage->maStreams[id].name.getStr(); } - // TODO: zip impl. + mxSeekable->seek(0); + + if (isZip()) + { + ensureZipIsInitialized(); + + if (mpZipStorage->maStreams.size() <= id) + return 0; + + return mpZipStorage->maStreams[id].aName.getStr(); + } return 0; } @@ -456,8 +635,13 @@ bool WPXSvInputStreamImpl::existsSubStream(const char *const name) return mpOLEStorage->maNameMap.end() != mpOLEStorage->maNameMap.find(aName); } + mxSeekable->seek(0); + if (isZip()) - return mxZipStorage->hasByHierarchicalName(aName); + { + ensureZipIsInitialized(); + return mpZipStorage->maNameMap.end() != mpZipStorage->maNameMap.find(aName); + } return false; } @@ -481,12 +665,15 @@ WPXInputStream *WPXSvInputStreamImpl::getSubStreamByName(const char *const name) return createWPXStream(mpOLEStorage->getStream(aName)); } + mxSeekable->seek(0); + if (isZip()) { + ensureZipIsInitialized(); + try { - const Reference<XStream> xStream(mxZipStorage->getByHierarchicalName(aName), UNO_QUERY_THROW); - return new WPXSvInputStream(xStream->getInputStream()); + return new WPXSvInputStream(mpZipStorage->getStream(aName)); } catch (const Exception &) { @@ -515,8 +702,24 @@ WPXInputStream *WPXSvInputStreamImpl::getSubStreamById(const unsigned id) return createWPXStream(mpOLEStorage->getStream(id)); } - // TODO: zip impl. + mxSeekable->seek(0); + + if (isZip()) + { + ensureZipIsInitialized(); + + if (mpZipStorage->maStreams.size() <= id) + return 0; + try + { + return new WPXSvInputStream(mpZipStorage->getStream(id)); + } + catch (const Exception &) + { + // nothing needed + } + } return 0; } @@ -568,9 +771,10 @@ bool WPXSvInputStreamImpl::isZip() aArgs[0] <<= mxStream; const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext(), UNO_QUERY_THROW); - mxZipStorage.set( + const Reference<container::XHierarchicalNameAccess> xZipStorage( xContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.packages.Package", aArgs, xContext), UNO_QUERY_THROW); + mpZipStorage.reset(new ZipStorageImpl(xZipStorage)); } catch (const Exception &) { @@ -580,7 +784,7 @@ bool WPXSvInputStreamImpl::isZip() mbCheckedZip = true; } - return mxZipStorage.is(); + return bool(mpZipStorage); } void WPXSvInputStreamImpl::ensureOLEIsInitialized() @@ -591,6 +795,14 @@ void WPXSvInputStreamImpl::ensureOLEIsInitialized() mpOLEStorage->initialize(utl::UcbStreamHelper::CreateStream( mxStream )); } +void WPXSvInputStreamImpl::ensureZipIsInitialized() +{ + assert(mpZipStorage); + + if (!mpZipStorage->mbInitialized) + mpZipStorage->initialize(); +} + WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) : mpImpl(new WPXSvInputStreamImpl(xStream)) { commit 5b2cca80eeb2c8ee210820cc8ed95e5d69214807 Author: David Tardon <dtar...@redhat.com> Date: Wed Jan 15 15:14:04 2014 +0100 impl. enumeration for ZipPackage Change-Id: I800d22d8ec99e943b59467cf64b96aaa1f797953 diff --git a/package/inc/ZipPackage.hxx b/package/inc/ZipPackage.hxx index 3631799..9ee401b 100644 --- a/package/inc/ZipPackage.hxx +++ b/package/inc/ZipPackage.hxx @@ -19,8 +19,9 @@ #ifndef _ZIP_PACKAGE_HXX #define _ZIP_PACKAGE_HXX -#include <cppuhelper/implbase7.hxx> +#include <cppuhelper/implbase8.hxx> #include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> #include <com/sun/star/container/XHierarchicalNameAccess.hpp> #include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/util/XChangesBatch.hpp> @@ -63,12 +64,13 @@ enum InitialisationMode e_IMode_XStream }; -class ZipPackage : public cppu::WeakImplHelper7 +class ZipPackage : public cppu::WeakImplHelper8 < com::sun::star::lang::XInitialization, com::sun::star::lang::XSingleServiceFactory, com::sun::star::lang::XUnoTunnel, com::sun::star::lang::XServiceInfo, + com::sun::star::container::XEnumerationAccess, com::sun::star::container::XHierarchicalNameAccess, com::sun::star::util::XChangesBatch, com::sun::star::beans::XPropertySet @@ -141,6 +143,14 @@ public: // XInitialization virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + // XEnumerationAccess + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration() + throw(::com::sun::star::uno::RuntimeException); + // XElementType + virtual ::com::sun::star::uno::Type getElementType() + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool hasElements() + throw(::com::sun::star::uno::RuntimeException); // XHierarchicalNameAccess virtual ::com::sun::star::uno::Any SAL_CALL getByHierarchicalName( const OUString& aName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx index f20b1f0..77b7862 100644 --- a/package/source/zippackage/ZipPackage.cxx +++ b/package/source/zippackage/ZipPackage.cxx @@ -66,6 +66,7 @@ #include <osl/time.h> #include "com/sun/star/io/XAsyncOutputMonitor.hpp" +#include <cassert> #include <cstring> #include <memory> #include <vector> @@ -777,6 +778,30 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) } } +::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL ZipPackage::createEnumeration() + throw( RuntimeException ) +{ + assert(m_pRootFolder); + + return m_pRootFolder->createEnumeration(); +} + +::com::sun::star::uno::Type ZipPackage::getElementType() + throw( RuntimeException ) +{ + assert(m_pRootFolder); + + return m_pRootFolder->getElementType(); +} + +sal_Bool ZipPackage::hasElements() + throw( RuntimeException ) +{ + assert(m_pRootFolder); + + return m_pRootFolder->hasElements(); +} + Any SAL_CALL ZipPackage::getByHierarchicalName( const OUString& aName ) throw( NoSuchElementException, RuntimeException ) { commit e9a036aca1062fd5512b8dbd93ef7172831b3bc4 Author: David Tardon <dtar...@redhat.com> Date: Wed Jan 15 14:33:58 2014 +0100 add BIPU support for zip to WPXSvInputStream Change-Id: I14d6febcff49421b6ee3f2c463e78ff98660aab5 diff --git a/writerperfect/source/common/WPXSvStream.cxx b/writerperfect/source/common/WPXSvStream.cxx index d705ba5..9bc6984 100644 --- a/writerperfect/source/common/WPXSvStream.cxx +++ b/writerperfect/source/common/WPXSvStream.cxx @@ -9,6 +9,11 @@ #include "WPXSvStream.hxx" +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/uno/Any.hxx> + +#include <comphelper/processfactory.hxx> + #include <rtl/string.hxx> #include <tools/stream.hxx> #include <unotools/streamwrap.hxx> @@ -23,6 +28,10 @@ using namespace ::com::sun::star::uno; using namespace ::com::sun::star::io; +namespace container = com::sun::star::container; +namespace lang = com::sun::star::lang; +namespace packages = com::sun::star::packages; + namespace { @@ -259,6 +268,8 @@ private: bool isOLE(); void ensureOLEIsInitialized(); + bool isZip(); + WPXInputStream *createWPXStream(const SotStorageStreamRef &rxStorage); private: @@ -266,7 +277,12 @@ private: ::com::sun::star::uno::Reference< ::com::sun::star::io::XSeekable > mxSeekable; ::com::sun::star::uno::Sequence< sal_Int8 > maData; boost::scoped_ptr< OLEStorageImpl > mpOLEStorage; + // TODO: this is not sufficient to implement RVNGInputStream, as + // packages::Package does not support any kind of enumeration of + // its content + ::com::sun::star::uno::Reference< container::XHierarchicalNameAccess > mxZipStorage; bool mbCheckedOLE; + bool mbCheckedZip; public: sal_Int64 mnLength; unsigned char *mpReadBuffer; @@ -279,7 +295,9 @@ WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference< XInputStream > xStream ) mxSeekable(xStream, UNO_QUERY), maData(0), mpOLEStorage(0), + mxZipStorage(), mbCheckedOLE(false), + mbCheckedZip(false), mnLength(0), mpReadBuffer(0), mnReadBufferLength(0), @@ -373,7 +391,7 @@ bool WPXSvInputStreamImpl::isStructured() PositionHolder pos(mxSeekable); mxSeekable->seek(0); - return isOLE(); + return isOLE() || isZip(); } unsigned WPXSvInputStreamImpl::subStreamCount() @@ -391,6 +409,8 @@ unsigned WPXSvInputStreamImpl::subStreamCount() return mpOLEStorage->maStreams.size(); } + // TODO: zip impl. + return 0; } @@ -412,6 +432,8 @@ const char *WPXSvInputStreamImpl::subStreamName(const unsigned id) return mpOLEStorage->maStreams[id].name.getStr(); } + // TODO: zip impl. + return 0; } @@ -426,14 +448,17 @@ bool WPXSvInputStreamImpl::existsSubStream(const char *const name) PositionHolder pos(mxSeekable); mxSeekable->seek(0); + const rtl::OUString aName(rtl::OStringToOUString(rtl::OString(name), RTL_TEXTENCODING_UTF8)); + if (isOLE()) { ensureOLEIsInitialized(); - - const rtl::OUString aName(rtl::OStringToOUString(rtl::OString(name), RTL_TEXTENCODING_UTF8)); return mpOLEStorage->maNameMap.end() != mpOLEStorage->maNameMap.find(aName); } + if (isZip()) + return mxZipStorage->hasByHierarchicalName(aName); + return false; } @@ -448,14 +473,27 @@ WPXInputStream *WPXSvInputStreamImpl::getSubStreamByName(const char *const name) PositionHolder pos(mxSeekable); mxSeekable->seek(0); + const rtl::OUString aName(rtl::OStringToOUString(rtl::OString(name), RTL_TEXTENCODING_UTF8)); + if (isOLE()) { ensureOLEIsInitialized(); - - const rtl::OUString aName(rtl::OStringToOUString(rtl::OString(name), RTL_TEXTENCODING_UTF8)); return createWPXStream(mpOLEStorage->getStream(aName)); } + if (isZip()) + { + try + { + const Reference<XStream> xStream(mxZipStorage->getByHierarchicalName(aName), UNO_QUERY_THROW); + return new WPXSvInputStream(xStream->getInputStream()); + } + catch (const Exception &) + { + // nothing needed + } + } + return 0; } @@ -477,6 +515,8 @@ WPXInputStream *WPXSvInputStreamImpl::getSubStreamById(const unsigned id) return createWPXStream(mpOLEStorage->getStream(id)); } + // TODO: zip impl. + return 0; } @@ -516,6 +556,33 @@ bool WPXSvInputStreamImpl::isOLE() return bool(mpOLEStorage); } +bool WPXSvInputStreamImpl::isZip() +{ + if (!mbCheckedZip) + { + assert(0 == mxSeekable->getPosition()); + + try + { + Sequence<Any> aArgs(1); + aArgs[0] <<= mxStream; + + const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext(), UNO_QUERY_THROW); + mxZipStorage.set( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.packages.Package", aArgs, xContext), + UNO_QUERY_THROW); + } + catch (const Exception &) + { + // ignore + } + + mbCheckedZip = true; + } + + return mxZipStorage.is(); +} + void WPXSvInputStreamImpl::ensureOLEIsInitialized() { assert(mpOLEStorage); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits