Kaydet (Commit) 723863ff authored tarafından David Tardon's avatar David Tardon

finish zip support in WPXSvInputStream

Change-Id: I48017873991abdc054e8be93912f2b2f5ae4383f
üst 5b2cca80
...@@ -9,7 +9,10 @@ ...@@ -9,7 +9,10 @@
#include "WPXSvStream.hxx" #include "WPXSvStream.hxx"
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.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 <com/sun/star/uno/Any.hxx>
#include <comphelper/processfactory.hxx> #include <comphelper/processfactory.hxx>
...@@ -86,9 +89,9 @@ const rtl::OUString concatPath(const rtl::OUString &lhs, const rtl::OUString &rh ...@@ -86,9 +89,9 @@ const rtl::OUString concatPath(const rtl::OUString &lhs, const rtl::OUString &rh
return lhs + "/" + rhs; return lhs + "/" + rhs;
} }
struct StreamData struct OLEStreamData
{ {
explicit StreamData(const rtl::OString &rName); explicit OLEStreamData(const rtl::OString &rName);
SotStorageStreamRefWrapper stream; SotStorageStreamRefWrapper stream;
...@@ -136,12 +139,12 @@ private: ...@@ -136,12 +139,12 @@ private:
public: public:
SotStorageRefWrapper mxRootStorage; //< root storage of the OLE2 SotStorageRefWrapper mxRootStorage; //< root storage of the OLE2
OLEStorageMap_t maStorageMap; //< map of all sub storages by name 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) NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams)
bool mbInitialized; bool mbInitialized;
}; };
StreamData::StreamData(const rtl::OString &rName) OLEStreamData::OLEStreamData(const rtl::OString &rName)
: stream() : stream()
, name(rName) , name(rName)
{ {
...@@ -202,7 +205,7 @@ void OLEStorageImpl::traverse(const SotStorageRef &rStorage, const rtl::OUString ...@@ -202,7 +205,7 @@ void OLEStorageImpl::traverse(const SotStorageRef &rStorage, const rtl::OUString
{ {
if (aIt->IsStream()) 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; maNameMap[concatPath(rPath, aIt->GetName())] = maStreams.size() - 1;
} }
else if (aIt->IsStorage()) else if (aIt->IsStorage())
...@@ -243,6 +246,162 @@ SotStorageStreamRef OLEStorageImpl::createStream(const rtl::OUString &rPath) ...@@ -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 class WPXSvInputStreamImpl
{ {
public : public :
...@@ -269,6 +428,7 @@ private: ...@@ -269,6 +428,7 @@ private:
void ensureOLEIsInitialized(); void ensureOLEIsInitialized();
bool isZip(); bool isZip();
void ensureZipIsInitialized();
WPXInputStream *createWPXStream(const SotStorageStreamRef &rxStorage); WPXInputStream *createWPXStream(const SotStorageStreamRef &rxStorage);
...@@ -277,10 +437,7 @@ private: ...@@ -277,10 +437,7 @@ private:
::com::sun::star::uno::Reference< ::com::sun::star::io::XSeekable > mxSeekable; ::com::sun::star::uno::Reference< ::com::sun::star::io::XSeekable > mxSeekable;
::com::sun::star::uno::Sequence< sal_Int8 > maData; ::com::sun::star::uno::Sequence< sal_Int8 > maData;
boost::scoped_ptr< OLEStorageImpl > mpOLEStorage; boost::scoped_ptr< OLEStorageImpl > mpOLEStorage;
// TODO: this is not sufficient to implement RVNGInputStream, as boost::scoped_ptr< ZipStorageImpl > mpZipStorage;
// packages::Package does not support any kind of enumeration of
// its content
::com::sun::star::uno::Reference< container::XHierarchicalNameAccess > mxZipStorage;
bool mbCheckedOLE; bool mbCheckedOLE;
bool mbCheckedZip; bool mbCheckedZip;
public: public:
...@@ -295,7 +452,7 @@ WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference< XInputStream > xStream ) ...@@ -295,7 +452,7 @@ WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference< XInputStream > xStream )
mxSeekable(xStream, UNO_QUERY), mxSeekable(xStream, UNO_QUERY),
maData(0), maData(0),
mpOLEStorage(0), mpOLEStorage(0),
mxZipStorage(), mpZipStorage(0),
mbCheckedOLE(false), mbCheckedOLE(false),
mbCheckedZip(false), mbCheckedZip(false),
mnLength(0), mnLength(0),
...@@ -391,7 +548,12 @@ bool WPXSvInputStreamImpl::isStructured() ...@@ -391,7 +548,12 @@ bool WPXSvInputStreamImpl::isStructured()
PositionHolder pos(mxSeekable); PositionHolder pos(mxSeekable);
mxSeekable->seek(0); mxSeekable->seek(0);
return isOLE() || isZip(); if (isOLE())
return true;
mxSeekable->seek(0);
return isZip();
} }
unsigned WPXSvInputStreamImpl::subStreamCount() unsigned WPXSvInputStreamImpl::subStreamCount()
...@@ -409,7 +571,14 @@ unsigned WPXSvInputStreamImpl::subStreamCount() ...@@ -409,7 +571,14 @@ unsigned WPXSvInputStreamImpl::subStreamCount()
return mpOLEStorage->maStreams.size(); return mpOLEStorage->maStreams.size();
} }
// TODO: zip impl. mxSeekable->seek(0);
if (isZip())
{
ensureZipIsInitialized();
return mpZipStorage->maStreams.size();
}
return 0; return 0;
} }
...@@ -432,7 +601,17 @@ const char *WPXSvInputStreamImpl::subStreamName(const unsigned id) ...@@ -432,7 +601,17 @@ const char *WPXSvInputStreamImpl::subStreamName(const unsigned id)
return mpOLEStorage->maStreams[id].name.getStr(); 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; return 0;
} }
...@@ -456,8 +635,13 @@ bool WPXSvInputStreamImpl::existsSubStream(const char *const name) ...@@ -456,8 +635,13 @@ bool WPXSvInputStreamImpl::existsSubStream(const char *const name)
return mpOLEStorage->maNameMap.end() != mpOLEStorage->maNameMap.find(aName); return mpOLEStorage->maNameMap.end() != mpOLEStorage->maNameMap.find(aName);
} }
mxSeekable->seek(0);
if (isZip()) if (isZip())
return mxZipStorage->hasByHierarchicalName(aName); {
ensureZipIsInitialized();
return mpZipStorage->maNameMap.end() != mpZipStorage->maNameMap.find(aName);
}
return false; return false;
} }
...@@ -481,12 +665,15 @@ WPXInputStream *WPXSvInputStreamImpl::getSubStreamByName(const char *const name) ...@@ -481,12 +665,15 @@ WPXInputStream *WPXSvInputStreamImpl::getSubStreamByName(const char *const name)
return createWPXStream(mpOLEStorage->getStream(aName)); return createWPXStream(mpOLEStorage->getStream(aName));
} }
mxSeekable->seek(0);
if (isZip()) if (isZip())
{ {
ensureZipIsInitialized();
try try
{ {
const Reference<XStream> xStream(mxZipStorage->getByHierarchicalName(aName), UNO_QUERY_THROW); return new WPXSvInputStream(mpZipStorage->getStream(aName));
return new WPXSvInputStream(xStream->getInputStream());
} }
catch (const Exception &) catch (const Exception &)
{ {
...@@ -515,8 +702,24 @@ WPXInputStream *WPXSvInputStreamImpl::getSubStreamById(const unsigned id) ...@@ -515,8 +702,24 @@ WPXInputStream *WPXSvInputStreamImpl::getSubStreamById(const unsigned id)
return createWPXStream(mpOLEStorage->getStream(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; return 0;
} }
...@@ -568,9 +771,10 @@ bool WPXSvInputStreamImpl::isZip() ...@@ -568,9 +771,10 @@ bool WPXSvInputStreamImpl::isZip()
aArgs[0] <<= mxStream; aArgs[0] <<= mxStream;
const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext(), UNO_QUERY_THROW); 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), xContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.packages.Package", aArgs, xContext),
UNO_QUERY_THROW); UNO_QUERY_THROW);
mpZipStorage.reset(new ZipStorageImpl(xZipStorage));
} }
catch (const Exception &) catch (const Exception &)
{ {
...@@ -580,7 +784,7 @@ bool WPXSvInputStreamImpl::isZip() ...@@ -580,7 +784,7 @@ bool WPXSvInputStreamImpl::isZip()
mbCheckedZip = true; mbCheckedZip = true;
} }
return mxZipStorage.is(); return bool(mpZipStorage);
} }
void WPXSvInputStreamImpl::ensureOLEIsInitialized() void WPXSvInputStreamImpl::ensureOLEIsInitialized()
...@@ -591,6 +795,14 @@ void WPXSvInputStreamImpl::ensureOLEIsInitialized() ...@@ -591,6 +795,14 @@ void WPXSvInputStreamImpl::ensureOLEIsInitialized()
mpOLEStorage->initialize(utl::UcbStreamHelper::CreateStream( mxStream )); mpOLEStorage->initialize(utl::UcbStreamHelper::CreateStream( mxStream ));
} }
void WPXSvInputStreamImpl::ensureZipIsInitialized()
{
assert(mpZipStorage);
if (!mpZipStorage->mbInitialized)
mpZipStorage->initialize();
}
WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) : WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) :
mpImpl(new WPXSvInputStreamImpl(xStream)) mpImpl(new WPXSvInputStreamImpl(xStream))
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment