1d119d52dSAndrew Rist /**************************************************************
2*45ad4d42Smseidel  *
3d119d52dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4d119d52dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5d119d52dSAndrew Rist  * distributed with this work for additional information
6d119d52dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7d119d52dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8d119d52dSAndrew Rist  * "License"); you may not use this file except in compliance
9d119d52dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*45ad4d42Smseidel  *
11d119d52dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*45ad4d42Smseidel  *
13d119d52dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14d119d52dSAndrew Rist  * software distributed under the License is distributed on an
15d119d52dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16d119d52dSAndrew Rist  * KIND, either express or implied.  See the License for the
17d119d52dSAndrew Rist  * specific language governing permissions and limitations
18d119d52dSAndrew Rist  * under the License.
19*45ad4d42Smseidel  *
20d119d52dSAndrew Rist  *************************************************************/
21d119d52dSAndrew Rist 
22d119d52dSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "precompiled_sfx2.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include <sfx2/DocumentMetadataAccess.hxx>
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
29cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
30cdf0e10cSrcweir #include <com/sun/star/embed/ElementModes.hpp>
31cdf0e10cSrcweir #include <com/sun/star/embed/XStorage.hpp>
32cdf0e10cSrcweir #include <com/sun/star/embed/XTransactedObject.hpp>
33cdf0e10cSrcweir #include <com/sun/star/task/ErrorCodeIOException.hpp>
34cdf0e10cSrcweir #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
35cdf0e10cSrcweir #include <com/sun/star/rdf/FileFormat.hpp>
36cdf0e10cSrcweir #include <com/sun/star/rdf/URIs.hpp>
37cdf0e10cSrcweir #include <com/sun/star/rdf/Statement.hpp>
38cdf0e10cSrcweir #include <com/sun/star/rdf/Literal.hpp>
39cdf0e10cSrcweir #include <com/sun/star/rdf/URI.hpp>
40cdf0e10cSrcweir #include <com/sun/star/rdf/Repository.hpp>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #include <rtl/uuid.h>
43cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
44cdf0e10cSrcweir #include <rtl/uri.hxx>
45cdf0e10cSrcweir #include <rtl/bootstrap.hxx>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include <comphelper/interaction.hxx>
48cdf0e10cSrcweir #include <comphelper/makesequence.hxx>
49cdf0e10cSrcweir #include <comphelper/mediadescriptor.hxx>
50cdf0e10cSrcweir #include <comphelper/sequenceasvector.hxx>
51cdf0e10cSrcweir #include <comphelper/storagehelper.hxx>
52cdf0e10cSrcweir 
53cdf0e10cSrcweir #include <sfx2/docfile.hxx>
54cdf0e10cSrcweir #include <sfx2/XmlIdRegistry.hxx>
55cdf0e10cSrcweir 
56*45ad4d42Smseidel #include <libxml/tree.h> // for xmlValidateNCName
57cdf0e10cSrcweir 
58cdf0e10cSrcweir #include <boost/bind.hpp>
59cdf0e10cSrcweir #include <boost/shared_array.hpp>
60cdf0e10cSrcweir #include <boost/tuple/tuple.hpp>
61cdf0e10cSrcweir 
62cdf0e10cSrcweir #include <vector>
63cdf0e10cSrcweir #include <set>
64cdf0e10cSrcweir #include <map>
65cdf0e10cSrcweir #include <functional>
66cdf0e10cSrcweir #include <algorithm>
67cdf0e10cSrcweir 
68cdf0e10cSrcweir #include <unotools/ucbhelper.hxx>
69cdf0e10cSrcweir #include <com/sun/star/uri/XUriReference.hpp>
70cdf0e10cSrcweir #include <com/sun/star/uri/XUriReferenceFactory.hpp>
71cdf0e10cSrcweir #include <com/sun/star/uri/XVndSunStarPkgUrlReferenceFactory.hpp>
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 
74cdf0e10cSrcweir /*
75cdf0e10cSrcweir  Note: in the context of this implementation, all rdf.QueryExceptions and
76cdf0e10cSrcweir  rdf.RepositoryExceptions are RuntimeExceptions, and will be reported as such.
77cdf0e10cSrcweir 
78cdf0e10cSrcweir  This implementation assumes that it is only used with ODF documents, not mere
79cdf0e10cSrcweir  ODF packages. In other words, we enforce that metadata files must not be
80cdf0e10cSrcweir  called reserved names.
81cdf0e10cSrcweir  */
82cdf0e10cSrcweir 
83cdf0e10cSrcweir using namespace ::com::sun::star;
84cdf0e10cSrcweir 
85cdf0e10cSrcweir namespace sfx2 {
86cdf0e10cSrcweir 
87cdf0e10cSrcweir 
isValidNCName(::rtl::OUString const & i_rIdref)88cdf0e10cSrcweir bool isValidNCName(::rtl::OUString const & i_rIdref)
89cdf0e10cSrcweir {
90cdf0e10cSrcweir     const ::rtl::OString id(
91cdf0e10cSrcweir         ::rtl::OUStringToOString(i_rIdref, RTL_TEXTENCODING_UTF8) );
92cdf0e10cSrcweir     return !(xmlValidateNCName(
93cdf0e10cSrcweir         reinterpret_cast<const unsigned char*>(id.getStr()), 0));
94cdf0e10cSrcweir }
95cdf0e10cSrcweir 
96cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
97cdf0e10cSrcweir 
98cdf0e10cSrcweir static const char s_content [] = "content.xml";
99cdf0e10cSrcweir static const char s_styles  [] = "styles.xml";
100cdf0e10cSrcweir static const char s_meta    [] = "meta.xml";
101cdf0e10cSrcweir static const char s_settings[] = "settings.xml";
102cdf0e10cSrcweir static const char s_manifest[] = "manifest.rdf";
103cdf0e10cSrcweir static const char s_rdfxml  [] = "application/rdf+xml";
104cdf0e10cSrcweir static const char s_odfmime [] = "application/vnd.oasis.opendocument.";
105cdf0e10cSrcweir 
106cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
107cdf0e10cSrcweir 
isContentFile(::rtl::OUString const & i_rPath)108cdf0e10cSrcweir static bool isContentFile(::rtl::OUString const & i_rPath)
109cdf0e10cSrcweir {
110cdf0e10cSrcweir     return i_rPath.equalsAscii(s_content);
111cdf0e10cSrcweir }
112cdf0e10cSrcweir 
isStylesFile(::rtl::OUString const & i_rPath)113cdf0e10cSrcweir static bool isStylesFile (::rtl::OUString const & i_rPath)
114cdf0e10cSrcweir {
115cdf0e10cSrcweir     return i_rPath.equalsAscii(s_styles);
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
isReservedFile(::rtl::OUString const & i_rPath)118cdf0e10cSrcweir static bool isReservedFile(::rtl::OUString const & i_rPath)
119cdf0e10cSrcweir {
120cdf0e10cSrcweir     return isContentFile(i_rPath)
121cdf0e10cSrcweir         || isStylesFile(i_rPath)
122cdf0e10cSrcweir         || i_rPath.equalsAscii(s_meta)
123cdf0e10cSrcweir         || i_rPath.equalsAscii(s_settings);
124cdf0e10cSrcweir }
125cdf0e10cSrcweir 
126cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
127cdf0e10cSrcweir 
createBaseURI(uno::Reference<uno::XComponentContext> const & i_xContext,uno::Reference<embed::XStorage> const & i_xStorage,::rtl::OUString const & i_rPkgURI,::rtl::OUString const & i_rSubDocument)128cdf0e10cSrcweir uno::Reference<rdf::XURI> createBaseURI(
129cdf0e10cSrcweir     uno::Reference<uno::XComponentContext> const & i_xContext,
130cdf0e10cSrcweir     uno::Reference<embed::XStorage> const & i_xStorage,
131cdf0e10cSrcweir     ::rtl::OUString const & i_rPkgURI, ::rtl::OUString const & i_rSubDocument)
132cdf0e10cSrcweir {
133cdf0e10cSrcweir     if (!i_xContext.is() || !i_xStorage.is() || !i_rPkgURI.getLength()) {
134cdf0e10cSrcweir         throw uno::RuntimeException();
135cdf0e10cSrcweir     }
136cdf0e10cSrcweir 
137cdf0e10cSrcweir     // #i108078# workaround non-hierarchical vnd.sun.star.expand URIs
138cdf0e10cSrcweir     // this really should be done somewhere else, not here.
139cdf0e10cSrcweir     ::rtl::OUString pkgURI(i_rPkgURI);
140cdf0e10cSrcweir     if (pkgURI.matchIgnoreAsciiCaseAsciiL(
141cdf0e10cSrcweir             RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:")))
142cdf0e10cSrcweir     {
143cdf0e10cSrcweir         // expand it here (makeAbsolute requires hierarchical URI)
144cdf0e10cSrcweir         pkgURI = pkgURI.copy( RTL_CONSTASCII_LENGTH("vnd.sun.star.expand:") );
145cdf0e10cSrcweir         if (pkgURI.getLength() != 0) {
146cdf0e10cSrcweir             pkgURI = ::rtl::Uri::decode(
147cdf0e10cSrcweir                     pkgURI, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
148cdf0e10cSrcweir             if (pkgURI.getLength() == 0) {
149cdf0e10cSrcweir                 throw uno::RuntimeException();
150cdf0e10cSrcweir             }
151cdf0e10cSrcweir             ::rtl::Bootstrap::expandMacros(pkgURI);
152cdf0e10cSrcweir         }
153cdf0e10cSrcweir     }
154cdf0e10cSrcweir 
155cdf0e10cSrcweir     const uno::Reference<lang::XMultiComponentFactory> xServiceFactory(
156cdf0e10cSrcweir         i_xContext->getServiceManager(), uno::UNO_SET_THROW);
157cdf0e10cSrcweir     const uno::Reference<uri::XUriReferenceFactory> xUriFactory(
158cdf0e10cSrcweir         xServiceFactory->createInstanceWithContext(
159cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
160cdf0e10cSrcweir                 "com.sun.star.uri.UriReferenceFactory"), i_xContext),
161cdf0e10cSrcweir         uno::UNO_QUERY_THROW);
162cdf0e10cSrcweir     uno::Reference< uri::XUriReference > xBaseURI;
163cdf0e10cSrcweir 
164cdf0e10cSrcweir     const uno::Reference< uri::XUriReference > xPkgURI(
165cdf0e10cSrcweir         xUriFactory->parse(pkgURI), uno::UNO_SET_THROW );
166cdf0e10cSrcweir     xPkgURI->clearFragment();
167cdf0e10cSrcweir 
168cdf0e10cSrcweir     // need to know whether the storage is a FileSystemStorage
169cdf0e10cSrcweir     // XServiceInfo would be better, but it is not implemented
170cdf0e10cSrcweir //    if ( pkgURI.getLength() && ::utl::UCBContentHelper::IsFolder(pkgURI) )
171cdf0e10cSrcweir     if (true) {
172cdf0e10cSrcweir         xBaseURI.set( xPkgURI, uno::UNO_SET_THROW );
173cdf0e10cSrcweir #if 0
174cdf0e10cSrcweir     } else {
175cdf0e10cSrcweir         const uno::Reference<uri::XVndSunStarPkgUrlReferenceFactory>
176cdf0e10cSrcweir             xPkgUriFactory( xServiceFactory->createInstanceWithContext(
177cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
178cdf0e10cSrcweir                     "com.sun.star.uri.VndSunStarPkgUrlReferenceFactory"),
179cdf0e10cSrcweir                 i_xContext),
180cdf0e10cSrcweir             uno::UNO_QUERY_THROW);
181cdf0e10cSrcweir         xBaseURI.set( xPkgUriFactory->createVndSunStarPkgUrlReference(xPkgURI),
182cdf0e10cSrcweir             uno::UNO_SET_THROW );
183cdf0e10cSrcweir #endif
184cdf0e10cSrcweir     }
185cdf0e10cSrcweir     ::rtl::OUStringBuffer buf;
186cdf0e10cSrcweir     if (!xBaseURI->getUriReference().endsWithAsciiL("/", 1))
187cdf0e10cSrcweir     {
188cdf0e10cSrcweir         const sal_Int32 count( xBaseURI->getPathSegmentCount() );
189cdf0e10cSrcweir         if (count > 0)
190cdf0e10cSrcweir         {
191cdf0e10cSrcweir             const ::rtl::OUString last( xBaseURI->getPathSegment(count - 1) );
192cdf0e10cSrcweir             buf.append(last);
193cdf0e10cSrcweir         }
194cdf0e10cSrcweir         buf.append(static_cast<sal_Unicode>('/'));
195cdf0e10cSrcweir     }
196cdf0e10cSrcweir     if (i_rSubDocument.getLength())
197cdf0e10cSrcweir     {
198cdf0e10cSrcweir         buf.append(i_rSubDocument);
199cdf0e10cSrcweir         buf.append(static_cast<sal_Unicode>('/'));
200cdf0e10cSrcweir     }
201cdf0e10cSrcweir     const ::rtl::OUString Path(buf.makeStringAndClear());
202cdf0e10cSrcweir     if (Path.getLength())
203cdf0e10cSrcweir     {
204cdf0e10cSrcweir         const uno::Reference< uri::XUriReference > xPathURI(
205cdf0e10cSrcweir             xUriFactory->parse(Path), uno::UNO_SET_THROW );
206cdf0e10cSrcweir         xBaseURI.set(
207cdf0e10cSrcweir             xUriFactory->makeAbsolute(xBaseURI, xPathURI,
208cdf0e10cSrcweir                 true, uri::RelativeUriExcessParentSegments_ERROR),
209cdf0e10cSrcweir             uno::UNO_SET_THROW);
210cdf0e10cSrcweir     }
211cdf0e10cSrcweir 
212cdf0e10cSrcweir     return rdf::URI::create(i_xContext, xBaseURI->getUriReference());
213cdf0e10cSrcweir }
214cdf0e10cSrcweir 
215cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
216cdf0e10cSrcweir 
217cdf0e10cSrcweir struct DocumentMetadataAccess_Impl
218cdf0e10cSrcweir {
219cdf0e10cSrcweir     // note: these are all initialized in constructor, and loadFromStorage
220cdf0e10cSrcweir     const uno::Reference<uno::XComponentContext> m_xContext;
221cdf0e10cSrcweir     const IXmlIdRegistrySupplier & m_rXmlIdRegistrySupplier;
222cdf0e10cSrcweir     uno::Reference<rdf::XURI> m_xBaseURI;
223cdf0e10cSrcweir     uno::Reference<rdf::XRepository> m_xRepository;
224cdf0e10cSrcweir     uno::Reference<rdf::XNamedGraph> m_xManifest;
DocumentMetadataAccess_Implsfx2::DocumentMetadataAccess_Impl225cdf0e10cSrcweir     DocumentMetadataAccess_Impl(
226cdf0e10cSrcweir             uno::Reference<uno::XComponentContext> const& i_xContext,
227cdf0e10cSrcweir             IXmlIdRegistrySupplier const & i_rRegistrySupplier)
228cdf0e10cSrcweir       : m_xContext(i_xContext)
229cdf0e10cSrcweir       , m_rXmlIdRegistrySupplier(i_rRegistrySupplier)
230cdf0e10cSrcweir       , m_xBaseURI()
231cdf0e10cSrcweir       , m_xRepository()
232cdf0e10cSrcweir       , m_xManifest()
233cdf0e10cSrcweir     {
234cdf0e10cSrcweir         OSL_ENSURE(m_xContext.is(), "context null");
235cdf0e10cSrcweir     }
236cdf0e10cSrcweir };
237cdf0e10cSrcweir 
238cdf0e10cSrcweir // this is... a hack.
239cdf0e10cSrcweir template<sal_Int16 Constant>
240cdf0e10cSrcweir /*static*/ uno::Reference<rdf::XURI>
getURI(uno::Reference<uno::XComponentContext> const & i_xContext)241cdf0e10cSrcweir getURI(uno::Reference< uno::XComponentContext > const & i_xContext)
242cdf0e10cSrcweir {
243cdf0e10cSrcweir     static uno::Reference< rdf::XURI > xURI(
244cdf0e10cSrcweir         rdf::URI::createKnown(i_xContext, Constant), uno::UNO_QUERY_THROW);
245cdf0e10cSrcweir     return xURI;
246cdf0e10cSrcweir }
247cdf0e10cSrcweir 
248cdf0e10cSrcweir 
249cdf0e10cSrcweir /** would storing the file to a XStorage succeed? */
isFileNameValid(const::rtl::OUString & i_rFileName)250cdf0e10cSrcweir static bool isFileNameValid(const ::rtl::OUString & i_rFileName)
251cdf0e10cSrcweir {
252cdf0e10cSrcweir     if (i_rFileName.getLength() <= 0) return false;
253cdf0e10cSrcweir     if (i_rFileName[0] == '/')        return false; // no absolute paths!
254cdf0e10cSrcweir     sal_Int32 idx(0);
255cdf0e10cSrcweir     do {
256cdf0e10cSrcweir       const ::rtl::OUString segment(
257cdf0e10cSrcweir         i_rFileName.getToken(0, static_cast<sal_Unicode> ('/'), idx) );
258cdf0e10cSrcweir       if (!segment.getLength()      ||  // no empty segments
259cdf0e10cSrcweir           segment.equalsAscii(".")  ||  // no . segments
260cdf0e10cSrcweir           segment.equalsAscii("..") ||  // no .. segments
261cdf0e10cSrcweir           !::comphelper::OStorageHelper::IsValidZipEntryFileName(
262cdf0e10cSrcweir               segment, sal_False))      // no invalid characters
263cdf0e10cSrcweir                                       return false;
264cdf0e10cSrcweir     } while (idx >= 0);
265cdf0e10cSrcweir     return true;
266cdf0e10cSrcweir }
267cdf0e10cSrcweir 
268cdf0e10cSrcweir /** split a uri hierarchy into first segment and rest */
269cdf0e10cSrcweir static bool
splitPath(::rtl::OUString const & i_rPath,::rtl::OUString & o_rDir,::rtl::OUString & o_rRest)270cdf0e10cSrcweir splitPath(::rtl::OUString const & i_rPath,
271cdf0e10cSrcweir     ::rtl::OUString & o_rDir, ::rtl::OUString& o_rRest)
272cdf0e10cSrcweir {
273cdf0e10cSrcweir     const sal_Int32 idx(i_rPath.indexOf(static_cast<sal_Unicode>('/')));
274cdf0e10cSrcweir     if (idx < 0 || idx >= i_rPath.getLength()) {
275cdf0e10cSrcweir         o_rDir = ::rtl::OUString();
276cdf0e10cSrcweir         o_rRest = i_rPath;
277cdf0e10cSrcweir         return true;
278cdf0e10cSrcweir     } else if (idx == 0 || idx == i_rPath.getLength() - 1) {
279cdf0e10cSrcweir         // input must not start or end with '/'
280cdf0e10cSrcweir         return false;
281cdf0e10cSrcweir     } else {
282cdf0e10cSrcweir         o_rDir  = (i_rPath.copy(0, idx));
283cdf0e10cSrcweir         o_rRest = (i_rPath.copy(idx+1));
284cdf0e10cSrcweir         return true;
285cdf0e10cSrcweir     }
286cdf0e10cSrcweir }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir static bool
splitXmlId(::rtl::OUString const & i_XmlId,::rtl::OUString & o_StreamName,::rtl::OUString & o_Idref)289cdf0e10cSrcweir splitXmlId(::rtl::OUString const & i_XmlId,
290cdf0e10cSrcweir     ::rtl::OUString & o_StreamName, ::rtl::OUString& o_Idref )
291cdf0e10cSrcweir {
292cdf0e10cSrcweir     const sal_Int32 idx(i_XmlId.indexOf(static_cast<sal_Unicode>('#')));
293cdf0e10cSrcweir     if ((idx <= 0) || (idx >= i_XmlId.getLength() - 1)) {
294cdf0e10cSrcweir         return false;
295cdf0e10cSrcweir     } else {
296cdf0e10cSrcweir         o_StreamName = (i_XmlId.copy(0, idx));
297cdf0e10cSrcweir         o_Idref      = (i_XmlId.copy(idx+1));
298cdf0e10cSrcweir         return isValidXmlId(o_StreamName, o_Idref);
299cdf0e10cSrcweir     }
300cdf0e10cSrcweir }
301cdf0e10cSrcweir 
302cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
303cdf0e10cSrcweir 
304cdf0e10cSrcweir static uno::Reference<rdf::XURI>
getURIForStream(struct DocumentMetadataAccess_Impl & i_rImpl,::rtl::OUString const & i_rPath)305cdf0e10cSrcweir getURIForStream(struct DocumentMetadataAccess_Impl& i_rImpl,
306cdf0e10cSrcweir     ::rtl::OUString const& i_rPath)
307cdf0e10cSrcweir {
308cdf0e10cSrcweir     const uno::Reference<rdf::XURI> xURI(
309cdf0e10cSrcweir         rdf::URI::createNS( i_rImpl.m_xContext,
310cdf0e10cSrcweir             i_rImpl.m_xBaseURI->getStringValue(), i_rPath),
311cdf0e10cSrcweir         uno::UNO_SET_THROW);
312cdf0e10cSrcweir     return xURI;
313cdf0e10cSrcweir }
314cdf0e10cSrcweir 
315cdf0e10cSrcweir /** add statements declaring i_xResource to be a file of type i_xType with
316cdf0e10cSrcweir     path i_rPath to manifest, with optional additional types i_pTypes */
317cdf0e10cSrcweir static void
addFile(struct DocumentMetadataAccess_Impl & i_rImpl,uno::Reference<rdf::XURI> const & i_xType,::rtl::OUString const & i_rPath,const uno::Sequence<uno::Reference<rdf::XURI>> * i_pTypes=0)318cdf0e10cSrcweir addFile(struct DocumentMetadataAccess_Impl & i_rImpl,
319cdf0e10cSrcweir     uno::Reference<rdf::XURI> const& i_xType,
320cdf0e10cSrcweir     ::rtl::OUString const & i_rPath,
321cdf0e10cSrcweir     const uno::Sequence < uno::Reference< rdf::XURI > > * i_pTypes = 0)
322cdf0e10cSrcweir {
323cdf0e10cSrcweir     try {
324cdf0e10cSrcweir         const uno::Reference<rdf::XURI> xURI( getURIForStream(
325cdf0e10cSrcweir             i_rImpl, i_rPath) );
326cdf0e10cSrcweir 
327cdf0e10cSrcweir         i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
328cdf0e10cSrcweir             getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext),
329cdf0e10cSrcweir             xURI.get());
330cdf0e10cSrcweir         i_rImpl.m_xManifest->addStatement(xURI.get(),
331cdf0e10cSrcweir             getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
332cdf0e10cSrcweir             i_xType.get());
333cdf0e10cSrcweir         if (i_pTypes) {
334cdf0e10cSrcweir             for (sal_Int32 i = 0; i < i_pTypes->getLength(); ++i) {
335cdf0e10cSrcweir                 i_rImpl.m_xManifest->addStatement(xURI.get(),
336cdf0e10cSrcweir                     getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
337cdf0e10cSrcweir                     (*i_pTypes)[i].get());
338cdf0e10cSrcweir             }
339cdf0e10cSrcweir         }
340cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
341cdf0e10cSrcweir         throw;
342cdf0e10cSrcweir     } catch (uno::Exception & e) {
343cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
344cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
345cdf0e10cSrcweir                 "addFile: exception"), /*this*/0, uno::makeAny(e));
346cdf0e10cSrcweir     }
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
349cdf0e10cSrcweir /** add content.xml or styles.xml to manifest */
350cdf0e10cSrcweir static bool
addContentOrStylesFileImpl(struct DocumentMetadataAccess_Impl & i_rImpl,const::rtl::OUString & i_rPath)351cdf0e10cSrcweir addContentOrStylesFileImpl(struct DocumentMetadataAccess_Impl & i_rImpl,
352cdf0e10cSrcweir     const ::rtl::OUString & i_rPath)
353cdf0e10cSrcweir {
354cdf0e10cSrcweir     uno::Reference<rdf::XURI> xType;
355cdf0e10cSrcweir     if (isContentFile(i_rPath)) {
356cdf0e10cSrcweir         xType.set(getURI<rdf::URIs::ODF_CONTENTFILE>(i_rImpl.m_xContext));
357cdf0e10cSrcweir     } else if (isStylesFile(i_rPath)) {
358cdf0e10cSrcweir         xType.set(getURI<rdf::URIs::ODF_STYLESFILE>(i_rImpl.m_xContext));
359cdf0e10cSrcweir     } else {
360cdf0e10cSrcweir         return false;
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir     addFile(i_rImpl, xType.get(), i_rPath);
363cdf0e10cSrcweir     return true;
364cdf0e10cSrcweir }
365cdf0e10cSrcweir 
366cdf0e10cSrcweir /** add metadata file to manifest */
367cdf0e10cSrcweir static void
addMetadataFileImpl(struct DocumentMetadataAccess_Impl & i_rImpl,const::rtl::OUString & i_rPath,const uno::Sequence<uno::Reference<rdf::XURI>> & i_rTypes)368cdf0e10cSrcweir addMetadataFileImpl(struct DocumentMetadataAccess_Impl & i_rImpl,
369cdf0e10cSrcweir     const ::rtl::OUString & i_rPath,
370cdf0e10cSrcweir     const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
371cdf0e10cSrcweir {
372cdf0e10cSrcweir     addFile(i_rImpl,
373cdf0e10cSrcweir             getURI<rdf::URIs::PKG_METADATAFILE>(i_rImpl.m_xContext),
374cdf0e10cSrcweir             i_rPath, &i_rTypes);
375cdf0e10cSrcweir }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir /** remove a file from the manifest */
378cdf0e10cSrcweir static void
removeFile(struct DocumentMetadataAccess_Impl & i_rImpl,uno::Reference<rdf::XURI> const & i_xPart)379cdf0e10cSrcweir removeFile(struct DocumentMetadataAccess_Impl & i_rImpl,
380cdf0e10cSrcweir     uno::Reference<rdf::XURI> const& i_xPart)
381cdf0e10cSrcweir {
382cdf0e10cSrcweir     if (!i_xPart.is()) throw uno::RuntimeException();
383cdf0e10cSrcweir     try {
384cdf0e10cSrcweir         i_rImpl.m_xManifest->removeStatements(i_rImpl.m_xBaseURI.get(),
385cdf0e10cSrcweir             getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext),
386cdf0e10cSrcweir             i_xPart.get());
387cdf0e10cSrcweir         i_rImpl.m_xManifest->removeStatements(i_xPart.get(),
388cdf0e10cSrcweir             getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext), 0);
389cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
390cdf0e10cSrcweir         throw;
391cdf0e10cSrcweir     } catch (uno::Exception & e) {
392cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
393cdf0e10cSrcweir             ::rtl::OUString::createFromAscii("removeFile: exception"),
394cdf0e10cSrcweir             0, uno::makeAny(e));
395cdf0e10cSrcweir     }
396cdf0e10cSrcweir }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir static ::std::vector< uno::Reference< rdf::XURI > >
getAllParts(struct DocumentMetadataAccess_Impl & i_rImpl)399cdf0e10cSrcweir getAllParts(struct DocumentMetadataAccess_Impl & i_rImpl)
400cdf0e10cSrcweir {
401cdf0e10cSrcweir     ::std::vector< uno::Reference< rdf::XURI > > ret;
402cdf0e10cSrcweir     try {
403cdf0e10cSrcweir         const uno::Reference<container::XEnumeration> xEnum(
404cdf0e10cSrcweir             i_rImpl.m_xManifest->getStatements( i_rImpl.m_xBaseURI.get(),
405cdf0e10cSrcweir                 getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext), 0),
406cdf0e10cSrcweir             uno::UNO_SET_THROW);
407cdf0e10cSrcweir         while (xEnum->hasMoreElements()) {
408cdf0e10cSrcweir             rdf::Statement stmt;
409cdf0e10cSrcweir             if (!(xEnum->nextElement() >>= stmt)) {
410cdf0e10cSrcweir                 throw uno::RuntimeException();
411cdf0e10cSrcweir             }
412cdf0e10cSrcweir             const uno::Reference<rdf::XURI> xPart(stmt.Object,
413cdf0e10cSrcweir                 uno::UNO_QUERY);
414cdf0e10cSrcweir             if (!xPart.is()) continue;
415cdf0e10cSrcweir             ret.push_back(xPart);
416cdf0e10cSrcweir         }
417cdf0e10cSrcweir         return ret;
418cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
419cdf0e10cSrcweir         throw;
420cdf0e10cSrcweir     } catch (uno::Exception & e) {
421cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
422cdf0e10cSrcweir             ::rtl::OUString::createFromAscii("getAllParts: exception"),
423cdf0e10cSrcweir             0, uno::makeAny(e));
424cdf0e10cSrcweir     }
425cdf0e10cSrcweir }
426cdf0e10cSrcweir 
427cdf0e10cSrcweir static bool
isPartOfType(struct DocumentMetadataAccess_Impl & i_rImpl,uno::Reference<rdf::XURI> const & i_xPart,uno::Reference<rdf::XURI> const & i_xType)428cdf0e10cSrcweir isPartOfType(struct DocumentMetadataAccess_Impl & i_rImpl,
429cdf0e10cSrcweir     uno::Reference<rdf::XURI> const & i_xPart,
430cdf0e10cSrcweir     uno::Reference<rdf::XURI> const & i_xType)
431cdf0e10cSrcweir {
432cdf0e10cSrcweir     if (!i_xPart.is() || !i_xType.is()) throw uno::RuntimeException();
433cdf0e10cSrcweir     try {
434cdf0e10cSrcweir         const uno::Reference<container::XEnumeration> xEnum(
435cdf0e10cSrcweir             i_rImpl.m_xManifest->getStatements(i_xPart.get(),
436cdf0e10cSrcweir                 getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
437cdf0e10cSrcweir                 i_xType.get()),
438cdf0e10cSrcweir             uno::UNO_SET_THROW);
439cdf0e10cSrcweir         return (xEnum->hasMoreElements());
440cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
441cdf0e10cSrcweir         throw;
442cdf0e10cSrcweir     } catch (uno::Exception & e) {
443cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
444cdf0e10cSrcweir             ::rtl::OUString::createFromAscii("isPartOfType: exception"),
445cdf0e10cSrcweir             0, uno::makeAny(e));
446cdf0e10cSrcweir     }
447cdf0e10cSrcweir }
448cdf0e10cSrcweir 
449cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
450cdf0e10cSrcweir 
451cdf0e10cSrcweir static ucb::InteractiveAugmentedIOException
mkException(::rtl::OUString const & i_rMessage,ucb::IOErrorCode const i_ErrorCode,::rtl::OUString const & i_rUri,::rtl::OUString const & i_rResource)452cdf0e10cSrcweir mkException( ::rtl::OUString const & i_rMessage,
453cdf0e10cSrcweir     ucb::IOErrorCode const i_ErrorCode,
454cdf0e10cSrcweir     ::rtl::OUString const & i_rUri, ::rtl::OUString const & i_rResource)
455cdf0e10cSrcweir {
456cdf0e10cSrcweir     ucb::InteractiveAugmentedIOException iaioe;
457cdf0e10cSrcweir     iaioe.Message = i_rMessage;
458cdf0e10cSrcweir     iaioe.Classification = task::InteractionClassification_ERROR;
459cdf0e10cSrcweir     iaioe.Code = i_ErrorCode;
460cdf0e10cSrcweir 
461cdf0e10cSrcweir     const beans::PropertyValue uriProp(::rtl::OUString::createFromAscii("Uri"),
462cdf0e10cSrcweir         -1, uno::makeAny(i_rUri), static_cast<beans::PropertyState>(0));
463cdf0e10cSrcweir     const beans::PropertyValue rnProp(
464cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("ResourceName"),
465cdf0e10cSrcweir         -1, uno::makeAny(i_rResource), static_cast<beans::PropertyState>(0));
466cdf0e10cSrcweir     iaioe.Arguments = ::comphelper::makeSequence(
467cdf0e10cSrcweir         uno::makeAny(uriProp), uno::makeAny(rnProp));
468cdf0e10cSrcweir     return iaioe;
469cdf0e10cSrcweir }
470cdf0e10cSrcweir 
471cdf0e10cSrcweir /** error handling policy.
472cdf0e10cSrcweir     <p>If a handler is given, ask it how to proceed:
473cdf0e10cSrcweir     <ul><li>(default:) cancel import, raise exception</li>
474cdf0e10cSrcweir         <li>ignore the error and continue</li>
475cdf0e10cSrcweir         <li>retry the action that led to the error</li></ul></p>
476*45ad4d42Smseidel     N.B.: must not be called before DMA is fully initialized!
477*45ad4d42Smseidel     @returns true if caller should retry
478cdf0e10cSrcweir  */
479cdf0e10cSrcweir static bool
handleError(ucb::InteractiveAugmentedIOException const & i_rException,const uno::Reference<task::XInteractionHandler> & i_xHandler)480cdf0e10cSrcweir handleError( ucb::InteractiveAugmentedIOException const & i_rException,
481cdf0e10cSrcweir     const uno::Reference<task::XInteractionHandler> & i_xHandler)
482cdf0e10cSrcweir {
483cdf0e10cSrcweir     if (!i_xHandler.is()) {
484cdf0e10cSrcweir         throw lang::WrappedTargetException(::rtl::OUString::createFromAscii(
485cdf0e10cSrcweir             "DocumentMetadataAccess::loadMetadataFromStorage: exception"),
486cdf0e10cSrcweir             /* *this*/ 0, uno::makeAny(i_rException));
487cdf0e10cSrcweir     }
488cdf0e10cSrcweir 
489cdf0e10cSrcweir     ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest(
490cdf0e10cSrcweir         new ::comphelper::OInteractionRequest(uno::makeAny(i_rException)) );
491cdf0e10cSrcweir     ::rtl::Reference< ::comphelper::OInteractionRetry > pRetry(
492cdf0e10cSrcweir         new ::comphelper::OInteractionRetry );
493cdf0e10cSrcweir     ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove(
494cdf0e10cSrcweir         new ::comphelper::OInteractionApprove );
495cdf0e10cSrcweir     ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort(
496cdf0e10cSrcweir         new ::comphelper::OInteractionAbort );
497cdf0e10cSrcweir     /* this does not seem to work
498cdf0e10cSrcweir     if (i_rException.Code != ucb::IOErrorCode_WRONG_FORMAT) {
499cdf0e10cSrcweir         pRequest->addContinuation( pRetry.get() );
500cdf0e10cSrcweir     }
501cdf0e10cSrcweir     */
502cdf0e10cSrcweir     pRequest->addContinuation( pApprove.get() );
503cdf0e10cSrcweir     pRequest->addContinuation( pAbort.get() );
504cdf0e10cSrcweir     // actually call the handler
505cdf0e10cSrcweir     i_xHandler->handle( pRequest.get() );
506cdf0e10cSrcweir     if (pRetry->wasSelected()) {
507cdf0e10cSrcweir         return true;
508cdf0e10cSrcweir     } else if (pApprove->wasSelected()) {
509cdf0e10cSrcweir         return false;
510cdf0e10cSrcweir     } else {
511cdf0e10cSrcweir         OSL_ENSURE(pAbort->wasSelected(), "no continuation selected?");
512cdf0e10cSrcweir         throw lang::WrappedTargetException(::rtl::OUString::createFromAscii(
513cdf0e10cSrcweir             "DocumentMetadataAccess::loadMetadataFromStorage: exception"),
514cdf0e10cSrcweir             /* *this*/ 0, uno::makeAny(i_rException));
515cdf0e10cSrcweir     }
516cdf0e10cSrcweir }
517cdf0e10cSrcweir 
518cdf0e10cSrcweir /** check if storage has content.xml/styles.xml;
519cdf0e10cSrcweir     e.g. ODB files seem to only have content.xml */
520cdf0e10cSrcweir static void
collectFilesFromStorage(uno::Reference<embed::XStorage> const & i_xStorage,::rtl::OUString i_Path,std::set<::rtl::OUString> & o_rFiles)521cdf0e10cSrcweir collectFilesFromStorage(uno::Reference<embed::XStorage> const& i_xStorage,
522cdf0e10cSrcweir     ::rtl::OUString i_Path,
523cdf0e10cSrcweir     std::set< ::rtl::OUString > & o_rFiles)
524cdf0e10cSrcweir {
525cdf0e10cSrcweir     static ::rtl::OUString content(::rtl::OUString::createFromAscii(s_content));
526cdf0e10cSrcweir     static ::rtl::OUString styles (::rtl::OUString::createFromAscii(s_styles ));
527cdf0e10cSrcweir     try {
528cdf0e10cSrcweir         if (i_xStorage->hasByName(content) &&
529cdf0e10cSrcweir             i_xStorage->isStreamElement(content))
530cdf0e10cSrcweir         {
531cdf0e10cSrcweir             o_rFiles.insert(i_Path + content);
532cdf0e10cSrcweir         }
533cdf0e10cSrcweir         if (i_xStorage->hasByName(styles) &&
534cdf0e10cSrcweir             i_xStorage->isStreamElement(styles))
535cdf0e10cSrcweir         {
536cdf0e10cSrcweir             o_rFiles.insert(i_Path + styles);
537cdf0e10cSrcweir         }
538cdf0e10cSrcweir     } catch (uno::Exception &) {
539cdf0e10cSrcweir         OSL_TRACE("collectFilesFromStorage: exception?");
540cdf0e10cSrcweir     }
541cdf0e10cSrcweir }
542cdf0e10cSrcweir 
543cdf0e10cSrcweir /** import a metadata file into repository */
544cdf0e10cSrcweir static void
readStream(struct DocumentMetadataAccess_Impl & i_rImpl,uno::Reference<embed::XStorage> const & i_xStorage,::rtl::OUString const & i_rPath,::rtl::OUString const & i_rBaseURI)545cdf0e10cSrcweir readStream(struct DocumentMetadataAccess_Impl & i_rImpl,
546cdf0e10cSrcweir     uno::Reference< embed::XStorage > const & i_xStorage,
547cdf0e10cSrcweir     ::rtl::OUString const & i_rPath,
548cdf0e10cSrcweir     ::rtl::OUString const & i_rBaseURI)
549cdf0e10cSrcweir {
550cdf0e10cSrcweir     ::rtl::OUString dir;
551cdf0e10cSrcweir     ::rtl::OUString rest;
552cdf0e10cSrcweir     try {
553cdf0e10cSrcweir         if (!splitPath(i_rPath, dir, rest)) throw uno::RuntimeException();
554cdf0e10cSrcweir         if (dir.equalsAscii("")) {
555cdf0e10cSrcweir             if (i_xStorage->isStreamElement(i_rPath)) {
556cdf0e10cSrcweir                 const uno::Reference<io::XStream> xStream(
557cdf0e10cSrcweir                     i_xStorage->openStreamElement(i_rPath,
558cdf0e10cSrcweir                         embed::ElementModes::READ), uno::UNO_SET_THROW);
559cdf0e10cSrcweir                 const uno::Reference<io::XInputStream> xInStream(
560cdf0e10cSrcweir                     xStream->getInputStream(), uno::UNO_SET_THROW );
561cdf0e10cSrcweir                 const uno::Reference<rdf::XURI> xBaseURI(
562cdf0e10cSrcweir                     rdf::URI::create(i_rImpl.m_xContext, i_rBaseURI));
563cdf0e10cSrcweir                 const uno::Reference<rdf::XURI> xURI(
564cdf0e10cSrcweir                     rdf::URI::createNS(i_rImpl.m_xContext,
565cdf0e10cSrcweir                         i_rBaseURI, i_rPath));
566cdf0e10cSrcweir                 i_rImpl.m_xRepository->importGraph(rdf::FileFormat::RDF_XML,
567cdf0e10cSrcweir                     xInStream, xURI, xBaseURI);
568cdf0e10cSrcweir             } else {
569cdf0e10cSrcweir                 throw mkException(::rtl::OUString::createFromAscii(
570cdf0e10cSrcweir                     "readStream: is not a stream"),
571cdf0e10cSrcweir                     ucb::IOErrorCode_NO_FILE, i_rBaseURI + i_rPath, i_rPath);
572cdf0e10cSrcweir             }
573cdf0e10cSrcweir         } else {
574cdf0e10cSrcweir             if (i_xStorage->isStorageElement(dir)) {
575cdf0e10cSrcweir                 const uno::Reference<embed::XStorage> xDir(
576cdf0e10cSrcweir                     i_xStorage->openStorageElement(dir,
577cdf0e10cSrcweir                         embed::ElementModes::READ));
578cdf0e10cSrcweir                 const uno::Reference< beans::XPropertySet > xDirProps(xDir,
579cdf0e10cSrcweir                     uno::UNO_QUERY_THROW);
580cdf0e10cSrcweir                 try {
581cdf0e10cSrcweir                     ::rtl::OUString mimeType;
582cdf0e10cSrcweir                     xDirProps->getPropertyValue(
583cdf0e10cSrcweir                             ::comphelper::MediaDescriptor::PROP_MEDIATYPE() )
584cdf0e10cSrcweir                         >>= mimeType;
585cdf0e10cSrcweir                     if (mimeType.matchAsciiL(s_odfmime, sizeof(s_odfmime) - 1))
586cdf0e10cSrcweir                     {
587cdf0e10cSrcweir                         OSL_TRACE("readStream: "
588cdf0e10cSrcweir                             "refusing to recurse into embedded document");
589cdf0e10cSrcweir                         return;
590cdf0e10cSrcweir                     }
591cdf0e10cSrcweir                 } catch (uno::Exception &) { }
592cdf0e10cSrcweir                 ::rtl::OUStringBuffer buf(i_rBaseURI);
593cdf0e10cSrcweir                 buf.append(dir).append(static_cast<sal_Unicode>('/'));
594cdf0e10cSrcweir                 readStream(i_rImpl, xDir, rest, buf.makeStringAndClear() );
595cdf0e10cSrcweir             } else {
596cdf0e10cSrcweir                 throw mkException(::rtl::OUString::createFromAscii(
597cdf0e10cSrcweir                     "readStream: is not a directory"),
598cdf0e10cSrcweir                     ucb::IOErrorCode_NO_DIRECTORY, i_rBaseURI + dir, dir);
599cdf0e10cSrcweir             }
600cdf0e10cSrcweir         }
601cdf0e10cSrcweir     } catch (container::NoSuchElementException & e) {
602cdf0e10cSrcweir         throw mkException(e.Message, ucb::IOErrorCode_NOT_EXISTING_PATH,
603cdf0e10cSrcweir             i_rBaseURI + i_rPath, i_rPath);
604cdf0e10cSrcweir     } catch (io::IOException & e) {
605cdf0e10cSrcweir         throw mkException(e.Message, ucb::IOErrorCode_CANT_READ,
606cdf0e10cSrcweir             i_rBaseURI + i_rPath, i_rPath);
607cdf0e10cSrcweir     } catch (rdf::ParseException & e) {
608cdf0e10cSrcweir         throw mkException(e.Message, ucb::IOErrorCode_WRONG_FORMAT,
609cdf0e10cSrcweir             i_rBaseURI + i_rPath, i_rPath);
610cdf0e10cSrcweir     }
611cdf0e10cSrcweir }
612cdf0e10cSrcweir 
613cdf0e10cSrcweir /** import a metadata file into repository */
614cdf0e10cSrcweir static void
importFile(struct DocumentMetadataAccess_Impl & i_rImpl,uno::Reference<embed::XStorage> const & i_xStorage,::rtl::OUString const & i_rBaseURI,uno::Reference<task::XInteractionHandler> const & i_xHandler,::rtl::OUString i_rPath)615cdf0e10cSrcweir importFile(struct DocumentMetadataAccess_Impl & i_rImpl,
616cdf0e10cSrcweir     uno::Reference<embed::XStorage> const & i_xStorage,
617cdf0e10cSrcweir     ::rtl::OUString const & i_rBaseURI,
618cdf0e10cSrcweir     uno::Reference<task::XInteractionHandler> const & i_xHandler,
619cdf0e10cSrcweir     ::rtl::OUString i_rPath)
620cdf0e10cSrcweir {
621cdf0e10cSrcweir retry:
622cdf0e10cSrcweir     try {
623cdf0e10cSrcweir         readStream(i_rImpl, i_xStorage, i_rPath, i_rBaseURI);
624cdf0e10cSrcweir     } catch (ucb::InteractiveAugmentedIOException & e) {
625cdf0e10cSrcweir         if (handleError(e, i_xHandler)) goto retry;
626cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
627cdf0e10cSrcweir         throw;
628cdf0e10cSrcweir     } catch (uno::Exception & e) {
629cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
630cdf0e10cSrcweir             ::rtl::OUString::createFromAscii("importFile: exception"),
631cdf0e10cSrcweir             0, uno::makeAny(e));
632cdf0e10cSrcweir     }
633cdf0e10cSrcweir }
634cdf0e10cSrcweir 
635cdf0e10cSrcweir /** actually write a metadata file to the storage */
636cdf0e10cSrcweir static void
exportStream(struct DocumentMetadataAccess_Impl & i_rImpl,uno::Reference<embed::XStorage> const & i_xStorage,uno::Reference<rdf::XURI> const & i_xGraphName,::rtl::OUString const & i_rFileName,::rtl::OUString const & i_rBaseURI)637cdf0e10cSrcweir exportStream(struct DocumentMetadataAccess_Impl & i_rImpl,
638cdf0e10cSrcweir     uno::Reference< embed::XStorage > const & i_xStorage,
639cdf0e10cSrcweir     uno::Reference<rdf::XURI> const & i_xGraphName,
640cdf0e10cSrcweir     ::rtl::OUString const & i_rFileName,
641cdf0e10cSrcweir     ::rtl::OUString const & i_rBaseURI)
642cdf0e10cSrcweir {
643cdf0e10cSrcweir     const uno::Reference<io::XStream> xStream(
644cdf0e10cSrcweir         i_xStorage->openStreamElement(i_rFileName,
645cdf0e10cSrcweir             embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE),
646cdf0e10cSrcweir         uno::UNO_SET_THROW);
647cdf0e10cSrcweir     const uno::Reference< beans::XPropertySet > xStreamProps(xStream,
648cdf0e10cSrcweir         uno::UNO_QUERY);
649cdf0e10cSrcweir     if (xStreamProps.is()) { // this is NOT supported in FileSystemStorage
650cdf0e10cSrcweir         xStreamProps->setPropertyValue(
651cdf0e10cSrcweir             ::rtl::OUString::createFromAscii("MediaType"),
652cdf0e10cSrcweir             uno::makeAny(::rtl::OUString::createFromAscii(s_rdfxml)));
653cdf0e10cSrcweir     }
654cdf0e10cSrcweir     const uno::Reference<io::XOutputStream> xOutStream(
655cdf0e10cSrcweir         xStream->getOutputStream(), uno::UNO_SET_THROW );
656cdf0e10cSrcweir     const uno::Reference<rdf::XURI> xBaseURI(
657cdf0e10cSrcweir         rdf::URI::create(i_rImpl.m_xContext, i_rBaseURI));
658cdf0e10cSrcweir     i_rImpl.m_xRepository->exportGraph(rdf::FileFormat::RDF_XML,
659cdf0e10cSrcweir         xOutStream, i_xGraphName, xBaseURI);
660cdf0e10cSrcweir }
661cdf0e10cSrcweir 
662cdf0e10cSrcweir /** write a metadata file to the storage */
663cdf0e10cSrcweir static void
writeStream(struct DocumentMetadataAccess_Impl & i_rImpl,uno::Reference<embed::XStorage> const & i_xStorage,uno::Reference<rdf::XURI> const & i_xGraphName,::rtl::OUString const & i_rPath,::rtl::OUString const & i_rBaseURI)664cdf0e10cSrcweir writeStream(struct DocumentMetadataAccess_Impl & i_rImpl,
665cdf0e10cSrcweir     uno::Reference< embed::XStorage > const & i_xStorage,
666cdf0e10cSrcweir     uno::Reference<rdf::XURI> const & i_xGraphName,
667cdf0e10cSrcweir     ::rtl::OUString const & i_rPath,
668cdf0e10cSrcweir     ::rtl::OUString const & i_rBaseURI)
669cdf0e10cSrcweir {
670cdf0e10cSrcweir     ::rtl::OUString dir;
671cdf0e10cSrcweir     ::rtl::OUString rest;
672cdf0e10cSrcweir     if (!splitPath(i_rPath, dir, rest)) throw uno::RuntimeException();
673cdf0e10cSrcweir     try {
674cdf0e10cSrcweir         if (dir.equalsAscii("")) {
675cdf0e10cSrcweir             exportStream(i_rImpl, i_xStorage, i_xGraphName, i_rPath,
676cdf0e10cSrcweir                 i_rBaseURI);
677cdf0e10cSrcweir         } else {
678cdf0e10cSrcweir             const uno::Reference<embed::XStorage> xDir(
679cdf0e10cSrcweir                 i_xStorage->openStorageElement(dir,
680cdf0e10cSrcweir                     embed::ElementModes::WRITE));
681cdf0e10cSrcweir             const uno::Reference< beans::XPropertySet > xDirProps(xDir,
682cdf0e10cSrcweir                 uno::UNO_QUERY_THROW);
683cdf0e10cSrcweir             try {
684cdf0e10cSrcweir                 ::rtl::OUString mimeType;
685cdf0e10cSrcweir                 xDirProps->getPropertyValue(
686cdf0e10cSrcweir                         ::comphelper::MediaDescriptor::PROP_MEDIATYPE() )
687cdf0e10cSrcweir                     >>= mimeType;
688cdf0e10cSrcweir                 if (mimeType.matchAsciiL(s_odfmime, sizeof(s_odfmime) - 1)) {
689cdf0e10cSrcweir                     OSL_TRACE("writeStream: "
690cdf0e10cSrcweir                         "refusing to recurse into embedded document");
691cdf0e10cSrcweir                     return;
692cdf0e10cSrcweir                 }
693cdf0e10cSrcweir             } catch (uno::Exception &) { }
694cdf0e10cSrcweir             ::rtl::OUStringBuffer buf(i_rBaseURI);
695cdf0e10cSrcweir             buf.append(dir).append(static_cast<sal_Unicode>('/'));
696cdf0e10cSrcweir             writeStream(i_rImpl, xDir, i_xGraphName, rest,
697cdf0e10cSrcweir                 buf.makeStringAndClear());
698cdf0e10cSrcweir             uno::Reference<embed::XTransactedObject> const xTransaction(
699cdf0e10cSrcweir                 xDir, uno::UNO_QUERY);
700cdf0e10cSrcweir             if (xTransaction.is()) {
701cdf0e10cSrcweir                 xTransaction->commit();
702cdf0e10cSrcweir             }
703cdf0e10cSrcweir         }
704cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
705cdf0e10cSrcweir         throw;
706cdf0e10cSrcweir     } catch (io::IOException &) {
707cdf0e10cSrcweir         throw;
708cdf0e10cSrcweir     }
709cdf0e10cSrcweir }
710cdf0e10cSrcweir 
711cdf0e10cSrcweir static void
initLoading(struct DocumentMetadataAccess_Impl & i_rImpl,const uno::Reference<embed::XStorage> & i_xStorage,const uno::Reference<rdf::XURI> & i_xBaseURI,const uno::Reference<task::XInteractionHandler> & i_xHandler)712cdf0e10cSrcweir initLoading(struct DocumentMetadataAccess_Impl & i_rImpl,
713cdf0e10cSrcweir     const uno::Reference< embed::XStorage > & i_xStorage,
714cdf0e10cSrcweir     const uno::Reference<rdf::XURI> & i_xBaseURI,
715cdf0e10cSrcweir     const uno::Reference<task::XInteractionHandler> & i_xHandler)
716cdf0e10cSrcweir {
717cdf0e10cSrcweir retry:
718cdf0e10cSrcweir     // clear old data
719cdf0e10cSrcweir     i_rImpl.m_xManifest.clear();
720cdf0e10cSrcweir     // init BaseURI
721cdf0e10cSrcweir     i_rImpl.m_xBaseURI = i_xBaseURI;
722cdf0e10cSrcweir 
723cdf0e10cSrcweir     // create repository
724cdf0e10cSrcweir     i_rImpl.m_xRepository.clear();
725cdf0e10cSrcweir     i_rImpl.m_xRepository.set(rdf::Repository::create(i_rImpl.m_xContext),
726cdf0e10cSrcweir             uno::UNO_SET_THROW);
727cdf0e10cSrcweir 
728cdf0e10cSrcweir     const ::rtl::OUString manifest (
729cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(s_manifest));
730cdf0e10cSrcweir     const ::rtl::OUString baseURI( i_xBaseURI->getStringValue() );
731cdf0e10cSrcweir     // try to delay raising errors until after initialization is done
732cdf0e10cSrcweir     uno::Any rterr;
733cdf0e10cSrcweir     ucb::InteractiveAugmentedIOException iaioe;
734cdf0e10cSrcweir     bool err(false);
735cdf0e10cSrcweir 
736cdf0e10cSrcweir     const uno::Reference <rdf::XURI> xManifest(
737cdf0e10cSrcweir         getURIForStream(i_rImpl, manifest));
738cdf0e10cSrcweir     try {
739cdf0e10cSrcweir         readStream(i_rImpl, i_xStorage, manifest, baseURI);
740cdf0e10cSrcweir     } catch (ucb::InteractiveAugmentedIOException & e) {
741cdf0e10cSrcweir         // no manifest.rdf: this is not an error in ODF < 1.2
742cdf0e10cSrcweir         if (!(ucb::IOErrorCode_NOT_EXISTING_PATH == e.Code)) {
743cdf0e10cSrcweir             iaioe = e;
744cdf0e10cSrcweir             err = true;
745cdf0e10cSrcweir         }
746cdf0e10cSrcweir     } catch (uno::Exception & e) {
747cdf0e10cSrcweir         rterr <<= e;
748cdf0e10cSrcweir     }
749cdf0e10cSrcweir 
750cdf0e10cSrcweir     // init manifest graph
751cdf0e10cSrcweir     const uno::Reference<rdf::XNamedGraph> xManifestGraph(
752cdf0e10cSrcweir         i_rImpl.m_xRepository->getGraph(xManifest));
753cdf0e10cSrcweir     i_rImpl.m_xManifest.set(xManifestGraph.is() ? xManifestGraph :
754cdf0e10cSrcweir         i_rImpl.m_xRepository->createGraph(xManifest), uno::UNO_SET_THROW);
755cdf0e10cSrcweir     const uno::Reference<container::XEnumeration> xEnum(
756cdf0e10cSrcweir         i_rImpl.m_xManifest->getStatements(0,
757cdf0e10cSrcweir             getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
758cdf0e10cSrcweir             getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get()));
759cdf0e10cSrcweir 
760cdf0e10cSrcweir     // document statement
761cdf0e10cSrcweir     i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
762cdf0e10cSrcweir         getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
763cdf0e10cSrcweir         getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get());
764cdf0e10cSrcweir 
765cdf0e10cSrcweir     OSL_ENSURE(i_rImpl.m_xBaseURI.is(), "base URI is null");
766cdf0e10cSrcweir     OSL_ENSURE(i_rImpl.m_xRepository.is(), "repository is null");
767cdf0e10cSrcweir     OSL_ENSURE(i_rImpl.m_xManifest.is(), "manifest is null");
768cdf0e10cSrcweir 
769cdf0e10cSrcweir     if (rterr.hasValue()) {
770cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
771cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
772cdf0e10cSrcweir                 "DocumentMetadataAccess::loadMetadataFromStorage: "
773cdf0e10cSrcweir                 "exception"), 0, rterr);
774cdf0e10cSrcweir     }
775cdf0e10cSrcweir 
776cdf0e10cSrcweir     if (err) {
777cdf0e10cSrcweir         if (handleError(iaioe, i_xHandler)) goto retry;
778cdf0e10cSrcweir     }
779cdf0e10cSrcweir }
780cdf0e10cSrcweir 
781cdf0e10cSrcweir /** init Impl struct */
init(struct DocumentMetadataAccess_Impl & i_rImpl)782cdf0e10cSrcweir static void init(struct DocumentMetadataAccess_Impl & i_rImpl)
783cdf0e10cSrcweir {
784cdf0e10cSrcweir     try {
785cdf0e10cSrcweir 
786cdf0e10cSrcweir         i_rImpl.m_xManifest.set(i_rImpl.m_xRepository->createGraph(
787cdf0e10cSrcweir             getURIForStream(i_rImpl,
788cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(s_manifest))),
789cdf0e10cSrcweir             uno::UNO_SET_THROW);
790cdf0e10cSrcweir 
791cdf0e10cSrcweir         // insert the document statement
792cdf0e10cSrcweir         i_rImpl.m_xManifest->addStatement(i_rImpl.m_xBaseURI.get(),
793cdf0e10cSrcweir             getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext),
794cdf0e10cSrcweir             getURI<rdf::URIs::PKG_DOCUMENT>(i_rImpl.m_xContext).get());
795cdf0e10cSrcweir     } catch (uno::Exception & e) {
796cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
797cdf0e10cSrcweir             ::rtl::OUString::createFromAscii("init: unexpected exception"), 0,
798cdf0e10cSrcweir             uno::makeAny(e));
799cdf0e10cSrcweir     }
800cdf0e10cSrcweir 
801cdf0e10cSrcweir     // add top-level content files
802cdf0e10cSrcweir     if (!addContentOrStylesFileImpl(i_rImpl,
803cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(s_content))) {
804cdf0e10cSrcweir         throw uno::RuntimeException();
805cdf0e10cSrcweir     }
806cdf0e10cSrcweir     if (!addContentOrStylesFileImpl(i_rImpl,
807cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(s_styles))) {
808cdf0e10cSrcweir         throw uno::RuntimeException();
809cdf0e10cSrcweir     }
810cdf0e10cSrcweir }
811cdf0e10cSrcweir 
812cdf0e10cSrcweir 
813cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
814cdf0e10cSrcweir 
DocumentMetadataAccess(uno::Reference<uno::XComponentContext> const & i_xContext,const IXmlIdRegistrySupplier & i_rRegistrySupplier)815cdf0e10cSrcweir DocumentMetadataAccess::DocumentMetadataAccess(
816cdf0e10cSrcweir         uno::Reference< uno::XComponentContext > const & i_xContext,
817cdf0e10cSrcweir         const IXmlIdRegistrySupplier & i_rRegistrySupplier)
818cdf0e10cSrcweir     : m_pImpl(new DocumentMetadataAccess_Impl(i_xContext, i_rRegistrySupplier))
819cdf0e10cSrcweir {
82030acf5e8Spfg     // no initialization: must call loadFrom...
821cdf0e10cSrcweir }
822cdf0e10cSrcweir 
DocumentMetadataAccess(uno::Reference<uno::XComponentContext> const & i_xContext,const IXmlIdRegistrySupplier & i_rRegistrySupplier,::rtl::OUString const & i_rURI)823cdf0e10cSrcweir DocumentMetadataAccess::DocumentMetadataAccess(
824cdf0e10cSrcweir         uno::Reference< uno::XComponentContext > const & i_xContext,
825cdf0e10cSrcweir         const IXmlIdRegistrySupplier & i_rRegistrySupplier,
826cdf0e10cSrcweir         ::rtl::OUString const & i_rURI)
827cdf0e10cSrcweir     : m_pImpl(new DocumentMetadataAccess_Impl(i_xContext, i_rRegistrySupplier))
828cdf0e10cSrcweir {
829cdf0e10cSrcweir     OSL_ENSURE(i_rURI.getLength(), "DMA::DMA: no URI given!");
830cdf0e10cSrcweir     OSL_ENSURE(i_rURI.endsWithAsciiL("/", 1), "DMA::DMA: URI without / given!");
831cdf0e10cSrcweir     if (!i_rURI.endsWithAsciiL("/", 1)) throw uno::RuntimeException();
832cdf0e10cSrcweir     m_pImpl->m_xBaseURI.set(rdf::URI::create(m_pImpl->m_xContext, i_rURI));
833cdf0e10cSrcweir     m_pImpl->m_xRepository.set(rdf::Repository::create(m_pImpl->m_xContext),
834cdf0e10cSrcweir             uno::UNO_SET_THROW);
835cdf0e10cSrcweir 
836cdf0e10cSrcweir     // init repository
837cdf0e10cSrcweir     init(*m_pImpl);
838cdf0e10cSrcweir 
839cdf0e10cSrcweir     OSL_ENSURE(m_pImpl->m_xBaseURI.is(), "base URI is null");
840cdf0e10cSrcweir     OSL_ENSURE(m_pImpl->m_xRepository.is(), "repository is null");
841cdf0e10cSrcweir     OSL_ENSURE(m_pImpl->m_xManifest.is(), "manifest is null");
842cdf0e10cSrcweir }
843cdf0e10cSrcweir 
~DocumentMetadataAccess()844cdf0e10cSrcweir DocumentMetadataAccess::~DocumentMetadataAccess()
845cdf0e10cSrcweir {
846cdf0e10cSrcweir }
847cdf0e10cSrcweir 
848cdf0e10cSrcweir 
849cdf0e10cSrcweir // ::com::sun::star::rdf::XRepositorySupplier:
850cdf0e10cSrcweir uno::Reference< rdf::XRepository > SAL_CALL
getRDFRepository()851cdf0e10cSrcweir DocumentMetadataAccess::getRDFRepository() throw (uno::RuntimeException)
852cdf0e10cSrcweir {
853cdf0e10cSrcweir     OSL_ENSURE(m_pImpl->m_xRepository.is(), "repository not initialized");
854cdf0e10cSrcweir     return m_pImpl->m_xRepository;
855cdf0e10cSrcweir }
856cdf0e10cSrcweir 
857cdf0e10cSrcweir // ::com::sun::star::rdf::XNode:
858cdf0e10cSrcweir ::rtl::OUString SAL_CALL
getStringValue()859cdf0e10cSrcweir DocumentMetadataAccess::getStringValue() throw (uno::RuntimeException)
860cdf0e10cSrcweir {
861cdf0e10cSrcweir     return m_pImpl->m_xBaseURI->getStringValue();
862cdf0e10cSrcweir }
863cdf0e10cSrcweir 
864cdf0e10cSrcweir // ::com::sun::star::rdf::XURI:
865cdf0e10cSrcweir ::rtl::OUString SAL_CALL
getNamespace()866cdf0e10cSrcweir DocumentMetadataAccess::getNamespace() throw (uno::RuntimeException)
867cdf0e10cSrcweir {
868cdf0e10cSrcweir     return m_pImpl->m_xBaseURI->getNamespace();
869cdf0e10cSrcweir }
870cdf0e10cSrcweir 
871cdf0e10cSrcweir ::rtl::OUString SAL_CALL
getLocalName()872cdf0e10cSrcweir DocumentMetadataAccess::getLocalName() throw (uno::RuntimeException)
873cdf0e10cSrcweir {
874cdf0e10cSrcweir     return m_pImpl->m_xBaseURI->getLocalName();
875cdf0e10cSrcweir }
876cdf0e10cSrcweir 
877cdf0e10cSrcweir // ::com::sun::star::rdf::XDocumentMetadataAccess:
878cdf0e10cSrcweir uno::Reference< rdf::XMetadatable > SAL_CALL
getElementByMetadataReference(const::com::sun::star::beans::StringPair & i_rReference)879cdf0e10cSrcweir DocumentMetadataAccess::getElementByMetadataReference(
880cdf0e10cSrcweir     const ::com::sun::star::beans::StringPair & i_rReference)
881cdf0e10cSrcweir throw (uno::RuntimeException)
882cdf0e10cSrcweir {
883cdf0e10cSrcweir     const IXmlIdRegistry * pReg(
884cdf0e10cSrcweir         m_pImpl->m_rXmlIdRegistrySupplier.GetXmlIdRegistry() );
885cdf0e10cSrcweir     if (!pReg) {
886cdf0e10cSrcweir         throw uno::RuntimeException(::rtl::OUString::createFromAscii(
887cdf0e10cSrcweir             "DocumentMetadataAccess::getElementByXmlId: no registry"), *this);
888cdf0e10cSrcweir     }
889cdf0e10cSrcweir     return pReg->GetElementByMetadataReference(i_rReference);
890cdf0e10cSrcweir }
891cdf0e10cSrcweir 
892cdf0e10cSrcweir uno::Reference< rdf::XMetadatable > SAL_CALL
getElementByURI(const uno::Reference<rdf::XURI> & i_xURI)893cdf0e10cSrcweir DocumentMetadataAccess::getElementByURI(
894cdf0e10cSrcweir     const uno::Reference< rdf::XURI > & i_xURI )
895cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException)
896cdf0e10cSrcweir {
897cdf0e10cSrcweir     if (!i_xURI.is()) {
898cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
899cdf0e10cSrcweir             "DocumentMetadataAccess::getElementByURI: URI is null"), *this, 0);
900cdf0e10cSrcweir     }
901cdf0e10cSrcweir 
902cdf0e10cSrcweir     const ::rtl::OUString baseURI( m_pImpl->m_xBaseURI->getStringValue() );
903cdf0e10cSrcweir     const ::rtl::OUString name( i_xURI->getStringValue() );
904cdf0e10cSrcweir     if (!name.match(baseURI)) {
905cdf0e10cSrcweir         return 0;
906cdf0e10cSrcweir     }
907cdf0e10cSrcweir     const ::rtl::OUString relName( name.copy(baseURI.getLength()) );
908cdf0e10cSrcweir     ::rtl::OUString path;
909cdf0e10cSrcweir     ::rtl::OUString idref;
910cdf0e10cSrcweir     if (!splitXmlId(relName, path, idref)) {
911cdf0e10cSrcweir         return 0;
912cdf0e10cSrcweir     }
913cdf0e10cSrcweir 
914cdf0e10cSrcweir     return getElementByMetadataReference( beans::StringPair(path, idref) );
915cdf0e10cSrcweir }
916cdf0e10cSrcweir 
917cdf0e10cSrcweir 
918cdf0e10cSrcweir uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
getMetadataGraphsWithType(const uno::Reference<rdf::XURI> & i_xType)919cdf0e10cSrcweir DocumentMetadataAccess::getMetadataGraphsWithType(
920cdf0e10cSrcweir     const uno::Reference<rdf::XURI> & i_xType)
921cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException)
922cdf0e10cSrcweir {
923cdf0e10cSrcweir     if (!i_xType.is()) {
924cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
925cdf0e10cSrcweir             "DocumentMetadataAccess::getMetadataGraphsWithType: "
926cdf0e10cSrcweir             "type is null"), *this, 0);
927cdf0e10cSrcweir     }
928cdf0e10cSrcweir 
929cdf0e10cSrcweir     ::comphelper::SequenceAsVector< uno::Reference< rdf::XURI > > ret;
930cdf0e10cSrcweir     const ::std::vector< uno::Reference< rdf::XURI > > parts(
931cdf0e10cSrcweir         getAllParts(*m_pImpl) );
932cdf0e10cSrcweir     ::std::remove_copy_if(parts.begin(), parts.end(),
933cdf0e10cSrcweir         ::std::back_inserter(ret),
934cdf0e10cSrcweir         ::boost::bind(
935cdf0e10cSrcweir             ::std::logical_not<bool>(),
936cdf0e10cSrcweir             ::boost::bind(&isPartOfType, ::boost::ref(*m_pImpl), _1, i_xType) ));
937cdf0e10cSrcweir     return ret.getAsConstList();
938cdf0e10cSrcweir }
939cdf0e10cSrcweir 
940cdf0e10cSrcweir uno::Reference<rdf::XURI> SAL_CALL
addMetadataFile(const::rtl::OUString & i_rFileName,const uno::Sequence<uno::Reference<rdf::XURI>> & i_rTypes)941cdf0e10cSrcweir DocumentMetadataAccess::addMetadataFile(const ::rtl::OUString & i_rFileName,
942cdf0e10cSrcweir     const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
943cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
944cdf0e10cSrcweir     container::ElementExistException)
945cdf0e10cSrcweir {
946cdf0e10cSrcweir     if (!isFileNameValid(i_rFileName)) {
947cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
948cdf0e10cSrcweir             "DocumentMetadataAccess::addMetadataFile: invalid FileName"),
949cdf0e10cSrcweir             *this, 0);
950cdf0e10cSrcweir     }
951cdf0e10cSrcweir     if (isReservedFile(i_rFileName)) {
952cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
953cdf0e10cSrcweir             "DocumentMetadataAccess::addMetadataFile:"
954cdf0e10cSrcweir             "invalid FileName: reserved"), *this, 0);
955cdf0e10cSrcweir     }
956cdf0e10cSrcweir     for (sal_Int32 i = 0; i < i_rTypes.getLength(); ++i) {
957cdf0e10cSrcweir         if (!i_rTypes[i].is()) {
958cdf0e10cSrcweir             throw lang::IllegalArgumentException(
959cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
960cdf0e10cSrcweir                     "DocumentMetadataAccess::addMetadataFile: "
961cdf0e10cSrcweir                     "null type"), *this, 2);
962cdf0e10cSrcweir         }
963cdf0e10cSrcweir     }
964cdf0e10cSrcweir 
965cdf0e10cSrcweir     const uno::Reference<rdf::XURI> xGraphName(
966cdf0e10cSrcweir         getURIForStream(*m_pImpl, i_rFileName) );
967cdf0e10cSrcweir 
968cdf0e10cSrcweir     try {
969cdf0e10cSrcweir         m_pImpl->m_xRepository->createGraph(xGraphName);
970cdf0e10cSrcweir     } catch (rdf::RepositoryException & e) {
971cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
972cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
973cdf0e10cSrcweir                 "DocumentMetadataAccess::addMetadataFile: exception"),
974cdf0e10cSrcweir             *this, uno::makeAny(e));
975cdf0e10cSrcweir         // note: all other exceptions are propagated
976cdf0e10cSrcweir     }
977cdf0e10cSrcweir 
978cdf0e10cSrcweir     addMetadataFileImpl(*m_pImpl, i_rFileName, i_rTypes);
979cdf0e10cSrcweir     return xGraphName;
980cdf0e10cSrcweir }
981cdf0e10cSrcweir 
982cdf0e10cSrcweir uno::Reference<rdf::XURI> SAL_CALL
importMetadataFile(::sal_Int16 i_Format,const uno::Reference<io::XInputStream> & i_xInStream,const::rtl::OUString & i_rFileName,const uno::Reference<rdf::XURI> & i_xBaseURI,const uno::Sequence<uno::Reference<rdf::XURI>> & i_rTypes)983cdf0e10cSrcweir DocumentMetadataAccess::importMetadataFile(::sal_Int16 i_Format,
984cdf0e10cSrcweir     const uno::Reference< io::XInputStream > & i_xInStream,
985cdf0e10cSrcweir     const ::rtl::OUString & i_rFileName,
986cdf0e10cSrcweir     const uno::Reference< rdf::XURI > & i_xBaseURI,
987cdf0e10cSrcweir     const uno::Sequence < uno::Reference< rdf::XURI > > & i_rTypes)
988cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
989cdf0e10cSrcweir     datatransfer::UnsupportedFlavorException,
990cdf0e10cSrcweir     container::ElementExistException, rdf::ParseException, io::IOException)
991cdf0e10cSrcweir {
992cdf0e10cSrcweir     if (!isFileNameValid(i_rFileName)) {
993cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
994cdf0e10cSrcweir             "DocumentMetadataAccess::importMetadataFile: invalid FileName"),
995cdf0e10cSrcweir             *this, 0);
996cdf0e10cSrcweir     }
997cdf0e10cSrcweir     if (isReservedFile(i_rFileName)) {
998cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
999cdf0e10cSrcweir             "DocumentMetadataAccess::importMetadataFile:"
1000cdf0e10cSrcweir             "invalid FileName: reserved"), *this, 0);
1001cdf0e10cSrcweir     }
1002cdf0e10cSrcweir     for (sal_Int32 i = 0; i < i_rTypes.getLength(); ++i) {
1003cdf0e10cSrcweir         if (!i_rTypes[i].is()) {
1004cdf0e10cSrcweir             throw lang::IllegalArgumentException(
1005cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
1006cdf0e10cSrcweir                     "DocumentMetadataAccess::importMetadataFile: null type"),
1007cdf0e10cSrcweir                 *this, 5);
1008cdf0e10cSrcweir         }
1009cdf0e10cSrcweir     }
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir     const uno::Reference<rdf::XURI> xGraphName(
1012cdf0e10cSrcweir         getURIForStream(*m_pImpl, i_rFileName) );
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir     try {
1015cdf0e10cSrcweir         m_pImpl->m_xRepository->importGraph(
1016cdf0e10cSrcweir             i_Format, i_xInStream, xGraphName, i_xBaseURI);
1017cdf0e10cSrcweir     } catch (rdf::RepositoryException & e) {
1018cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
1019cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
1020cdf0e10cSrcweir                 "DocumentMetadataAccess::importMetadataFile: "
1021cdf0e10cSrcweir                 "RepositoryException"), *this, uno::makeAny(e));
1022cdf0e10cSrcweir         // note: all other exceptions are propagated
1023cdf0e10cSrcweir     }
1024cdf0e10cSrcweir 
1025cdf0e10cSrcweir     // add to manifest
1026cdf0e10cSrcweir     addMetadataFileImpl(*m_pImpl, i_rFileName, i_rTypes);
1027cdf0e10cSrcweir     return xGraphName;
1028cdf0e10cSrcweir }
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir void SAL_CALL
removeMetadataFile(const uno::Reference<rdf::XURI> & i_xGraphName)1031cdf0e10cSrcweir DocumentMetadataAccess::removeMetadataFile(
1032cdf0e10cSrcweir     const uno::Reference< rdf::XURI > & i_xGraphName)
1033cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
1034cdf0e10cSrcweir     container::NoSuchElementException)
1035cdf0e10cSrcweir {
1036cdf0e10cSrcweir     try {
1037cdf0e10cSrcweir         m_pImpl->m_xRepository->destroyGraph(i_xGraphName);
1038cdf0e10cSrcweir     } catch (rdf::RepositoryException & e) {
1039cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
1040cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
1041cdf0e10cSrcweir                 "DocumentMetadataAccess::removeMetadataFile: "
1042cdf0e10cSrcweir                 "RepositoryException"), *this, uno::makeAny(e));
1043cdf0e10cSrcweir         // note: all other exceptions are propagated
1044cdf0e10cSrcweir     }
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir     // remove file from manifest
1047cdf0e10cSrcweir     removeFile(*m_pImpl, i_xGraphName.get());
1048cdf0e10cSrcweir }
1049cdf0e10cSrcweir 
1050cdf0e10cSrcweir void SAL_CALL
addContentOrStylesFile(const::rtl::OUString & i_rFileName)1051cdf0e10cSrcweir DocumentMetadataAccess::addContentOrStylesFile(
1052cdf0e10cSrcweir     const ::rtl::OUString & i_rFileName)
1053cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
1054cdf0e10cSrcweir     container::ElementExistException)
1055cdf0e10cSrcweir {
1056cdf0e10cSrcweir     if (!isFileNameValid(i_rFileName)) {
1057cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1058cdf0e10cSrcweir             "DocumentMetadataAccess::addContentOrStylesFile: "
1059cdf0e10cSrcweir             "invalid FileName"), *this, 0);
1060cdf0e10cSrcweir     }
1061cdf0e10cSrcweir 
1062cdf0e10cSrcweir     if (!addContentOrStylesFileImpl(*m_pImpl, i_rFileName)) {
1063cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1064cdf0e10cSrcweir             "DocumentMetadataAccess::addContentOrStylesFile: "
1065cdf0e10cSrcweir             "invalid FileName: must end with content.xml or styles.xml"),
1066cdf0e10cSrcweir             *this, 0);
1067cdf0e10cSrcweir     }
1068cdf0e10cSrcweir }
1069cdf0e10cSrcweir 
1070cdf0e10cSrcweir void SAL_CALL
removeContentOrStylesFile(const::rtl::OUString & i_rFileName)1071cdf0e10cSrcweir DocumentMetadataAccess::removeContentOrStylesFile(
1072cdf0e10cSrcweir     const ::rtl::OUString & i_rFileName)
1073cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
1074cdf0e10cSrcweir     container::NoSuchElementException)
1075cdf0e10cSrcweir {
1076cdf0e10cSrcweir     if (!isFileNameValid(i_rFileName)) {
1077cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1078cdf0e10cSrcweir             "DocumentMetadataAccess::removeContentOrStylesFile: "
1079cdf0e10cSrcweir             "invalid FileName"), *this, 0);
1080cdf0e10cSrcweir     }
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir     try {
1083cdf0e10cSrcweir         const uno::Reference<rdf::XURI> xPart(
1084cdf0e10cSrcweir             getURIForStream(*m_pImpl, i_rFileName) );
1085cdf0e10cSrcweir         const uno::Reference<container::XEnumeration> xEnum(
1086cdf0e10cSrcweir             m_pImpl->m_xManifest->getStatements( m_pImpl->m_xBaseURI.get(),
1087cdf0e10cSrcweir                 getURI<rdf::URIs::PKG_HASPART>(m_pImpl->m_xContext),
1088cdf0e10cSrcweir                 xPart.get()),
1089cdf0e10cSrcweir             uno::UNO_SET_THROW);
1090cdf0e10cSrcweir         if (!xEnum->hasMoreElements()) {
1091cdf0e10cSrcweir             throw container::NoSuchElementException(
1092cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
1093cdf0e10cSrcweir                     "DocumentMetadataAccess::removeContentOrStylesFile: "
1094cdf0e10cSrcweir                     "cannot find stream in manifest graph: ") + i_rFileName,
1095cdf0e10cSrcweir                 *this);
1096cdf0e10cSrcweir         }
1097cdf0e10cSrcweir 
1098cdf0e10cSrcweir         // remove file from manifest
1099cdf0e10cSrcweir         removeFile(*m_pImpl, xPart);
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
1102cdf0e10cSrcweir         throw;
1103cdf0e10cSrcweir     } catch (uno::Exception & e) {
1104cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
1105cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
1106cdf0e10cSrcweir                 "DocumentMetadataAccess::removeContentOrStylesFile: exception"),
1107cdf0e10cSrcweir             *this, uno::makeAny(e));
1108cdf0e10cSrcweir     }
1109cdf0e10cSrcweir }
1110cdf0e10cSrcweir 
loadMetadataFromStorage(const uno::Reference<embed::XStorage> & i_xStorage,const uno::Reference<rdf::XURI> & i_xBaseURI,const uno::Reference<task::XInteractionHandler> & i_xHandler)1111cdf0e10cSrcweir void SAL_CALL DocumentMetadataAccess::loadMetadataFromStorage(
1112cdf0e10cSrcweir     const uno::Reference< embed::XStorage > & i_xStorage,
1113cdf0e10cSrcweir     const uno::Reference<rdf::XURI> & i_xBaseURI,
1114cdf0e10cSrcweir     const uno::Reference<task::XInteractionHandler> & i_xHandler)
1115cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
1116cdf0e10cSrcweir     lang::WrappedTargetException)
1117cdf0e10cSrcweir {
1118cdf0e10cSrcweir     if (!i_xStorage.is()) {
1119cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1120cdf0e10cSrcweir             "DocumentMetadataAccess::loadMetadataFromStorage: "
1121cdf0e10cSrcweir             "storage is null"), *this, 0);
1122cdf0e10cSrcweir     }
1123cdf0e10cSrcweir     if (!i_xBaseURI.is()) {
1124cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1125cdf0e10cSrcweir             "DocumentMetadataAccess::loadMetadataFromStorage: "
1126cdf0e10cSrcweir             "base URI is null"), *this, 1);
1127cdf0e10cSrcweir     }
1128cdf0e10cSrcweir     const ::rtl::OUString baseURI( i_xBaseURI->getStringValue());
1129cdf0e10cSrcweir     if (baseURI.indexOf('#') >= 0) {
1130cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1131cdf0e10cSrcweir             "DocumentMetadataAccess::loadMetadataFromStorage: "
1132cdf0e10cSrcweir             "base URI not absolute"), *this, 1);
1133cdf0e10cSrcweir     }
1134cdf0e10cSrcweir     if (!baseURI.getLength() || !baseURI.endsWithAsciiL("/", 1)) {
1135cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1136cdf0e10cSrcweir             "DocumentMetadataAccess::loadMetadataFromStorage: "
1137cdf0e10cSrcweir             "base URI does not end with slash"), *this, 1);
1138cdf0e10cSrcweir     }
1139cdf0e10cSrcweir 
1140cdf0e10cSrcweir     initLoading(*m_pImpl, i_xStorage, i_xBaseURI, i_xHandler);
1141cdf0e10cSrcweir 
1142cdf0e10cSrcweir     std::set< ::rtl::OUString > StgFiles;
1143cdf0e10cSrcweir     collectFilesFromStorage(i_xStorage,
1144cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(""), StgFiles);
1145cdf0e10cSrcweir 
1146cdf0e10cSrcweir     std::vector< ::rtl::OUString > MfstMetadataFiles;
1147cdf0e10cSrcweir 
1148cdf0e10cSrcweir     try {
1149cdf0e10cSrcweir         const ::std::vector< uno::Reference< rdf::XURI > > parts(
1150cdf0e10cSrcweir             getAllParts(*m_pImpl) );
1151cdf0e10cSrcweir         const uno::Reference<rdf::XURI> xContentFile(
1152cdf0e10cSrcweir             getURI<rdf::URIs::ODF_CONTENTFILE>(m_pImpl->m_xContext));
1153cdf0e10cSrcweir         const uno::Reference<rdf::XURI> xStylesFile(
1154cdf0e10cSrcweir             getURI<rdf::URIs::ODF_STYLESFILE>(m_pImpl->m_xContext));
1155cdf0e10cSrcweir         const uno::Reference<rdf::XURI> xMetadataFile(
1156cdf0e10cSrcweir             getURI<rdf::URIs::PKG_METADATAFILE>(m_pImpl->m_xContext));
1157cdf0e10cSrcweir         const sal_Int32 len( baseURI.getLength() );
1158cdf0e10cSrcweir         const ::rtl::OUString manifest (
1159cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(s_manifest));
1160cdf0e10cSrcweir         for (::std::vector< uno::Reference< rdf::XURI > >::const_iterator it
1161cdf0e10cSrcweir                 = parts.begin();
1162cdf0e10cSrcweir                 it != parts.end(); ++it) {
1163cdf0e10cSrcweir             const ::rtl::OUString name((*it)->getStringValue());
1164cdf0e10cSrcweir             if (!name.match(baseURI)) {
1165cdf0e10cSrcweir                 OSL_TRACE("loadMetadataFromStorage: graph not in document: %s",
1166cdf0e10cSrcweir                     ::rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)
1167cdf0e10cSrcweir                     .getStr());
1168cdf0e10cSrcweir                 continue;
1169cdf0e10cSrcweir             }
1170cdf0e10cSrcweir             const ::rtl::OUString relName( name.copy(len) );
1171cdf0e10cSrcweir             if (relName == manifest) {
1172cdf0e10cSrcweir                 OSL_TRACE("loadMetadataFromStorage: "
1173cdf0e10cSrcweir                     "found ourselves a recursive manifest!");
1174cdf0e10cSrcweir                 continue;
1175cdf0e10cSrcweir             }
1176cdf0e10cSrcweir             // remove found items from StgFiles
1177cdf0e10cSrcweir             StgFiles.erase(relName);
1178cdf0e10cSrcweir             if (isContentFile(relName)) {
1179cdf0e10cSrcweir                 if (!isPartOfType(*m_pImpl, *it, xContentFile)) {
1180cdf0e10cSrcweir                     const uno::Reference <rdf::XURI> xName(
1181cdf0e10cSrcweir                         getURIForStream(*m_pImpl, relName) );
1182cdf0e10cSrcweir                     // add missing type statement
1183cdf0e10cSrcweir                     m_pImpl->m_xManifest->addStatement(xName.get(),
1184cdf0e10cSrcweir                         getURI<rdf::URIs::RDF_TYPE>(m_pImpl->m_xContext),
1185cdf0e10cSrcweir                         xContentFile.get());
1186cdf0e10cSrcweir                 }
1187cdf0e10cSrcweir             } else if (isStylesFile(relName)) {
1188cdf0e10cSrcweir                 if (!isPartOfType(*m_pImpl, *it, xStylesFile)) {
1189cdf0e10cSrcweir                     const uno::Reference <rdf::XURI> xName(
1190cdf0e10cSrcweir                         getURIForStream(*m_pImpl, relName) );
1191cdf0e10cSrcweir                     // add missing type statement
1192cdf0e10cSrcweir                     m_pImpl->m_xManifest->addStatement(xName.get(),
1193cdf0e10cSrcweir                         getURI<rdf::URIs::RDF_TYPE>(m_pImpl->m_xContext),
1194cdf0e10cSrcweir                         xStylesFile.get());
1195cdf0e10cSrcweir                 }
1196cdf0e10cSrcweir             } else if (isReservedFile(relName)) {
1197cdf0e10cSrcweir                 OSL_TRACE("loadMetadataFromStorage: "
1198cdf0e10cSrcweir                     "reserved file name in manifest");
1199cdf0e10cSrcweir             } else {
1200cdf0e10cSrcweir                 if (isPartOfType(*m_pImpl, *it, xMetadataFile)) {
1201cdf0e10cSrcweir                     MfstMetadataFiles.push_back(relName);
1202cdf0e10cSrcweir                 }
1203cdf0e10cSrcweir                 // do not add statement for MetadataFile; it could be
1204cdf0e10cSrcweir                 // something else! just ignore it...
1205cdf0e10cSrcweir             }
1206cdf0e10cSrcweir         }
1207cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
1208cdf0e10cSrcweir         throw;
1209cdf0e10cSrcweir     } catch (uno::Exception & e) {
1210cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
1211cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
1212cdf0e10cSrcweir                 "DocumentMetadataAccess::loadMetadataFromStorage: "
1213cdf0e10cSrcweir                 "exception"), *this, uno::makeAny(e));
1214cdf0e10cSrcweir     }
1215cdf0e10cSrcweir 
1216cdf0e10cSrcweir     std::for_each(StgFiles.begin(), StgFiles.end(),
1217cdf0e10cSrcweir         boost::bind(addContentOrStylesFileImpl, boost::ref(*m_pImpl), _1));
1218cdf0e10cSrcweir 
1219cdf0e10cSrcweir     std::for_each(MfstMetadataFiles.begin(), MfstMetadataFiles.end(),
1220cdf0e10cSrcweir         boost::bind(importFile, boost::ref(*m_pImpl),
1221cdf0e10cSrcweir             i_xStorage, baseURI, i_xHandler, _1));
1222cdf0e10cSrcweir }
1223cdf0e10cSrcweir 
storeMetadataToStorage(const uno::Reference<embed::XStorage> & i_xStorage)1224cdf0e10cSrcweir void SAL_CALL DocumentMetadataAccess::storeMetadataToStorage(
1225cdf0e10cSrcweir     const uno::Reference< embed::XStorage > & i_xStorage)
1226cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
1227cdf0e10cSrcweir     lang::WrappedTargetException)
1228cdf0e10cSrcweir {
1229cdf0e10cSrcweir     if (!i_xStorage.is()) {
1230cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1231cdf0e10cSrcweir             "DocumentMetadataAccess::storeMetadataToStorage: "
1232cdf0e10cSrcweir             "storage is null"), *this, 0);
1233cdf0e10cSrcweir     }
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir     // export manifest
1236cdf0e10cSrcweir     const ::rtl::OUString manifest (
1237cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(s_manifest));
1238cdf0e10cSrcweir     const uno::Reference <rdf::XURI> xManifest(
1239cdf0e10cSrcweir         getURIForStream(*m_pImpl, manifest) );
1240cdf0e10cSrcweir     const ::rtl::OUString baseURI( m_pImpl->m_xBaseURI->getStringValue() );
1241cdf0e10cSrcweir     try {
1242cdf0e10cSrcweir         writeStream(*m_pImpl, i_xStorage, xManifest, manifest, baseURI);
1243cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
1244cdf0e10cSrcweir         throw;
1245cdf0e10cSrcweir     } catch (io::IOException & e) {
1246cdf0e10cSrcweir         throw lang::WrappedTargetException( ::rtl::OUString::createFromAscii(
1247cdf0e10cSrcweir             "storeMetadataToStorage: IO exception"), *this, uno::makeAny(e));
1248cdf0e10cSrcweir     } catch (uno::Exception & e) {
1249cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
1250cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
1251cdf0e10cSrcweir                 "storeMetadataToStorage: exception"), *this, uno::makeAny(e));
1252cdf0e10cSrcweir     }
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir     // export metadata streams
1255cdf0e10cSrcweir     try {
1256cdf0e10cSrcweir         const uno::Sequence<uno::Reference<rdf::XURI> > graphs(
1257cdf0e10cSrcweir             m_pImpl->m_xRepository->getGraphNames());
1258cdf0e10cSrcweir         const sal_Int32 len( baseURI.getLength() );
1259cdf0e10cSrcweir         for (sal_Int32 i = 0; i < graphs.getLength(); ++i) {
1260cdf0e10cSrcweir             const uno::Reference<rdf::XURI> xName(graphs[i]);
1261cdf0e10cSrcweir             const ::rtl::OUString name(xName->getStringValue());
1262cdf0e10cSrcweir             if (!name.match(baseURI)) {
1263cdf0e10cSrcweir                 OSL_TRACE("storeMetadataToStorage: graph not in document: %s",
1264cdf0e10cSrcweir                     ::rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)
1265cdf0e10cSrcweir                     .getStr());
1266cdf0e10cSrcweir                 continue;
1267cdf0e10cSrcweir             }
1268cdf0e10cSrcweir             const ::rtl::OUString relName( name.copy(len) );
1269cdf0e10cSrcweir             if (relName == manifest) {
1270cdf0e10cSrcweir                 continue;
1271cdf0e10cSrcweir             }
1272cdf0e10cSrcweir             if (!isFileNameValid(relName) || isReservedFile(relName)) {
1273cdf0e10cSrcweir                 OSL_TRACE("storeMetadataToStorage: invalid file name: %s",
1274cdf0e10cSrcweir                     ::rtl::OUStringToOString(relName, RTL_TEXTENCODING_UTF8)
1275cdf0e10cSrcweir                     .getStr());
1276cdf0e10cSrcweir                 continue;
1277cdf0e10cSrcweir             }
1278cdf0e10cSrcweir             try {
1279cdf0e10cSrcweir                 writeStream(*m_pImpl, i_xStorage, xName, relName, baseURI);
1280cdf0e10cSrcweir             } catch (uno::RuntimeException &) {
1281cdf0e10cSrcweir                 throw;
1282cdf0e10cSrcweir             } catch (io::IOException & e) {
1283cdf0e10cSrcweir                 throw lang::WrappedTargetException(
1284cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii(
1285cdf0e10cSrcweir                         "storeMetadataToStorage: IO exception"),
1286cdf0e10cSrcweir                     *this, uno::makeAny(e));
1287cdf0e10cSrcweir             } catch (uno::Exception & e) {
1288cdf0e10cSrcweir                 throw lang::WrappedTargetRuntimeException(
1289cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii(
1290cdf0e10cSrcweir                         "storeMetadataToStorage: exception"),
1291cdf0e10cSrcweir                     *this, uno::makeAny(e));
1292cdf0e10cSrcweir             }
1293cdf0e10cSrcweir         }
1294cdf0e10cSrcweir     } catch (rdf::RepositoryException & e) {
1295cdf0e10cSrcweir         throw lang::WrappedTargetRuntimeException(
1296cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(
1297cdf0e10cSrcweir                 "storeMetadataToStorage: exception"), *this, uno::makeAny(e));
1298cdf0e10cSrcweir     }
1299cdf0e10cSrcweir }
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir void SAL_CALL
loadMetadataFromMedium(const uno::Sequence<beans::PropertyValue> & i_rMedium)1302cdf0e10cSrcweir DocumentMetadataAccess::loadMetadataFromMedium(
1303cdf0e10cSrcweir     const uno::Sequence< beans::PropertyValue > & i_rMedium)
1304cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
1305cdf0e10cSrcweir     lang::WrappedTargetException)
1306cdf0e10cSrcweir {
1307cdf0e10cSrcweir     uno::Reference<io::XInputStream> xIn;
1308cdf0e10cSrcweir     ::comphelper::MediaDescriptor md(i_rMedium);
1309cdf0e10cSrcweir     ::rtl::OUString URL;
1310cdf0e10cSrcweir     md[ ::comphelper::MediaDescriptor::PROP_URL() ] >>= URL;
1311cdf0e10cSrcweir     ::rtl::OUString BaseURL;
1312cdf0e10cSrcweir     md[ ::comphelper::MediaDescriptor::PROP_DOCUMENTBASEURL() ] >>= BaseURL;
1313cdf0e10cSrcweir     if (md.addInputStream()) {
1314cdf0e10cSrcweir         md[ ::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] >>= xIn;
1315cdf0e10cSrcweir     }
1316cdf0e10cSrcweir     if (!xIn.is() && URL.equalsAscii("")) {
1317cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1318cdf0e10cSrcweir             "DocumentMetadataAccess::loadMetadataFromMedium: "
1319cdf0e10cSrcweir             "inalid medium: no URL, no input stream"), *this, 0);
1320cdf0e10cSrcweir     }
1321cdf0e10cSrcweir     uno::Reference<embed::XStorage> xStorage;
1322cdf0e10cSrcweir     try {
1323cdf0e10cSrcweir         const uno::Reference<lang::XMultiServiceFactory> xMsf (
1324cdf0e10cSrcweir             m_pImpl->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
1325cdf0e10cSrcweir         if (xIn.is()) {
1326cdf0e10cSrcweir             xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream(
1327cdf0e10cSrcweir                             xIn, xMsf);
1328cdf0e10cSrcweir         } else { // fallback to url
1329cdf0e10cSrcweir             xStorage = ::comphelper::OStorageHelper::GetStorageFromURL2(
1330cdf0e10cSrcweir                             URL, embed::ElementModes::READ, xMsf);
1331cdf0e10cSrcweir         }
1332cdf0e10cSrcweir     } catch (uno::RuntimeException &) {
1333cdf0e10cSrcweir         throw;
1334cdf0e10cSrcweir     } catch (io::IOException &) {
1335cdf0e10cSrcweir         throw;
1336cdf0e10cSrcweir     } catch (uno::Exception & e) {
1337cdf0e10cSrcweir         throw lang::WrappedTargetException(
1338cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
1339cdf0e10cSrcweir                     "DocumentMetadataAccess::loadMetadataFromMedium: "
1340cdf0e10cSrcweir                     "exception"), *this, uno::makeAny(e));
1341cdf0e10cSrcweir     }
1342cdf0e10cSrcweir     if (!xStorage.is()) {
1343cdf0e10cSrcweir         throw uno::RuntimeException(::rtl::OUString::createFromAscii(
1344cdf0e10cSrcweir             "DocumentMetadataAccess::loadMetadataFromMedium: "
1345cdf0e10cSrcweir             "cannot get Storage"), *this);
1346cdf0e10cSrcweir     }
1347cdf0e10cSrcweir     uno::Reference<rdf::XURI> xBaseURI;
1348cdf0e10cSrcweir     try {
1349cdf0e10cSrcweir         xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, BaseURL);
1350cdf0e10cSrcweir     } catch (uno::Exception &) {
1351cdf0e10cSrcweir         // fall back to URL
1352cdf0e10cSrcweir         try {
1353cdf0e10cSrcweir             xBaseURI = createBaseURI(m_pImpl->m_xContext, xStorage, URL);
1354cdf0e10cSrcweir         } catch (uno::Exception &) {
1355cdf0e10cSrcweir             OSL_ENSURE(false, "cannot create base URI");
1356cdf0e10cSrcweir         }
1357cdf0e10cSrcweir     }
1358cdf0e10cSrcweir     uno::Reference<task::XInteractionHandler> xIH;
1359cdf0e10cSrcweir     md[ ::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER() ] >>= xIH;
1360cdf0e10cSrcweir     loadMetadataFromStorage(xStorage, xBaseURI, xIH);
1361cdf0e10cSrcweir }
1362cdf0e10cSrcweir 
1363cdf0e10cSrcweir void SAL_CALL
storeMetadataToMedium(const uno::Sequence<beans::PropertyValue> & i_rMedium)1364cdf0e10cSrcweir DocumentMetadataAccess::storeMetadataToMedium(
1365cdf0e10cSrcweir     const uno::Sequence< beans::PropertyValue > & i_rMedium)
1366cdf0e10cSrcweir throw (uno::RuntimeException, lang::IllegalArgumentException,
1367cdf0e10cSrcweir     lang::WrappedTargetException)
1368cdf0e10cSrcweir {
1369cdf0e10cSrcweir     ::comphelper::MediaDescriptor md(i_rMedium);
1370cdf0e10cSrcweir     ::rtl::OUString URL;
1371cdf0e10cSrcweir     md[ ::comphelper::MediaDescriptor::PROP_URL() ] >>= URL;
1372cdf0e10cSrcweir     if (URL.equalsAscii("")) {
1373cdf0e10cSrcweir         throw lang::IllegalArgumentException(::rtl::OUString::createFromAscii(
1374cdf0e10cSrcweir             "DocumentMetadataAccess::storeMetadataToMedium: "
1375cdf0e10cSrcweir             "invalid medium: no URL"), *this, 0);
1376cdf0e10cSrcweir     }
1377cdf0e10cSrcweir 
1378cdf0e10cSrcweir     SfxMedium aMedium(i_rMedium);
1379cdf0e10cSrcweir     uno::Reference<embed::XStorage> xStorage(aMedium.GetOutputStorage());
1380cdf0e10cSrcweir 
1381cdf0e10cSrcweir     bool sfx(false);
1382cdf0e10cSrcweir     if (xStorage.is()) {
1383cdf0e10cSrcweir         sfx = true;
1384cdf0e10cSrcweir     } else {
1385cdf0e10cSrcweir         const uno::Reference<lang::XMultiServiceFactory> xMsf (
1386cdf0e10cSrcweir             m_pImpl->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
1387cdf0e10cSrcweir         xStorage = ::comphelper::OStorageHelper::GetStorageFromURL2(
1388cdf0e10cSrcweir                         URL, embed::ElementModes::WRITE, xMsf);
1389cdf0e10cSrcweir     }
1390cdf0e10cSrcweir 
1391cdf0e10cSrcweir     if (!xStorage.is()) {
1392cdf0e10cSrcweir         throw uno::RuntimeException(::rtl::OUString::createFromAscii(
1393cdf0e10cSrcweir             "DocumentMetadataAccess::storeMetadataToMedium: "
1394cdf0e10cSrcweir             "cannot get Storage"), *this);
1395cdf0e10cSrcweir     }
1396cdf0e10cSrcweir     // set MIME type of the storage
1397cdf0e10cSrcweir     ::comphelper::MediaDescriptor::const_iterator iter
1398cdf0e10cSrcweir         = md.find(::comphelper::MediaDescriptor::PROP_MEDIATYPE());
1399cdf0e10cSrcweir     if (iter != md.end()) {
1400cdf0e10cSrcweir         uno::Reference< beans::XPropertySet > xProps(xStorage,
1401cdf0e10cSrcweir             uno::UNO_QUERY_THROW);
1402cdf0e10cSrcweir         try {
1403cdf0e10cSrcweir             // this is NOT supported in FileSystemStorage
1404cdf0e10cSrcweir             xProps->setPropertyValue(
1405cdf0e10cSrcweir                 ::comphelper::MediaDescriptor::PROP_MEDIATYPE(),
1406cdf0e10cSrcweir                 iter->second);
1407cdf0e10cSrcweir         } catch (uno::Exception &) { }
1408cdf0e10cSrcweir     }
1409cdf0e10cSrcweir     storeMetadataToStorage(xStorage);
1410cdf0e10cSrcweir 
1411cdf0e10cSrcweir     if (sfx) {
1412cdf0e10cSrcweir         const sal_Bool bOk = aMedium.Commit();
1413cdf0e10cSrcweir         aMedium.Close();
1414cdf0e10cSrcweir         if ( !bOk ) {
1415cdf0e10cSrcweir             sal_uInt32 nError = aMedium.GetError();
1416cdf0e10cSrcweir             if ( nError == ERRCODE_NONE ) {
1417cdf0e10cSrcweir                 nError = ERRCODE_IO_GENERAL;
1418cdf0e10cSrcweir             }
1419cdf0e10cSrcweir             task::ErrorCodeIOException ex( ::rtl::OUString(),
1420cdf0e10cSrcweir                     uno::Reference< uno::XInterface >(), nError);
1421cdf0e10cSrcweir             throw lang::WrappedTargetException(::rtl::OUString(), *this,
1422cdf0e10cSrcweir                     uno::makeAny(ex));
1423cdf0e10cSrcweir         }
1424cdf0e10cSrcweir     }
1425cdf0e10cSrcweir }
1426cdf0e10cSrcweir 
1427cdf0e10cSrcweir } // namespace sfx2
1428cdf0e10cSrcweir 
1429