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