So,
One of the things I was rather missing with our UNO storage interfaces
was the ability to resolve paths: [ would be quite a nice feature -
right ? ]. Unfortunately, since we have a mess of different UNO
interfaces to use for file-system (and storage) access, and few of them
overlap, from:
* URLs - to XSimpleFileAccess
* ucb's monstrous interfaces
* XStorage / XStream / ...
It seemed there was no way to do this - is that so ? anyhow, I wrote
some vaguely clean path resolution code that could be shared, in some
nice shared place. Of course, since interfaces are so beautifully
abstract - there is no way to associate these to with the underlying
interfaces usefully - they can't be added to the interface without
crippling each implementor: what we really need is some magic way to
associate implementations with interfaces (what an idea!) but anyhow -
perhaps someone else might just find comphelper's storagehelper if they
want this, urgh.
Anyhow - package/'s ZipPackage.cxx does some hierarchical naming
lookups to validate the manifest - but does that via XTunnel and is
specific to its own implementation. Anyway, I got this written and
then ...
Amazing - package/store/xstor/ocompinstream.cxx stream -magically-
invalidates itself if we don't keep a reference around to the parent
storage: a compelling feature if ever I saw one.
At which point - I had to add this grotesque LifecycleProxy hack
(appended). If I was -really- 'clever' I could have - you know - done an
adaptive proxy object that would pretend to be whatever it is pointing
at, and hold the list of parents in there. [ Unfortunately, for all its
meta-power, UNO doesn't provide such an ability AFAICS - though it is
conceptually quite possible to have a 'TransparentProxy' object that
would do this ].
Anyhow - distressed at having to do this; thoughts / indulgences
appreciated; since this is one of the cleaner hackarounds the Any("UNO")
"de-coupling" madness I'll push it.
HTH,
Michael.
diff --git a/comphelper/inc/comphelper/storagehelper.hxx
b/comphelper/inc/comphelper/storagehelper.hxx
index 078bfb8..f4f0f81 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 70b7852..52b8e67 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: */
--
michael.meeks@novell.com <><, Pseudo Engineer, itinerant idiot
Context
- [Libreoffice] inelegancy in XStorage / path handling ... · Michael Meeks
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.