diff options
-rw-r--r-- | comphelper/inc/comphelper/storagehelper.hxx | 20 | ||||
-rw-r--r-- | comphelper/source/misc/storagehelper.cxx | 53 |
2 files changed, 73 insertions, 0 deletions
diff --git a/comphelper/inc/comphelper/storagehelper.hxx b/comphelper/inc/comphelper/storagehelper.hxx index 078bfb81c885..f4f0f81ea805 100644 --- a/comphelper/inc/comphelper/storagehelper.hxx +++ b/comphelper/inc/comphelper/storagehelper.hxx @@ -167,6 +167,26 @@ public: static sal_Bool IsValidZipEntryFileName( const sal_Unicode *pChar, sal_Int32 nLength, sal_Bool bSlashAllowed ); static sal_Bool PathHasSegment( const ::rtl::OUString& aPath, const ::rtl::OUString& aSegment ); + + // Methods to allow easy use of hierachical names inside storages + + // Unfortunately - the impl.s of XStorage like to invalidate all + // their sub streams and storages when you release references, so + // it is necessary to keep references to all storages down the + // path - this is 'beautiful' (TM). So we need this ugly hack: + class LifecycleProxyImpl; + class LifecycleProxy { + public: + LifecycleProxyImpl *pBadness; + LifecycleProxy(); + ~LifecycleProxy(); + }; + static ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > GetStorageAtPath( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > &xStorage, + const ::rtl::OUString& aPath, sal_uInt32 nOpenMode, LifecycleProxy &rNastiness ); + static ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > GetStreamAtPath( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > &xStorage, + const ::rtl::OUString& aPath, sal_uInt32 nOpenMode, LifecycleProxy &rNastiness ); }; } diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx index 70b7852b579a..52b8e677f5ab 100644 --- a/comphelper/source/misc/storagehelper.cxx +++ b/comphelper/source/misc/storagehelper.cxx @@ -39,6 +39,7 @@ #include <com/sun/star/xml/crypto/XDigestContextSupplier.hpp> #include <com/sun/star/xml/crypto/DigestID.hpp> +#include <vector> #include <rtl/digest.h> #include <ucbhelper/content.hxx> @@ -536,6 +537,58 @@ sal_Bool OStorageHelper::PathHasSegment( const ::rtl::OUString& aPath, const ::r return bResult; } +class OStorageHelper::LifecycleProxyImpl : public std::vector< uno::Reference< embed::XStorage > > {}; +OStorageHelper::LifecycleProxy::LifecycleProxy() : + pBadness( new OStorageHelper::LifecycleProxyImpl() ) { } +OStorageHelper::LifecycleProxy::~LifecycleProxy() { delete pBadness; } + +static void splitPath( std::vector<rtl::OUString> &rElems, + const ::rtl::OUString& rPath ) +{ + for (sal_Int32 i = 0; i >= 0;) + rElems.push_back( rPath.getToken( 0, '/', i ) ); +} + +static uno::Reference< embed::XStorage > LookupStorageAtPath( + const uno::Reference< embed::XStorage > &xParentStorage, + std::vector<rtl::OUString> &rElems, sal_uInt32 nOpenMode, + OStorageHelper::LifecycleProxy &rNastiness ) +{ + uno::Reference< embed::XStorage > xStorage( xParentStorage ); + rNastiness.pBadness->push_back( xStorage ); + for( size_t i = 0; i < rElems.size() && xStorage.is(); i++ ) + { + xStorage = xStorage->openStorageElement( rElems[i], nOpenMode ); + rNastiness.pBadness->push_back( xStorage ); + } + return xStorage; +} + +uno::Reference< embed::XStorage > OStorageHelper::GetStorageAtPath( + const uno::Reference< embed::XStorage > &xStorage, + const ::rtl::OUString& rPath, sal_uInt32 nOpenMode, + OStorageHelper::LifecycleProxy &rNastiness ) +{ + std::vector<rtl::OUString> aElems; + splitPath( aElems, rPath ); + return LookupStorageAtPath( xStorage, aElems, nOpenMode, rNastiness ); +} + +uno::Reference< io::XStream > OStorageHelper::GetStreamAtPath( + const uno::Reference< embed::XStorage > &xParentStorage, + const ::rtl::OUString& rPath, sal_uInt32 nOpenMode, + OStorageHelper::LifecycleProxy &rNastiness ) +{ + std::vector<rtl::OUString> aElems; + splitPath( aElems, rPath ); + rtl::OUString aName( aElems.back() ); + aElems.pop_back(); + uno::Reference< embed::XStorage > xStorage( + LookupStorageAtPath( xParentStorage, aElems, nOpenMode, rNastiness ), + uno::UNO_QUERY_THROW ); + return xStorage->openStreamElement( aName, nOpenMode ); +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |