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