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 "sal/config.h"
31*cdf0e10cSrcweir #include "cppuhelper/factory.hxx"
32*cdf0e10cSrcweir #include "cppuhelper/implementationentry.hxx"
33*cdf0e10cSrcweir #include "cppuhelper/compbase6.hxx"
34*cdf0e10cSrcweir #include "com/sun/star/lang/XServiceInfo.hpp"
35*cdf0e10cSrcweir #include "com/sun/star/document/XDocumentProperties.hpp"
36*cdf0e10cSrcweir #include "com/sun/star/lang/XInitialization.hpp"
37*cdf0e10cSrcweir #include "com/sun/star/util/XCloneable.hpp"
38*cdf0e10cSrcweir #include "com/sun/star/util/XModifiable.hpp"
39*cdf0e10cSrcweir #include "com/sun/star/xml/sax/XSAXSerializable.hpp"
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
42*cdf0e10cSrcweir #include "com/sun/star/lang/EventObject.hpp"
43*cdf0e10cSrcweir #include "com/sun/star/beans/XPropertySet.hpp"
44*cdf0e10cSrcweir #include "com/sun/star/beans/XPropertySetInfo.hpp"
45*cdf0e10cSrcweir #include "com/sun/star/beans/PropertyAttribute.hpp"
46*cdf0e10cSrcweir #include "com/sun/star/task/ErrorCodeIOException.hpp"
47*cdf0e10cSrcweir #include "com/sun/star/embed/XStorage.hpp"
48*cdf0e10cSrcweir #include "com/sun/star/embed/XTransactedObject.hpp"
49*cdf0e10cSrcweir #include "com/sun/star/embed/ElementModes.hpp"
50*cdf0e10cSrcweir #include "com/sun/star/io/XActiveDataControl.hpp"
51*cdf0e10cSrcweir #include "com/sun/star/io/XActiveDataSource.hpp"
52*cdf0e10cSrcweir #include "com/sun/star/io/XStream.hpp"
53*cdf0e10cSrcweir #include "com/sun/star/document/XImporter.hpp"
54*cdf0e10cSrcweir #include "com/sun/star/document/XExporter.hpp"
55*cdf0e10cSrcweir #include "com/sun/star/document/XFilter.hpp"
56*cdf0e10cSrcweir #include "com/sun/star/xml/sax/XParser.hpp"
57*cdf0e10cSrcweir #include "com/sun/star/xml/dom/XDocument.hpp"
58*cdf0e10cSrcweir #include "com/sun/star/xml/dom/XElement.hpp"
59*cdf0e10cSrcweir #include "com/sun/star/xml/dom/XDocumentBuilder.hpp"
60*cdf0e10cSrcweir #include "com/sun/star/xml/dom/XSAXDocumentBuilder.hpp"
61*cdf0e10cSrcweir #include "com/sun/star/xml/dom/NodeType.hpp"
62*cdf0e10cSrcweir #include "com/sun/star/xml/xpath/XXPathAPI.hpp"
63*cdf0e10cSrcweir #include "com/sun/star/util/Date.hpp"
64*cdf0e10cSrcweir #include "com/sun/star/util/Time.hpp"
65*cdf0e10cSrcweir #include "com/sun/star/util/Duration.hpp"
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir #include "SfxDocumentMetaData.hxx"
68*cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
69*cdf0e10cSrcweir #include "tools/debug.hxx"
70*cdf0e10cSrcweir #include "tools/string.hxx" // for DBG
71*cdf0e10cSrcweir #include "tools/datetime.hxx"
72*cdf0e10cSrcweir #include "tools/urlobj.hxx"
73*cdf0e10cSrcweir #include "osl/mutex.hxx"
74*cdf0e10cSrcweir #include "cppuhelper/basemutex.hxx"
75*cdf0e10cSrcweir #include "cppuhelper/interfacecontainer.hxx"
76*cdf0e10cSrcweir #include "comphelper/storagehelper.hxx"
77*cdf0e10cSrcweir #include "comphelper/mediadescriptor.hxx"
78*cdf0e10cSrcweir #include "comphelper/sequenceasvector.hxx"
79*cdf0e10cSrcweir #include "comphelper/stlunosequence.hxx"
80*cdf0e10cSrcweir #include "sot/storage.hxx"
81*cdf0e10cSrcweir #include "sfx2/docfile.hxx"
82*cdf0e10cSrcweir #include "sax/tools/converter.hxx"
83*cdf0e10cSrcweir 
84*cdf0e10cSrcweir #include <utility>
85*cdf0e10cSrcweir #include <vector>
86*cdf0e10cSrcweir #include <map>
87*cdf0e10cSrcweir #include <cstring>
88*cdf0e10cSrcweir #include <limits>
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir /**
91*cdf0e10cSrcweir  * This file contains the implementation of the service
92*cdf0e10cSrcweir  * com.sun.star.document.DocumentProperties.
93*cdf0e10cSrcweir  * This service enables access to the meta-data stored in documents.
94*cdf0e10cSrcweir  * Currently, this service only handles documents in ODF format.
95*cdf0e10cSrcweir  *
96*cdf0e10cSrcweir  * The implementation uses an XML DOM to store the properties.
97*cdf0e10cSrcweir  * This approach was taken because it allows for preserving arbitrary XML data
98*cdf0e10cSrcweir  * in loaded documents, which will be stored unmodified when saving the
99*cdf0e10cSrcweir  * document again.
100*cdf0e10cSrcweir  *
101*cdf0e10cSrcweir  * Upon access, some properties are directly read from and updated in the DOM.
102*cdf0e10cSrcweir  * Exception: it seems impossible to get notified upon addition of a property
103*cdf0e10cSrcweir  * to a com.sun.star.beans.PropertyBag, which is used for storing user-defined
104*cdf0e10cSrcweir  * properties; because of this, user-defined properties are updated in the
105*cdf0e10cSrcweir  * XML DOM only when storing the document.
106*cdf0e10cSrcweir  * Exception 2: when setting certain properties which correspond to attributes
107*cdf0e10cSrcweir  * in the XML DOM, we want to remove the corresponding XML element. Detecting
108*cdf0e10cSrcweir  * this condition can get messy, so we store all such properties as members,
109*cdf0e10cSrcweir  * and update the DOM tree only when storing the document (in
110*cdf0e10cSrcweir  * <method>updateUserDefinedAndAttributes</method>).
111*cdf0e10cSrcweir  *
112*cdf0e10cSrcweir  * @author mst
113*cdf0e10cSrcweir  */
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir /// anonymous implementation namespace
116*cdf0e10cSrcweir namespace {
117*cdf0e10cSrcweir 
118*cdf0e10cSrcweir namespace css = ::com::sun::star;
119*cdf0e10cSrcweir 
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir /// a list of attribute-lists, where attribute means name and content
122*cdf0e10cSrcweir typedef std::vector<std::vector<std::pair<const char*, ::rtl::OUString> > >
123*cdf0e10cSrcweir         AttrVector;
124*cdf0e10cSrcweir 
125*cdf0e10cSrcweir typedef ::cppu::WeakComponentImplHelper6<
126*cdf0e10cSrcweir             css::lang::XServiceInfo,
127*cdf0e10cSrcweir             css::document::XDocumentProperties,
128*cdf0e10cSrcweir             css::lang::XInitialization,
129*cdf0e10cSrcweir             css::util::XCloneable,
130*cdf0e10cSrcweir             css::util::XModifiable,
131*cdf0e10cSrcweir             css::xml::sax::XSAXSerializable>
132*cdf0e10cSrcweir     SfxDocumentMetaData_Base;
133*cdf0e10cSrcweir 
134*cdf0e10cSrcweir class SfxDocumentMetaData:
135*cdf0e10cSrcweir     private ::cppu::BaseMutex,
136*cdf0e10cSrcweir     public SfxDocumentMetaData_Base
137*cdf0e10cSrcweir {
138*cdf0e10cSrcweir public:
139*cdf0e10cSrcweir     explicit SfxDocumentMetaData(
140*cdf0e10cSrcweir         css::uno::Reference< css::uno::XComponentContext > const & context);
141*cdf0e10cSrcweir 
142*cdf0e10cSrcweir     // ::com::sun::star::lang::XServiceInfo:
143*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getImplementationName()
144*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
145*cdf0e10cSrcweir     virtual ::sal_Bool SAL_CALL supportsService(
146*cdf0e10cSrcweir         const ::rtl::OUString & ServiceName) throw (css::uno::RuntimeException);
147*cdf0e10cSrcweir     virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL
148*cdf0e10cSrcweir         getSupportedServiceNames() throw (css::uno::RuntimeException);
149*cdf0e10cSrcweir 
150*cdf0e10cSrcweir     // ::com::sun::star::lang::XComponent:
151*cdf0e10cSrcweir     virtual void SAL_CALL dispose() throw (css::uno::RuntimeException);
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir     // ::com::sun::star::document::XDocumentProperties:
154*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getAuthor()
155*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
156*cdf0e10cSrcweir     virtual void SAL_CALL setAuthor(const ::rtl::OUString & the_value)
157*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
158*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getGenerator()
159*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
160*cdf0e10cSrcweir     virtual void SAL_CALL setGenerator(const ::rtl::OUString & the_value)
161*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
162*cdf0e10cSrcweir     virtual css::util::DateTime SAL_CALL getCreationDate()
163*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
164*cdf0e10cSrcweir     virtual void SAL_CALL setCreationDate(const css::util::DateTime & the_value)
165*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
166*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getTitle()
167*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
168*cdf0e10cSrcweir     virtual void SAL_CALL setTitle(const ::rtl::OUString & the_value)
169*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
170*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getSubject()
171*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
172*cdf0e10cSrcweir     virtual void SAL_CALL setSubject(const ::rtl::OUString & the_value)
173*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
174*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getDescription()
175*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
176*cdf0e10cSrcweir     virtual void SAL_CALL setDescription(const ::rtl::OUString & the_value)
177*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
178*cdf0e10cSrcweir     virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getKeywords()
179*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
180*cdf0e10cSrcweir     virtual void SAL_CALL setKeywords(
181*cdf0e10cSrcweir         const css::uno::Sequence< ::rtl::OUString > & the_value)
182*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
183*cdf0e10cSrcweir     virtual css::lang::Locale SAL_CALL getLanguage()
184*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
185*cdf0e10cSrcweir     virtual void SAL_CALL setLanguage(const css::lang::Locale & the_value)
186*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
187*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getModifiedBy()
188*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
189*cdf0e10cSrcweir     virtual void SAL_CALL setModifiedBy(const ::rtl::OUString & the_value)
190*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
191*cdf0e10cSrcweir     virtual css::util::DateTime SAL_CALL getModificationDate()
192*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
193*cdf0e10cSrcweir     virtual void SAL_CALL setModificationDate(
194*cdf0e10cSrcweir             const css::util::DateTime & the_value)
195*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
196*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getPrintedBy()
197*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
198*cdf0e10cSrcweir     virtual void SAL_CALL setPrintedBy(const ::rtl::OUString & the_value)
199*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
200*cdf0e10cSrcweir     virtual css::util::DateTime SAL_CALL getPrintDate()
201*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
202*cdf0e10cSrcweir     virtual void SAL_CALL setPrintDate(const css::util::DateTime & the_value)
203*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
204*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getTemplateName()
205*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
206*cdf0e10cSrcweir     virtual void SAL_CALL setTemplateName(const ::rtl::OUString & the_value)
207*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
208*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getTemplateURL()
209*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
210*cdf0e10cSrcweir     virtual void SAL_CALL setTemplateURL(const ::rtl::OUString & the_value)
211*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
212*cdf0e10cSrcweir     virtual css::util::DateTime SAL_CALL getTemplateDate()
213*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
214*cdf0e10cSrcweir     virtual void SAL_CALL setTemplateDate(const css::util::DateTime & the_value)
215*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
216*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getAutoloadURL()
217*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
218*cdf0e10cSrcweir     virtual void SAL_CALL setAutoloadURL(const ::rtl::OUString & the_value)
219*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
220*cdf0e10cSrcweir     virtual ::sal_Int32 SAL_CALL getAutoloadSecs()
221*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
222*cdf0e10cSrcweir     virtual void SAL_CALL setAutoloadSecs(::sal_Int32 the_value)
223*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
224*cdf0e10cSrcweir     virtual ::rtl::OUString SAL_CALL getDefaultTarget()
225*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
226*cdf0e10cSrcweir     virtual void SAL_CALL setDefaultTarget(const ::rtl::OUString & the_value)
227*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
228*cdf0e10cSrcweir     virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL
229*cdf0e10cSrcweir         getDocumentStatistics() throw (css::uno::RuntimeException);
230*cdf0e10cSrcweir     virtual void SAL_CALL setDocumentStatistics(
231*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::NamedValue > & the_value)
232*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
233*cdf0e10cSrcweir     virtual ::sal_Int16 SAL_CALL getEditingCycles()
234*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
235*cdf0e10cSrcweir     virtual void SAL_CALL setEditingCycles(::sal_Int16 the_value)
236*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
237*cdf0e10cSrcweir     virtual ::sal_Int32 SAL_CALL getEditingDuration()
238*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
239*cdf0e10cSrcweir     virtual void SAL_CALL setEditingDuration(::sal_Int32 the_value)
240*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
241*cdf0e10cSrcweir     virtual void SAL_CALL resetUserData(const ::rtl::OUString & the_value)
242*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
243*cdf0e10cSrcweir     virtual css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
244*cdf0e10cSrcweir         getUserDefinedProperties() throw (css::uno::RuntimeException);
245*cdf0e10cSrcweir     virtual void SAL_CALL loadFromStorage(
246*cdf0e10cSrcweir         const css::uno::Reference< css::embed::XStorage > & Storage,
247*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::PropertyValue > & Medium)
248*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
249*cdf0e10cSrcweir                css::io::WrongFormatException,
250*cdf0e10cSrcweir                css::lang::WrappedTargetException, css::io::IOException);
251*cdf0e10cSrcweir     virtual void SAL_CALL loadFromMedium(const ::rtl::OUString & URL,
252*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::PropertyValue > & Medium)
253*cdf0e10cSrcweir         throw (css::uno::RuntimeException,
254*cdf0e10cSrcweir                css::io::WrongFormatException,
255*cdf0e10cSrcweir                css::lang::WrappedTargetException, css::io::IOException);
256*cdf0e10cSrcweir     virtual void SAL_CALL storeToStorage(
257*cdf0e10cSrcweir         const css::uno::Reference< css::embed::XStorage > & Storage,
258*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::PropertyValue > & Medium)
259*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
260*cdf0e10cSrcweir                css::lang::WrappedTargetException, css::io::IOException);
261*cdf0e10cSrcweir     virtual void SAL_CALL storeToMedium(const ::rtl::OUString & URL,
262*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::PropertyValue > & Medium)
263*cdf0e10cSrcweir         throw (css::uno::RuntimeException,
264*cdf0e10cSrcweir                css::lang::WrappedTargetException, css::io::IOException);
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir     // ::com::sun::star::lang::XInitialization:
267*cdf0e10cSrcweir     virtual void SAL_CALL initialize(
268*cdf0e10cSrcweir         const css::uno::Sequence< css::uno::Any > & aArguments)
269*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::uno::Exception);
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir     // ::com::sun::star::util::XCloneable:
272*cdf0e10cSrcweir     virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone()
273*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
274*cdf0e10cSrcweir 
275*cdf0e10cSrcweir     // ::com::sun::star::util::XModifiable:
276*cdf0e10cSrcweir     virtual ::sal_Bool SAL_CALL isModified(  )
277*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
278*cdf0e10cSrcweir     virtual void SAL_CALL setModified( ::sal_Bool bModified )
279*cdf0e10cSrcweir         throw (css::beans::PropertyVetoException, css::uno::RuntimeException);
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir     // ::com::sun::star::util::XModifyBroadcaster:
282*cdf0e10cSrcweir     virtual void SAL_CALL addModifyListener(
283*cdf0e10cSrcweir         const css::uno::Reference< css::util::XModifyListener > & xListener)
284*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
285*cdf0e10cSrcweir     virtual void SAL_CALL removeModifyListener(
286*cdf0e10cSrcweir         const css::uno::Reference< css::util::XModifyListener > & xListener)
287*cdf0e10cSrcweir         throw (css::uno::RuntimeException);
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir     // ::com::sun::star::xml::sax::XSAXSerializable
290*cdf0e10cSrcweir     virtual void SAL_CALL serialize(
291*cdf0e10cSrcweir         const css::uno::Reference<css::xml::sax::XDocumentHandler>& i_xHandler,
292*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::StringPair >& i_rNamespaces)
293*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::xml::sax::SAXException);
294*cdf0e10cSrcweir 
295*cdf0e10cSrcweir private:
296*cdf0e10cSrcweir     SfxDocumentMetaData(SfxDocumentMetaData &); // not defined
297*cdf0e10cSrcweir     SfxDocumentMetaData& operator =(SfxDocumentMetaData &); // not defined
298*cdf0e10cSrcweir 
299*cdf0e10cSrcweir     virtual ~SfxDocumentMetaData() {}
300*cdf0e10cSrcweir 
301*cdf0e10cSrcweir     const css::uno::Reference< css::uno::XComponentContext > m_xContext;
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir     /// for notification
304*cdf0e10cSrcweir     ::cppu::OInterfaceContainerHelper m_NotifyListeners;
305*cdf0e10cSrcweir     /// flag: false means not initialized yet, or disposed
306*cdf0e10cSrcweir     bool m_isInitialized;
307*cdf0e10cSrcweir     /// flag
308*cdf0e10cSrcweir     bool m_isModified;
309*cdf0e10cSrcweir     /// meta-data DOM tree
310*cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XDocument > m_xDoc;
311*cdf0e10cSrcweir     /// meta-data super node in the meta-data DOM tree
312*cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode> m_xParent;
313*cdf0e10cSrcweir     /// standard meta data (single occurrence)
314*cdf0e10cSrcweir     std::map< ::rtl::OUString, css::uno::Reference<css::xml::dom::XNode> >
315*cdf0e10cSrcweir         m_meta;
316*cdf0e10cSrcweir     /// standard meta data (multiple occurrences)
317*cdf0e10cSrcweir     std::map< ::rtl::OUString,
318*cdf0e10cSrcweir         std::vector<css::uno::Reference<css::xml::dom::XNode> > > m_metaList;
319*cdf0e10cSrcweir     /// user-defined meta data (meta:user-defined) @ATTENTION may be null!
320*cdf0e10cSrcweir     css::uno::Reference<css::beans::XPropertyContainer> m_xUserDefined;
321*cdf0e10cSrcweir     // now for some meta-data attributes; these are not updated directly in the
322*cdf0e10cSrcweir     // DOM because updates (detecting "empty" elements) would be quite messy
323*cdf0e10cSrcweir     ::rtl::OUString m_TemplateName;
324*cdf0e10cSrcweir     ::rtl::OUString m_TemplateURL;
325*cdf0e10cSrcweir     css::util::DateTime m_TemplateDate;
326*cdf0e10cSrcweir     ::rtl::OUString m_AutoloadURL;
327*cdf0e10cSrcweir     sal_Int32 m_AutoloadSecs;
328*cdf0e10cSrcweir     ::rtl::OUString m_DefaultTarget;
329*cdf0e10cSrcweir 
330*cdf0e10cSrcweir     /// check if we are initialized properly
331*cdf0e10cSrcweir     void SAL_CALL checkInit() const;
332*cdf0e10cSrcweir     //    throw (css::uno::RuntimeException);
333*cdf0e10cSrcweir     /// initialize state from given DOM tree
334*cdf0e10cSrcweir     void SAL_CALL init(css::uno::Reference<css::xml::dom::XDocument> i_xDom);
335*cdf0e10cSrcweir     //    throw (css::uno::RuntimeException, css::io::WrongFormatException,
336*cdf0e10cSrcweir     //        css::uno::Exception);
337*cdf0e10cSrcweir     /// update element in DOM tree
338*cdf0e10cSrcweir     void SAL_CALL updateElement(const char *i_name,
339*cdf0e10cSrcweir         std::vector<std::pair<const char *, ::rtl::OUString> >* i_pAttrs = 0);
340*cdf0e10cSrcweir     /// update user-defined meta data and attributes in DOM tree
341*cdf0e10cSrcweir     void SAL_CALL updateUserDefinedAndAttributes();
342*cdf0e10cSrcweir     /// create empty DOM tree (XDocument)
343*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XDocument> SAL_CALL createDOM() const;
344*cdf0e10cSrcweir     /// extract base URL (necessary for converting relative links)
345*cdf0e10cSrcweir     css::uno::Reference<css::beans::XPropertySet> SAL_CALL getURLProperties(
346*cdf0e10cSrcweir         const css::uno::Sequence<css::beans::PropertyValue> & i_rMedium) const;
347*cdf0e10cSrcweir     //    throw (css::uno::RuntimeException);
348*cdf0e10cSrcweir     /// get text of standard meta data element
349*cdf0e10cSrcweir     ::rtl::OUString SAL_CALL getMetaText(const char* i_name) const;
350*cdf0e10cSrcweir     //    throw (css::uno::RuntimeException);
351*cdf0e10cSrcweir     /// set text of standard meta data element iff not equal to existing text
352*cdf0e10cSrcweir     bool SAL_CALL setMetaText(const char* i_name,
353*cdf0e10cSrcweir         const ::rtl::OUString & i_rValue);
354*cdf0e10cSrcweir     //    throw (css::uno::RuntimeException);
355*cdf0e10cSrcweir     /// set text of standard meta data element iff not equal to existing text
356*cdf0e10cSrcweir     void SAL_CALL setMetaTextAndNotify(const char* i_name,
357*cdf0e10cSrcweir         const ::rtl::OUString & i_rValue);
358*cdf0e10cSrcweir     //    throw (css::uno::RuntimeException);
359*cdf0e10cSrcweir     /// get text of standard meta data element's attribute
360*cdf0e10cSrcweir     ::rtl::OUString SAL_CALL getMetaAttr(const char* i_name,
361*cdf0e10cSrcweir         const char* i_attr) const;
362*cdf0e10cSrcweir     //    throw (css::uno::RuntimeException);
363*cdf0e10cSrcweir     /// get text of a list of standard meta data elements (multiple occ.)
364*cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString > SAL_CALL getMetaList(
365*cdf0e10cSrcweir         const char* i_name) const;
366*cdf0e10cSrcweir     //    throw (css::uno::RuntimeException);
367*cdf0e10cSrcweir     /// set text of a list of standard meta data elements (multiple occ.)
368*cdf0e10cSrcweir     bool SAL_CALL setMetaList(const char* i_name,
369*cdf0e10cSrcweir         const css::uno::Sequence< ::rtl::OUString > & i_rValue,
370*cdf0e10cSrcweir         AttrVector const* = 0);
371*cdf0e10cSrcweir     // throw (css::uno::RuntimeException);
372*cdf0e10cSrcweir     void createUserDefined();
373*cdf0e10cSrcweir };
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
376*cdf0e10cSrcweir 
377*cdf0e10cSrcweir bool operator== (const css::util::DateTime &i_rLeft,
378*cdf0e10cSrcweir                  const css::util::DateTime &i_rRight)
379*cdf0e10cSrcweir {
380*cdf0e10cSrcweir     return i_rLeft.Year             == i_rRight.Year
381*cdf0e10cSrcweir         && i_rLeft.Month            == i_rRight.Month
382*cdf0e10cSrcweir         && i_rLeft.Day              == i_rRight.Day
383*cdf0e10cSrcweir         && i_rLeft.Hours            == i_rRight.Hours
384*cdf0e10cSrcweir         && i_rLeft.Minutes          == i_rRight.Minutes
385*cdf0e10cSrcweir         && i_rLeft.Seconds          == i_rRight.Seconds
386*cdf0e10cSrcweir         && i_rLeft.HundredthSeconds == i_rRight.HundredthSeconds;
387*cdf0e10cSrcweir }
388*cdf0e10cSrcweir 
389*cdf0e10cSrcweir // NB: keep these two arrays in sync!
390*cdf0e10cSrcweir const char* s_stdStatAttrs[] = {
391*cdf0e10cSrcweir     "meta:page-count",
392*cdf0e10cSrcweir     "meta:table-count",
393*cdf0e10cSrcweir     "meta:draw-count",
394*cdf0e10cSrcweir     "meta:image-count",
395*cdf0e10cSrcweir     "meta:object-count",
396*cdf0e10cSrcweir     "meta:ole-object-count",
397*cdf0e10cSrcweir     "meta:paragraph-count",
398*cdf0e10cSrcweir     "meta:word-count",
399*cdf0e10cSrcweir     "meta:character-count",
400*cdf0e10cSrcweir     "meta:row-count",
401*cdf0e10cSrcweir     "meta:frame-count",
402*cdf0e10cSrcweir     "meta:sentence-count",
403*cdf0e10cSrcweir     "meta:syllable-count",
404*cdf0e10cSrcweir     "meta:non-whitespace-character-count",
405*cdf0e10cSrcweir     "meta:cell-count",
406*cdf0e10cSrcweir     0
407*cdf0e10cSrcweir };
408*cdf0e10cSrcweir 
409*cdf0e10cSrcweir // NB: keep these two arrays in sync!
410*cdf0e10cSrcweir const char* s_stdStats[] = {
411*cdf0e10cSrcweir     "PageCount",
412*cdf0e10cSrcweir     "TableCount",
413*cdf0e10cSrcweir     "DrawCount",
414*cdf0e10cSrcweir     "ImageCount",
415*cdf0e10cSrcweir     "ObjectCount",
416*cdf0e10cSrcweir     "OLEObjectCount",
417*cdf0e10cSrcweir     "ParagraphCount",
418*cdf0e10cSrcweir     "WordCount",
419*cdf0e10cSrcweir     "CharacterCount",
420*cdf0e10cSrcweir     "RowCount",
421*cdf0e10cSrcweir     "FrameCount",
422*cdf0e10cSrcweir     "SentenceCount",
423*cdf0e10cSrcweir     "SyllableCount",
424*cdf0e10cSrcweir     "NonWhitespaceCharacterCount",
425*cdf0e10cSrcweir     "CellCount",
426*cdf0e10cSrcweir     0
427*cdf0e10cSrcweir };
428*cdf0e10cSrcweir 
429*cdf0e10cSrcweir const char* s_stdMeta[] = {
430*cdf0e10cSrcweir     "meta:generator",           // string
431*cdf0e10cSrcweir     "dc:title",                 // string
432*cdf0e10cSrcweir     "dc:description",           // string
433*cdf0e10cSrcweir     "dc:subject",               // string
434*cdf0e10cSrcweir     "meta:initial-creator",     // string
435*cdf0e10cSrcweir     "dc:creator",               // string
436*cdf0e10cSrcweir     "meta:printed-by",          // string
437*cdf0e10cSrcweir     "meta:creation-date",       // dateTime
438*cdf0e10cSrcweir     "dc:date",                  // dateTime
439*cdf0e10cSrcweir     "meta:print-date",          // dateTime
440*cdf0e10cSrcweir     "meta:template",            // XLink
441*cdf0e10cSrcweir     "meta:auto-reload",         // ...
442*cdf0e10cSrcweir     "meta:hyperlink-behaviour", // ...
443*cdf0e10cSrcweir     "dc:language",              // language
444*cdf0e10cSrcweir     "meta:editing-cycles",      // nonNegativeInteger
445*cdf0e10cSrcweir     "meta:editing-duration",    // duration
446*cdf0e10cSrcweir     "meta:document-statistic",  // ... // note: statistic is singular, no s!
447*cdf0e10cSrcweir     0
448*cdf0e10cSrcweir };
449*cdf0e10cSrcweir 
450*cdf0e10cSrcweir const char* s_stdMetaList[] = {
451*cdf0e10cSrcweir     "meta:keyword",             // string*
452*cdf0e10cSrcweir     "meta:user-defined",        // ...*
453*cdf0e10cSrcweir     0
454*cdf0e10cSrcweir };
455*cdf0e10cSrcweir 
456*cdf0e10cSrcweir const char* s_nsXLink   = "http://www.w3.org/1999/xlink";
457*cdf0e10cSrcweir const char* s_nsDC      = "http://purl.org/dc/elements/1.1/";
458*cdf0e10cSrcweir const char* s_nsODF     = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
459*cdf0e10cSrcweir const char* s_nsODFMeta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0";
460*cdf0e10cSrcweir // const char* s_nsOOo     = "http://openoffice.org/2004/office"; // not used (yet?)
461*cdf0e10cSrcweir 
462*cdf0e10cSrcweir const char* s_metaXml = "meta.xml";
463*cdf0e10cSrcweir 
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir bool isValidDate(const css::util::Date & i_rDate)
466*cdf0e10cSrcweir {
467*cdf0e10cSrcweir     return i_rDate.Month > 0;
468*cdf0e10cSrcweir }
469*cdf0e10cSrcweir 
470*cdf0e10cSrcweir bool isValidDateTime(const css::util::DateTime & i_rDateTime)
471*cdf0e10cSrcweir {
472*cdf0e10cSrcweir     return i_rDateTime.Month > 0;
473*cdf0e10cSrcweir }
474*cdf0e10cSrcweir 
475*cdf0e10cSrcweir std::pair< ::rtl::OUString, ::rtl::OUString > SAL_CALL
476*cdf0e10cSrcweir getQualifier(const char* i_name) {
477*cdf0e10cSrcweir     ::rtl::OUString nm = ::rtl::OUString::createFromAscii(i_name);
478*cdf0e10cSrcweir     sal_Int32 ix = nm.indexOf(static_cast<sal_Unicode> (':'));
479*cdf0e10cSrcweir     if (ix == -1) {
480*cdf0e10cSrcweir         return std::make_pair(::rtl::OUString(), nm);
481*cdf0e10cSrcweir     } else {
482*cdf0e10cSrcweir         return std::make_pair(nm.copy(0,ix), nm.copy(ix+1));
483*cdf0e10cSrcweir     }
484*cdf0e10cSrcweir }
485*cdf0e10cSrcweir 
486*cdf0e10cSrcweir // get namespace for standard qualified names
487*cdf0e10cSrcweir // NB: only call this with statically known strings!
488*cdf0e10cSrcweir ::rtl::OUString SAL_CALL getNameSpace(const char* i_qname) throw ()
489*cdf0e10cSrcweir {
490*cdf0e10cSrcweir     DBG_ASSERT(i_qname, "SfxDocumentMetaData: getNameSpace: argument is null");
491*cdf0e10cSrcweir     const char * ns = "";
492*cdf0e10cSrcweir     ::rtl::OUString n = getQualifier(i_qname).first;
493*cdf0e10cSrcweir     if (n.equalsAscii("xlink" )) ns = s_nsXLink;
494*cdf0e10cSrcweir     if (n.equalsAscii("dc"    )) ns = s_nsDC;
495*cdf0e10cSrcweir     if (n.equalsAscii("office")) ns = s_nsODF;
496*cdf0e10cSrcweir     if (n.equalsAscii("meta"  )) ns = s_nsODFMeta;
497*cdf0e10cSrcweir     DBG_ASSERT(*ns, "SfxDocumentMetaData: unknown namespace prefix");
498*cdf0e10cSrcweir     return ::rtl::OUString::createFromAscii(ns);
499*cdf0e10cSrcweir }
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir bool SAL_CALL
502*cdf0e10cSrcweir textToDateOrDateTime(css::util::Date & io_rd, css::util::DateTime & io_rdt,
503*cdf0e10cSrcweir         bool & o_rIsDateTime, ::rtl::OUString i_text) throw ()
504*cdf0e10cSrcweir {
505*cdf0e10cSrcweir     if (::sax::Converter::convertDateOrDateTime(
506*cdf0e10cSrcweir                 io_rd, io_rdt, o_rIsDateTime, i_text)) {
507*cdf0e10cSrcweir         return true;
508*cdf0e10cSrcweir     } else {
509*cdf0e10cSrcweir         DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
510*cdf0e10cSrcweir             OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr());
511*cdf0e10cSrcweir         return false;
512*cdf0e10cSrcweir     }
513*cdf0e10cSrcweir }
514*cdf0e10cSrcweir 
515*cdf0e10cSrcweir // convert string to date/time
516*cdf0e10cSrcweir bool SAL_CALL
517*cdf0e10cSrcweir textToDateTime(css::util::DateTime & io_rdt, ::rtl::OUString i_text) throw ()
518*cdf0e10cSrcweir {
519*cdf0e10cSrcweir     if (::sax::Converter::convertDateTime(io_rdt, i_text)) {
520*cdf0e10cSrcweir         return true;
521*cdf0e10cSrcweir     } else {
522*cdf0e10cSrcweir         DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
523*cdf0e10cSrcweir             OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr());
524*cdf0e10cSrcweir         return false;
525*cdf0e10cSrcweir     }
526*cdf0e10cSrcweir }
527*cdf0e10cSrcweir 
528*cdf0e10cSrcweir // convert string to date/time with default return value
529*cdf0e10cSrcweir css::util::DateTime SAL_CALL
530*cdf0e10cSrcweir textToDateTimeDefault(::rtl::OUString i_text) throw ()
531*cdf0e10cSrcweir {
532*cdf0e10cSrcweir     css::util::DateTime dt;
533*cdf0e10cSrcweir     static_cast<void> (textToDateTime(dt, i_text));
534*cdf0e10cSrcweir     // on conversion error: return default value (unchanged)
535*cdf0e10cSrcweir     return dt;
536*cdf0e10cSrcweir }
537*cdf0e10cSrcweir 
538*cdf0e10cSrcweir // convert date to string
539*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
540*cdf0e10cSrcweir dateToText(css::util::Date const& i_rd) throw ()
541*cdf0e10cSrcweir {
542*cdf0e10cSrcweir     if (isValidDate(i_rd)) {
543*cdf0e10cSrcweir         ::rtl::OUStringBuffer buf;
544*cdf0e10cSrcweir         ::sax::Converter::convertDate(buf, i_rd);
545*cdf0e10cSrcweir         return buf.makeStringAndClear();
546*cdf0e10cSrcweir     } else {
547*cdf0e10cSrcweir         return ::rtl::OUString();
548*cdf0e10cSrcweir     }
549*cdf0e10cSrcweir }
550*cdf0e10cSrcweir 
551*cdf0e10cSrcweir 
552*cdf0e10cSrcweir // convert date/time to string
553*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
554*cdf0e10cSrcweir dateTimeToText(css::util::DateTime const& i_rdt) throw ()
555*cdf0e10cSrcweir {
556*cdf0e10cSrcweir     if (isValidDateTime(i_rdt)) {
557*cdf0e10cSrcweir         ::rtl::OUStringBuffer buf;
558*cdf0e10cSrcweir         ::sax::Converter::convertDateTime(buf, i_rdt, true);
559*cdf0e10cSrcweir         return buf.makeStringAndClear();
560*cdf0e10cSrcweir     } else {
561*cdf0e10cSrcweir         return ::rtl::OUString();
562*cdf0e10cSrcweir     }
563*cdf0e10cSrcweir }
564*cdf0e10cSrcweir 
565*cdf0e10cSrcweir // convert string to duration
566*cdf0e10cSrcweir bool
567*cdf0e10cSrcweir textToDuration(css::util::Duration& io_rDur, ::rtl::OUString const& i_rText)
568*cdf0e10cSrcweir throw ()
569*cdf0e10cSrcweir {
570*cdf0e10cSrcweir     if (::sax::Converter::convertDuration(io_rDur, i_rText)) {
571*cdf0e10cSrcweir         return true;
572*cdf0e10cSrcweir     } else {
573*cdf0e10cSrcweir         DBG_WARNING1("SfxDocumentMetaData: invalid duration: %s",
574*cdf0e10cSrcweir             OUStringToOString(i_rText, RTL_TEXTENCODING_UTF8).getStr());
575*cdf0e10cSrcweir         return false;
576*cdf0e10cSrcweir     }
577*cdf0e10cSrcweir }
578*cdf0e10cSrcweir 
579*cdf0e10cSrcweir sal_Int32 textToDuration(::rtl::OUString const& i_rText) throw ()
580*cdf0e10cSrcweir {
581*cdf0e10cSrcweir     css::util::Duration d;
582*cdf0e10cSrcweir     if (textToDuration(d, i_rText)) {
583*cdf0e10cSrcweir         // #i107372#: approximate years/months
584*cdf0e10cSrcweir         const sal_Int32 days( (d.Years * 365) + (d.Months * 30) + d.Days );
585*cdf0e10cSrcweir         return  (days * (24*3600))
586*cdf0e10cSrcweir                 + (d.Hours * 3600) + (d.Minutes * 60) + d.Seconds;
587*cdf0e10cSrcweir     } else {
588*cdf0e10cSrcweir         return 0; // default
589*cdf0e10cSrcweir     }
590*cdf0e10cSrcweir }
591*cdf0e10cSrcweir 
592*cdf0e10cSrcweir // convert duration to string
593*cdf0e10cSrcweir ::rtl::OUString durationToText(css::util::Duration const& i_rDur) throw ()
594*cdf0e10cSrcweir {
595*cdf0e10cSrcweir     ::rtl::OUStringBuffer buf;
596*cdf0e10cSrcweir     ::sax::Converter::convertDuration(buf, i_rDur);
597*cdf0e10cSrcweir     return buf.makeStringAndClear();
598*cdf0e10cSrcweir }
599*cdf0e10cSrcweir 
600*cdf0e10cSrcweir // convert duration to string
601*cdf0e10cSrcweir ::rtl::OUString SAL_CALL durationToText(sal_Int32 i_value) throw ()
602*cdf0e10cSrcweir {
603*cdf0e10cSrcweir     css::util::Duration ud;
604*cdf0e10cSrcweir     ud.Days    = static_cast<sal_Int16>(i_value / (24 * 3600));
605*cdf0e10cSrcweir     ud.Hours   = static_cast<sal_Int16>((i_value % (24 * 3600)) / 3600);
606*cdf0e10cSrcweir     ud.Minutes = static_cast<sal_Int16>((i_value % 3600) / 60);
607*cdf0e10cSrcweir     ud.Seconds = static_cast<sal_Int16>(i_value % 60);
608*cdf0e10cSrcweir     ud.MilliSeconds = 0;
609*cdf0e10cSrcweir     return durationToText(ud);
610*cdf0e10cSrcweir }
611*cdf0e10cSrcweir 
612*cdf0e10cSrcweir // extract base URL (necessary for converting relative links)
613*cdf0e10cSrcweir css::uno::Reference< css::beans::XPropertySet > SAL_CALL
614*cdf0e10cSrcweir SfxDocumentMetaData::getURLProperties(
615*cdf0e10cSrcweir     const css::uno::Sequence< css::beans::PropertyValue > & i_rMedium) const
616*cdf0e10cSrcweir {
617*cdf0e10cSrcweir     css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
618*cdf0e10cSrcweir         m_xContext->getServiceManager());
619*cdf0e10cSrcweir     css::uno::Reference< css::beans::XPropertyContainer> xPropArg(
620*cdf0e10cSrcweir         xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
621*cdf0e10cSrcweir                 "com.sun.star.beans.PropertyBag"), m_xContext),
622*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
623*cdf0e10cSrcweir     try {
624*cdf0e10cSrcweir         ::rtl::OUString dburl =
625*cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentBaseURL"));
626*cdf0e10cSrcweir         ::rtl::OUString hdn =
627*cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HierarchicalDocumentName"));
628*cdf0e10cSrcweir         for (sal_Int32 i = 0; i < i_rMedium.getLength(); ++i) {
629*cdf0e10cSrcweir             if (i_rMedium[i].Name.equals(dburl)) {
630*cdf0e10cSrcweir                 xPropArg->addProperty(
631*cdf0e10cSrcweir                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI")),
632*cdf0e10cSrcweir                     css::beans::PropertyAttribute::MAYBEVOID,
633*cdf0e10cSrcweir                     i_rMedium[i].Value);
634*cdf0e10cSrcweir             } else if (i_rMedium[i].Name.equals(hdn)) {
635*cdf0e10cSrcweir                 xPropArg->addProperty(
636*cdf0e10cSrcweir                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath")),
637*cdf0e10cSrcweir                     css::beans::PropertyAttribute::MAYBEVOID,
638*cdf0e10cSrcweir                     i_rMedium[i].Value);
639*cdf0e10cSrcweir             }
640*cdf0e10cSrcweir         }
641*cdf0e10cSrcweir         xPropArg->addProperty(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamName")),
642*cdf0e10cSrcweir                 css::beans::PropertyAttribute::MAYBEVOID,
643*cdf0e10cSrcweir                 css::uno::makeAny(::rtl::OUString::createFromAscii(s_metaXml)));
644*cdf0e10cSrcweir     } catch (css::uno::Exception &) {
645*cdf0e10cSrcweir         // ignore
646*cdf0e10cSrcweir     }
647*cdf0e10cSrcweir     return css::uno::Reference< css::beans::XPropertySet>(xPropArg,
648*cdf0e10cSrcweir                 css::uno::UNO_QUERY_THROW);
649*cdf0e10cSrcweir }
650*cdf0e10cSrcweir 
651*cdf0e10cSrcweir // return the text of the (hopefully unique, i.e., normalize first!) text
652*cdf0e10cSrcweir // node _below_ the given node
653*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
654*cdf0e10cSrcweir getNodeText(css::uno::Reference<css::xml::dom::XNode> i_xNode)
655*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
656*cdf0e10cSrcweir {
657*cdf0e10cSrcweir     if (!i_xNode.is()) throw css::uno::RuntimeException(
658*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(
659*cdf0e10cSrcweir                 "SfxDocumentMetaData::getNodeText: argument is null"), i_xNode);
660*cdf0e10cSrcweir     for (css::uno::Reference<css::xml::dom::XNode> c = i_xNode->getFirstChild();
661*cdf0e10cSrcweir             c.is();
662*cdf0e10cSrcweir             c = c->getNextSibling()) {
663*cdf0e10cSrcweir         if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
664*cdf0e10cSrcweir             try {
665*cdf0e10cSrcweir                 return c->getNodeValue();
666*cdf0e10cSrcweir             } catch (css::xml::dom::DOMException &) { // too big?
667*cdf0e10cSrcweir                 return ::rtl::OUString();
668*cdf0e10cSrcweir             }
669*cdf0e10cSrcweir         }
670*cdf0e10cSrcweir     }
671*cdf0e10cSrcweir     return ::rtl::OUString();
672*cdf0e10cSrcweir }
673*cdf0e10cSrcweir 
674*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
675*cdf0e10cSrcweir SfxDocumentMetaData::getMetaText(const char* i_name) const
676*cdf0e10cSrcweir //        throw (css::uno::RuntimeException)
677*cdf0e10cSrcweir {
678*cdf0e10cSrcweir     checkInit();
679*cdf0e10cSrcweir 
680*cdf0e10cSrcweir     const ::rtl::OUString name( ::rtl::OUString::createFromAscii(i_name) );
681*cdf0e10cSrcweir     DBG_ASSERT(m_meta.find(name) != m_meta.end(),
682*cdf0e10cSrcweir         "SfxDocumentMetaData::getMetaText: not found");
683*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
684*cdf0e10cSrcweir     return (xNode.is()) ? getNodeText(xNode) : ::rtl::OUString();
685*cdf0e10cSrcweir }
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir bool SAL_CALL
688*cdf0e10cSrcweir SfxDocumentMetaData::setMetaText(const char* i_name,
689*cdf0e10cSrcweir         const ::rtl::OUString & i_rValue)
690*cdf0e10cSrcweir     // throw (css::uno::RuntimeException)
691*cdf0e10cSrcweir {
692*cdf0e10cSrcweir     checkInit();
693*cdf0e10cSrcweir 
694*cdf0e10cSrcweir     const ::rtl::OUString name( ::rtl::OUString::createFromAscii(i_name) );
695*cdf0e10cSrcweir     DBG_ASSERT(m_meta.find(name) != m_meta.end(),
696*cdf0e10cSrcweir         "SfxDocumentMetaData::setMetaText: not found");
697*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
698*cdf0e10cSrcweir 
699*cdf0e10cSrcweir     try {
700*cdf0e10cSrcweir         if (i_rValue.equalsAscii("")) {
701*cdf0e10cSrcweir             if (xNode.is()) { // delete
702*cdf0e10cSrcweir                 m_xParent->removeChild(xNode);
703*cdf0e10cSrcweir                 xNode.clear();
704*cdf0e10cSrcweir                 m_meta[name] = xNode;
705*cdf0e10cSrcweir                 return true;
706*cdf0e10cSrcweir             } else {
707*cdf0e10cSrcweir                 return false;
708*cdf0e10cSrcweir             }
709*cdf0e10cSrcweir         } else {
710*cdf0e10cSrcweir             if (xNode.is()) { // update
711*cdf0e10cSrcweir                 for (css::uno::Reference<css::xml::dom::XNode> c =
712*cdf0e10cSrcweir                             xNode->getFirstChild();
713*cdf0e10cSrcweir                         c.is();
714*cdf0e10cSrcweir                         c = c->getNextSibling()) {
715*cdf0e10cSrcweir                     if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
716*cdf0e10cSrcweir                         if (!c->getNodeValue().equals(i_rValue)) {
717*cdf0e10cSrcweir                             c->setNodeValue(i_rValue);
718*cdf0e10cSrcweir                             return true;
719*cdf0e10cSrcweir                         } else {
720*cdf0e10cSrcweir                             return false;
721*cdf0e10cSrcweir                         }
722*cdf0e10cSrcweir                     }
723*cdf0e10cSrcweir                 }
724*cdf0e10cSrcweir             } else { // insert
725*cdf0e10cSrcweir                 xNode.set(m_xDoc->createElementNS(getNameSpace(i_name), name),
726*cdf0e10cSrcweir                             css::uno::UNO_QUERY_THROW);
727*cdf0e10cSrcweir                 m_xParent->appendChild(xNode);
728*cdf0e10cSrcweir                 m_meta[name] = xNode;
729*cdf0e10cSrcweir             }
730*cdf0e10cSrcweir             css::uno::Reference<css::xml::dom::XNode> xTextNode(
731*cdf0e10cSrcweir                 m_xDoc->createTextNode(i_rValue), css::uno::UNO_QUERY_THROW);
732*cdf0e10cSrcweir             xNode->appendChild(xTextNode);
733*cdf0e10cSrcweir             return true;
734*cdf0e10cSrcweir         }
735*cdf0e10cSrcweir     } catch (css::xml::dom::DOMException & e) {
736*cdf0e10cSrcweir         css::uno::Any a(e);
737*cdf0e10cSrcweir         throw css::lang::WrappedTargetRuntimeException(
738*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
739*cdf0e10cSrcweir                         "SfxDocumentMetaData::setMetaText: DOM exception"),
740*cdf0e10cSrcweir                 css::uno::Reference<css::uno::XInterface>(*this), a);
741*cdf0e10cSrcweir     }
742*cdf0e10cSrcweir }
743*cdf0e10cSrcweir 
744*cdf0e10cSrcweir void SAL_CALL
745*cdf0e10cSrcweir SfxDocumentMetaData::setMetaTextAndNotify(const char* i_name,
746*cdf0e10cSrcweir         const ::rtl::OUString & i_rValue)
747*cdf0e10cSrcweir     // throw (css::uno::RuntimeException)
748*cdf0e10cSrcweir {
749*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
750*cdf0e10cSrcweir     if (setMetaText(i_name, i_rValue)) {
751*cdf0e10cSrcweir         g.clear();
752*cdf0e10cSrcweir         setModified(true);
753*cdf0e10cSrcweir     }
754*cdf0e10cSrcweir }
755*cdf0e10cSrcweir 
756*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
757*cdf0e10cSrcweir SfxDocumentMetaData::getMetaAttr(const char* i_name, const char* i_attr) const
758*cdf0e10cSrcweir //        throw (css::uno::RuntimeException)
759*cdf0e10cSrcweir {
760*cdf0e10cSrcweir //    checkInit();
761*cdf0e10cSrcweir     ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
762*cdf0e10cSrcweir     DBG_ASSERT(m_meta.find(name) != m_meta.end(),
763*cdf0e10cSrcweir         "SfxDocumentMetaData::getMetaAttr: not found");
764*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
765*cdf0e10cSrcweir     if (xNode.is()) {
766*cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XElement> xElem(xNode,
767*cdf0e10cSrcweir             css::uno::UNO_QUERY_THROW);
768*cdf0e10cSrcweir         return xElem->getAttributeNS(getNameSpace(i_attr),
769*cdf0e10cSrcweir                     getQualifier(i_attr).second);
770*cdf0e10cSrcweir     } else {
771*cdf0e10cSrcweir         return ::rtl::OUString();
772*cdf0e10cSrcweir     }
773*cdf0e10cSrcweir }
774*cdf0e10cSrcweir 
775*cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString> SAL_CALL
776*cdf0e10cSrcweir SfxDocumentMetaData::getMetaList(const char* i_name) const
777*cdf0e10cSrcweir //        throw (css::uno::RuntimeException)
778*cdf0e10cSrcweir {
779*cdf0e10cSrcweir     checkInit();
780*cdf0e10cSrcweir     ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
781*cdf0e10cSrcweir     DBG_ASSERT(m_metaList.find(name) != m_metaList.end(),
782*cdf0e10cSrcweir         "SfxDocumentMetaData::getMetaList: not found");
783*cdf0e10cSrcweir     std::vector<css::uno::Reference<css::xml::dom::XNode> > const & vec =
784*cdf0e10cSrcweir         m_metaList.find(name)->second;
785*cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString> ret(vec.size());
786*cdf0e10cSrcweir     for (size_t i = 0; i < vec.size(); ++i) {
787*cdf0e10cSrcweir         ret[i] = getNodeText(vec.at(i));
788*cdf0e10cSrcweir     }
789*cdf0e10cSrcweir     return ret;
790*cdf0e10cSrcweir }
791*cdf0e10cSrcweir 
792*cdf0e10cSrcweir bool SAL_CALL
793*cdf0e10cSrcweir SfxDocumentMetaData::setMetaList(const char* i_name,
794*cdf0e10cSrcweir         const css::uno::Sequence< ::rtl::OUString> & i_rValue,
795*cdf0e10cSrcweir         AttrVector const* i_pAttrs)
796*cdf0e10cSrcweir     // throw (css::uno::RuntimeException)
797*cdf0e10cSrcweir {
798*cdf0e10cSrcweir     checkInit();
799*cdf0e10cSrcweir     DBG_ASSERT((i_pAttrs == 0) ||
800*cdf0e10cSrcweir                (static_cast<size_t>(i_rValue.getLength()) == i_pAttrs->size()),
801*cdf0e10cSrcweir         "SfxDocumentMetaData::setMetaList: invalid args");
802*cdf0e10cSrcweir 
803*cdf0e10cSrcweir     try {
804*cdf0e10cSrcweir         ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
805*cdf0e10cSrcweir         DBG_ASSERT(m_metaList.find(name) != m_metaList.end(),
806*cdf0e10cSrcweir             "SfxDocumentMetaData::setMetaList: not found");
807*cdf0e10cSrcweir         std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
808*cdf0e10cSrcweir             m_metaList[name];
809*cdf0e10cSrcweir 
810*cdf0e10cSrcweir         // if nothing changed, do nothing
811*cdf0e10cSrcweir         // alas, this does not check for permutations, or attributes...
812*cdf0e10cSrcweir         if ((0 == i_pAttrs)) {
813*cdf0e10cSrcweir             if (static_cast<size_t>(i_rValue.getLength()) == vec.size()) {
814*cdf0e10cSrcweir                 bool isEqual(true);
815*cdf0e10cSrcweir                 for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
816*cdf0e10cSrcweir                     css::uno::Reference<css::xml::dom::XNode> xNode(vec.at(i));
817*cdf0e10cSrcweir                     if (xNode.is()) {
818*cdf0e10cSrcweir                         ::rtl::OUString val = getNodeText(xNode);
819*cdf0e10cSrcweir                         if (!val.equals(i_rValue[i])) {
820*cdf0e10cSrcweir                             isEqual = false;
821*cdf0e10cSrcweir                             break;
822*cdf0e10cSrcweir                         }
823*cdf0e10cSrcweir                     }
824*cdf0e10cSrcweir                 }
825*cdf0e10cSrcweir                 if (isEqual) return false;
826*cdf0e10cSrcweir             }
827*cdf0e10cSrcweir         }
828*cdf0e10cSrcweir 
829*cdf0e10cSrcweir         // remove old meta data nodes
830*cdf0e10cSrcweir         {
831*cdf0e10cSrcweir             std::vector<css::uno::Reference<css::xml::dom::XNode> >
832*cdf0e10cSrcweir                 ::reverse_iterator it(vec.rbegin());
833*cdf0e10cSrcweir             try {
834*cdf0e10cSrcweir                 for ( ;it != vec.rend(); ++it)
835*cdf0e10cSrcweir                 {
836*cdf0e10cSrcweir                     m_xParent->removeChild(*it);
837*cdf0e10cSrcweir                 }
838*cdf0e10cSrcweir             }
839*cdf0e10cSrcweir             catch (...)
840*cdf0e10cSrcweir             {
841*cdf0e10cSrcweir                 // Clean up already removed nodes
842*cdf0e10cSrcweir                 vec.erase(it.base(), vec.end());
843*cdf0e10cSrcweir                 throw;
844*cdf0e10cSrcweir             }
845*cdf0e10cSrcweir             vec.clear();
846*cdf0e10cSrcweir         }
847*cdf0e10cSrcweir 
848*cdf0e10cSrcweir         // insert new meta data nodes into DOM tree
849*cdf0e10cSrcweir         for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
850*cdf0e10cSrcweir             css::uno::Reference<css::xml::dom::XElement> xElem(
851*cdf0e10cSrcweir                 m_xDoc->createElementNS(getNameSpace(i_name), name),
852*cdf0e10cSrcweir                 css::uno::UNO_QUERY_THROW);
853*cdf0e10cSrcweir             css::uno::Reference<css::xml::dom::XNode> xNode(xElem,
854*cdf0e10cSrcweir                 css::uno::UNO_QUERY_THROW);
855*cdf0e10cSrcweir             css::uno::Reference<css::xml::dom::XNode> xTextNode(
856*cdf0e10cSrcweir                 m_xDoc->createTextNode(i_rValue[i]), css::uno::UNO_QUERY_THROW);
857*cdf0e10cSrcweir             // set attributes
858*cdf0e10cSrcweir             if (i_pAttrs != 0) {
859*cdf0e10cSrcweir                 for (std::vector<std::pair<const char*, ::rtl::OUString> >
860*cdf0e10cSrcweir                                 ::const_iterator it = (*i_pAttrs)[i].begin();
861*cdf0e10cSrcweir                         it != (*i_pAttrs)[i].end(); ++it) {
862*cdf0e10cSrcweir                     xElem->setAttributeNS(getNameSpace(it->first),
863*cdf0e10cSrcweir                         ::rtl::OUString::createFromAscii(it->first),
864*cdf0e10cSrcweir                         it->second);
865*cdf0e10cSrcweir                 }
866*cdf0e10cSrcweir             }
867*cdf0e10cSrcweir             xNode->appendChild(xTextNode);
868*cdf0e10cSrcweir             m_xParent->appendChild(xNode);
869*cdf0e10cSrcweir             vec.push_back(xNode);
870*cdf0e10cSrcweir         }
871*cdf0e10cSrcweir 
872*cdf0e10cSrcweir         return true;
873*cdf0e10cSrcweir     } catch (css::xml::dom::DOMException & e) {
874*cdf0e10cSrcweir         css::uno::Any a(e);
875*cdf0e10cSrcweir         throw css::lang::WrappedTargetRuntimeException(
876*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
877*cdf0e10cSrcweir                         "SfxDocumentMetaData::setMetaList: DOM exception"),
878*cdf0e10cSrcweir                 css::uno::Reference<css::uno::XInterface>(*this), a);
879*cdf0e10cSrcweir     }
880*cdf0e10cSrcweir }
881*cdf0e10cSrcweir 
882*cdf0e10cSrcweir // convert property list to string list and attribute list
883*cdf0e10cSrcweir std::pair<css::uno::Sequence< ::rtl::OUString>, AttrVector> SAL_CALL
884*cdf0e10cSrcweir propsToStrings(css::uno::Reference<css::beans::XPropertySet> const & i_xPropSet)
885*cdf0e10cSrcweir {
886*cdf0e10cSrcweir     ::comphelper::SequenceAsVector< ::rtl::OUString > values;
887*cdf0e10cSrcweir     AttrVector attrs;
888*cdf0e10cSrcweir 
889*cdf0e10cSrcweir     css::uno::Reference<css::beans::XPropertySetInfo> xSetInfo
890*cdf0e10cSrcweir         = i_xPropSet->getPropertySetInfo();
891*cdf0e10cSrcweir     css::uno::Sequence<css::beans::Property> props = xSetInfo->getProperties();
892*cdf0e10cSrcweir 
893*cdf0e10cSrcweir     for (sal_Int32 i = 0; i < props.getLength(); ++i) {
894*cdf0e10cSrcweir         if (props[i].Attributes & css::beans::PropertyAttribute::TRANSIENT) {
895*cdf0e10cSrcweir             continue;
896*cdf0e10cSrcweir         }
897*cdf0e10cSrcweir         const ::rtl::OUString name = props[i].Name;
898*cdf0e10cSrcweir         css::uno::Any any;
899*cdf0e10cSrcweir         try {
900*cdf0e10cSrcweir             any = i_xPropSet->getPropertyValue(name);
901*cdf0e10cSrcweir         } catch (css::uno::Exception &) {
902*cdf0e10cSrcweir             // ignore
903*cdf0e10cSrcweir         }
904*cdf0e10cSrcweir         const css::uno::Type & type = any.getValueType();
905*cdf0e10cSrcweir         std::vector<std::pair<const char*, ::rtl::OUString> > as;
906*cdf0e10cSrcweir         as.push_back(std::make_pair(static_cast<const char*>("meta:name"),
907*cdf0e10cSrcweir                                         name));
908*cdf0e10cSrcweir         const char* vt = "meta:value-type";
909*cdf0e10cSrcweir 
910*cdf0e10cSrcweir         // convert according to type
911*cdf0e10cSrcweir         if (type == ::cppu::UnoType<bool>::get()) {
912*cdf0e10cSrcweir             bool b = false;
913*cdf0e10cSrcweir             any >>= b;
914*cdf0e10cSrcweir             ::rtl::OUStringBuffer buf;
915*cdf0e10cSrcweir             ::sax::Converter::convertBool(buf, b);
916*cdf0e10cSrcweir             values.push_back(buf.makeStringAndClear());
917*cdf0e10cSrcweir             as.push_back(std::make_pair(vt,
918*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("boolean"))));
919*cdf0e10cSrcweir         } else if (type == ::cppu::UnoType< ::rtl::OUString>::get()) {
920*cdf0e10cSrcweir             ::rtl::OUString s;
921*cdf0e10cSrcweir             any >>= s;
922*cdf0e10cSrcweir             values.push_back(s);
923*cdf0e10cSrcweir // #i90847# OOo 2.x does stupid things if value-type="string";
924*cdf0e10cSrcweir // fortunately string is default anyway, so we can just omit it
925*cdf0e10cSrcweir // #i107502#: however, OOo 2.x only reads 4 user-defined without @value-type
926*cdf0e10cSrcweir // => best backward compatibility: first 4 without @value-type, rest with
927*cdf0e10cSrcweir             if (4 <= i)
928*cdf0e10cSrcweir             {
929*cdf0e10cSrcweir                 as.push_back(std::make_pair(vt,
930*cdf0e10cSrcweir                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("string"))));
931*cdf0e10cSrcweir             }
932*cdf0e10cSrcweir         } else if (type == ::cppu::UnoType<css::util::DateTime>::get()) {
933*cdf0e10cSrcweir             css::util::DateTime dt;
934*cdf0e10cSrcweir             any >>= dt;
935*cdf0e10cSrcweir             values.push_back(dateTimeToText(dt));
936*cdf0e10cSrcweir             as.push_back(std::make_pair(vt,
937*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("date"))));
938*cdf0e10cSrcweir         } else if (type == ::cppu::UnoType<css::util::Date>::get()) {
939*cdf0e10cSrcweir             css::util::Date d;
940*cdf0e10cSrcweir             any >>= d;
941*cdf0e10cSrcweir             values.push_back(dateToText(d));
942*cdf0e10cSrcweir             as.push_back(std::make_pair(vt,
943*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("date"))));
944*cdf0e10cSrcweir         } else if (type == ::cppu::UnoType<css::util::Time>::get()) {
945*cdf0e10cSrcweir             // #i97029#: replaced by Duration
946*cdf0e10cSrcweir             // Time is supported for backward compatibility with OOo 3.x, x<=2
947*cdf0e10cSrcweir             css::util::Time ut;
948*cdf0e10cSrcweir             any >>= ut;
949*cdf0e10cSrcweir             css::util::Duration ud;
950*cdf0e10cSrcweir             ud.Hours   = ut.Hours;
951*cdf0e10cSrcweir             ud.Minutes = ut.Minutes;
952*cdf0e10cSrcweir             ud.Seconds = ut.Seconds;
953*cdf0e10cSrcweir             ud.MilliSeconds = 10 * ut.HundredthSeconds;
954*cdf0e10cSrcweir             values.push_back(durationToText(ud));
955*cdf0e10cSrcweir             as.push_back(std::make_pair(vt,
956*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("time"))));
957*cdf0e10cSrcweir         } else if (type == ::cppu::UnoType<css::util::Duration>::get()) {
958*cdf0e10cSrcweir             css::util::Duration ud;
959*cdf0e10cSrcweir             any >>= ud;
960*cdf0e10cSrcweir             values.push_back(durationToText(ud));
961*cdf0e10cSrcweir             as.push_back(std::make_pair(vt,
962*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("time"))));
963*cdf0e10cSrcweir         } else if (::cppu::UnoType<double>::get().isAssignableFrom(type)) {
964*cdf0e10cSrcweir             // support not just double, but anything that can be converted
965*cdf0e10cSrcweir             double d = 0;
966*cdf0e10cSrcweir             any >>= d;
967*cdf0e10cSrcweir             ::rtl::OUStringBuffer buf;
968*cdf0e10cSrcweir             ::sax::Converter::convertDouble(buf, d);
969*cdf0e10cSrcweir             values.push_back(buf.makeStringAndClear());
970*cdf0e10cSrcweir             as.push_back(std::make_pair(vt,
971*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("float"))));
972*cdf0e10cSrcweir         } else {
973*cdf0e10cSrcweir             DBG_WARNING1("SfxDocumentMetaData: unsupported property type: %s",
974*cdf0e10cSrcweir                 OUStringToOString(any.getValueTypeName(),
975*cdf0e10cSrcweir                     RTL_TEXTENCODING_UTF8).getStr());
976*cdf0e10cSrcweir             continue;
977*cdf0e10cSrcweir         }
978*cdf0e10cSrcweir         attrs.push_back(as);
979*cdf0e10cSrcweir     }
980*cdf0e10cSrcweir 
981*cdf0e10cSrcweir     return std::make_pair(values.getAsConstList(), attrs);
982*cdf0e10cSrcweir }
983*cdf0e10cSrcweir 
984*cdf0e10cSrcweir // remove the given element from the DOM, and iff i_pAttrs != 0 insert new one
985*cdf0e10cSrcweir void SAL_CALL
986*cdf0e10cSrcweir SfxDocumentMetaData::updateElement(const char *i_name,
987*cdf0e10cSrcweir         std::vector<std::pair<const char *, ::rtl::OUString> >* i_pAttrs)
988*cdf0e10cSrcweir {
989*cdf0e10cSrcweir     ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
990*cdf0e10cSrcweir     try {
991*cdf0e10cSrcweir         // remove old element
992*cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XNode> xNode =
993*cdf0e10cSrcweir             m_meta.find(name)->second;
994*cdf0e10cSrcweir         if (xNode.is()) {
995*cdf0e10cSrcweir             m_xParent->removeChild(xNode);
996*cdf0e10cSrcweir             xNode.clear();
997*cdf0e10cSrcweir         }
998*cdf0e10cSrcweir         // add new element
999*cdf0e10cSrcweir         if (0 != i_pAttrs) {
1000*cdf0e10cSrcweir             css::uno::Reference<css::xml::dom::XElement> xElem(
1001*cdf0e10cSrcweir                 m_xDoc->createElementNS(getNameSpace(i_name), name),
1002*cdf0e10cSrcweir                     css::uno::UNO_QUERY_THROW);
1003*cdf0e10cSrcweir             xNode.set(xElem, css::uno::UNO_QUERY_THROW);
1004*cdf0e10cSrcweir             // set attributes
1005*cdf0e10cSrcweir             for (std::vector<std::pair<const char *, ::rtl::OUString> >
1006*cdf0e10cSrcweir                     ::const_iterator it = i_pAttrs->begin();
1007*cdf0e10cSrcweir                     it != i_pAttrs->end(); ++it) {
1008*cdf0e10cSrcweir                 xElem->setAttributeNS(getNameSpace(it->first),
1009*cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii(it->first), it->second);
1010*cdf0e10cSrcweir             }
1011*cdf0e10cSrcweir             m_xParent->appendChild(xNode);
1012*cdf0e10cSrcweir         }
1013*cdf0e10cSrcweir         m_meta[name] = xNode;
1014*cdf0e10cSrcweir     } catch (css::xml::dom::DOMException & e) {
1015*cdf0e10cSrcweir         css::uno::Any a(e);
1016*cdf0e10cSrcweir         throw css::lang::WrappedTargetRuntimeException(
1017*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
1018*cdf0e10cSrcweir                     "SfxDocumentMetaData::updateElement: DOM exception"),
1019*cdf0e10cSrcweir                 css::uno::Reference<css::uno::XInterface>(*this), a);
1020*cdf0e10cSrcweir     }
1021*cdf0e10cSrcweir }
1022*cdf0e10cSrcweir 
1023*cdf0e10cSrcweir // update user-defined meta data in DOM tree
1024*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::updateUserDefinedAndAttributes()
1025*cdf0e10cSrcweir {
1026*cdf0e10cSrcweir     createUserDefined();
1027*cdf0e10cSrcweir     const css::uno::Reference<css::beans::XPropertySet> xPSet(m_xUserDefined,
1028*cdf0e10cSrcweir             css::uno::UNO_QUERY_THROW);
1029*cdf0e10cSrcweir     const std::pair<css::uno::Sequence< ::rtl::OUString>, AttrVector>
1030*cdf0e10cSrcweir         udStringsAttrs( propsToStrings(xPSet) );
1031*cdf0e10cSrcweir     (void) setMetaList("meta:user-defined", udStringsAttrs.first,
1032*cdf0e10cSrcweir             &udStringsAttrs.second);
1033*cdf0e10cSrcweir 
1034*cdf0e10cSrcweir     // update elements with attributes
1035*cdf0e10cSrcweir     std::vector<std::pair<const char *, ::rtl::OUString> > attributes;
1036*cdf0e10cSrcweir     if (!m_TemplateName.equalsAscii("") || !m_TemplateURL.equalsAscii("")
1037*cdf0e10cSrcweir             || isValidDateTime(m_TemplateDate)) {
1038*cdf0e10cSrcweir         attributes.push_back(std::make_pair(
1039*cdf0e10cSrcweir                 static_cast<const char*>("xlink:type"),
1040*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simple"))));
1041*cdf0e10cSrcweir         attributes.push_back(std::make_pair(
1042*cdf0e10cSrcweir                 static_cast<const char*>("xlink:actuate"),
1043*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("onRequest"))));
1044*cdf0e10cSrcweir         attributes.push_back(std::make_pair(
1045*cdf0e10cSrcweir                 static_cast<const char*>("xlink:title"), m_TemplateName));
1046*cdf0e10cSrcweir         attributes.push_back(std::make_pair(
1047*cdf0e10cSrcweir                 static_cast<const char*>("xlink:href" ), m_TemplateURL ));
1048*cdf0e10cSrcweir         if (isValidDateTime(m_TemplateDate)) {
1049*cdf0e10cSrcweir             attributes.push_back(std::make_pair(
1050*cdf0e10cSrcweir                 static_cast<const char*>("meta:date"  ),
1051*cdf0e10cSrcweir                 dateTimeToText(m_TemplateDate)));
1052*cdf0e10cSrcweir         }
1053*cdf0e10cSrcweir         updateElement("meta:template", &attributes);
1054*cdf0e10cSrcweir     } else {
1055*cdf0e10cSrcweir         updateElement("meta:template");
1056*cdf0e10cSrcweir     }
1057*cdf0e10cSrcweir     attributes.clear();
1058*cdf0e10cSrcweir 
1059*cdf0e10cSrcweir     if (!m_AutoloadURL.equalsAscii("") || (0 != m_AutoloadSecs)) {
1060*cdf0e10cSrcweir         attributes.push_back(std::make_pair(
1061*cdf0e10cSrcweir                 static_cast<const char*>("xlink:href" ), m_AutoloadURL ));
1062*cdf0e10cSrcweir         attributes.push_back(std::make_pair(
1063*cdf0e10cSrcweir                 static_cast<const char*>("meta:delay" ),
1064*cdf0e10cSrcweir                 durationToText(m_AutoloadSecs)));
1065*cdf0e10cSrcweir         updateElement("meta:auto-reload", &attributes);
1066*cdf0e10cSrcweir     } else {
1067*cdf0e10cSrcweir         updateElement("meta:auto-reload");
1068*cdf0e10cSrcweir     }
1069*cdf0e10cSrcweir     attributes.clear();
1070*cdf0e10cSrcweir 
1071*cdf0e10cSrcweir     if (!m_DefaultTarget.equalsAscii("")) {
1072*cdf0e10cSrcweir         attributes.push_back(std::make_pair(
1073*cdf0e10cSrcweir                 static_cast<const char*>("office:target-frame-name"),
1074*cdf0e10cSrcweir                 m_DefaultTarget));
1075*cdf0e10cSrcweir         // xlink:show: _blank -> new, any other value -> replace
1076*cdf0e10cSrcweir         const sal_Char* show = m_DefaultTarget.equalsAscii("_blank")
1077*cdf0e10cSrcweir             ? "new" : "replace";
1078*cdf0e10cSrcweir         attributes.push_back(std::make_pair(
1079*cdf0e10cSrcweir                 static_cast<const char*>("xlink:show"),
1080*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(show)));
1081*cdf0e10cSrcweir         updateElement("meta:hyperlink-behaviour", &attributes);
1082*cdf0e10cSrcweir     } else {
1083*cdf0e10cSrcweir         updateElement("meta:hyperlink-behaviour");
1084*cdf0e10cSrcweir     }
1085*cdf0e10cSrcweir     attributes.clear();
1086*cdf0e10cSrcweir }
1087*cdf0e10cSrcweir 
1088*cdf0e10cSrcweir // create empty DOM tree (XDocument)
1089*cdf0e10cSrcweir css::uno::Reference<css::xml::dom::XDocument> SAL_CALL
1090*cdf0e10cSrcweir SfxDocumentMetaData::createDOM() const // throw (css::uno::RuntimeException)
1091*cdf0e10cSrcweir {
1092*cdf0e10cSrcweir     css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1093*cdf0e10cSrcweir         m_xContext->getServiceManager());
1094*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XDocumentBuilder> xBuilder(
1095*cdf0e10cSrcweir         xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
1096*cdf0e10cSrcweir                 "com.sun.star.xml.dom.DocumentBuilder"), m_xContext),
1097*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW );
1098*cdf0e10cSrcweir     if (!xBuilder.is()) throw css::uno::RuntimeException(
1099*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("SfxDocumentMetaData::createDOM: "
1100*cdf0e10cSrcweir                 "cannot create DocumentBuilder service"),
1101*cdf0e10cSrcweir                 *const_cast<SfxDocumentMetaData*>(this));
1102*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XDocument> xDoc =
1103*cdf0e10cSrcweir                 xBuilder->newDocument();
1104*cdf0e10cSrcweir     if (!xDoc.is()) throw css::uno::RuntimeException(
1105*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("SfxDocumentMetaData::createDOM: "
1106*cdf0e10cSrcweir                 "cannot create new document"),
1107*cdf0e10cSrcweir                 *const_cast<SfxDocumentMetaData*>(this));
1108*cdf0e10cSrcweir     return xDoc;
1109*cdf0e10cSrcweir }
1110*cdf0e10cSrcweir 
1111*cdf0e10cSrcweir void SAL_CALL
1112*cdf0e10cSrcweir SfxDocumentMetaData::checkInit() const // throw (css::uno::RuntimeException)
1113*cdf0e10cSrcweir {
1114*cdf0e10cSrcweir     if (!m_isInitialized) {
1115*cdf0e10cSrcweir         throw css::uno::RuntimeException(::rtl::OUString::createFromAscii(
1116*cdf0e10cSrcweir                 "SfxDocumentMetaData::checkInit: not initialized"),
1117*cdf0e10cSrcweir                 *const_cast<SfxDocumentMetaData*>(this));
1118*cdf0e10cSrcweir     }
1119*cdf0e10cSrcweir     DBG_ASSERT((m_xDoc.is() && m_xParent.is() ),
1120*cdf0e10cSrcweir                 "SfxDocumentMetaData::checkInit: reference is null");
1121*cdf0e10cSrcweir }
1122*cdf0e10cSrcweir 
1123*cdf0e10cSrcweir // initialize state from DOM tree
1124*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::init(
1125*cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XDocument> i_xDoc)
1126*cdf0e10cSrcweir //        throw (css::uno::RuntimeException, css::io::WrongFormatException,
1127*cdf0e10cSrcweir //               css::uno::Exception)
1128*cdf0e10cSrcweir {
1129*cdf0e10cSrcweir     if (!i_xDoc.is()) throw css::uno::RuntimeException(
1130*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(
1131*cdf0e10cSrcweir                 "SfxDocumentMetaData::init: no DOM tree given"), *this);
1132*cdf0e10cSrcweir 
1133*cdf0e10cSrcweir     css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1134*cdf0e10cSrcweir         m_xContext->getServiceManager());
1135*cdf0e10cSrcweir     css::uno::Reference<css::xml::xpath::XXPathAPI> xPath(
1136*cdf0e10cSrcweir         xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
1137*cdf0e10cSrcweir                 "com.sun.star.xml.xpath.XPathAPI"), m_xContext),
1138*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW );
1139*cdf0e10cSrcweir     if (!xPath.is()) throw css::uno::RuntimeException(
1140*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("SfxDocumentMetaData::init:"
1141*cdf0e10cSrcweir                 " cannot create XPathAPI service"), *this);
1142*cdf0e10cSrcweir 
1143*cdf0e10cSrcweir     m_isInitialized = false;
1144*cdf0e10cSrcweir     m_xDoc = i_xDoc;
1145*cdf0e10cSrcweir 
1146*cdf0e10cSrcweir     // select nodes for standard meta data stuff
1147*cdf0e10cSrcweir     xPath->registerNS(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")),
1148*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(s_nsXLink));
1149*cdf0e10cSrcweir     xPath->registerNS(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("dc")),
1150*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(s_nsDC));
1151*cdf0e10cSrcweir     xPath->registerNS(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("office")),
1152*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(s_nsODF));
1153*cdf0e10cSrcweir     xPath->registerNS(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("meta")),
1154*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(s_nsODFMeta));
1155*cdf0e10cSrcweir     // NB: we do not handle the single-XML-file ODF variant, which would
1156*cdf0e10cSrcweir     //     have the root element office:document.
1157*cdf0e10cSrcweir     //     The root of such documents must be converted in the importer!
1158*cdf0e10cSrcweir     ::rtl::OUString prefix = ::rtl::OUString::createFromAscii(
1159*cdf0e10cSrcweir         "/child::office:document-meta/child::office:meta");
1160*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XNode> xDocNode(
1161*cdf0e10cSrcweir         m_xDoc, css::uno::UNO_QUERY_THROW);
1162*cdf0e10cSrcweir     m_xParent.clear();
1163*cdf0e10cSrcweir     try {
1164*cdf0e10cSrcweir         m_xParent = xPath->selectSingleNode(xDocNode, prefix);
1165*cdf0e10cSrcweir     } catch (com::sun::star::uno::Exception &) {
1166*cdf0e10cSrcweir //        DBG_WARNING("SfxDocumentMetaData::init: "
1167*cdf0e10cSrcweir //            "caught RuntimeException from libxml!");
1168*cdf0e10cSrcweir     }
1169*cdf0e10cSrcweir 
1170*cdf0e10cSrcweir     if (!m_xParent.is()) {
1171*cdf0e10cSrcweir         // all this create/append stuff may throw DOMException
1172*cdf0e10cSrcweir         try {
1173*cdf0e10cSrcweir             css::uno::Reference<css::xml::dom::XElement> xRElem;
1174*cdf0e10cSrcweir             css::uno::Reference<css::xml::dom::XNode> xNode(
1175*cdf0e10cSrcweir                 i_xDoc->getFirstChild());
1176*cdf0e10cSrcweir             while (xNode.is()) {
1177*cdf0e10cSrcweir                 if (css::xml::dom::NodeType_ELEMENT_NODE ==xNode->getNodeType())
1178*cdf0e10cSrcweir                 {
1179*cdf0e10cSrcweir                     if (xNode->getNamespaceURI().equalsAscii(s_nsODF) &&
1180*cdf0e10cSrcweir                         xNode->getLocalName().equalsAscii("document-meta"))
1181*cdf0e10cSrcweir                     {
1182*cdf0e10cSrcweir                         xRElem.set(xNode, css::uno::UNO_QUERY_THROW);
1183*cdf0e10cSrcweir                         break;
1184*cdf0e10cSrcweir                     }
1185*cdf0e10cSrcweir                     else
1186*cdf0e10cSrcweir                     {
1187*cdf0e10cSrcweir                         OSL_TRACE("SfxDocumentMetaData::init(): "
1188*cdf0e10cSrcweir                                 "deleting unexpected root element: %s",
1189*cdf0e10cSrcweir                             ::rtl::OUStringToOString(xNode->getLocalName(),
1190*cdf0e10cSrcweir                                 RTL_TEXTENCODING_UTF8).getStr());
1191*cdf0e10cSrcweir                         i_xDoc->removeChild(xNode);
1192*cdf0e10cSrcweir                         xNode = i_xDoc->getFirstChild(); // start over
1193*cdf0e10cSrcweir                     }
1194*cdf0e10cSrcweir                 } else {
1195*cdf0e10cSrcweir                     xNode = xNode->getNextSibling();
1196*cdf0e10cSrcweir                 }
1197*cdf0e10cSrcweir             }
1198*cdf0e10cSrcweir             if (!xRElem.is()) {
1199*cdf0e10cSrcweir                 xRElem = i_xDoc->createElementNS(
1200*cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii(s_nsODF),
1201*cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii("office:document-meta"));
1202*cdf0e10cSrcweir                 css::uno::Reference<css::xml::dom::XNode> xRNode(xRElem,
1203*cdf0e10cSrcweir                     css::uno::UNO_QUERY_THROW);
1204*cdf0e10cSrcweir                 i_xDoc->appendChild(xRNode);
1205*cdf0e10cSrcweir             }
1206*cdf0e10cSrcweir             xRElem->setAttributeNS(::rtl::OUString::createFromAscii(s_nsODF),
1207*cdf0e10cSrcweir                         ::rtl::OUString::createFromAscii("office:version"),
1208*cdf0e10cSrcweir                         ::rtl::OUString::createFromAscii("1.0"));
1209*cdf0e10cSrcweir             // does not exist, otherwise m_xParent would not be null
1210*cdf0e10cSrcweir             css::uno::Reference<css::xml::dom::XNode> xParent (
1211*cdf0e10cSrcweir                 i_xDoc->createElementNS(
1212*cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii(s_nsODF),
1213*cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii("office:meta")),
1214*cdf0e10cSrcweir             css::uno::UNO_QUERY_THROW);
1215*cdf0e10cSrcweir             xRElem->appendChild(xParent);
1216*cdf0e10cSrcweir             m_xParent = xParent;
1217*cdf0e10cSrcweir         } catch (css::xml::dom::DOMException & e) {
1218*cdf0e10cSrcweir             css::uno::Any a(e);
1219*cdf0e10cSrcweir             throw css::lang::WrappedTargetRuntimeException(
1220*cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii(
1221*cdf0e10cSrcweir                             "SfxDocumentMetaData::init: DOM exception"),
1222*cdf0e10cSrcweir                     css::uno::Reference<css::uno::XInterface>(*this), a);
1223*cdf0e10cSrcweir         }
1224*cdf0e10cSrcweir     }
1225*cdf0e10cSrcweir 
1226*cdf0e10cSrcweir 
1227*cdf0e10cSrcweir     // select nodes for elements of which we only handle one occurrence
1228*cdf0e10cSrcweir     for (const char **pName = s_stdMeta; *pName != 0; ++pName) {
1229*cdf0e10cSrcweir         ::rtl::OUString name = ::rtl::OUString::createFromAscii(*pName);
1230*cdf0e10cSrcweir         // NB: If a document contains more than one occurrence of a
1231*cdf0e10cSrcweir         // meta-data element, we arbitrarily pick one of them here.
1232*cdf0e10cSrcweir         // We do not remove the others, i.e., when we write the
1233*cdf0e10cSrcweir         // document, it will contain the duplicates unchanged.
1234*cdf0e10cSrcweir         // The ODF spec says that handling multiple occurrences is
1235*cdf0e10cSrcweir         // application-specific.
1236*cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XNode> xNode =
1237*cdf0e10cSrcweir             xPath->selectSingleNode(m_xParent,
1238*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii("child::") + name);
1239*cdf0e10cSrcweir         // Do not create an empty element if it is missing;
1240*cdf0e10cSrcweir         // for certain elements, such as dateTime, this would be invalid
1241*cdf0e10cSrcweir         m_meta[name] = xNode;
1242*cdf0e10cSrcweir     }
1243*cdf0e10cSrcweir 
1244*cdf0e10cSrcweir     // select nodes for elements of which we handle all occurrences
1245*cdf0e10cSrcweir     for (const char **pName = s_stdMetaList; *pName != 0; ++pName) {
1246*cdf0e10cSrcweir         ::rtl::OUString name = ::rtl::OUString::createFromAscii(*pName);
1247*cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XNodeList> nodes =
1248*cdf0e10cSrcweir             xPath->selectNodeList(m_xParent,
1249*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii("child::") + name);
1250*cdf0e10cSrcweir         std::vector<css::uno::Reference<css::xml::dom::XNode> > v;
1251*cdf0e10cSrcweir         for (sal_Int32 i = 0; i < nodes->getLength(); ++i) {
1252*cdf0e10cSrcweir             v.push_back(nodes->item(i));
1253*cdf0e10cSrcweir         }
1254*cdf0e10cSrcweir         m_metaList[name] = v;
1255*cdf0e10cSrcweir     }
1256*cdf0e10cSrcweir 
1257*cdf0e10cSrcweir     // initialize members corresponding to attributes from DOM nodes
1258*cdf0e10cSrcweir     m_TemplateName  = getMetaAttr("meta:template", "xlink:title");
1259*cdf0e10cSrcweir     m_TemplateURL   = getMetaAttr("meta:template", "xlink:href");
1260*cdf0e10cSrcweir     m_TemplateDate  =
1261*cdf0e10cSrcweir         textToDateTimeDefault(getMetaAttr("meta:template", "meta:date"));
1262*cdf0e10cSrcweir     m_AutoloadURL   = getMetaAttr("meta:auto-reload", "xlink:href");
1263*cdf0e10cSrcweir     m_AutoloadSecs  =
1264*cdf0e10cSrcweir         textToDuration(getMetaAttr("meta:auto-reload", "meta:delay"));
1265*cdf0e10cSrcweir     m_DefaultTarget =
1266*cdf0e10cSrcweir         getMetaAttr("meta:hyperlink-behaviour", "office:target-frame-name");
1267*cdf0e10cSrcweir 
1268*cdf0e10cSrcweir 
1269*cdf0e10cSrcweir     std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
1270*cdf0e10cSrcweir         m_metaList[::rtl::OUString::createFromAscii("meta:user-defined")];
1271*cdf0e10cSrcweir     m_xUserDefined.clear(); // #i105826#: reset (may be re-initialization)
1272*cdf0e10cSrcweir     if ( !vec.empty() )
1273*cdf0e10cSrcweir     {
1274*cdf0e10cSrcweir         createUserDefined();
1275*cdf0e10cSrcweir     }
1276*cdf0e10cSrcweir 
1277*cdf0e10cSrcweir     // user-defined meta data: initialize PropertySet from DOM nodes
1278*cdf0e10cSrcweir     for (std::vector<css::uno::Reference<css::xml::dom::XNode> >::iterator
1279*cdf0e10cSrcweir             it = vec.begin(); it != vec.end(); ++it) {
1280*cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XElement> xElem(*it,
1281*cdf0e10cSrcweir             css::uno::UNO_QUERY_THROW);
1282*cdf0e10cSrcweir         css::uno::Any any;
1283*cdf0e10cSrcweir         ::rtl::OUString name = xElem->getAttributeNS(
1284*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(s_nsODFMeta),
1285*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("name")));
1286*cdf0e10cSrcweir         ::rtl::OUString type = xElem->getAttributeNS(
1287*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(s_nsODFMeta),
1288*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii("value-type"));
1289*cdf0e10cSrcweir         ::rtl::OUString text = getNodeText(*it);
1290*cdf0e10cSrcweir         if (type.equalsAscii("float")) {
1291*cdf0e10cSrcweir             double d;
1292*cdf0e10cSrcweir             if (::sax::Converter::convertDouble(d, text)) {
1293*cdf0e10cSrcweir                 any <<= d;
1294*cdf0e10cSrcweir             } else {
1295*cdf0e10cSrcweir                 DBG_WARNING1("SfxDocumentMetaData: invalid float: %s",
1296*cdf0e10cSrcweir                     OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1297*cdf0e10cSrcweir                 continue;
1298*cdf0e10cSrcweir             }
1299*cdf0e10cSrcweir         } else if (type.equalsAscii("date")) {
1300*cdf0e10cSrcweir             bool isDateTime;
1301*cdf0e10cSrcweir             css::util::Date d;
1302*cdf0e10cSrcweir             css::util::DateTime dt;
1303*cdf0e10cSrcweir             if (textToDateOrDateTime(d, dt, isDateTime, text)) {
1304*cdf0e10cSrcweir                 if (isDateTime) {
1305*cdf0e10cSrcweir                     any <<= dt;
1306*cdf0e10cSrcweir                 } else {
1307*cdf0e10cSrcweir                     any <<= d;
1308*cdf0e10cSrcweir                 }
1309*cdf0e10cSrcweir             } else {
1310*cdf0e10cSrcweir                 DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
1311*cdf0e10cSrcweir                     OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1312*cdf0e10cSrcweir                 continue;
1313*cdf0e10cSrcweir             }
1314*cdf0e10cSrcweir         } else if (type.equalsAscii("time")) {
1315*cdf0e10cSrcweir             css::util::Duration ud;
1316*cdf0e10cSrcweir             if (textToDuration(ud, text)) {
1317*cdf0e10cSrcweir                 any <<= ud;
1318*cdf0e10cSrcweir             } else {
1319*cdf0e10cSrcweir                 DBG_WARNING1("SfxDocumentMetaData: invalid time: %s",
1320*cdf0e10cSrcweir                     OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1321*cdf0e10cSrcweir                 continue;
1322*cdf0e10cSrcweir             }
1323*cdf0e10cSrcweir         } else if (type.equalsAscii("boolean")) {
1324*cdf0e10cSrcweir             bool b;
1325*cdf0e10cSrcweir             if (::sax::Converter::convertBool(b, text)) {
1326*cdf0e10cSrcweir                 any <<= b;
1327*cdf0e10cSrcweir             } else {
1328*cdf0e10cSrcweir                 DBG_WARNING1("SfxDocumentMetaData: invalid boolean: %s",
1329*cdf0e10cSrcweir                     OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1330*cdf0e10cSrcweir                 continue;
1331*cdf0e10cSrcweir             }
1332*cdf0e10cSrcweir         } else if (type.equalsAscii("string") || true) { // default
1333*cdf0e10cSrcweir             any <<= text;
1334*cdf0e10cSrcweir         }
1335*cdf0e10cSrcweir         try {
1336*cdf0e10cSrcweir             m_xUserDefined->addProperty(name,
1337*cdf0e10cSrcweir                 css::beans::PropertyAttribute::REMOVEABLE, any);
1338*cdf0e10cSrcweir         } catch (css::beans::PropertyExistException &) {
1339*cdf0e10cSrcweir             DBG_WARNING1("SfxDocumentMetaData: duplicate: %s",
1340*cdf0e10cSrcweir                     OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
1341*cdf0e10cSrcweir             // ignore; duplicate
1342*cdf0e10cSrcweir         } catch (css::beans::IllegalTypeException &) {
1343*cdf0e10cSrcweir             DBG_ERROR1("SfxDocumentMetaData: illegal type: %s",
1344*cdf0e10cSrcweir                     OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
1345*cdf0e10cSrcweir         } catch (css::lang::IllegalArgumentException &) {
1346*cdf0e10cSrcweir             DBG_ERROR1("SfxDocumentMetaData: illegal arg: %s",
1347*cdf0e10cSrcweir                     OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
1348*cdf0e10cSrcweir         }
1349*cdf0e10cSrcweir     }
1350*cdf0e10cSrcweir 
1351*cdf0e10cSrcweir     m_isModified = false;
1352*cdf0e10cSrcweir     m_isInitialized = true;
1353*cdf0e10cSrcweir }
1354*cdf0e10cSrcweir 
1355*cdf0e10cSrcweir 
1356*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
1357*cdf0e10cSrcweir 
1358*cdf0e10cSrcweir SfxDocumentMetaData::SfxDocumentMetaData(
1359*cdf0e10cSrcweir         css::uno::Reference< css::uno::XComponentContext > const & context)
1360*cdf0e10cSrcweir     : BaseMutex()
1361*cdf0e10cSrcweir     , SfxDocumentMetaData_Base(m_aMutex)
1362*cdf0e10cSrcweir     , m_xContext(context)
1363*cdf0e10cSrcweir     , m_NotifyListeners(m_aMutex)
1364*cdf0e10cSrcweir     , m_isInitialized(false)
1365*cdf0e10cSrcweir     , m_isModified(false)
1366*cdf0e10cSrcweir     , m_AutoloadSecs(0)
1367*cdf0e10cSrcweir {
1368*cdf0e10cSrcweir     DBG_ASSERT(context.is(), "SfxDocumentMetaData: context is null");
1369*cdf0e10cSrcweir     DBG_ASSERT(context->getServiceManager().is(),
1370*cdf0e10cSrcweir         "SfxDocumentMetaData: context has no service manager");
1371*cdf0e10cSrcweir     init(createDOM());
1372*cdf0e10cSrcweir }
1373*cdf0e10cSrcweir 
1374*cdf0e10cSrcweir // com.sun.star.uno.XServiceInfo:
1375*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1376*cdf0e10cSrcweir SfxDocumentMetaData::getImplementationName() throw (css::uno::RuntimeException)
1377*cdf0e10cSrcweir {
1378*cdf0e10cSrcweir     return comp_SfxDocumentMetaData::_getImplementationName();
1379*cdf0e10cSrcweir }
1380*cdf0e10cSrcweir 
1381*cdf0e10cSrcweir ::sal_Bool SAL_CALL
1382*cdf0e10cSrcweir SfxDocumentMetaData::supportsService(::rtl::OUString const & serviceName)
1383*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1384*cdf0e10cSrcweir {
1385*cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString > serviceNames =
1386*cdf0e10cSrcweir         comp_SfxDocumentMetaData::_getSupportedServiceNames();
1387*cdf0e10cSrcweir     for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
1388*cdf0e10cSrcweir         if (serviceNames[i] == serviceName)
1389*cdf0e10cSrcweir             return sal_True;
1390*cdf0e10cSrcweir     }
1391*cdf0e10cSrcweir     return sal_False;
1392*cdf0e10cSrcweir }
1393*cdf0e10cSrcweir 
1394*cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString > SAL_CALL
1395*cdf0e10cSrcweir SfxDocumentMetaData::getSupportedServiceNames()
1396*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1397*cdf0e10cSrcweir {
1398*cdf0e10cSrcweir     return comp_SfxDocumentMetaData::_getSupportedServiceNames();
1399*cdf0e10cSrcweir }
1400*cdf0e10cSrcweir 
1401*cdf0e10cSrcweir 
1402*cdf0e10cSrcweir // ::com::sun::star::lang::XComponent:
1403*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::dispose() throw (css::uno::RuntimeException)
1404*cdf0e10cSrcweir {
1405*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1406*cdf0e10cSrcweir     if (!m_isInitialized) {
1407*cdf0e10cSrcweir         return;
1408*cdf0e10cSrcweir     }
1409*cdf0e10cSrcweir     WeakComponentImplHelperBase::dispose(); // superclass
1410*cdf0e10cSrcweir     m_NotifyListeners.disposeAndClear(css::lang::EventObject(
1411*cdf0e10cSrcweir             static_cast< ::cppu::OWeakObject* >(this)));
1412*cdf0e10cSrcweir     m_isInitialized = false;
1413*cdf0e10cSrcweir     m_meta.clear();
1414*cdf0e10cSrcweir     m_metaList.clear();
1415*cdf0e10cSrcweir     m_xParent.clear();
1416*cdf0e10cSrcweir     m_xDoc.clear();
1417*cdf0e10cSrcweir     m_xUserDefined.clear();
1418*cdf0e10cSrcweir }
1419*cdf0e10cSrcweir 
1420*cdf0e10cSrcweir 
1421*cdf0e10cSrcweir // ::com::sun::star::document::XDocumentProperties:
1422*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1423*cdf0e10cSrcweir SfxDocumentMetaData::getAuthor() throw (css::uno::RuntimeException)
1424*cdf0e10cSrcweir {
1425*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1426*cdf0e10cSrcweir     return getMetaText("meta:initial-creator");
1427*cdf0e10cSrcweir }
1428*cdf0e10cSrcweir 
1429*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::setAuthor(const ::rtl::OUString & the_value)
1430*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1431*cdf0e10cSrcweir {
1432*cdf0e10cSrcweir     setMetaTextAndNotify("meta:initial-creator", the_value);
1433*cdf0e10cSrcweir }
1434*cdf0e10cSrcweir 
1435*cdf0e10cSrcweir 
1436*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1437*cdf0e10cSrcweir SfxDocumentMetaData::getGenerator() throw (css::uno::RuntimeException)
1438*cdf0e10cSrcweir {
1439*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1440*cdf0e10cSrcweir     return getMetaText("meta:generator");
1441*cdf0e10cSrcweir }
1442*cdf0e10cSrcweir 
1443*cdf0e10cSrcweir void SAL_CALL
1444*cdf0e10cSrcweir SfxDocumentMetaData::setGenerator(const ::rtl::OUString & the_value)
1445*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1446*cdf0e10cSrcweir {
1447*cdf0e10cSrcweir     setMetaTextAndNotify("meta:generator", the_value);
1448*cdf0e10cSrcweir }
1449*cdf0e10cSrcweir 
1450*cdf0e10cSrcweir css::util::DateTime SAL_CALL
1451*cdf0e10cSrcweir SfxDocumentMetaData::getCreationDate() throw (css::uno::RuntimeException)
1452*cdf0e10cSrcweir {
1453*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1454*cdf0e10cSrcweir     return textToDateTimeDefault(getMetaText("meta:creation-date"));
1455*cdf0e10cSrcweir }
1456*cdf0e10cSrcweir 
1457*cdf0e10cSrcweir void SAL_CALL
1458*cdf0e10cSrcweir SfxDocumentMetaData::setCreationDate(const css::util::DateTime & the_value)
1459*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1460*cdf0e10cSrcweir {
1461*cdf0e10cSrcweir     setMetaTextAndNotify("meta:creation-date", dateTimeToText(the_value));
1462*cdf0e10cSrcweir }
1463*cdf0e10cSrcweir 
1464*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1465*cdf0e10cSrcweir SfxDocumentMetaData::getTitle() throw (css::uno::RuntimeException)
1466*cdf0e10cSrcweir {
1467*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1468*cdf0e10cSrcweir     return getMetaText("dc:title");
1469*cdf0e10cSrcweir }
1470*cdf0e10cSrcweir 
1471*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::setTitle(const ::rtl::OUString & the_value)
1472*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1473*cdf0e10cSrcweir {
1474*cdf0e10cSrcweir     setMetaTextAndNotify("dc:title", the_value);
1475*cdf0e10cSrcweir }
1476*cdf0e10cSrcweir 
1477*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1478*cdf0e10cSrcweir SfxDocumentMetaData::getSubject() throw (css::uno::RuntimeException)
1479*cdf0e10cSrcweir {
1480*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1481*cdf0e10cSrcweir     return getMetaText("dc:subject");
1482*cdf0e10cSrcweir }
1483*cdf0e10cSrcweir 
1484*cdf0e10cSrcweir void SAL_CALL
1485*cdf0e10cSrcweir SfxDocumentMetaData::setSubject(const ::rtl::OUString & the_value)
1486*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1487*cdf0e10cSrcweir {
1488*cdf0e10cSrcweir     setMetaTextAndNotify("dc:subject", the_value);
1489*cdf0e10cSrcweir }
1490*cdf0e10cSrcweir 
1491*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1492*cdf0e10cSrcweir SfxDocumentMetaData::getDescription() throw (css::uno::RuntimeException)
1493*cdf0e10cSrcweir {
1494*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1495*cdf0e10cSrcweir     return getMetaText("dc:description");
1496*cdf0e10cSrcweir }
1497*cdf0e10cSrcweir 
1498*cdf0e10cSrcweir void SAL_CALL
1499*cdf0e10cSrcweir SfxDocumentMetaData::setDescription(const ::rtl::OUString & the_value)
1500*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1501*cdf0e10cSrcweir {
1502*cdf0e10cSrcweir     setMetaTextAndNotify("dc:description", the_value);
1503*cdf0e10cSrcweir }
1504*cdf0e10cSrcweir 
1505*cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString >
1506*cdf0e10cSrcweir SAL_CALL SfxDocumentMetaData::getKeywords() throw (css::uno::RuntimeException)
1507*cdf0e10cSrcweir {
1508*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1509*cdf0e10cSrcweir     return getMetaList("meta:keyword");
1510*cdf0e10cSrcweir }
1511*cdf0e10cSrcweir 
1512*cdf0e10cSrcweir void SAL_CALL
1513*cdf0e10cSrcweir SfxDocumentMetaData::setKeywords(
1514*cdf0e10cSrcweir         const css::uno::Sequence< ::rtl::OUString > & the_value)
1515*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1516*cdf0e10cSrcweir {
1517*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1518*cdf0e10cSrcweir     if (setMetaList("meta:keyword", the_value)) {
1519*cdf0e10cSrcweir         g.clear();
1520*cdf0e10cSrcweir         setModified(true);
1521*cdf0e10cSrcweir     }
1522*cdf0e10cSrcweir }
1523*cdf0e10cSrcweir 
1524*cdf0e10cSrcweir css::lang::Locale SAL_CALL
1525*cdf0e10cSrcweir         SfxDocumentMetaData::getLanguage() throw (css::uno::RuntimeException)
1526*cdf0e10cSrcweir {
1527*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1528*cdf0e10cSrcweir     css::lang::Locale loc;
1529*cdf0e10cSrcweir     ::rtl::OUString text = getMetaText("dc:language");
1530*cdf0e10cSrcweir     sal_Int32 ix = text.indexOf(static_cast<sal_Unicode> ('-'));
1531*cdf0e10cSrcweir     if (ix == -1) {
1532*cdf0e10cSrcweir         loc.Language = text;
1533*cdf0e10cSrcweir     } else {
1534*cdf0e10cSrcweir         loc.Language = text.copy(0, ix);
1535*cdf0e10cSrcweir         loc.Country = text.copy(ix+1);
1536*cdf0e10cSrcweir     }
1537*cdf0e10cSrcweir     return loc;
1538*cdf0e10cSrcweir }
1539*cdf0e10cSrcweir 
1540*cdf0e10cSrcweir void SAL_CALL
1541*cdf0e10cSrcweir SfxDocumentMetaData::setLanguage(const css::lang::Locale & the_value)
1542*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1543*cdf0e10cSrcweir {
1544*cdf0e10cSrcweir     ::rtl::OUString text = the_value.Language;
1545*cdf0e10cSrcweir     if (the_value.Country.getLength() > 0) {
1546*cdf0e10cSrcweir         text += ::rtl::OUString::createFromAscii("-").concat(the_value.Country);
1547*cdf0e10cSrcweir     }
1548*cdf0e10cSrcweir     setMetaTextAndNotify("dc:language", text);
1549*cdf0e10cSrcweir }
1550*cdf0e10cSrcweir 
1551*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1552*cdf0e10cSrcweir SfxDocumentMetaData::getModifiedBy() throw (css::uno::RuntimeException)
1553*cdf0e10cSrcweir {
1554*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1555*cdf0e10cSrcweir     return getMetaText("dc:creator");
1556*cdf0e10cSrcweir }
1557*cdf0e10cSrcweir 
1558*cdf0e10cSrcweir void SAL_CALL
1559*cdf0e10cSrcweir SfxDocumentMetaData::setModifiedBy(const ::rtl::OUString & the_value)
1560*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1561*cdf0e10cSrcweir {
1562*cdf0e10cSrcweir     setMetaTextAndNotify("dc:creator", the_value);
1563*cdf0e10cSrcweir }
1564*cdf0e10cSrcweir 
1565*cdf0e10cSrcweir css::util::DateTime SAL_CALL
1566*cdf0e10cSrcweir SfxDocumentMetaData::getModificationDate() throw (css::uno::RuntimeException)
1567*cdf0e10cSrcweir {
1568*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1569*cdf0e10cSrcweir     return textToDateTimeDefault(getMetaText("dc:date"));
1570*cdf0e10cSrcweir }
1571*cdf0e10cSrcweir 
1572*cdf0e10cSrcweir void SAL_CALL
1573*cdf0e10cSrcweir SfxDocumentMetaData::setModificationDate(const css::util::DateTime & the_value)
1574*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1575*cdf0e10cSrcweir {
1576*cdf0e10cSrcweir     setMetaTextAndNotify("dc:date", dateTimeToText(the_value));
1577*cdf0e10cSrcweir }
1578*cdf0e10cSrcweir 
1579*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1580*cdf0e10cSrcweir SfxDocumentMetaData::getPrintedBy() throw (css::uno::RuntimeException)
1581*cdf0e10cSrcweir {
1582*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1583*cdf0e10cSrcweir     return getMetaText("meta:printed-by");
1584*cdf0e10cSrcweir }
1585*cdf0e10cSrcweir 
1586*cdf0e10cSrcweir void SAL_CALL
1587*cdf0e10cSrcweir SfxDocumentMetaData::setPrintedBy(const ::rtl::OUString & the_value)
1588*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1589*cdf0e10cSrcweir {
1590*cdf0e10cSrcweir     setMetaTextAndNotify("meta:printed-by", the_value);
1591*cdf0e10cSrcweir }
1592*cdf0e10cSrcweir 
1593*cdf0e10cSrcweir css::util::DateTime SAL_CALL
1594*cdf0e10cSrcweir SfxDocumentMetaData::getPrintDate() throw (css::uno::RuntimeException)
1595*cdf0e10cSrcweir {
1596*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1597*cdf0e10cSrcweir     return textToDateTimeDefault(getMetaText("meta:print-date"));
1598*cdf0e10cSrcweir }
1599*cdf0e10cSrcweir 
1600*cdf0e10cSrcweir void SAL_CALL
1601*cdf0e10cSrcweir SfxDocumentMetaData::setPrintDate(const css::util::DateTime & the_value)
1602*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1603*cdf0e10cSrcweir {
1604*cdf0e10cSrcweir     setMetaTextAndNotify("meta:print-date", dateTimeToText(the_value));
1605*cdf0e10cSrcweir }
1606*cdf0e10cSrcweir 
1607*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1608*cdf0e10cSrcweir SfxDocumentMetaData::getTemplateName() throw (css::uno::RuntimeException)
1609*cdf0e10cSrcweir {
1610*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1611*cdf0e10cSrcweir     checkInit();
1612*cdf0e10cSrcweir     return m_TemplateName;
1613*cdf0e10cSrcweir }
1614*cdf0e10cSrcweir 
1615*cdf0e10cSrcweir void SAL_CALL
1616*cdf0e10cSrcweir SfxDocumentMetaData::setTemplateName(const ::rtl::OUString & the_value)
1617*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1618*cdf0e10cSrcweir {
1619*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1620*cdf0e10cSrcweir     checkInit();
1621*cdf0e10cSrcweir     if (m_TemplateName != the_value) {
1622*cdf0e10cSrcweir         m_TemplateName = the_value;
1623*cdf0e10cSrcweir         g.clear();
1624*cdf0e10cSrcweir         setModified(true);
1625*cdf0e10cSrcweir     }
1626*cdf0e10cSrcweir }
1627*cdf0e10cSrcweir 
1628*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1629*cdf0e10cSrcweir SfxDocumentMetaData::getTemplateURL() throw (css::uno::RuntimeException)
1630*cdf0e10cSrcweir {
1631*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1632*cdf0e10cSrcweir     checkInit();
1633*cdf0e10cSrcweir     return m_TemplateURL;
1634*cdf0e10cSrcweir }
1635*cdf0e10cSrcweir 
1636*cdf0e10cSrcweir void SAL_CALL
1637*cdf0e10cSrcweir SfxDocumentMetaData::setTemplateURL(const ::rtl::OUString & the_value)
1638*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1639*cdf0e10cSrcweir {
1640*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1641*cdf0e10cSrcweir     checkInit();
1642*cdf0e10cSrcweir     if (m_TemplateURL != the_value) {
1643*cdf0e10cSrcweir         m_TemplateURL = the_value;
1644*cdf0e10cSrcweir         g.clear();
1645*cdf0e10cSrcweir         setModified(true);
1646*cdf0e10cSrcweir     }
1647*cdf0e10cSrcweir }
1648*cdf0e10cSrcweir 
1649*cdf0e10cSrcweir css::util::DateTime SAL_CALL
1650*cdf0e10cSrcweir SfxDocumentMetaData::getTemplateDate() throw (css::uno::RuntimeException)
1651*cdf0e10cSrcweir {
1652*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1653*cdf0e10cSrcweir     checkInit();
1654*cdf0e10cSrcweir     return m_TemplateDate;
1655*cdf0e10cSrcweir }
1656*cdf0e10cSrcweir 
1657*cdf0e10cSrcweir void SAL_CALL
1658*cdf0e10cSrcweir SfxDocumentMetaData::setTemplateDate(const css::util::DateTime & the_value)
1659*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1660*cdf0e10cSrcweir {
1661*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1662*cdf0e10cSrcweir     checkInit();
1663*cdf0e10cSrcweir     if (!(m_TemplateDate == the_value)) {
1664*cdf0e10cSrcweir         m_TemplateDate = the_value;
1665*cdf0e10cSrcweir         g.clear();
1666*cdf0e10cSrcweir         setModified(true);
1667*cdf0e10cSrcweir     }
1668*cdf0e10cSrcweir }
1669*cdf0e10cSrcweir 
1670*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1671*cdf0e10cSrcweir SfxDocumentMetaData::getAutoloadURL() throw (css::uno::RuntimeException)
1672*cdf0e10cSrcweir {
1673*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1674*cdf0e10cSrcweir     checkInit();
1675*cdf0e10cSrcweir     return m_AutoloadURL;
1676*cdf0e10cSrcweir }
1677*cdf0e10cSrcweir 
1678*cdf0e10cSrcweir void SAL_CALL
1679*cdf0e10cSrcweir SfxDocumentMetaData::setAutoloadURL(const ::rtl::OUString & the_value)
1680*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1681*cdf0e10cSrcweir {
1682*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1683*cdf0e10cSrcweir     checkInit();
1684*cdf0e10cSrcweir     if (m_AutoloadURL != the_value) {
1685*cdf0e10cSrcweir         m_AutoloadURL = the_value;
1686*cdf0e10cSrcweir         g.clear();
1687*cdf0e10cSrcweir         setModified(true);
1688*cdf0e10cSrcweir     }
1689*cdf0e10cSrcweir }
1690*cdf0e10cSrcweir 
1691*cdf0e10cSrcweir ::sal_Int32 SAL_CALL
1692*cdf0e10cSrcweir SfxDocumentMetaData::getAutoloadSecs() throw (css::uno::RuntimeException)
1693*cdf0e10cSrcweir {
1694*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1695*cdf0e10cSrcweir     checkInit();
1696*cdf0e10cSrcweir     return m_AutoloadSecs;
1697*cdf0e10cSrcweir }
1698*cdf0e10cSrcweir 
1699*cdf0e10cSrcweir void SAL_CALL
1700*cdf0e10cSrcweir SfxDocumentMetaData::setAutoloadSecs(::sal_Int32 the_value)
1701*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
1702*cdf0e10cSrcweir {
1703*cdf0e10cSrcweir     if (the_value < 0) throw css::lang::IllegalArgumentException(
1704*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(
1705*cdf0e10cSrcweir             "SfxDocumentMetaData::setAutoloadSecs: argument is negative"),
1706*cdf0e10cSrcweir             *this, 0);
1707*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1708*cdf0e10cSrcweir     checkInit();
1709*cdf0e10cSrcweir     if (m_AutoloadSecs != the_value) {
1710*cdf0e10cSrcweir         m_AutoloadSecs = the_value;
1711*cdf0e10cSrcweir         g.clear();
1712*cdf0e10cSrcweir         setModified(true);
1713*cdf0e10cSrcweir     }
1714*cdf0e10cSrcweir }
1715*cdf0e10cSrcweir 
1716*cdf0e10cSrcweir ::rtl::OUString SAL_CALL
1717*cdf0e10cSrcweir SfxDocumentMetaData::getDefaultTarget() throw (css::uno::RuntimeException)
1718*cdf0e10cSrcweir {
1719*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1720*cdf0e10cSrcweir     checkInit();
1721*cdf0e10cSrcweir     return m_DefaultTarget;
1722*cdf0e10cSrcweir }
1723*cdf0e10cSrcweir 
1724*cdf0e10cSrcweir void SAL_CALL
1725*cdf0e10cSrcweir SfxDocumentMetaData::setDefaultTarget(const ::rtl::OUString & the_value)
1726*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1727*cdf0e10cSrcweir {
1728*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1729*cdf0e10cSrcweir     checkInit();
1730*cdf0e10cSrcweir     if (m_DefaultTarget != the_value) {
1731*cdf0e10cSrcweir         m_DefaultTarget = the_value;
1732*cdf0e10cSrcweir         g.clear();
1733*cdf0e10cSrcweir         setModified(true);
1734*cdf0e10cSrcweir     }
1735*cdf0e10cSrcweir }
1736*cdf0e10cSrcweir 
1737*cdf0e10cSrcweir css::uno::Sequence< css::beans::NamedValue > SAL_CALL
1738*cdf0e10cSrcweir SfxDocumentMetaData::getDocumentStatistics() throw (css::uno::RuntimeException)
1739*cdf0e10cSrcweir {
1740*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1741*cdf0e10cSrcweir     checkInit();
1742*cdf0e10cSrcweir     ::comphelper::SequenceAsVector<css::beans::NamedValue> stats;
1743*cdf0e10cSrcweir     for (size_t i = 0; s_stdStats[i] != 0; ++i) {
1744*cdf0e10cSrcweir         const char * aName = s_stdStatAttrs[i];
1745*cdf0e10cSrcweir         ::rtl::OUString text = getMetaAttr("meta:document-statistic", aName);
1746*cdf0e10cSrcweir         if (text.equalsAscii("")) continue;
1747*cdf0e10cSrcweir         css::beans::NamedValue stat;
1748*cdf0e10cSrcweir         stat.Name = ::rtl::OUString::createFromAscii(s_stdStats[i]);
1749*cdf0e10cSrcweir         sal_Int32 val;
1750*cdf0e10cSrcweir         css::uno::Any any;
1751*cdf0e10cSrcweir         if (!::sax::Converter::convertNumber(val, text, 0,
1752*cdf0e10cSrcweir                 std::numeric_limits<sal_Int32>::max()) || (val < 0)) {
1753*cdf0e10cSrcweir             val = 0;
1754*cdf0e10cSrcweir             DBG_WARNING1("SfxDocumentMetaData: invalid number: %s",
1755*cdf0e10cSrcweir                 OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1756*cdf0e10cSrcweir         }
1757*cdf0e10cSrcweir         any <<= val;
1758*cdf0e10cSrcweir         stat.Value = any;
1759*cdf0e10cSrcweir         stats.push_back(stat);
1760*cdf0e10cSrcweir     }
1761*cdf0e10cSrcweir 
1762*cdf0e10cSrcweir     return stats.getAsConstList();
1763*cdf0e10cSrcweir }
1764*cdf0e10cSrcweir 
1765*cdf0e10cSrcweir void SAL_CALL
1766*cdf0e10cSrcweir SfxDocumentMetaData::setDocumentStatistics(
1767*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::NamedValue > & the_value)
1768*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1769*cdf0e10cSrcweir {
1770*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1771*cdf0e10cSrcweir     checkInit();
1772*cdf0e10cSrcweir     std::vector<std::pair<const char *, ::rtl::OUString> > attributes;
1773*cdf0e10cSrcweir     for (sal_Int32 i = 0; i < the_value.getLength(); ++i) {
1774*cdf0e10cSrcweir         const ::rtl::OUString name = the_value[i].Name;
1775*cdf0e10cSrcweir         // inefficently search for matching attribute
1776*cdf0e10cSrcweir         for (size_t j = 0; s_stdStats[j] != 0; ++j) {
1777*cdf0e10cSrcweir             if (name.equalsAscii(s_stdStats[j])) {
1778*cdf0e10cSrcweir                 const css::uno::Any any = the_value[i].Value;
1779*cdf0e10cSrcweir                 sal_Int32 val = 0;
1780*cdf0e10cSrcweir                 if (any >>= val) {
1781*cdf0e10cSrcweir                     ::rtl::OUStringBuffer buf;
1782*cdf0e10cSrcweir                     ::sax::Converter::convertNumber(buf, val);
1783*cdf0e10cSrcweir                     attributes.push_back(std::make_pair(s_stdStatAttrs[j],
1784*cdf0e10cSrcweir                                 buf.makeStringAndClear()));
1785*cdf0e10cSrcweir                 } else {
1786*cdf0e10cSrcweir                     DBG_WARNING1("SfxDocumentMetaData: invalid statistic: %s",
1787*cdf0e10cSrcweir                         OUStringToOString(name, RTL_TEXTENCODING_UTF8)
1788*cdf0e10cSrcweir                             .getStr());
1789*cdf0e10cSrcweir                 }
1790*cdf0e10cSrcweir                 break;
1791*cdf0e10cSrcweir             }
1792*cdf0e10cSrcweir         }
1793*cdf0e10cSrcweir     }
1794*cdf0e10cSrcweir     updateElement("meta:document-statistic", &attributes);
1795*cdf0e10cSrcweir     g.clear();
1796*cdf0e10cSrcweir     setModified(true);
1797*cdf0e10cSrcweir }
1798*cdf0e10cSrcweir 
1799*cdf0e10cSrcweir ::sal_Int16 SAL_CALL
1800*cdf0e10cSrcweir SfxDocumentMetaData::getEditingCycles() throw (css::uno::RuntimeException)
1801*cdf0e10cSrcweir {
1802*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1803*cdf0e10cSrcweir     ::rtl::OUString text = getMetaText("meta:editing-cycles");
1804*cdf0e10cSrcweir     sal_Int32 ret;
1805*cdf0e10cSrcweir     if (::sax::Converter::convertNumber(ret, text,
1806*cdf0e10cSrcweir             0, std::numeric_limits<sal_Int16>::max())) {
1807*cdf0e10cSrcweir         return static_cast<sal_Int16>(ret);
1808*cdf0e10cSrcweir     } else {
1809*cdf0e10cSrcweir         return 0;
1810*cdf0e10cSrcweir     }
1811*cdf0e10cSrcweir }
1812*cdf0e10cSrcweir 
1813*cdf0e10cSrcweir void SAL_CALL
1814*cdf0e10cSrcweir SfxDocumentMetaData::setEditingCycles(::sal_Int16 the_value)
1815*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
1816*cdf0e10cSrcweir {
1817*cdf0e10cSrcweir     if (the_value < 0) throw css::lang::IllegalArgumentException(
1818*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(
1819*cdf0e10cSrcweir                 "SfxDocumentMetaData::setEditingCycles: argument is negative"),
1820*cdf0e10cSrcweir                 *this, 0);
1821*cdf0e10cSrcweir     ::rtl::OUStringBuffer buf;
1822*cdf0e10cSrcweir     ::sax::Converter::convertNumber(buf, the_value);
1823*cdf0e10cSrcweir     setMetaTextAndNotify("meta:editing-cycles", buf.makeStringAndClear());
1824*cdf0e10cSrcweir }
1825*cdf0e10cSrcweir 
1826*cdf0e10cSrcweir ::sal_Int32 SAL_CALL
1827*cdf0e10cSrcweir SfxDocumentMetaData::getEditingDuration() throw (css::uno::RuntimeException)
1828*cdf0e10cSrcweir {
1829*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1830*cdf0e10cSrcweir     return textToDuration(getMetaText("meta:editing-duration"));
1831*cdf0e10cSrcweir }
1832*cdf0e10cSrcweir 
1833*cdf0e10cSrcweir void SAL_CALL
1834*cdf0e10cSrcweir SfxDocumentMetaData::setEditingDuration(::sal_Int32 the_value)
1835*cdf0e10cSrcweir         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
1836*cdf0e10cSrcweir {
1837*cdf0e10cSrcweir     if (the_value < 0) throw css::lang::IllegalArgumentException(
1838*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii(
1839*cdf0e10cSrcweir             "SfxDocumentMetaData::setEditingDuration: argument is negative"),
1840*cdf0e10cSrcweir             *this, 0);
1841*cdf0e10cSrcweir     setMetaTextAndNotify("meta:editing-duration", durationToText(the_value));
1842*cdf0e10cSrcweir }
1843*cdf0e10cSrcweir 
1844*cdf0e10cSrcweir void SAL_CALL
1845*cdf0e10cSrcweir SfxDocumentMetaData::resetUserData(const ::rtl::OUString & the_value)
1846*cdf0e10cSrcweir     throw (css::uno::RuntimeException)
1847*cdf0e10cSrcweir {
1848*cdf0e10cSrcweir     ::osl::ClearableMutexGuard g(m_aMutex);
1849*cdf0e10cSrcweir 
1850*cdf0e10cSrcweir     bool bModified( false );
1851*cdf0e10cSrcweir     bModified |= setMetaText("meta:initial-creator", the_value);
1852*cdf0e10cSrcweir     ::DateTime now = DateTime();
1853*cdf0e10cSrcweir     css::util::DateTime uDT(now.Get100Sec(), now.GetSec(), now.GetMin(),
1854*cdf0e10cSrcweir         now.GetHour(), now.GetDay(), now.GetMonth(), now.GetYear());
1855*cdf0e10cSrcweir     bModified |= setMetaText("meta:creation-date", dateTimeToText(uDT));
1856*cdf0e10cSrcweir     bModified |= setMetaText("dc:creator", ::rtl::OUString());
1857*cdf0e10cSrcweir     bModified |= setMetaText("meta:printed-by", ::rtl::OUString());
1858*cdf0e10cSrcweir     bModified |= setMetaText("dc:date", dateTimeToText(css::util::DateTime()));
1859*cdf0e10cSrcweir     bModified |= setMetaText("meta:print-date",
1860*cdf0e10cSrcweir         dateTimeToText(css::util::DateTime()));
1861*cdf0e10cSrcweir     bModified |= setMetaText("meta:editing-duration", durationToText(0));
1862*cdf0e10cSrcweir     bModified |= setMetaText("meta:editing-cycles",
1863*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("1"));
1864*cdf0e10cSrcweir 
1865*cdf0e10cSrcweir     if (bModified) {
1866*cdf0e10cSrcweir         g.clear();
1867*cdf0e10cSrcweir         setModified(true);
1868*cdf0e10cSrcweir     }
1869*cdf0e10cSrcweir }
1870*cdf0e10cSrcweir 
1871*cdf0e10cSrcweir 
1872*cdf0e10cSrcweir css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
1873*cdf0e10cSrcweir SfxDocumentMetaData::getUserDefinedProperties()
1874*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
1875*cdf0e10cSrcweir {
1876*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1877*cdf0e10cSrcweir     checkInit();
1878*cdf0e10cSrcweir     createUserDefined();
1879*cdf0e10cSrcweir     return m_xUserDefined;
1880*cdf0e10cSrcweir }
1881*cdf0e10cSrcweir 
1882*cdf0e10cSrcweir 
1883*cdf0e10cSrcweir void SAL_CALL
1884*cdf0e10cSrcweir SfxDocumentMetaData::loadFromStorage(
1885*cdf0e10cSrcweir         const css::uno::Reference< css::embed::XStorage > & xStorage,
1886*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::PropertyValue > & Medium)
1887*cdf0e10cSrcweir     throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
1888*cdf0e10cSrcweir            css::io::WrongFormatException,
1889*cdf0e10cSrcweir            css::lang::WrappedTargetException, css::io::IOException)
1890*cdf0e10cSrcweir {
1891*cdf0e10cSrcweir     if (!xStorage.is()) throw css::lang::IllegalArgumentException(
1892*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("SfxDocumentMetaData::loadFromStorage:"
1893*cdf0e10cSrcweir                 " argument is null"), *this, 0);
1894*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1895*cdf0e10cSrcweir 
1896*cdf0e10cSrcweir     // open meta data file
1897*cdf0e10cSrcweir     css::uno::Reference<css::io::XStream> xStream(
1898*cdf0e10cSrcweir         xStorage->openStreamElement(
1899*cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(s_metaXml),
1900*cdf0e10cSrcweir             css::embed::ElementModes::READ) );
1901*cdf0e10cSrcweir     if (!xStream.is()) throw css::uno::RuntimeException();
1902*cdf0e10cSrcweir     css::uno::Reference<css::io::XInputStream> xInStream =
1903*cdf0e10cSrcweir         xStream->getInputStream();
1904*cdf0e10cSrcweir     if (!xInStream.is()) throw css::uno::RuntimeException();
1905*cdf0e10cSrcweir 
1906*cdf0e10cSrcweir     // create DOM parser service
1907*cdf0e10cSrcweir     css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1908*cdf0e10cSrcweir         m_xContext->getServiceManager());
1909*cdf0e10cSrcweir     css::uno::Reference<css::xml::sax::XParser> xParser (
1910*cdf0e10cSrcweir         xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
1911*cdf0e10cSrcweir                 "com.sun.star.xml.sax.Parser"), m_xContext),
1912*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
1913*cdf0e10cSrcweir     if (!xParser.is()) throw css::uno::RuntimeException(
1914*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("SfxDocumentMetaData::loadFromStorage:"
1915*cdf0e10cSrcweir                 " cannot create Parser service"), *this);
1916*cdf0e10cSrcweir     css::xml::sax::InputSource input;
1917*cdf0e10cSrcweir     input.aInputStream = xInStream;
1918*cdf0e10cSrcweir 
1919*cdf0e10cSrcweir     sal_uInt64 version = SotStorage::GetVersion( xStorage );
1920*cdf0e10cSrcweir     // Oasis is also the default (0)
1921*cdf0e10cSrcweir     sal_Bool bOasis = ( version > SOFFICE_FILEFORMAT_60 || version == 0 );
1922*cdf0e10cSrcweir     const sal_Char *pServiceName = bOasis
1923*cdf0e10cSrcweir         ? "com.sun.star.document.XMLOasisMetaImporter"
1924*cdf0e10cSrcweir         : "com.sun.star.document.XMLMetaImporter";
1925*cdf0e10cSrcweir 
1926*cdf0e10cSrcweir     // set base URL
1927*cdf0e10cSrcweir     css::uno::Reference<css::beans::XPropertySet> xPropArg =
1928*cdf0e10cSrcweir         getURLProperties(Medium);
1929*cdf0e10cSrcweir     try {
1930*cdf0e10cSrcweir         xPropArg->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI")))
1931*cdf0e10cSrcweir             >>= input.sSystemId;
1932*cdf0e10cSrcweir         input.sSystemId += ::rtl::OUString::createFromAscii("/").concat(
1933*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(s_metaXml));
1934*cdf0e10cSrcweir     } catch (css::uno::Exception &) {
1935*cdf0e10cSrcweir         input.sSystemId = ::rtl::OUString::createFromAscii(s_metaXml);
1936*cdf0e10cSrcweir     }
1937*cdf0e10cSrcweir     css::uno::Sequence< css::uno::Any > args(1);
1938*cdf0e10cSrcweir     args[0] <<= xPropArg;
1939*cdf0e10cSrcweir 
1940*cdf0e10cSrcweir     css::uno::Reference<css::xml::sax::XDocumentHandler> xDocHandler (
1941*cdf0e10cSrcweir         xMsf->createInstanceWithArgumentsAndContext(
1942*cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(pServiceName), args, m_xContext),
1943*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
1944*cdf0e10cSrcweir     if (!xDocHandler.is()) throw css::uno::RuntimeException(
1945*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("SfxDocumentMetaData::loadFromStorage:"
1946*cdf0e10cSrcweir                 " cannot create XMLOasisMetaImporter service"), *this);
1947*cdf0e10cSrcweir     css::uno::Reference<css::document::XImporter> xImp (xDocHandler,
1948*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
1949*cdf0e10cSrcweir     xImp->setTargetDocument(css::uno::Reference<css::lang::XComponent>(this));
1950*cdf0e10cSrcweir     xParser->setDocumentHandler(xDocHandler);
1951*cdf0e10cSrcweir     try {
1952*cdf0e10cSrcweir         xParser->parseStream(input);
1953*cdf0e10cSrcweir     } catch (css::xml::sax::SAXException &) {
1954*cdf0e10cSrcweir         throw css::io::WrongFormatException(::rtl::OUString::createFromAscii(
1955*cdf0e10cSrcweir                 "SfxDocumentMetaData::loadFromStorage:"
1956*cdf0e10cSrcweir                 " XML parsing exception"), *this);
1957*cdf0e10cSrcweir     }
1958*cdf0e10cSrcweir     // NB: the implementation of XMLOasisMetaImporter calls initialize
1959*cdf0e10cSrcweir //    init(xDocBuilder->getDocument());
1960*cdf0e10cSrcweir     checkInit();
1961*cdf0e10cSrcweir }
1962*cdf0e10cSrcweir 
1963*cdf0e10cSrcweir void SAL_CALL
1964*cdf0e10cSrcweir SfxDocumentMetaData::storeToStorage(
1965*cdf0e10cSrcweir         const css::uno::Reference< css::embed::XStorage > & xStorage,
1966*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::PropertyValue > & Medium)
1967*cdf0e10cSrcweir     throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
1968*cdf0e10cSrcweir            css::lang::WrappedTargetException, css::io::IOException)
1969*cdf0e10cSrcweir {
1970*cdf0e10cSrcweir     if (!xStorage.is()) throw css::lang::IllegalArgumentException(
1971*cdf0e10cSrcweir         ::rtl::OUString::createFromAscii("SfxDocumentMetaData::storeToStorage:"
1972*cdf0e10cSrcweir                 " argument is null"), *this, 0);
1973*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
1974*cdf0e10cSrcweir     checkInit();
1975*cdf0e10cSrcweir 
1976*cdf0e10cSrcweir     // update user-defined meta data in DOM tree
1977*cdf0e10cSrcweir //    updateUserDefinedAndAttributes(); // this will be done in serialize!
1978*cdf0e10cSrcweir 
1979*cdf0e10cSrcweir     // write into storage
1980*cdf0e10cSrcweir     css::uno::Reference<css::io::XStream> xStream =
1981*cdf0e10cSrcweir         xStorage->openStreamElement(::rtl::OUString::createFromAscii(s_metaXml),
1982*cdf0e10cSrcweir             css::embed::ElementModes::WRITE
1983*cdf0e10cSrcweir             | css::embed::ElementModes::TRUNCATE);
1984*cdf0e10cSrcweir     if (!xStream.is()) throw css::uno::RuntimeException();
1985*cdf0e10cSrcweir     css::uno::Reference< css::beans::XPropertySet > xStreamProps(xStream,
1986*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
1987*cdf0e10cSrcweir     xStreamProps->setPropertyValue(
1988*cdf0e10cSrcweir         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MediaType")),
1989*cdf0e10cSrcweir         css::uno::makeAny(::rtl::OUString::createFromAscii("text/xml")));
1990*cdf0e10cSrcweir     xStreamProps->setPropertyValue(
1991*cdf0e10cSrcweir         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Compressed")),
1992*cdf0e10cSrcweir         css::uno::makeAny(static_cast<sal_Bool> (sal_False)));
1993*cdf0e10cSrcweir     xStreamProps->setPropertyValue(
1994*cdf0e10cSrcweir         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption")),
1995*cdf0e10cSrcweir         css::uno::makeAny(static_cast<sal_Bool> (sal_False)));
1996*cdf0e10cSrcweir     css::uno::Reference<css::io::XOutputStream> xOutStream =
1997*cdf0e10cSrcweir         xStream->getOutputStream();
1998*cdf0e10cSrcweir     if (!xOutStream.is()) throw css::uno::RuntimeException();
1999*cdf0e10cSrcweir     css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
2000*cdf0e10cSrcweir         m_xContext->getServiceManager());
2001*cdf0e10cSrcweir     css::uno::Reference<css::io::XActiveDataSource> xSaxWriter(
2002*cdf0e10cSrcweir         xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
2003*cdf0e10cSrcweir                 "com.sun.star.xml.sax.Writer"), m_xContext),
2004*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
2005*cdf0e10cSrcweir     xSaxWriter->setOutputStream(xOutStream);
2006*cdf0e10cSrcweir     css::uno::Reference<css::xml::sax::XDocumentHandler> xDocHandler (
2007*cdf0e10cSrcweir         xSaxWriter, css::uno::UNO_QUERY_THROW);
2008*cdf0e10cSrcweir 
2009*cdf0e10cSrcweir     const sal_uInt64 version = SotStorage::GetVersion( xStorage );
2010*cdf0e10cSrcweir     // Oasis is also the default (0)
2011*cdf0e10cSrcweir     const sal_Bool bOasis = ( version > SOFFICE_FILEFORMAT_60 || version == 0 );
2012*cdf0e10cSrcweir     const sal_Char *pServiceName = bOasis
2013*cdf0e10cSrcweir         ? "com.sun.star.document.XMLOasisMetaExporter"
2014*cdf0e10cSrcweir         : "com.sun.star.document.XMLMetaExporter";
2015*cdf0e10cSrcweir 
2016*cdf0e10cSrcweir     // set base URL
2017*cdf0e10cSrcweir     css::uno::Reference<css::beans::XPropertySet> xPropArg =
2018*cdf0e10cSrcweir         getURLProperties(Medium);
2019*cdf0e10cSrcweir     css::uno::Sequence< css::uno::Any > args(2);
2020*cdf0e10cSrcweir     args[0] <<= xDocHandler;
2021*cdf0e10cSrcweir     args[1] <<= xPropArg;
2022*cdf0e10cSrcweir 
2023*cdf0e10cSrcweir     css::uno::Reference<css::document::XExporter> xExp(
2024*cdf0e10cSrcweir         xMsf->createInstanceWithArgumentsAndContext(
2025*cdf0e10cSrcweir             ::rtl::OUString::createFromAscii(pServiceName), args, m_xContext),
2026*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
2027*cdf0e10cSrcweir     xExp->setSourceDocument(css::uno::Reference<css::lang::XComponent>(this));
2028*cdf0e10cSrcweir     css::uno::Reference<css::document::XFilter> xFilter(xExp,
2029*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
2030*cdf0e10cSrcweir     if (xFilter->filter(css::uno::Sequence< css::beans::PropertyValue >())) {
2031*cdf0e10cSrcweir         css::uno::Reference<css::embed::XTransactedObject> xTransaction(
2032*cdf0e10cSrcweir             xStorage, css::uno::UNO_QUERY);
2033*cdf0e10cSrcweir         if (xTransaction.is()) {
2034*cdf0e10cSrcweir             xTransaction->commit();
2035*cdf0e10cSrcweir         }
2036*cdf0e10cSrcweir     } else {
2037*cdf0e10cSrcweir         throw css::io::IOException(::rtl::OUString::createFromAscii(
2038*cdf0e10cSrcweir                 "SfxDocumentMetaData::storeToStorage: cannot filter"), *this);
2039*cdf0e10cSrcweir     }
2040*cdf0e10cSrcweir }
2041*cdf0e10cSrcweir 
2042*cdf0e10cSrcweir void SAL_CALL
2043*cdf0e10cSrcweir SfxDocumentMetaData::loadFromMedium(const ::rtl::OUString & URL,
2044*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::PropertyValue > & Medium)
2045*cdf0e10cSrcweir     throw (css::uno::RuntimeException, css::io::WrongFormatException,
2046*cdf0e10cSrcweir            css::lang::WrappedTargetException, css::io::IOException)
2047*cdf0e10cSrcweir {
2048*cdf0e10cSrcweir     css::uno::Reference<css::io::XInputStream> xIn;
2049*cdf0e10cSrcweir     ::comphelper::MediaDescriptor md(Medium);
2050*cdf0e10cSrcweir     // if we have an URL parameter, it replaces the one in the media descriptor
2051*cdf0e10cSrcweir     if (!URL.equalsAscii("")) {
2052*cdf0e10cSrcweir         md[ ::comphelper::MediaDescriptor::PROP_URL() ] <<= URL;
2053*cdf0e10cSrcweir     }
2054*cdf0e10cSrcweir     if (sal_True == md.addInputStream()) {
2055*cdf0e10cSrcweir         md[ ::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] >>= xIn;
2056*cdf0e10cSrcweir     }
2057*cdf0e10cSrcweir     css::uno::Reference<css::embed::XStorage> xStorage;
2058*cdf0e10cSrcweir     css::uno::Reference<css::lang::XMultiServiceFactory> xMsf (
2059*cdf0e10cSrcweir         m_xContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
2060*cdf0e10cSrcweir     try {
2061*cdf0e10cSrcweir         if (xIn.is()) {
2062*cdf0e10cSrcweir             xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream(
2063*cdf0e10cSrcweir                             xIn, xMsf);
2064*cdf0e10cSrcweir         } else { // fallback to url parameter
2065*cdf0e10cSrcweir             xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
2066*cdf0e10cSrcweir                             URL, css::embed::ElementModes::READ, xMsf);
2067*cdf0e10cSrcweir         }
2068*cdf0e10cSrcweir     } catch (css::uno::RuntimeException &) {
2069*cdf0e10cSrcweir         throw;
2070*cdf0e10cSrcweir     } catch (css::io::IOException &) {
2071*cdf0e10cSrcweir         throw;
2072*cdf0e10cSrcweir     } catch (css::uno::Exception & e) {
2073*cdf0e10cSrcweir         throw css::lang::WrappedTargetException(
2074*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
2075*cdf0e10cSrcweir                     "SfxDocumentMetaData::loadFromMedium: exception"),
2076*cdf0e10cSrcweir                 css::uno::Reference<css::uno::XInterface>(*this),
2077*cdf0e10cSrcweir                 css::uno::makeAny(e));
2078*cdf0e10cSrcweir     }
2079*cdf0e10cSrcweir     if (!xStorage.is()) {
2080*cdf0e10cSrcweir         throw css::uno::RuntimeException(::rtl::OUString::createFromAscii(
2081*cdf0e10cSrcweir                 "SfxDocumentMetaData::loadFromMedium: cannot get Storage"),
2082*cdf0e10cSrcweir                 *this);
2083*cdf0e10cSrcweir     }
2084*cdf0e10cSrcweir     loadFromStorage(xStorage, md.getAsConstPropertyValueList());
2085*cdf0e10cSrcweir }
2086*cdf0e10cSrcweir 
2087*cdf0e10cSrcweir void SAL_CALL
2088*cdf0e10cSrcweir SfxDocumentMetaData::storeToMedium(const ::rtl::OUString & URL,
2089*cdf0e10cSrcweir         const css::uno::Sequence< css::beans::PropertyValue > & Medium)
2090*cdf0e10cSrcweir     throw (css::uno::RuntimeException,
2091*cdf0e10cSrcweir            css::lang::WrappedTargetException, css::io::IOException)
2092*cdf0e10cSrcweir {
2093*cdf0e10cSrcweir     ::comphelper::MediaDescriptor md(Medium);
2094*cdf0e10cSrcweir     if (!URL.equalsAscii("")) {
2095*cdf0e10cSrcweir         md[ ::comphelper::MediaDescriptor::PROP_URL() ] <<= URL;
2096*cdf0e10cSrcweir     }
2097*cdf0e10cSrcweir     SfxMedium aMedium(md.getAsConstPropertyValueList());
2098*cdf0e10cSrcweir     css::uno::Reference<css::embed::XStorage> xStorage
2099*cdf0e10cSrcweir         = aMedium.GetOutputStorage();
2100*cdf0e10cSrcweir 
2101*cdf0e10cSrcweir 
2102*cdf0e10cSrcweir     if (!xStorage.is()) {
2103*cdf0e10cSrcweir         throw css::uno::RuntimeException(::rtl::OUString::createFromAscii(
2104*cdf0e10cSrcweir                 "SfxDocumentMetaData::storeToMedium: cannot get Storage"),
2105*cdf0e10cSrcweir                 *this);
2106*cdf0e10cSrcweir     }
2107*cdf0e10cSrcweir     // set MIME type of the storage
2108*cdf0e10cSrcweir     ::comphelper::MediaDescriptor::const_iterator iter
2109*cdf0e10cSrcweir         = md.find(::comphelper::MediaDescriptor::PROP_MEDIATYPE());
2110*cdf0e10cSrcweir     if (iter != md.end()) {
2111*cdf0e10cSrcweir         css::uno::Reference< css::beans::XPropertySet > xProps(xStorage,
2112*cdf0e10cSrcweir             css::uno::UNO_QUERY_THROW);
2113*cdf0e10cSrcweir         xProps->setPropertyValue(
2114*cdf0e10cSrcweir             ::comphelper::MediaDescriptor::PROP_MEDIATYPE(),
2115*cdf0e10cSrcweir             iter->second);
2116*cdf0e10cSrcweir     }
2117*cdf0e10cSrcweir     storeToStorage(xStorage, md.getAsConstPropertyValueList());
2118*cdf0e10cSrcweir 
2119*cdf0e10cSrcweir 
2120*cdf0e10cSrcweir     const sal_Bool bOk = aMedium.Commit();
2121*cdf0e10cSrcweir     aMedium.Close();
2122*cdf0e10cSrcweir     if ( !bOk ) {
2123*cdf0e10cSrcweir         sal_uInt32 nError = aMedium.GetError();
2124*cdf0e10cSrcweir         if ( nError == ERRCODE_NONE ) {
2125*cdf0e10cSrcweir             nError = ERRCODE_IO_GENERAL;
2126*cdf0e10cSrcweir         }
2127*cdf0e10cSrcweir 
2128*cdf0e10cSrcweir         throw css::task::ErrorCodeIOException( ::rtl::OUString(),
2129*cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >(), nError);
2130*cdf0e10cSrcweir 
2131*cdf0e10cSrcweir     }
2132*cdf0e10cSrcweir }
2133*cdf0e10cSrcweir 
2134*cdf0e10cSrcweir // ::com::sun::star::lang::XInitialization:
2135*cdf0e10cSrcweir void SAL_CALL
2136*cdf0e10cSrcweir SfxDocumentMetaData::initialize(
2137*cdf0e10cSrcweir         const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments)
2138*cdf0e10cSrcweir     throw (css::uno::RuntimeException, css::uno::Exception)
2139*cdf0e10cSrcweir {
2140*cdf0e10cSrcweir     // possible arguments:
2141*cdf0e10cSrcweir     // - no argument: default initialization (empty DOM)
2142*cdf0e10cSrcweir     // - 1 argument, XDocument: initialize with given DOM and empty base URL
2143*cdf0e10cSrcweir     // NB: links in document must be absolute
2144*cdf0e10cSrcweir 
2145*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
2146*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XDocument> xDoc;
2147*cdf0e10cSrcweir 
2148*cdf0e10cSrcweir     for (sal_Int32 i = 0; i < aArguments.getLength(); ++i) {
2149*cdf0e10cSrcweir         const css::uno::Any any = aArguments[i];
2150*cdf0e10cSrcweir         if (any >>= xDoc) {
2151*cdf0e10cSrcweir             if (!xDoc.is()) {
2152*cdf0e10cSrcweir                 throw css::lang::IllegalArgumentException(
2153*cdf0e10cSrcweir                     ::rtl::OUString::createFromAscii("SfxDocumentMetaData::"
2154*cdf0e10cSrcweir                         "initialize: argument is null"),
2155*cdf0e10cSrcweir                     *this, static_cast<sal_Int16>(i));
2156*cdf0e10cSrcweir             }
2157*cdf0e10cSrcweir         } else {
2158*cdf0e10cSrcweir             throw css::lang::IllegalArgumentException(
2159*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::"
2160*cdf0e10cSrcweir                     "initialize: argument must be XDocument"),
2161*cdf0e10cSrcweir                 *this, static_cast<sal_Int16>(i));
2162*cdf0e10cSrcweir         }
2163*cdf0e10cSrcweir     }
2164*cdf0e10cSrcweir 
2165*cdf0e10cSrcweir     if (!xDoc.is()) {
2166*cdf0e10cSrcweir         // For a new document, we create a new DOM tree here.
2167*cdf0e10cSrcweir         xDoc = createDOM();
2168*cdf0e10cSrcweir     }
2169*cdf0e10cSrcweir 
2170*cdf0e10cSrcweir     init(xDoc);
2171*cdf0e10cSrcweir }
2172*cdf0e10cSrcweir 
2173*cdf0e10cSrcweir // ::com::sun::star::util::XCloneable:
2174*cdf0e10cSrcweir css::uno::Reference<css::util::XCloneable> SAL_CALL
2175*cdf0e10cSrcweir SfxDocumentMetaData::createClone()
2176*cdf0e10cSrcweir     throw (css::uno::RuntimeException)
2177*cdf0e10cSrcweir {
2178*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
2179*cdf0e10cSrcweir     checkInit();
2180*cdf0e10cSrcweir 
2181*cdf0e10cSrcweir     SfxDocumentMetaData *pNew = new SfxDocumentMetaData(m_xContext);
2182*cdf0e10cSrcweir 
2183*cdf0e10cSrcweir     // NB: do not copy the modification listeners, only DOM
2184*cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XDocument> xDoc = createDOM();
2185*cdf0e10cSrcweir     try {
2186*cdf0e10cSrcweir         updateUserDefinedAndAttributes();
2187*cdf0e10cSrcweir         // deep copy of root node
2188*cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XNode> xRoot(
2189*cdf0e10cSrcweir             m_xDoc->getDocumentElement(), css::uno::UNO_QUERY_THROW);
2190*cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XNode> xRootNew(
2191*cdf0e10cSrcweir             xDoc->importNode(xRoot, true));
2192*cdf0e10cSrcweir         xDoc->appendChild(xRootNew);
2193*cdf0e10cSrcweir         pNew->init(xDoc);
2194*cdf0e10cSrcweir     } catch (css::uno::RuntimeException &) {
2195*cdf0e10cSrcweir         throw;
2196*cdf0e10cSrcweir     } catch (css::uno::Exception & e) {
2197*cdf0e10cSrcweir         css::uno::Any a(e);
2198*cdf0e10cSrcweir         throw css::lang::WrappedTargetRuntimeException(
2199*cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(
2200*cdf0e10cSrcweir                     "SfxDocumentMetaData::createClone: exception"),
2201*cdf0e10cSrcweir                 css::uno::Reference<css::uno::XInterface>(*this), a);
2202*cdf0e10cSrcweir     }
2203*cdf0e10cSrcweir //    return static_cast< ::cppu::OWeakObject * > (pNew);
2204*cdf0e10cSrcweir     return css::uno::Reference<css::util::XCloneable> (pNew);
2205*cdf0e10cSrcweir }
2206*cdf0e10cSrcweir 
2207*cdf0e10cSrcweir // ::com::sun::star::util::XModifiable:
2208*cdf0e10cSrcweir ::sal_Bool SAL_CALL SfxDocumentMetaData::isModified(  )
2209*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
2210*cdf0e10cSrcweir {
2211*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
2212*cdf0e10cSrcweir     checkInit();
2213*cdf0e10cSrcweir     css::uno::Reference<css::util::XModifiable> xMB(m_xUserDefined,
2214*cdf0e10cSrcweir         css::uno::UNO_QUERY);
2215*cdf0e10cSrcweir     return m_isModified || (xMB.is() ? xMB->isModified() : sal_False);
2216*cdf0e10cSrcweir }
2217*cdf0e10cSrcweir 
2218*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::setModified( ::sal_Bool bModified )
2219*cdf0e10cSrcweir         throw (css::beans::PropertyVetoException, css::uno::RuntimeException)
2220*cdf0e10cSrcweir {
2221*cdf0e10cSrcweir     css::uno::Reference<css::util::XModifiable> xMB;
2222*cdf0e10cSrcweir     { // do not lock mutex while notifying (#i93514#) to prevent deadlock
2223*cdf0e10cSrcweir         ::osl::MutexGuard g(m_aMutex);
2224*cdf0e10cSrcweir         checkInit();
2225*cdf0e10cSrcweir         m_isModified = bModified;
2226*cdf0e10cSrcweir         if ( !bModified && m_xUserDefined.is() )
2227*cdf0e10cSrcweir         {
2228*cdf0e10cSrcweir             xMB.set(m_xUserDefined, css::uno::UNO_QUERY);
2229*cdf0e10cSrcweir             DBG_ASSERT(xMB.is(),
2230*cdf0e10cSrcweir                 "SfxDocumentMetaData::setModified: PropertyBag not Modifiable?");
2231*cdf0e10cSrcweir         }
2232*cdf0e10cSrcweir     }
2233*cdf0e10cSrcweir     if (bModified) {
2234*cdf0e10cSrcweir         try {
2235*cdf0e10cSrcweir             css::uno::Reference<css::uno::XInterface> xThis(*this);
2236*cdf0e10cSrcweir             css::lang::EventObject event(xThis);
2237*cdf0e10cSrcweir             m_NotifyListeners.notifyEach(&css::util::XModifyListener::modified,
2238*cdf0e10cSrcweir                 event);
2239*cdf0e10cSrcweir         } catch (css::uno::RuntimeException &) {
2240*cdf0e10cSrcweir             throw;
2241*cdf0e10cSrcweir         } catch (css::uno::Exception & e) {
2242*cdf0e10cSrcweir             // ignore
2243*cdf0e10cSrcweir             DBG_WARNING1("SfxDocumentMetaData::setModified: exception:\n%s",
2244*cdf0e10cSrcweir                 OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
2245*cdf0e10cSrcweir             (void) e;
2246*cdf0e10cSrcweir         }
2247*cdf0e10cSrcweir     } else {
2248*cdf0e10cSrcweir         if (xMB.is()) {
2249*cdf0e10cSrcweir             xMB->setModified(false);
2250*cdf0e10cSrcweir         }
2251*cdf0e10cSrcweir     }
2252*cdf0e10cSrcweir }
2253*cdf0e10cSrcweir 
2254*cdf0e10cSrcweir // ::com::sun::star::util::XModifyBroadcaster:
2255*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::addModifyListener(
2256*cdf0e10cSrcweir         const css::uno::Reference< css::util::XModifyListener > & xListener)
2257*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
2258*cdf0e10cSrcweir {
2259*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
2260*cdf0e10cSrcweir     checkInit();
2261*cdf0e10cSrcweir     m_NotifyListeners.addInterface(xListener);
2262*cdf0e10cSrcweir     css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
2263*cdf0e10cSrcweir         css::uno::UNO_QUERY);
2264*cdf0e10cSrcweir     if (xMB.is()) {
2265*cdf0e10cSrcweir         xMB->addModifyListener(xListener);
2266*cdf0e10cSrcweir     }
2267*cdf0e10cSrcweir }
2268*cdf0e10cSrcweir 
2269*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::removeModifyListener(
2270*cdf0e10cSrcweir         const css::uno::Reference< css::util::XModifyListener > & xListener)
2271*cdf0e10cSrcweir         throw (css::uno::RuntimeException)
2272*cdf0e10cSrcweir {
2273*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
2274*cdf0e10cSrcweir     checkInit();
2275*cdf0e10cSrcweir     m_NotifyListeners.removeInterface(xListener);
2276*cdf0e10cSrcweir     css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
2277*cdf0e10cSrcweir         css::uno::UNO_QUERY);
2278*cdf0e10cSrcweir     if (xMB.is()) {
2279*cdf0e10cSrcweir         xMB->removeModifyListener(xListener);
2280*cdf0e10cSrcweir     }
2281*cdf0e10cSrcweir }
2282*cdf0e10cSrcweir 
2283*cdf0e10cSrcweir // ::com::sun::star::xml::sax::XSAXSerializable
2284*cdf0e10cSrcweir void SAL_CALL SfxDocumentMetaData::serialize(
2285*cdf0e10cSrcweir     const css::uno::Reference<css::xml::sax::XDocumentHandler>& i_xHandler,
2286*cdf0e10cSrcweir     const css::uno::Sequence< css::beans::StringPair >& i_rNamespaces)
2287*cdf0e10cSrcweir     throw (css::uno::RuntimeException, css::xml::sax::SAXException)
2288*cdf0e10cSrcweir {
2289*cdf0e10cSrcweir     ::osl::MutexGuard g(m_aMutex);
2290*cdf0e10cSrcweir     checkInit();
2291*cdf0e10cSrcweir     updateUserDefinedAndAttributes();
2292*cdf0e10cSrcweir     css::uno::Reference<css::xml::sax::XSAXSerializable> xSAXable(m_xDoc,
2293*cdf0e10cSrcweir         css::uno::UNO_QUERY_THROW);
2294*cdf0e10cSrcweir     xSAXable->serialize(i_xHandler, i_rNamespaces);
2295*cdf0e10cSrcweir }
2296*cdf0e10cSrcweir 
2297*cdf0e10cSrcweir void SfxDocumentMetaData::createUserDefined()
2298*cdf0e10cSrcweir {
2299*cdf0e10cSrcweir     // user-defined meta data: create PropertyBag which only accepts property
2300*cdf0e10cSrcweir     // values of allowed types
2301*cdf0e10cSrcweir     if ( !m_xUserDefined.is() )
2302*cdf0e10cSrcweir     {
2303*cdf0e10cSrcweir         css::uno::Sequence<css::uno::Type> types(11);
2304*cdf0e10cSrcweir         types[0] = ::cppu::UnoType<bool>::get();
2305*cdf0e10cSrcweir         types[1] = ::cppu::UnoType< ::rtl::OUString>::get();
2306*cdf0e10cSrcweir         types[2] = ::cppu::UnoType<css::util::DateTime>::get();
2307*cdf0e10cSrcweir         types[3] = ::cppu::UnoType<css::util::Date>::get();
2308*cdf0e10cSrcweir         types[4] = ::cppu::UnoType<css::util::Duration>::get();
2309*cdf0e10cSrcweir         types[5] = ::cppu::UnoType<float>::get();
2310*cdf0e10cSrcweir         types[6] = ::cppu::UnoType<double>::get();
2311*cdf0e10cSrcweir         types[7] = ::cppu::UnoType<sal_Int16>::get();
2312*cdf0e10cSrcweir         types[8] = ::cppu::UnoType<sal_Int32>::get();
2313*cdf0e10cSrcweir         types[9] = ::cppu::UnoType<sal_Int64>::get();
2314*cdf0e10cSrcweir         // Time is supported for backward compatibility with OOo 3.x, x<=2
2315*cdf0e10cSrcweir         types[10] = ::cppu::UnoType<css::util::Time>::get();
2316*cdf0e10cSrcweir         css::uno::Sequence<css::uno::Any> args(2);
2317*cdf0e10cSrcweir         args[0] <<= css::beans::NamedValue(
2318*cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AllowedTypes")),
2319*cdf0e10cSrcweir             css::uno::makeAny(types));
2320*cdf0e10cSrcweir         // #i94175#:  ODF allows empty user-defined property names!
2321*cdf0e10cSrcweir         args[1] <<= css::beans::NamedValue( ::rtl::OUString(
2322*cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM("AllowEmptyPropertyName")),
2323*cdf0e10cSrcweir             css::uno::makeAny(sal_True));
2324*cdf0e10cSrcweir 
2325*cdf0e10cSrcweir         const css::uno::Reference<css::lang::XMultiComponentFactory> xMsf(
2326*cdf0e10cSrcweir                 m_xContext->getServiceManager());
2327*cdf0e10cSrcweir         m_xUserDefined.set(
2328*cdf0e10cSrcweir             xMsf->createInstanceWithContext(
2329*cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2330*cdf0e10cSrcweir                     "com.sun.star.beans.PropertyBag")), m_xContext),
2331*cdf0e10cSrcweir             css::uno::UNO_QUERY_THROW);
2332*cdf0e10cSrcweir         const css::uno::Reference<css::lang::XInitialization> xInit(
2333*cdf0e10cSrcweir             m_xUserDefined, css::uno::UNO_QUERY);
2334*cdf0e10cSrcweir         if (xInit.is()) {
2335*cdf0e10cSrcweir             xInit->initialize(args);
2336*cdf0e10cSrcweir         }
2337*cdf0e10cSrcweir 
2338*cdf0e10cSrcweir         const css::uno::Reference<css::util::XModifyBroadcaster> xMB(
2339*cdf0e10cSrcweir             m_xUserDefined, css::uno::UNO_QUERY);
2340*cdf0e10cSrcweir         if (xMB.is())
2341*cdf0e10cSrcweir         {
2342*cdf0e10cSrcweir             const css::uno::Sequence<css::uno::Reference<css::uno::XInterface> >
2343*cdf0e10cSrcweir                 listeners(m_NotifyListeners.getElements());
2344*cdf0e10cSrcweir             for (css::uno::Reference< css::uno::XInterface > const * iter =
2345*cdf0e10cSrcweir                                 ::comphelper::stl_begin(listeners);
2346*cdf0e10cSrcweir                         iter != ::comphelper::stl_end(listeners); ++iter) {
2347*cdf0e10cSrcweir                 xMB->addModifyListener(
2348*cdf0e10cSrcweir                     css::uno::Reference< css::util::XModifyListener >(*iter,
2349*cdf0e10cSrcweir                         css::uno::UNO_QUERY));
2350*cdf0e10cSrcweir             }
2351*cdf0e10cSrcweir         }
2352*cdf0e10cSrcweir     }
2353*cdf0e10cSrcweir }
2354*cdf0e10cSrcweir 
2355*cdf0e10cSrcweir } // closing anonymous implementation namespace
2356*cdf0e10cSrcweir 
2357*cdf0e10cSrcweir 
2358*cdf0e10cSrcweir // component helper namespace
2359*cdf0e10cSrcweir namespace comp_SfxDocumentMetaData {
2360*cdf0e10cSrcweir 
2361*cdf0e10cSrcweir ::rtl::OUString SAL_CALL _getImplementationName() {
2362*cdf0e10cSrcweir     return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2363*cdf0e10cSrcweir         "SfxDocumentMetaData"));
2364*cdf0e10cSrcweir }
2365*cdf0e10cSrcweir 
2366*cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
2367*cdf0e10cSrcweir {
2368*cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString > s(1);
2369*cdf0e10cSrcweir     s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2370*cdf0e10cSrcweir         "com.sun.star.document.DocumentProperties"));
2371*cdf0e10cSrcweir     return s;
2372*cdf0e10cSrcweir }
2373*cdf0e10cSrcweir 
2374*cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface > SAL_CALL _create(
2375*cdf0e10cSrcweir     const css::uno::Reference< css::uno::XComponentContext > & context)
2376*cdf0e10cSrcweir         SAL_THROW((css::uno::Exception))
2377*cdf0e10cSrcweir {
2378*cdf0e10cSrcweir     return static_cast< ::cppu::OWeakObject * >
2379*cdf0e10cSrcweir                 (new SfxDocumentMetaData(context));
2380*cdf0e10cSrcweir }
2381*cdf0e10cSrcweir 
2382*cdf0e10cSrcweir } // closing component helper namespace
2383*cdf0e10cSrcweir 
2384*cdf0e10cSrcweir static ::cppu::ImplementationEntry const entries[] = {
2385*cdf0e10cSrcweir     { &comp_SfxDocumentMetaData::_create,
2386*cdf0e10cSrcweir       &comp_SfxDocumentMetaData::_getImplementationName,
2387*cdf0e10cSrcweir       &comp_SfxDocumentMetaData::_getSupportedServiceNames,
2388*cdf0e10cSrcweir       &::cppu::createSingleComponentFactory, 0, 0 },
2389*cdf0e10cSrcweir     { 0, 0, 0, 0, 0, 0 }
2390*cdf0e10cSrcweir };
2391*cdf0e10cSrcweir 
2392*cdf0e10cSrcweir #if 0
2393*cdf0e10cSrcweir extern "C" void SAL_CALL component_getImplementationEnvironment(
2394*cdf0e10cSrcweir     const char ** envTypeName, uno_Environment **)
2395*cdf0e10cSrcweir {
2396*cdf0e10cSrcweir     *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
2397*cdf0e10cSrcweir }
2398*cdf0e10cSrcweir 
2399*cdf0e10cSrcweir extern "C" void * SAL_CALL component_getFactory(
2400*cdf0e10cSrcweir     const char * implName, void * serviceManager, void * registryKey)
2401*cdf0e10cSrcweir {
2402*cdf0e10cSrcweir     return ::cppu::component_getFactoryHelper(
2403*cdf0e10cSrcweir         implName, serviceManager, registryKey, entries);
2404*cdf0e10cSrcweir }
2405*cdf0e10cSrcweir #endif
2406*cdf0e10cSrcweir 
2407