update dev300-m58
[ooovba.git] / sfx2 / source / doc / SfxDocumentMetaData.cxx
bloba5b3e7f55506e93b62c5bfbb6c6923863065178b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SfxDocumentMetaData.cxx,v $
10 * $Revision: 1.10.32.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "precompiled_sfx2.hxx"
33 #include "sal/config.h"
34 #include "cppuhelper/factory.hxx"
35 #include "cppuhelper/implementationentry.hxx"
36 #include "cppuhelper/compbase6.hxx"
37 #include "com/sun/star/lang/XServiceInfo.hpp"
38 #include "com/sun/star/document/XDocumentProperties.hpp"
39 #include "com/sun/star/lang/XInitialization.hpp"
40 #include "com/sun/star/util/XCloneable.hpp"
41 #include "com/sun/star/util/XModifiable.hpp"
42 #include "com/sun/star/xml/sax/XSAXSerializable.hpp"
44 #include "com/sun/star/lang/NullPointerException.hpp"
45 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
46 #include "com/sun/star/lang/EventObject.hpp"
47 #include "com/sun/star/beans/XPropertySet.hpp"
48 #include "com/sun/star/beans/XPropertySetInfo.hpp"
49 #include "com/sun/star/beans/PropertyAttribute.hpp"
50 #include "com/sun/star/task/ErrorCodeIOException.hpp"
51 #include "com/sun/star/embed/XStorage.hpp"
52 #include "com/sun/star/embed/XTransactedObject.hpp"
53 #include "com/sun/star/embed/ElementModes.hpp"
54 #include "com/sun/star/io/XActiveDataControl.hpp"
55 #include "com/sun/star/io/XActiveDataSource.hpp"
56 #include "com/sun/star/io/XStream.hpp"
57 #include "com/sun/star/document/XImporter.hpp"
58 #include "com/sun/star/document/XExporter.hpp"
59 #include "com/sun/star/document/XFilter.hpp"
60 #include "com/sun/star/xml/sax/XParser.hpp"
61 #include "com/sun/star/xml/dom/XDocument.hpp"
62 #include "com/sun/star/xml/dom/XElement.hpp"
63 #include "com/sun/star/xml/dom/XDocumentBuilder.hpp"
64 #include "com/sun/star/xml/dom/XSAXDocumentBuilder.hpp"
65 #include "com/sun/star/xml/dom/NodeType.hpp"
66 #include "com/sun/star/xml/xpath/XXPathAPI.hpp"
67 #include "com/sun/star/util/Date.hpp"
68 #include "com/sun/star/util/Time.hpp"
70 #include "SfxDocumentMetaData.hxx"
71 #include "rtl/ustrbuf.hxx"
72 #include "tools/debug.hxx"
73 #include "tools/string.hxx" // for DBG
74 #include "tools/datetime.hxx"
75 #include "tools/urlobj.hxx"
76 #include "osl/mutex.hxx"
77 #include "cppuhelper/basemutex.hxx"
78 #include "cppuhelper/interfacecontainer.hxx"
79 #include "comphelper/storagehelper.hxx"
80 #include "comphelper/mediadescriptor.hxx"
81 #include "comphelper/sequenceasvector.hxx"
82 #include "sot/storage.hxx"
83 #include "sfx2/docfile.hxx"
84 #include "sax/tools/converter.hxx"
86 #include <utility>
87 #include <vector>
88 #include <map>
89 #include <cstring>
90 #include <limits>
93 #include <cppuhelper/implbase1.hxx>
94 #include <com/sun/star/document/XCompatWriterDocProperties.hpp>
96 /**
97 * This file contains the implementation of the service
98 * com.sun.star.document.DocumentProperties.
99 * This service enables access to the meta-data stored in documents.
100 * Currently, this service only handles documents in ODF format.
102 * The implementation uses an XML DOM to store the properties.
103 * This approach was taken because it allows for preserving arbitrary XML data
104 * in loaded documents, which will be stored unmodified when saving the
105 * document again.
107 * Upon access, some properties are directly read from and updated in the DOM.
108 * Exception: it seems impossible to get notified upon addition of a property
109 * to a com.sun.star.beans.PropertyBag, which is used for storing user-defined
110 * properties; because of this, user-defined properties are updated in the
111 * XML DOM only when storing the document.
112 * Exception 2: when setting certain properties which correspond to attributes
113 * in the XML DOM, we want to remove the corresponding XML element. Detecting
114 * this condition can get messy, so we store all such properties as members,
115 * and update the DOM tree only when storing the document (in
116 * <method>updateUserDefinedAndAttributes</method>).
118 * @author mst
121 /// anonymous implementation namespace
122 namespace {
124 namespace css = ::com::sun::star;
127 /// a list of attribute-lists, where attribute means name and content
128 typedef std::vector<std::vector<std::pair<const char*, ::rtl::OUString> > >
129 AttrVector;
131 typedef ::cppu::WeakComponentImplHelper6<
132 css::lang::XServiceInfo,
133 css::document::XDocumentProperties,
134 css::lang::XInitialization,
135 css::util::XCloneable,
136 css::util::XModifiable,
137 css::xml::sax::XSAXSerializable>
138 SfxDocumentMetaData_Base;
140 class SfxDocumentMetaData:
141 private ::cppu::BaseMutex,
142 public SfxDocumentMetaData_Base
144 public:
145 explicit SfxDocumentMetaData(
146 css::uno::Reference< css::uno::XComponentContext > const & context);
148 // ::com::sun::star::lang::XServiceInfo:
149 virtual ::rtl::OUString SAL_CALL getImplementationName()
150 throw (css::uno::RuntimeException);
151 virtual ::sal_Bool SAL_CALL supportsService(
152 const ::rtl::OUString & ServiceName) throw (css::uno::RuntimeException);
153 virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL
154 getSupportedServiceNames() throw (css::uno::RuntimeException);
156 // ::com::sun::star::lang::XComponent:
157 virtual void SAL_CALL dispose() throw (css::uno::RuntimeException);
159 // ::com::sun::star::document::XDocumentProperties:
160 virtual ::rtl::OUString SAL_CALL getAuthor()
161 throw (css::uno::RuntimeException);
162 virtual void SAL_CALL setAuthor(const ::rtl::OUString & the_value)
163 throw (css::uno::RuntimeException);
164 virtual ::rtl::OUString SAL_CALL getGenerator()
165 throw (css::uno::RuntimeException);
166 virtual void SAL_CALL setGenerator(const ::rtl::OUString & the_value)
167 throw (css::uno::RuntimeException);
168 virtual css::util::DateTime SAL_CALL getCreationDate()
169 throw (css::uno::RuntimeException);
170 virtual void SAL_CALL setCreationDate(const css::util::DateTime & the_value)
171 throw (css::uno::RuntimeException);
172 virtual ::rtl::OUString SAL_CALL getTitle()
173 throw (css::uno::RuntimeException);
174 virtual void SAL_CALL setTitle(const ::rtl::OUString & the_value)
175 throw (css::uno::RuntimeException);
176 virtual ::rtl::OUString SAL_CALL getSubject()
177 throw (css::uno::RuntimeException);
178 virtual void SAL_CALL setSubject(const ::rtl::OUString & the_value)
179 throw (css::uno::RuntimeException);
180 virtual ::rtl::OUString SAL_CALL getDescription()
181 throw (css::uno::RuntimeException);
182 virtual void SAL_CALL setDescription(const ::rtl::OUString & the_value)
183 throw (css::uno::RuntimeException);
184 virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getKeywords()
185 throw (css::uno::RuntimeException);
186 virtual void SAL_CALL setKeywords(
187 const css::uno::Sequence< ::rtl::OUString > & the_value)
188 throw (css::uno::RuntimeException);
189 virtual css::lang::Locale SAL_CALL getLanguage()
190 throw (css::uno::RuntimeException);
191 virtual void SAL_CALL setLanguage(const css::lang::Locale & the_value)
192 throw (css::uno::RuntimeException);
193 virtual ::rtl::OUString SAL_CALL getModifiedBy()
194 throw (css::uno::RuntimeException);
195 virtual void SAL_CALL setModifiedBy(const ::rtl::OUString & the_value)
196 throw (css::uno::RuntimeException);
197 virtual css::util::DateTime SAL_CALL getModificationDate()
198 throw (css::uno::RuntimeException);
199 virtual void SAL_CALL setModificationDate(
200 const css::util::DateTime & the_value)
201 throw (css::uno::RuntimeException);
202 virtual ::rtl::OUString SAL_CALL getPrintedBy()
203 throw (css::uno::RuntimeException);
204 virtual void SAL_CALL setPrintedBy(const ::rtl::OUString & the_value)
205 throw (css::uno::RuntimeException);
206 virtual css::util::DateTime SAL_CALL getPrintDate()
207 throw (css::uno::RuntimeException);
208 virtual void SAL_CALL setPrintDate(const css::util::DateTime & the_value)
209 throw (css::uno::RuntimeException);
210 virtual ::rtl::OUString SAL_CALL getTemplateName()
211 throw (css::uno::RuntimeException);
212 virtual void SAL_CALL setTemplateName(const ::rtl::OUString & the_value)
213 throw (css::uno::RuntimeException);
214 virtual ::rtl::OUString SAL_CALL getTemplateURL()
215 throw (css::uno::RuntimeException);
216 virtual void SAL_CALL setTemplateURL(const ::rtl::OUString & the_value)
217 throw (css::uno::RuntimeException);
218 virtual css::util::DateTime SAL_CALL getTemplateDate()
219 throw (css::uno::RuntimeException);
220 virtual void SAL_CALL setTemplateDate(const css::util::DateTime & the_value)
221 throw (css::uno::RuntimeException);
222 virtual ::rtl::OUString SAL_CALL getAutoloadURL()
223 throw (css::uno::RuntimeException);
224 virtual void SAL_CALL setAutoloadURL(const ::rtl::OUString & the_value)
225 throw (css::uno::RuntimeException);
226 virtual ::sal_Int32 SAL_CALL getAutoloadSecs()
227 throw (css::uno::RuntimeException);
228 virtual void SAL_CALL setAutoloadSecs(::sal_Int32 the_value)
229 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
230 virtual ::rtl::OUString SAL_CALL getDefaultTarget()
231 throw (css::uno::RuntimeException);
232 virtual void SAL_CALL setDefaultTarget(const ::rtl::OUString & the_value)
233 throw (css::uno::RuntimeException);
234 virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL
235 getDocumentStatistics() throw (css::uno::RuntimeException);
236 virtual void SAL_CALL setDocumentStatistics(
237 const css::uno::Sequence< css::beans::NamedValue > & the_value)
238 throw (css::uno::RuntimeException);
239 virtual ::sal_Int16 SAL_CALL getEditingCycles()
240 throw (css::uno::RuntimeException);
241 virtual void SAL_CALL setEditingCycles(::sal_Int16 the_value)
242 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
243 virtual ::sal_Int32 SAL_CALL getEditingDuration()
244 throw (css::uno::RuntimeException);
245 virtual void SAL_CALL setEditingDuration(::sal_Int32 the_value)
246 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
247 virtual void SAL_CALL resetUserData(const ::rtl::OUString & the_value)
248 throw (css::uno::RuntimeException);
249 virtual css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
250 getUserDefinedProperties() throw (css::uno::RuntimeException);
251 virtual void SAL_CALL loadFromStorage(
252 const css::uno::Reference< css::embed::XStorage > & Storage,
253 const css::uno::Sequence< css::beans::PropertyValue > & Medium)
254 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
255 css::io::WrongFormatException,
256 css::lang::WrappedTargetException, css::io::IOException,
257 css::uno::Exception);
258 virtual void SAL_CALL loadFromMedium(const ::rtl::OUString & URL,
259 const css::uno::Sequence< css::beans::PropertyValue > & Medium)
260 throw (css::uno::RuntimeException,
261 css::io::WrongFormatException,
262 css::lang::WrappedTargetException, css::io::IOException,
263 css::uno::Exception);
264 virtual void SAL_CALL storeToStorage(
265 const css::uno::Reference< css::embed::XStorage > & Storage,
266 const css::uno::Sequence< css::beans::PropertyValue > & Medium)
267 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
268 css::lang::WrappedTargetException, css::io::IOException,
269 css::uno::Exception);
270 virtual void SAL_CALL storeToMedium(const ::rtl::OUString & URL,
271 const css::uno::Sequence< css::beans::PropertyValue > & Medium)
272 throw (css::uno::RuntimeException,
273 css::lang::WrappedTargetException, css::io::IOException,
274 css::uno::Exception);
276 // ::com::sun::star::lang::XInitialization:
277 virtual void SAL_CALL initialize(
278 const css::uno::Sequence< css::uno::Any > & aArguments)
279 throw (css::uno::RuntimeException, css::uno::Exception);
281 // ::com::sun::star::util::XCloneable:
282 virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone()
283 throw (css::uno::RuntimeException);
285 // ::com::sun::star::util::XModifiable:
286 virtual ::sal_Bool SAL_CALL isModified( )
287 throw (css::uno::RuntimeException);
288 virtual void SAL_CALL setModified( ::sal_Bool bModified )
289 throw (css::beans::PropertyVetoException, css::uno::RuntimeException);
291 // ::com::sun::star::util::XModifyBroadcaster:
292 virtual void SAL_CALL addModifyListener(
293 const css::uno::Reference< css::util::XModifyListener > & xListener)
294 throw (css::uno::RuntimeException);
295 virtual void SAL_CALL removeModifyListener(
296 const css::uno::Reference< css::util::XModifyListener > & xListener)
297 throw (css::uno::RuntimeException);
299 // ::com::sun::star::xml::sax::XSAXSerializable
300 virtual void SAL_CALL serialize(
301 const css::uno::Reference<css::xml::sax::XDocumentHandler>& i_xHandler,
302 const css::uno::Sequence< css::beans::StringPair >& i_rNamespaces)
303 throw (css::uno::RuntimeException, css::xml::sax::SAXException);
305 protected:
306 SfxDocumentMetaData(SfxDocumentMetaData &); // not defined
307 SfxDocumentMetaData& operator =(SfxDocumentMetaData &); // not defined
309 virtual ~SfxDocumentMetaData() {}
310 virtual SfxDocumentMetaData* createMe( css::uno::Reference< css::uno::XComponentContext > const & context ) { return new SfxDocumentMetaData( context ); };
311 const css::uno::Reference< css::uno::XComponentContext > m_xContext;
313 /// for notification
314 ::cppu::OInterfaceContainerHelper m_NotifyListeners;
315 /// flag: false means not initialized yet, or disposed
316 bool m_isInitialized;
317 /// flag
318 bool m_isModified;
319 /// meta-data DOM tree
320 css::uno::Reference< css::xml::dom::XDocument > m_xDoc;
321 /// meta-data super node in the meta-data DOM tree
322 css::uno::Reference< css::xml::dom::XNode> m_xParent;
323 /// standard meta data (single occurrence)
324 std::map< ::rtl::OUString, css::uno::Reference<css::xml::dom::XNode> >
325 m_meta;
326 /// standard meta data (multiple occurrences)
327 std::map< ::rtl::OUString,
328 std::vector<css::uno::Reference<css::xml::dom::XNode> > > m_metaList;
329 /// user-defined meta data (meta:user-defined)
330 css::uno::Reference<css::beans::XPropertyContainer> m_xUserDefined;
331 // now for some meta-data attributes; these are not updated directly in the
332 // DOM because updates (detecting "empty" elements) would be quite messy
333 ::rtl::OUString m_TemplateName;
334 ::rtl::OUString m_TemplateURL;
335 css::util::DateTime m_TemplateDate;
336 ::rtl::OUString m_AutoloadURL;
337 sal_Int32 m_AutoloadSecs;
338 ::rtl::OUString m_DefaultTarget;
340 /// check if we are initialized properly
341 void SAL_CALL checkInit() const;
342 // throw (css::uno::RuntimeException);
343 /// initialize state from given DOM tree
344 void SAL_CALL init(css::uno::Reference<css::xml::dom::XDocument> i_xDom);
345 // throw (css::uno::RuntimeException, css::io::WrongFormatException,
346 // css::uno::Exception);
347 /// update element in DOM tree
348 void SAL_CALL updateElement(const char *i_name,
349 std::vector<std::pair<const char *, ::rtl::OUString> >* i_pAttrs = 0);
350 /// update user-defined meta data and attributes in DOM tree
351 void SAL_CALL updateUserDefinedAndAttributes();
352 /// create empty DOM tree (XDocument)
353 css::uno::Reference<css::xml::dom::XDocument> SAL_CALL createDOM() const;
354 /// extract base URL (necessary for converting relative links)
355 css::uno::Reference<css::beans::XPropertySet> SAL_CALL getURLProperties(
356 const css::uno::Sequence<css::beans::PropertyValue> & i_rMedium) const;
357 // throw (css::uno::RuntimeException);
358 /// get text of standard meta data element
359 ::rtl::OUString SAL_CALL getMetaText(const char* i_name) const;
360 // throw (css::uno::RuntimeException);
361 /// set text of standard meta data element iff not equal to existing text
362 bool SAL_CALL setMetaText(const char* i_name,
363 const ::rtl::OUString & i_rValue);
364 // throw (css::uno::RuntimeException);
365 /// set text of standard meta data element iff not equal to existing text
366 void SAL_CALL setMetaTextAndNotify(const char* i_name,
367 const ::rtl::OUString & i_rValue);
368 // throw (css::uno::RuntimeException);
369 /// get text of standard meta data element's attribute
370 ::rtl::OUString SAL_CALL getMetaAttr(const char* i_name,
371 const char* i_attr) const;
372 // throw (css::uno::RuntimeException);
373 /// get text of a list of standard meta data elements (multiple occ.)
374 css::uno::Sequence< ::rtl::OUString > SAL_CALL getMetaList(
375 const char* i_name) const;
376 // throw (css::uno::RuntimeException);
377 /// set text of a list of standard meta data elements (multiple occ.)
378 bool SAL_CALL setMetaList(const char* i_name,
379 const css::uno::Sequence< ::rtl::OUString > & i_rValue,
380 AttrVector const* = 0);
381 // throw (css::uno::RuntimeException);
382 void createUserDefined();
385 typedef ::cppu::ImplInheritanceHelper1< SfxDocumentMetaData, css::document::XCompatWriterDocProperties > CompatWriterDocPropsImpl_BASE;
387 class CompatWriterDocPropsImpl : public CompatWriterDocPropsImpl_BASE
389 rtl::OUString msManager;
390 rtl::OUString msCategory;
391 rtl::OUString msCompany;
392 protected:
393 virtual SfxDocumentMetaData* createMe( css::uno::Reference< css::uno::XComponentContext > const & context ) { return new CompatWriterDocPropsImpl( context ); };
394 public:
395 CompatWriterDocPropsImpl( css::uno::Reference< css::uno::XComponentContext > const & context) : CompatWriterDocPropsImpl_BASE( context ) {}
396 // XCompatWriterDocPropsImpl
397 virtual ::rtl::OUString SAL_CALL getManager() throw (::com::sun::star::uno::RuntimeException) { return msManager; }
398 virtual void SAL_CALL setManager( const ::rtl::OUString& _manager ) throw (::com::sun::star::uno::RuntimeException) { msManager = _manager; }
399 virtual ::rtl::OUString SAL_CALL getCategory() throw (::com::sun::star::uno::RuntimeException){ return msCategory; }
400 virtual void SAL_CALL setCategory( const ::rtl::OUString& _category ) throw (::com::sun::star::uno::RuntimeException){ msCategory = _category; }
401 virtual ::rtl::OUString SAL_CALL getCompany() throw (::com::sun::star::uno::RuntimeException){ return msCompany; }
402 virtual void SAL_CALL setCompany( const ::rtl::OUString& _company ) throw (::com::sun::star::uno::RuntimeException){ msCompany = _company; }
404 // XServiceInfo
405 virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException)
407 return comp_CompatWriterDocProps::_getImplementationName();
410 virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException)
412 css::uno::Sequence< rtl::OUString > sServiceNames= getSupportedServiceNames();
413 sal_Int32 nLen = sServiceNames.getLength();
414 rtl::OUString* pIt = sServiceNames.getArray();
415 rtl::OUString* pEnd = ( pIt + nLen );
416 sal_Bool bRes = sal_False;
417 for ( ; pIt != pEnd; ++pIt )
419 if ( pIt->equals( ServiceName ) )
421 bRes = sal_True;
422 break;
425 return bRes;
428 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException)
430 return comp_CompatWriterDocProps::_getSupportedServiceNames();
433 ////////////////////////////////////////////////////////////////////////////
435 bool operator== (const css::util::DateTime &i_rLeft,
436 const css::util::DateTime &i_rRight)
438 return i_rLeft.Year == i_rRight.Year
439 && i_rLeft.Month == i_rRight.Month
440 && i_rLeft.Day == i_rRight.Day
441 && i_rLeft.Hours == i_rRight.Hours
442 && i_rLeft.Minutes == i_rRight.Minutes
443 && i_rLeft.Seconds == i_rRight.Seconds
444 && i_rLeft.HundredthSeconds == i_rRight.HundredthSeconds;
447 // NB: keep these two arrays in sync!
448 const char* s_stdStatAttrs[] = {
449 "meta:page-count",
450 "meta:table-count",
451 "meta:draw-count",
452 "meta:image-count",
453 "meta:object-count",
454 "meta:ole-object-count",
455 "meta:paragraph-count",
456 "meta:word-count",
457 "meta:character-count",
458 "meta:row-count",
459 "meta:frame-count",
460 "meta:sentence-count",
461 "meta:syllable-count",
462 "meta:non-whitespace-character-count",
463 "meta:cell-count",
467 // NB: keep these two arrays in sync!
468 const char* s_stdStats[] = {
469 "PageCount",
470 "TableCount",
471 "DrawCount",
472 "ImageCount",
473 "ObjectCount",
474 "OLEObjectCount",
475 "ParagraphCount",
476 "WordCount",
477 "CharacterCount",
478 "RowCount",
479 "FrameCount",
480 "SentenceCount",
481 "SyllableCount",
482 "NonWhitespaceCharacterCount",
483 "CellCount",
487 const char* s_stdMeta[] = {
488 "meta:generator", // string
489 "dc:title", // string
490 "dc:description", // string
491 "dc:subject", // string
492 "meta:initial-creator", // string
493 "dc:creator", // string
494 "meta:printed-by", // string
495 "meta:creation-date", // dateTime
496 "dc:date", // dateTime
497 "meta:print-date", // dateTime
498 "meta:template", // XLink
499 "meta:auto-reload", // ...
500 "meta:hyperlink-behaviour", // ...
501 "dc:language", // language
502 "meta:editing-cycles", // nonNegativeInteger
503 "meta:editing-duration", // duration
504 "meta:document-statistic", // ... // note: statistic is singular, no s!
508 const char* s_stdMetaList[] = {
509 "meta:keyword", // string*
510 "meta:user-defined", // ...*
514 const char* s_nsXLink = "http://www.w3.org/1999/xlink";
515 const char* s_nsDC = "http://purl.org/dc/elements/1.1/";
516 const char* s_nsODF = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
517 const char* s_nsODFMeta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0";
518 // const char* s_nsOOo = "http://openoffice.org/2004/office"; // not used (yet?)
520 const char* s_metaXml = "meta.xml";
523 bool isValidDateTime(const css::util::DateTime & i_rDateTime)
525 return i_rDateTime.Month > 0;
528 std::pair< ::rtl::OUString, ::rtl::OUString > SAL_CALL
529 getQualifier(const char* i_name) {
530 ::rtl::OUString nm = ::rtl::OUString::createFromAscii(i_name);
531 sal_Int32 ix = nm.indexOf(static_cast<sal_Unicode> (':'));
532 if (ix == -1) {
533 return std::make_pair(::rtl::OUString(), nm);
534 } else {
535 return std::make_pair(nm.copy(0,ix), nm.copy(ix+1));
539 // get namespace for standard qualified names
540 // NB: only call this with statically known strings!
541 ::rtl::OUString SAL_CALL getNameSpace(const char* i_qname) throw ()
543 DBG_ASSERT(i_qname, "SfxDocumentMetaData: getNameSpace: argument is null");
544 const char * ns = "";
545 ::rtl::OUString n = getQualifier(i_qname).first;
546 if (n.equalsAscii("xlink" )) ns = s_nsXLink;
547 if (n.equalsAscii("dc" )) ns = s_nsDC;
548 if (n.equalsAscii("office")) ns = s_nsODF;
549 if (n.equalsAscii("meta" )) ns = s_nsODFMeta;
550 DBG_ASSERT(*ns, "SfxDocumentMetaData: unknown namespace prefix");
551 return ::rtl::OUString::createFromAscii(ns);
554 // convert string to date/time
555 bool SAL_CALL
556 textToDateTime(css::util::DateTime & io_rdt, ::rtl::OUString i_text) throw ()
558 if (::sax::Converter::convertDateTime(io_rdt, i_text)) {
559 // NB: there may be rounding errors; handle these here
560 if (io_rdt.HundredthSeconds > 0) {
561 io_rdt.Seconds++;
562 io_rdt.HundredthSeconds = 0;
564 return true;
565 } else {
566 DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
567 OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr());
568 return false;
572 // convert string to date/time with default return value
573 css::util::DateTime SAL_CALL
574 textToDateTimeDefault(::rtl::OUString i_text) throw ()
576 css::util::DateTime dt;
577 static_cast<void> (textToDateTime(dt, i_text));
578 // on conversion error: return default value (unchanged)
579 return dt;
582 // convert date/time to string
583 ::rtl::OUString SAL_CALL
584 dateTimeToText(css::util::DateTime const& i_rdt) throw ()
586 if (isValidDateTime(i_rdt)) {
587 ::rtl::OUStringBuffer buf;
588 ::sax::Converter::convertDateTime(buf, i_rdt, true);
589 return buf.makeStringAndClear();
590 } else {
591 return ::rtl::OUString();
595 // convert string to duration
596 bool SAL_CALL
597 textToDuration(css::util::Time& io_rut, ::rtl::OUString i_text) throw ()
599 css::util::DateTime dt;
600 if (::sax::Converter::convertTime(dt, i_text)) {
601 // NB: there may be rounding errors; handle these here
602 if (dt.HundredthSeconds > 0) {
603 dt.Seconds++;
604 dt.HundredthSeconds = 0;
606 io_rut.Hours = dt.Hours;
607 io_rut.Minutes = dt.Minutes;
608 io_rut.Seconds = dt.Seconds;
609 io_rut.HundredthSeconds = dt.HundredthSeconds;
610 return true;
611 } else {
612 DBG_WARNING1("SfxDocumentMetaData: invalid duration: %s",
613 OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr());
614 return false;
618 sal_Int32 SAL_CALL textToDuration(::rtl::OUString i_text) throw ()
620 css::util::Time t;
621 if (textToDuration(t, i_text)) {
622 return t.Hours * 3600 + t.Minutes * 60 + t.Seconds;
623 } else {
624 return 0; // default
628 // convert duration to string
629 ::rtl::OUString SAL_CALL durationToText(css::util::Time const& i_rut) throw ()
631 css::util::DateTime dt;
632 dt.Hours = i_rut.Hours;
633 dt.Minutes = i_rut.Minutes;
634 dt.Seconds = i_rut.Seconds;
635 dt.HundredthSeconds = i_rut.HundredthSeconds;
636 ::rtl::OUStringBuffer buf;
637 ::sax::Converter::convertTime(buf, dt);
638 return buf.makeStringAndClear();
641 // convert duration to string
642 ::rtl::OUString SAL_CALL durationToText(sal_Int32 i_value) throw ()
644 css::util::Time ut;
645 ut.Hours = static_cast<sal_Int16>(i_value / 3600);
646 ut.Minutes = static_cast<sal_Int16>((i_value % 3600) / 60);
647 ut.Seconds = static_cast<sal_Int16>(i_value % 60);
648 ut.HundredthSeconds = 0;
649 return durationToText(ut);
652 // extract base URL (necessary for converting relative links)
653 css::uno::Reference< css::beans::XPropertySet > SAL_CALL
654 SfxDocumentMetaData::getURLProperties(
655 const css::uno::Sequence< css::beans::PropertyValue > & i_rMedium) const
657 css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
658 m_xContext->getServiceManager());
659 css::uno::Reference< css::beans::XPropertyContainer> xPropArg(
660 xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
661 "com.sun.star.beans.PropertyBag"), m_xContext),
662 css::uno::UNO_QUERY_THROW);
663 try {
664 ::rtl::OUString dburl =
665 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentBaseURL"));
666 ::rtl::OUString hdn =
667 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HierarchicalDocumentName"));
668 for (sal_Int32 i = 0; i < i_rMedium.getLength(); ++i) {
669 if (i_rMedium[i].Name.equals(dburl)) {
670 xPropArg->addProperty(
671 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI")),
672 css::beans::PropertyAttribute::MAYBEVOID,
673 i_rMedium[i].Value);
674 } else if (i_rMedium[i].Name.equals(hdn)) {
675 xPropArg->addProperty(
676 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath")),
677 css::beans::PropertyAttribute::MAYBEVOID,
678 i_rMedium[i].Value);
681 xPropArg->addProperty(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamName")),
682 css::beans::PropertyAttribute::MAYBEVOID,
683 css::uno::makeAny(::rtl::OUString::createFromAscii(s_metaXml)));
684 } catch (css::uno::Exception &) {
685 // ignore
687 return css::uno::Reference< css::beans::XPropertySet>(xPropArg,
688 css::uno::UNO_QUERY_THROW);
691 // return the text of the (hopefully unique, i.e., normalize first!) text
692 // node _below_ the given node
693 ::rtl::OUString SAL_CALL
694 getNodeText(css::uno::Reference<css::xml::dom::XNode> i_xNode)
695 throw (css::uno::RuntimeException)
697 if (!i_xNode.is()) throw css::uno::RuntimeException(
698 ::rtl::OUString::createFromAscii(
699 "SfxDocumentMetaData::getNodeText: argument is null"), i_xNode);
700 for (css::uno::Reference<css::xml::dom::XNode> c = i_xNode->getFirstChild();
701 c.is();
702 c = c->getNextSibling()) {
703 if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
704 try {
705 return c->getNodeValue();
706 } catch (css::xml::dom::DOMException &) { // too big?
707 return ::rtl::OUString();
711 return ::rtl::OUString();
714 ::rtl::OUString SAL_CALL
715 SfxDocumentMetaData::getMetaText(const char* i_name) const
716 // throw (css::uno::RuntimeException)
718 checkInit();
720 const ::rtl::OUString name( ::rtl::OUString::createFromAscii(i_name) );
721 DBG_ASSERT(m_meta.find(name) != m_meta.end(),
722 "SfxDocumentMetaData::getMetaText: not found");
723 css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
724 return (xNode.is()) ? getNodeText(xNode) : ::rtl::OUString();
727 bool SAL_CALL
728 SfxDocumentMetaData::setMetaText(const char* i_name,
729 const ::rtl::OUString & i_rValue)
730 // throw (css::uno::RuntimeException)
732 checkInit();
734 const ::rtl::OUString name( ::rtl::OUString::createFromAscii(i_name) );
735 DBG_ASSERT(m_meta.find(name) != m_meta.end(),
736 "SfxDocumentMetaData::setMetaText: not found");
737 css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
739 try {
740 if (i_rValue.equalsAscii("")) {
741 if (xNode.is()) { // delete
742 m_xParent->removeChild(xNode);
743 xNode.clear();
744 m_meta[name] = xNode;
745 return true;
746 } else {
747 return false;
749 } else {
750 if (xNode.is()) { // update
751 for (css::uno::Reference<css::xml::dom::XNode> c =
752 xNode->getFirstChild();
753 c.is();
754 c = c->getNextSibling()) {
755 if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
756 if (!c->getNodeValue().equals(i_rValue)) {
757 c->setNodeValue(i_rValue);
758 return true;
759 } else {
760 return false;
764 } else { // insert
765 xNode.set(m_xDoc->createElementNS(getNameSpace(i_name), name),
766 css::uno::UNO_QUERY_THROW);
767 m_xParent->appendChild(xNode);
768 m_meta[name] = xNode;
770 css::uno::Reference<css::xml::dom::XNode> xTextNode(
771 m_xDoc->createTextNode(i_rValue), css::uno::UNO_QUERY_THROW);
772 xNode->appendChild(xTextNode);
773 return true;
775 } catch (css::xml::dom::DOMException & e) {
776 css::uno::Any a(e);
777 throw css::lang::WrappedTargetRuntimeException(
778 ::rtl::OUString::createFromAscii(
779 "SfxDocumentMetaData::setMetaText: DOM exception"),
780 css::uno::Reference<css::uno::XInterface>(*this), a);
784 void SAL_CALL
785 SfxDocumentMetaData::setMetaTextAndNotify(const char* i_name,
786 const ::rtl::OUString & i_rValue)
787 // throw (css::uno::RuntimeException)
789 ::osl::ClearableMutexGuard g(m_aMutex);
790 if (setMetaText(i_name, i_rValue)) {
791 g.clear();
792 setModified(true);
796 ::rtl::OUString SAL_CALL
797 SfxDocumentMetaData::getMetaAttr(const char* i_name, const char* i_attr) const
798 // throw (css::uno::RuntimeException)
800 // checkInit();
801 ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
802 DBG_ASSERT(m_meta.find(name) != m_meta.end(),
803 "SfxDocumentMetaData::getMetaAttr: not found");
804 css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
805 if (xNode.is()) {
806 css::uno::Reference<css::xml::dom::XElement> xElem(xNode,
807 css::uno::UNO_QUERY_THROW);
808 return xElem->getAttributeNS(getNameSpace(i_attr),
809 getQualifier(i_attr).second);
810 } else {
811 return ::rtl::OUString();
815 css::uno::Sequence< ::rtl::OUString> SAL_CALL
816 SfxDocumentMetaData::getMetaList(const char* i_name) const
817 // throw (css::uno::RuntimeException)
819 checkInit();
820 ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
821 DBG_ASSERT(m_metaList.find(name) != m_metaList.end(),
822 "SfxDocumentMetaData::getMetaList: not found");
823 std::vector<css::uno::Reference<css::xml::dom::XNode> > const & vec =
824 m_metaList.find(name)->second;
825 css::uno::Sequence< ::rtl::OUString> ret(vec.size());
826 for (size_t i = 0; i < vec.size(); ++i) {
827 ret[i] = getNodeText(vec.at(i));
829 return ret;
832 bool SAL_CALL
833 SfxDocumentMetaData::setMetaList(const char* i_name,
834 const css::uno::Sequence< ::rtl::OUString> & i_rValue,
835 AttrVector const* i_pAttrs)
836 // throw (css::uno::RuntimeException)
838 checkInit();
839 DBG_ASSERT((i_pAttrs == 0) ||
840 (static_cast<size_t>(i_rValue.getLength()) == i_pAttrs->size()),
841 "SfxDocumentMetaData::setMetaList: invalid args");
843 try {
844 ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
845 DBG_ASSERT(m_metaList.find(name) != m_metaList.end(),
846 "SfxDocumentMetaData::setMetaList: not found");
847 std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
848 m_metaList[name];
850 // if nothing changed, do nothing
851 // alas, this does not check for permutations, or attributes...
852 if ((0 == i_pAttrs)) {
853 if (static_cast<size_t>(i_rValue.getLength()) == vec.size()) {
854 bool isEqual(true);
855 for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
856 css::uno::Reference<css::xml::dom::XNode> xNode(vec.at(i));
857 if (xNode.is()) {
858 ::rtl::OUString val = getNodeText(xNode);
859 if (!val.equals(i_rValue[i])) {
860 isEqual = false;
861 break;
865 if (isEqual) return false;
869 // remove old meta data nodes
871 std::vector<css::uno::Reference<css::xml::dom::XNode> >
872 ::reverse_iterator it(vec.rbegin());
873 try {
874 for ( ;it != vec.rend(); ++it)
876 m_xParent->removeChild(*it);
879 catch (...)
881 // Clean up already removed nodes
882 vec.erase(it.base(), vec.end());
883 throw;
885 vec.clear();
888 // insert new meta data nodes into DOM tree
889 for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
890 css::uno::Reference<css::xml::dom::XElement> xElem(
891 m_xDoc->createElementNS(getNameSpace(i_name), name),
892 css::uno::UNO_QUERY_THROW);
893 css::uno::Reference<css::xml::dom::XNode> xNode(xElem,
894 css::uno::UNO_QUERY_THROW);
895 css::uno::Reference<css::xml::dom::XNode> xTextNode(
896 m_xDoc->createTextNode(i_rValue[i]), css::uno::UNO_QUERY_THROW);
897 // set attributes
898 if (i_pAttrs != 0) {
899 for (std::vector<std::pair<const char*, ::rtl::OUString> >
900 ::const_iterator it = (*i_pAttrs)[i].begin();
901 it != (*i_pAttrs)[i].end(); ++it) {
902 xElem->setAttributeNS(getNameSpace(it->first),
903 ::rtl::OUString::createFromAscii(it->first),
904 it->second);
907 xNode->appendChild(xTextNode);
908 m_xParent->appendChild(xNode);
909 vec.push_back(xNode);
912 return true;
913 } catch (css::xml::dom::DOMException & e) {
914 css::uno::Any a(e);
915 throw css::lang::WrappedTargetRuntimeException(
916 ::rtl::OUString::createFromAscii(
917 "SfxDocumentMetaData::setMetaList: DOM exception"),
918 css::uno::Reference<css::uno::XInterface>(*this), a);
922 // convert property list to string list and attribute list
923 std::pair<css::uno::Sequence< ::rtl::OUString>, AttrVector> SAL_CALL
924 propsToStrings(css::uno::Reference<css::beans::XPropertySet> const & i_xPropSet)
926 ::comphelper::SequenceAsVector< ::rtl::OUString > values;
927 AttrVector attrs;
929 css::uno::Reference<css::beans::XPropertySetInfo> xSetInfo
930 = i_xPropSet->getPropertySetInfo();
931 css::uno::Sequence<css::beans::Property> props = xSetInfo->getProperties();
933 for (sal_Int32 i = 0; i < props.getLength(); ++i) {
934 if (props[i].Attributes & css::beans::PropertyAttribute::TRANSIENT) {
935 continue;
937 const ::rtl::OUString name = props[i].Name;
938 css::uno::Any any;
939 try {
940 any = i_xPropSet->getPropertyValue(name);
941 } catch (css::uno::Exception &) {
942 // ignore
944 const css::uno::Type & type = any.getValueType();
945 std::vector<std::pair<const char*, ::rtl::OUString> > as;
946 as.push_back(std::make_pair(static_cast<const char*>("meta:name"),
947 name));
948 const char* vt = "meta:value-type";
950 // convert according to type
951 if (type == ::cppu::UnoType<bool>::get()) {
952 bool b = false;
953 any >>= b;
954 ::rtl::OUStringBuffer buf;
955 ::sax::Converter::convertBool(buf, b);
956 values.push_back(buf.makeStringAndClear());
957 as.push_back(std::make_pair(vt,
958 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("boolean"))));
959 } else if (type == ::cppu::UnoType< ::rtl::OUString>::get()) {
960 ::rtl::OUString s;
961 any >>= s;
962 values.push_back(s);
963 // #i90847# OOo 2.x does stupid things if value-type="string";
964 // fortunately string is default anyway, so we can just omit it
965 // as.push_back(std::make_pair(vt,
966 // ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("string"))));
967 } else if (type == ::cppu::UnoType<css::util::DateTime>::get()) {
968 css::util::DateTime dt;
969 any >>= dt;
970 values.push_back(dateTimeToText(dt));
971 as.push_back(std::make_pair(vt,
972 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("date"))));
973 } else if (type == ::cppu::UnoType<css::util::Date>::get()) {
974 css::util::Date d;
975 any >>= d;
976 css::util::DateTime dt;
977 dt.Year = d.Year;
978 dt.Month = d.Month;
979 dt.Day = d.Day;
980 values.push_back(dateTimeToText(dt));
981 as.push_back(std::make_pair(vt,
982 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("date"))));
983 } else if (type == ::cppu::UnoType<css::util::Time>::get()) {
984 css::util::Time ut;
985 any >>= ut;
986 values.push_back(durationToText(ut));
987 as.push_back(std::make_pair(vt,
988 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("time"))));
989 } else if (::cppu::UnoType<double>::get().isAssignableFrom(type)) {
990 // support not just double, but anything that can be converted
991 double d = 0;
992 any >>= d;
993 ::rtl::OUStringBuffer buf;
994 ::sax::Converter::convertDouble(buf, d);
995 values.push_back(buf.makeStringAndClear());
996 as.push_back(std::make_pair(vt,
997 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("float"))));
998 } else {
999 DBG_WARNING1("SfxDocumentMetaData: unsupported property type: %s",
1000 OUStringToOString(any.getValueTypeName(),
1001 RTL_TEXTENCODING_UTF8).getStr());
1002 continue;
1004 attrs.push_back(as);
1007 return std::make_pair(values.getAsConstList(), attrs);
1010 // remove the given element from the DOM, and iff i_pAttrs != 0 insert new one
1011 void SAL_CALL
1012 SfxDocumentMetaData::updateElement(const char *i_name,
1013 std::vector<std::pair<const char *, ::rtl::OUString> >* i_pAttrs)
1015 ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
1016 try {
1017 // remove old element
1018 css::uno::Reference<css::xml::dom::XNode> xNode =
1019 m_meta.find(name)->second;
1020 if (xNode.is()) {
1021 m_xParent->removeChild(xNode);
1022 xNode.clear();
1024 // add new element
1025 if (0 != i_pAttrs) {
1026 css::uno::Reference<css::xml::dom::XElement> xElem(
1027 m_xDoc->createElementNS(getNameSpace(i_name), name),
1028 css::uno::UNO_QUERY_THROW);
1029 xNode.set(xElem, css::uno::UNO_QUERY_THROW);
1030 // set attributes
1031 for (std::vector<std::pair<const char *, ::rtl::OUString> >
1032 ::const_iterator it = i_pAttrs->begin();
1033 it != i_pAttrs->end(); ++it) {
1034 xElem->setAttributeNS(getNameSpace(it->first),
1035 ::rtl::OUString::createFromAscii(it->first), it->second);
1037 m_xParent->appendChild(xNode);
1039 m_meta[name] = xNode;
1040 } catch (css::xml::dom::DOMException & e) {
1041 css::uno::Any a(e);
1042 throw css::lang::WrappedTargetRuntimeException(
1043 ::rtl::OUString::createFromAscii(
1044 "SfxDocumentMetaData::updateElement: DOM exception"),
1045 css::uno::Reference<css::uno::XInterface>(*this), a);
1049 // update user-defined meta data in DOM tree
1050 void SAL_CALL SfxDocumentMetaData::updateUserDefinedAndAttributes()
1052 createUserDefined();
1053 css::uno::Reference<css::beans::XPropertySet> xPSet(m_xUserDefined,css::uno::UNO_QUERY_THROW);
1054 std::pair<css::uno::Sequence< ::rtl::OUString>, AttrVector> udStringsAttrs = propsToStrings(xPSet);
1055 (void) setMetaList("meta:user-defined", udStringsAttrs.first,&udStringsAttrs.second);
1057 // update elements with attributes
1058 std::vector<std::pair<const char *, ::rtl::OUString> > attributes;
1059 if (!m_TemplateName.equalsAscii("") || !m_TemplateURL.equalsAscii("")
1060 || isValidDateTime(m_TemplateDate)) {
1061 attributes.push_back(std::make_pair(
1062 static_cast<const char*>("xlink:type"),
1063 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simple"))));
1064 attributes.push_back(std::make_pair(
1065 static_cast<const char*>("xlink:actuate"),
1066 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("onRequest"))));
1067 attributes.push_back(std::make_pair(
1068 static_cast<const char*>("xlink:title"), m_TemplateName));
1069 attributes.push_back(std::make_pair(
1070 static_cast<const char*>("xlink:href" ), m_TemplateURL ));
1071 if (isValidDateTime(m_TemplateDate)) {
1072 attributes.push_back(std::make_pair(
1073 static_cast<const char*>("meta:date" ),
1074 dateTimeToText(m_TemplateDate)));
1076 updateElement("meta:template", &attributes);
1077 } else {
1078 updateElement("meta:template");
1080 attributes.clear();
1082 if (!m_AutoloadURL.equalsAscii("") || (0 != m_AutoloadSecs)) {
1083 attributes.push_back(std::make_pair(
1084 static_cast<const char*>("xlink:href" ), m_AutoloadURL ));
1085 attributes.push_back(std::make_pair(
1086 static_cast<const char*>("meta:delay" ),
1087 durationToText(m_AutoloadSecs)));
1088 updateElement("meta:auto-reload", &attributes);
1089 } else {
1090 updateElement("meta:auto-reload");
1092 attributes.clear();
1094 if (!m_DefaultTarget.equalsAscii("")) {
1095 attributes.push_back(std::make_pair(
1096 static_cast<const char*>("office:target-frame-name"),
1097 m_DefaultTarget));
1098 // xlink:show: _blank -> new, any other value -> replace
1099 const sal_Char* show = m_DefaultTarget.equalsAscii("_blank")
1100 ? "new" : "replace";
1101 attributes.push_back(std::make_pair(
1102 static_cast<const char*>("xlink:show"),
1103 ::rtl::OUString::createFromAscii(show)));
1104 updateElement("meta:hyperlink-behaviour", &attributes);
1105 } else {
1106 updateElement("meta:hyperlink-behaviour");
1108 attributes.clear();
1111 // create empty DOM tree (XDocument)
1112 css::uno::Reference<css::xml::dom::XDocument> SAL_CALL
1113 SfxDocumentMetaData::createDOM() const // throw (css::uno::RuntimeException)
1115 css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1116 m_xContext->getServiceManager());
1117 css::uno::Reference<css::xml::dom::XDocumentBuilder> xBuilder(
1118 xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
1119 "com.sun.star.xml.dom.DocumentBuilder"), m_xContext),
1120 css::uno::UNO_QUERY_THROW );
1121 if (!xBuilder.is()) throw css::uno::RuntimeException(
1122 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::createDOM: "
1123 "cannot create DocumentBuilder service"),
1124 *const_cast<SfxDocumentMetaData*>(this));
1125 css::uno::Reference<css::xml::dom::XDocument> xDoc =
1126 xBuilder->newDocument();
1127 if (!xDoc.is()) throw css::uno::RuntimeException(
1128 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::createDOM: "
1129 "cannot create new document"),
1130 *const_cast<SfxDocumentMetaData*>(this));
1131 return xDoc;
1134 void SAL_CALL
1135 SfxDocumentMetaData::checkInit() const // throw (css::uno::RuntimeException)
1137 if (!m_isInitialized) {
1138 throw css::uno::RuntimeException(::rtl::OUString::createFromAscii(
1139 "SfxDocumentMetaData::checkInit: not initialized"),
1140 *const_cast<SfxDocumentMetaData*>(this));
1142 DBG_ASSERT((m_xDoc.is() && m_xParent.is() ),
1143 "SfxDocumentMetaData::checkInit: reference is null");
1146 // initialize state from DOM tree
1147 void SAL_CALL SfxDocumentMetaData::init(
1148 css::uno::Reference<css::xml::dom::XDocument> i_xDoc)
1149 // throw (css::uno::RuntimeException, css::io::WrongFormatException,
1150 // css::uno::Exception)
1152 if (!i_xDoc.is()) throw css::uno::RuntimeException(
1153 ::rtl::OUString::createFromAscii(
1154 "SfxDocumentMetaData::init: no DOM tree given"), *this);
1156 css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1157 m_xContext->getServiceManager());
1158 css::uno::Reference<css::xml::xpath::XXPathAPI> xPath(
1159 xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
1160 "com.sun.star.xml.xpath.XPathAPI"), m_xContext),
1161 css::uno::UNO_QUERY_THROW );
1162 if (!xPath.is()) throw css::uno::RuntimeException(
1163 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::init:"
1164 " cannot create XPathAPI service"), *this);
1166 m_isInitialized = false;
1167 m_xDoc = i_xDoc;
1168 m_xDoc->normalize();
1170 // select nodes for standard meta data stuff
1171 xPath->registerNS(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")),
1172 ::rtl::OUString::createFromAscii(s_nsXLink));
1173 xPath->registerNS(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("dc")),
1174 ::rtl::OUString::createFromAscii(s_nsDC));
1175 xPath->registerNS(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("office")),
1176 ::rtl::OUString::createFromAscii(s_nsODF));
1177 xPath->registerNS(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("meta")),
1178 ::rtl::OUString::createFromAscii(s_nsODFMeta));
1179 // NB: we do not handle the single-XML-file ODF variant, which would
1180 // have the root element office:document.
1181 // The root of such documents must be converted in the importer!
1182 ::rtl::OUString prefix = ::rtl::OUString::createFromAscii(
1183 "/child::office:document-meta/child::office:meta");
1184 css::uno::Reference<css::xml::dom::XNode> xDocNode(
1185 m_xDoc, css::uno::UNO_QUERY_THROW);
1186 m_xParent.clear();
1187 try {
1188 m_xParent = xPath->selectSingleNode(xDocNode, prefix);
1189 } catch (com::sun::star::uno::Exception &) {
1190 // DBG_WARNING("SfxDocumentMetaData::init: "
1191 // "caught RuntimeException from libxml!");
1194 if (!m_xParent.is()) {
1195 // all this create/append stuff may throw DOMException
1196 try {
1197 css::uno::Reference<css::xml::dom::XElement> xRElem(
1198 i_xDoc->createElementNS(
1199 ::rtl::OUString::createFromAscii(s_nsODF),
1200 ::rtl::OUString::createFromAscii("office:document-meta")));
1201 css::uno::Reference<css::xml::dom::XNode> xRNode(xRElem,
1202 css::uno::UNO_QUERY_THROW);
1203 // NB: the following is a _bad_idea_ with our DOM implementation
1204 // do _not_ create attributes with xmlns prefix!
1205 // xRElem->setAttribute(::rtl::OUString::createFromAscii("xmlns:office"),
1206 // ::rtl::OUString::createFromAscii(s_nsODF));
1207 xRElem->setAttributeNS(::rtl::OUString::createFromAscii(s_nsODF),
1208 ::rtl::OUString::createFromAscii("office:version"),
1209 ::rtl::OUString::createFromAscii("1.0"));
1210 i_xDoc->appendChild(xRNode);
1211 css::uno::Reference<css::xml::dom::XNode> xParent (
1212 i_xDoc->createElementNS(
1213 ::rtl::OUString::createFromAscii(s_nsODF),
1214 ::rtl::OUString::createFromAscii("office:meta")),
1215 css::uno::UNO_QUERY_THROW);
1216 xRNode->appendChild(xParent);
1217 m_xParent = xParent;
1218 } catch (css::xml::dom::DOMException & e) {
1219 css::uno::Any a(e);
1220 throw css::lang::WrappedTargetRuntimeException(
1221 ::rtl::OUString::createFromAscii(
1222 "SfxDocumentMetaData::init: DOM exception"),
1223 css::uno::Reference<css::uno::XInterface>(*this), a);
1228 // select nodes for elements of which we only handle one occurrence
1229 for (const char **pName = s_stdMeta; *pName != 0; ++pName) {
1230 ::rtl::OUString name = ::rtl::OUString::createFromAscii(*pName);
1231 // NB: If a document contains more than one occurrence of a
1232 // meta-data element, we arbitrarily pick one of them here.
1233 // We do not remove the others, i.e., when we write the
1234 // document, it will contain the duplicates unchanged.
1235 // The ODF spec says that handling multiple occurrences is
1236 // application-specific.
1237 css::uno::Reference<css::xml::dom::XNode> xNode =
1238 xPath->selectSingleNode(m_xParent,
1239 ::rtl::OUString::createFromAscii("child::") + name);
1240 // Do not create an empty element if it is missing;
1241 // for certain elements, such as dateTime, this would be invalid
1242 m_meta[name] = xNode;
1245 // select nodes for elements of which we handle all occurrences
1246 for (const char **pName = s_stdMetaList; *pName != 0; ++pName) {
1247 ::rtl::OUString name = ::rtl::OUString::createFromAscii(*pName);
1248 css::uno::Reference<css::xml::dom::XNodeList> nodes =
1249 xPath->selectNodeList(m_xParent,
1250 ::rtl::OUString::createFromAscii("child::") + name);
1251 std::vector<css::uno::Reference<css::xml::dom::XNode> > v;
1252 for (sal_Int32 i = 0; i < nodes->getLength(); ++i) {
1253 v.push_back(nodes->item(i));
1255 m_metaList[name] = v;
1258 // initialize members corresponding to attributes from DOM nodes
1259 m_TemplateName = getMetaAttr("meta:template", "xlink:title");
1260 m_TemplateURL = getMetaAttr("meta:template", "xlink:href");
1261 m_TemplateDate =
1262 textToDateTimeDefault(getMetaAttr("meta:template", "meta:date"));
1263 m_AutoloadURL = getMetaAttr("meta:auto-reload", "xlink:href");
1264 m_AutoloadSecs =
1265 textToDuration(getMetaAttr("meta:auto-reload", "meta:delay"));
1266 m_DefaultTarget =
1267 getMetaAttr("meta:hyperlink-behaviour", "office:target-frame-name");
1270 std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
1271 m_metaList[::rtl::OUString::createFromAscii("meta:user-defined")];
1272 // user-defined meta data: create PropertyBag which only accepts property
1273 // values of allowed types
1274 if ( !vec.empty() )
1276 createUserDefined();
1279 // user-defined meta data: initialize PropertySet from DOM nodes
1281 for (std::vector<css::uno::Reference<css::xml::dom::XNode> >::iterator
1282 it = vec.begin(); it != vec.end(); ++it) {
1283 css::uno::Reference<css::xml::dom::XElement> xElem(*it,
1284 css::uno::UNO_QUERY_THROW);
1285 css::uno::Any any;
1286 ::rtl::OUString name = xElem->getAttributeNS(
1287 ::rtl::OUString::createFromAscii(s_nsODFMeta),
1288 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("name")));
1289 ::rtl::OUString type = xElem->getAttributeNS(
1290 ::rtl::OUString::createFromAscii(s_nsODFMeta),
1291 ::rtl::OUString::createFromAscii("value-type"));
1292 ::rtl::OUString text = getNodeText(*it);
1293 if (type.equalsAscii("float")) {
1294 double d;
1295 if (::sax::Converter::convertDouble(d, text)) {
1296 any <<= d;
1297 } else {
1298 DBG_WARNING1("SfxDocumentMetaData: invalid float: %s",
1299 OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1300 continue;
1302 } else if (type.equalsAscii("date")) {
1303 css::util::DateTime dt;
1304 if (textToDateTime(dt, text)) {
1305 any <<= dt;
1306 } else {
1307 DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
1308 OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1309 continue;
1311 } else if (type.equalsAscii("time")) {
1312 css::util::Time ut;
1313 if (textToDuration(ut, text)) {
1314 any <<= ut;
1315 } else {
1316 DBG_WARNING1("SfxDocumentMetaData: invalid time: %s",
1317 OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1318 continue;
1320 } else if (type.equalsAscii("boolean")) {
1321 bool b;
1322 if (::sax::Converter::convertBool(b, text)) {
1323 any <<= b;
1324 } else {
1325 DBG_WARNING1("SfxDocumentMetaData: invalid boolean: %s",
1326 OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1327 continue;
1329 } else if (type.equalsAscii("string") || true) { // default
1330 any <<= text;
1332 try {
1333 m_xUserDefined->addProperty(name,
1334 css::beans::PropertyAttribute::REMOVEABLE, any);
1335 } catch (css::beans::PropertyExistException &) {
1336 DBG_WARNING1("SfxDocumentMetaData: duplicate: %s",
1337 OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
1338 // ignore; duplicate
1339 } catch (css::beans::IllegalTypeException &) {
1340 DBG_ERROR1("SfxDocumentMetaData: illegal type: %s",
1341 OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
1342 } catch (css::lang::IllegalArgumentException &) {
1343 DBG_ERROR1("SfxDocumentMetaData: illegal arg: %s",
1344 OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
1348 m_isModified = false;
1349 m_isInitialized = true;
1353 ////////////////////////////////////////////////////////////////////////////
1355 SfxDocumentMetaData::SfxDocumentMetaData(
1356 css::uno::Reference< css::uno::XComponentContext > const & context) :
1357 BaseMutex(), SfxDocumentMetaData_Base(m_aMutex),
1358 m_xContext(context), m_NotifyListeners(m_aMutex),
1359 m_isInitialized(false), m_isModified(false)
1361 DBG_ASSERT(context.is(), "SfxDocumentMetaData: context is null");
1362 DBG_ASSERT(context->getServiceManager().is(),
1363 "SfxDocumentMetaData: context has no service manager");
1364 init(createDOM());
1367 // com.sun.star.uno.XServiceInfo:
1368 ::rtl::OUString SAL_CALL
1369 SfxDocumentMetaData::getImplementationName() throw (css::uno::RuntimeException)
1371 return comp_SfxDocumentMetaData::_getImplementationName();
1374 ::sal_Bool SAL_CALL
1375 SfxDocumentMetaData::supportsService(::rtl::OUString const & serviceName)
1376 throw (css::uno::RuntimeException)
1378 css::uno::Sequence< ::rtl::OUString > serviceNames =
1379 comp_SfxDocumentMetaData::_getSupportedServiceNames();
1380 for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
1381 if (serviceNames[i] == serviceName)
1382 return sal_True;
1384 return sal_False;
1387 css::uno::Sequence< ::rtl::OUString > SAL_CALL
1388 SfxDocumentMetaData::getSupportedServiceNames()
1389 throw (css::uno::RuntimeException)
1391 return comp_SfxDocumentMetaData::_getSupportedServiceNames();
1395 // ::com::sun::star::lang::XComponent:
1396 void SAL_CALL SfxDocumentMetaData::dispose() throw (css::uno::RuntimeException)
1398 ::osl::MutexGuard g(m_aMutex);
1399 if (!m_isInitialized) {
1400 return;
1402 WeakComponentImplHelperBase::dispose(); // superclass
1403 m_NotifyListeners.disposeAndClear(css::lang::EventObject(
1404 static_cast< ::cppu::OWeakObject* >(this)));
1405 m_isInitialized = false;
1406 m_meta.clear();
1407 m_metaList.clear();
1408 m_xParent.clear();
1409 m_xDoc.clear();
1410 m_xUserDefined.clear();
1414 // ::com::sun::star::document::XDocumentProperties:
1415 ::rtl::OUString SAL_CALL
1416 SfxDocumentMetaData::getAuthor() throw (css::uno::RuntimeException)
1418 ::osl::MutexGuard g(m_aMutex);
1419 return getMetaText("meta:initial-creator");
1422 void SAL_CALL SfxDocumentMetaData::setAuthor(const ::rtl::OUString & the_value)
1423 throw (css::uno::RuntimeException)
1425 setMetaTextAndNotify("meta:initial-creator", the_value);
1429 ::rtl::OUString SAL_CALL
1430 SfxDocumentMetaData::getGenerator() throw (css::uno::RuntimeException)
1432 ::osl::MutexGuard g(m_aMutex);
1433 return getMetaText("meta:generator");
1436 void SAL_CALL
1437 SfxDocumentMetaData::setGenerator(const ::rtl::OUString & the_value)
1438 throw (css::uno::RuntimeException)
1440 setMetaTextAndNotify("meta:generator", the_value);
1443 css::util::DateTime SAL_CALL
1444 SfxDocumentMetaData::getCreationDate() throw (css::uno::RuntimeException)
1446 ::osl::MutexGuard g(m_aMutex);
1447 return textToDateTimeDefault(getMetaText("meta:creation-date"));
1450 void SAL_CALL
1451 SfxDocumentMetaData::setCreationDate(const css::util::DateTime & the_value)
1452 throw (css::uno::RuntimeException)
1454 setMetaTextAndNotify("meta:creation-date", dateTimeToText(the_value));
1457 ::rtl::OUString SAL_CALL
1458 SfxDocumentMetaData::getTitle() throw (css::uno::RuntimeException)
1460 ::osl::MutexGuard g(m_aMutex);
1461 return getMetaText("dc:title");
1464 void SAL_CALL SfxDocumentMetaData::setTitle(const ::rtl::OUString & the_value)
1465 throw (css::uno::RuntimeException)
1467 setMetaTextAndNotify("dc:title", the_value);
1470 ::rtl::OUString SAL_CALL
1471 SfxDocumentMetaData::getSubject() throw (css::uno::RuntimeException)
1473 ::osl::MutexGuard g(m_aMutex);
1474 return getMetaText("dc:subject");
1477 void SAL_CALL
1478 SfxDocumentMetaData::setSubject(const ::rtl::OUString & the_value)
1479 throw (css::uno::RuntimeException)
1481 setMetaTextAndNotify("dc:subject", the_value);
1484 ::rtl::OUString SAL_CALL
1485 SfxDocumentMetaData::getDescription() throw (css::uno::RuntimeException)
1487 ::osl::MutexGuard g(m_aMutex);
1488 return getMetaText("dc:description");
1491 void SAL_CALL
1492 SfxDocumentMetaData::setDescription(const ::rtl::OUString & the_value)
1493 throw (css::uno::RuntimeException)
1495 setMetaTextAndNotify("dc:description", the_value);
1498 css::uno::Sequence< ::rtl::OUString >
1499 SAL_CALL SfxDocumentMetaData::getKeywords() throw (css::uno::RuntimeException)
1501 ::osl::MutexGuard g(m_aMutex);
1502 return getMetaList("meta:keyword");
1505 void SAL_CALL
1506 SfxDocumentMetaData::setKeywords(
1507 const css::uno::Sequence< ::rtl::OUString > & the_value)
1508 throw (css::uno::RuntimeException)
1510 ::osl::ClearableMutexGuard g(m_aMutex);
1511 if (setMetaList("meta:keyword", the_value)) {
1512 g.clear();
1513 setModified(true);
1517 css::lang::Locale SAL_CALL
1518 SfxDocumentMetaData::getLanguage() throw (css::uno::RuntimeException)
1520 ::osl::MutexGuard g(m_aMutex);
1521 css::lang::Locale loc;
1522 ::rtl::OUString text = getMetaText("dc:language");
1523 sal_Int32 ix = text.indexOf(static_cast<sal_Unicode> ('-'));
1524 if (ix == -1) {
1525 loc.Language = text;
1526 } else {
1527 loc.Language = text.copy(0, ix);
1528 loc.Country = text.copy(ix+1);
1530 return loc;
1533 void SAL_CALL
1534 SfxDocumentMetaData::setLanguage(const css::lang::Locale & the_value)
1535 throw (css::uno::RuntimeException)
1537 ::rtl::OUString text = the_value.Language;
1538 if (the_value.Country.getLength() > 0) {
1539 text += ::rtl::OUString::createFromAscii("-").concat(the_value.Country);
1541 setMetaTextAndNotify("dc:language", text);
1544 ::rtl::OUString SAL_CALL
1545 SfxDocumentMetaData::getModifiedBy() throw (css::uno::RuntimeException)
1547 ::osl::MutexGuard g(m_aMutex);
1548 return getMetaText("dc:creator");
1551 void SAL_CALL
1552 SfxDocumentMetaData::setModifiedBy(const ::rtl::OUString & the_value)
1553 throw (css::uno::RuntimeException)
1555 setMetaTextAndNotify("dc:creator", the_value);
1558 css::util::DateTime SAL_CALL
1559 SfxDocumentMetaData::getModificationDate() throw (css::uno::RuntimeException)
1561 ::osl::MutexGuard g(m_aMutex);
1562 return textToDateTimeDefault(getMetaText("dc:date"));
1565 void SAL_CALL
1566 SfxDocumentMetaData::setModificationDate(const css::util::DateTime & the_value)
1567 throw (css::uno::RuntimeException)
1569 setMetaTextAndNotify("dc:date", dateTimeToText(the_value));
1572 ::rtl::OUString SAL_CALL
1573 SfxDocumentMetaData::getPrintedBy() throw (css::uno::RuntimeException)
1575 ::osl::MutexGuard g(m_aMutex);
1576 return getMetaText("meta:printed-by");
1579 void SAL_CALL
1580 SfxDocumentMetaData::setPrintedBy(const ::rtl::OUString & the_value)
1581 throw (css::uno::RuntimeException)
1583 setMetaTextAndNotify("meta:printed-by", the_value);
1586 css::util::DateTime SAL_CALL
1587 SfxDocumentMetaData::getPrintDate() throw (css::uno::RuntimeException)
1589 ::osl::MutexGuard g(m_aMutex);
1590 return textToDateTimeDefault(getMetaText("meta:print-date"));
1593 void SAL_CALL
1594 SfxDocumentMetaData::setPrintDate(const css::util::DateTime & the_value)
1595 throw (css::uno::RuntimeException)
1597 setMetaTextAndNotify("meta:print-date", dateTimeToText(the_value));
1600 ::rtl::OUString SAL_CALL
1601 SfxDocumentMetaData::getTemplateName() throw (css::uno::RuntimeException)
1603 ::osl::MutexGuard g(m_aMutex);
1604 checkInit();
1605 return m_TemplateName;
1608 void SAL_CALL
1609 SfxDocumentMetaData::setTemplateName(const ::rtl::OUString & the_value)
1610 throw (css::uno::RuntimeException)
1612 ::osl::ClearableMutexGuard g(m_aMutex);
1613 checkInit();
1614 if (m_TemplateName != the_value) {
1615 m_TemplateName = the_value;
1616 g.clear();
1617 setModified(true);
1621 ::rtl::OUString SAL_CALL
1622 SfxDocumentMetaData::getTemplateURL() throw (css::uno::RuntimeException)
1624 ::osl::MutexGuard g(m_aMutex);
1625 checkInit();
1626 return m_TemplateURL;
1629 void SAL_CALL
1630 SfxDocumentMetaData::setTemplateURL(const ::rtl::OUString & the_value)
1631 throw (css::uno::RuntimeException)
1633 ::osl::ClearableMutexGuard g(m_aMutex);
1634 checkInit();
1635 if (m_TemplateURL != the_value) {
1636 m_TemplateURL = the_value;
1637 g.clear();
1638 setModified(true);
1642 css::util::DateTime SAL_CALL
1643 SfxDocumentMetaData::getTemplateDate() throw (css::uno::RuntimeException)
1645 ::osl::MutexGuard g(m_aMutex);
1646 checkInit();
1647 return m_TemplateDate;
1650 void SAL_CALL
1651 SfxDocumentMetaData::setTemplateDate(const css::util::DateTime & the_value)
1652 throw (css::uno::RuntimeException)
1654 ::osl::ClearableMutexGuard g(m_aMutex);
1655 checkInit();
1656 if (!(m_TemplateDate == the_value)) {
1657 m_TemplateDate = the_value;
1658 g.clear();
1659 setModified(true);
1663 ::rtl::OUString SAL_CALL
1664 SfxDocumentMetaData::getAutoloadURL() throw (css::uno::RuntimeException)
1666 ::osl::MutexGuard g(m_aMutex);
1667 checkInit();
1668 return m_AutoloadURL;
1671 void SAL_CALL
1672 SfxDocumentMetaData::setAutoloadURL(const ::rtl::OUString & the_value)
1673 throw (css::uno::RuntimeException)
1675 ::osl::ClearableMutexGuard g(m_aMutex);
1676 checkInit();
1677 if (m_AutoloadURL != the_value) {
1678 m_AutoloadURL = the_value;
1679 g.clear();
1680 setModified(true);
1684 ::sal_Int32 SAL_CALL
1685 SfxDocumentMetaData::getAutoloadSecs() throw (css::uno::RuntimeException)
1687 ::osl::MutexGuard g(m_aMutex);
1688 checkInit();
1689 return m_AutoloadSecs;
1692 void SAL_CALL
1693 SfxDocumentMetaData::setAutoloadSecs(::sal_Int32 the_value)
1694 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
1696 if (the_value < 0) throw css::lang::IllegalArgumentException(
1697 ::rtl::OUString::createFromAscii(
1698 "SfxDocumentMetaData::setAutoloadSecs: argument is negative"),
1699 *this, 0);
1700 ::osl::ClearableMutexGuard g(m_aMutex);
1701 checkInit();
1702 if (m_AutoloadSecs != the_value) {
1703 m_AutoloadSecs = the_value;
1704 g.clear();
1705 setModified(true);
1709 ::rtl::OUString SAL_CALL
1710 SfxDocumentMetaData::getDefaultTarget() throw (css::uno::RuntimeException)
1712 ::osl::MutexGuard g(m_aMutex);
1713 checkInit();
1714 return m_DefaultTarget;
1717 void SAL_CALL
1718 SfxDocumentMetaData::setDefaultTarget(const ::rtl::OUString & the_value)
1719 throw (css::uno::RuntimeException)
1721 ::osl::ClearableMutexGuard g(m_aMutex);
1722 checkInit();
1723 if (m_DefaultTarget != the_value) {
1724 m_DefaultTarget = the_value;
1725 g.clear();
1726 setModified(true);
1730 css::uno::Sequence< css::beans::NamedValue > SAL_CALL
1731 SfxDocumentMetaData::getDocumentStatistics() throw (css::uno::RuntimeException)
1733 ::osl::MutexGuard g(m_aMutex);
1734 checkInit();
1735 ::comphelper::SequenceAsVector<css::beans::NamedValue> stats;
1736 for (size_t i = 0; s_stdStats[i] != 0; ++i) {
1737 const char * aName = s_stdStatAttrs[i];
1738 ::rtl::OUString text = getMetaAttr("meta:document-statistic", aName);
1739 if (text.equalsAscii("")) continue;
1740 css::beans::NamedValue stat;
1741 stat.Name = ::rtl::OUString::createFromAscii(s_stdStats[i]);
1742 sal_Int32 val;
1743 css::uno::Any any;
1744 if (!::sax::Converter::convertNumber(val, text, 0,
1745 std::numeric_limits<sal_Int32>::max()) || (val < 0)) {
1746 val = 0;
1747 DBG_WARNING1("SfxDocumentMetaData: invalid number: %s",
1748 OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
1750 any <<= val;
1751 stat.Value = any;
1752 stats.push_back(stat);
1755 return stats.getAsConstList();
1758 void SAL_CALL
1759 SfxDocumentMetaData::setDocumentStatistics(
1760 const css::uno::Sequence< css::beans::NamedValue > & the_value)
1761 throw (css::uno::RuntimeException)
1763 ::osl::ClearableMutexGuard g(m_aMutex);
1764 checkInit();
1765 std::vector<std::pair<const char *, ::rtl::OUString> > attributes;
1766 for (sal_Int32 i = 0; i < the_value.getLength(); ++i) {
1767 const ::rtl::OUString name = the_value[i].Name;
1768 // inefficently search for matching attribute
1769 for (size_t j = 0; s_stdStats[j] != 0; ++j) {
1770 if (name.equalsAscii(s_stdStats[j])) {
1771 const css::uno::Any any = the_value[i].Value;
1772 sal_Int32 val = 0;
1773 if (any >>= val) {
1774 ::rtl::OUStringBuffer buf;
1775 ::sax::Converter::convertNumber(buf, val);
1776 attributes.push_back(std::make_pair(s_stdStatAttrs[j],
1777 buf.makeStringAndClear()));
1778 } else {
1779 DBG_WARNING1("SfxDocumentMetaData: invalid statistic: %s",
1780 OUStringToOString(name, RTL_TEXTENCODING_UTF8)
1781 .getStr());
1783 break;
1787 updateElement("meta:document-statistic", &attributes);
1788 g.clear();
1789 setModified(true);
1792 ::sal_Int16 SAL_CALL
1793 SfxDocumentMetaData::getEditingCycles() throw (css::uno::RuntimeException)
1795 ::osl::MutexGuard g(m_aMutex);
1796 ::rtl::OUString text = getMetaText("meta:editing-cycles");
1797 sal_Int32 ret;
1798 if (::sax::Converter::convertNumber(ret, text,
1799 0, std::numeric_limits<sal_Int16>::max())) {
1800 return static_cast<sal_Int16>(ret);
1801 } else {
1802 return 0;
1806 void SAL_CALL
1807 SfxDocumentMetaData::setEditingCycles(::sal_Int16 the_value)
1808 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
1810 if (the_value < 0) throw css::lang::IllegalArgumentException(
1811 ::rtl::OUString::createFromAscii(
1812 "SfxDocumentMetaData::setEditingCycles: argument is negative"),
1813 *this, 0);
1814 ::rtl::OUStringBuffer buf;
1815 ::sax::Converter::convertNumber(buf, the_value);
1816 setMetaTextAndNotify("meta:editing-cycles", buf.makeStringAndClear());
1819 ::sal_Int32 SAL_CALL
1820 SfxDocumentMetaData::getEditingDuration() throw (css::uno::RuntimeException)
1822 ::osl::MutexGuard g(m_aMutex);
1823 return textToDuration(getMetaText("meta:editing-duration"));
1826 void SAL_CALL
1827 SfxDocumentMetaData::setEditingDuration(::sal_Int32 the_value)
1828 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
1830 if (the_value < 0) throw css::lang::IllegalArgumentException(
1831 ::rtl::OUString::createFromAscii(
1832 "SfxDocumentMetaData::setEditingDuration: argument is negative"),
1833 *this, 0);
1834 setMetaTextAndNotify("meta:editing-duration", durationToText(the_value));
1837 void SAL_CALL
1838 SfxDocumentMetaData::resetUserData(const ::rtl::OUString & the_value)
1839 throw (css::uno::RuntimeException)
1841 ::osl::ClearableMutexGuard g(m_aMutex);
1843 bool bModified( false );
1844 bModified |= setMetaText("meta:initial-creator", the_value);
1845 ::DateTime now = DateTime();
1846 css::util::DateTime uDT(now.Get100Sec(), now.GetSec(), now.GetMin(),
1847 now.GetHour(), now.GetDay(), now.GetMonth(), now.GetYear());
1848 bModified |= setMetaText("meta:creation-date", dateTimeToText(uDT));
1849 bModified |= setMetaText("dc:creator", ::rtl::OUString());
1850 bModified |= setMetaText("meta:printed-by", ::rtl::OUString());
1851 bModified |= setMetaText("dc:date", dateTimeToText(css::util::DateTime()));
1852 bModified |= setMetaText("meta:print-date",
1853 dateTimeToText(css::util::DateTime()));
1854 bModified |= setMetaText("meta:editing-duration", durationToText(0));
1855 bModified |= setMetaText("meta:editing-cycles",
1856 ::rtl::OUString::createFromAscii("1"));
1858 if (bModified) {
1859 g.clear();
1860 setModified(true);
1865 css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
1866 SfxDocumentMetaData::getUserDefinedProperties()
1867 throw (css::uno::RuntimeException)
1869 ::osl::MutexGuard g(m_aMutex);
1870 checkInit();
1871 createUserDefined();
1872 return m_xUserDefined;
1876 void SAL_CALL
1877 SfxDocumentMetaData::loadFromStorage(
1878 const css::uno::Reference< css::embed::XStorage > & xStorage,
1879 const css::uno::Sequence< css::beans::PropertyValue > & Medium)
1880 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
1881 css::io::WrongFormatException,
1882 css::lang::WrappedTargetException, css::io::IOException,
1883 css::uno::Exception)
1885 if (!xStorage.is()) throw css::lang::IllegalArgumentException(
1886 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::loadFromStorage:"
1887 " argument is null"), *this, 0);
1888 ::osl::MutexGuard g(m_aMutex);
1890 // open meta data file
1891 css::uno::Reference<css::io::XStream> xStream(
1892 xStorage->openStreamElement(
1893 ::rtl::OUString::createFromAscii(s_metaXml),
1894 css::embed::ElementModes::READ) );
1895 if (!xStream.is()) throw css::lang::NullPointerException();
1896 css::uno::Reference<css::io::XInputStream> xInStream =
1897 xStream->getInputStream();
1898 if (!xInStream.is()) throw css::lang::NullPointerException();
1900 // create DOM parser service
1901 css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1902 m_xContext->getServiceManager());
1903 css::uno::Reference<css::xml::sax::XParser> xParser (
1904 xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
1905 "com.sun.star.xml.sax.Parser"), m_xContext),
1906 css::uno::UNO_QUERY_THROW);
1907 if (!xParser.is()) throw css::uno::RuntimeException(
1908 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::loadFromStorage:"
1909 " cannot create Parser service"), *this);
1910 css::xml::sax::InputSource input;
1911 input.aInputStream = xInStream;
1913 sal_uInt64 version = SotStorage::GetVersion( xStorage );
1914 // Oasis is also the default (0)
1915 sal_Bool bOasis = ( version > SOFFICE_FILEFORMAT_60 || version == 0 );
1916 const sal_Char *pServiceName = bOasis
1917 ? "com.sun.star.document.XMLOasisMetaImporter"
1918 : "com.sun.star.document.XMLMetaImporter";
1920 // set base URL
1921 css::uno::Reference<css::beans::XPropertySet> xPropArg =
1922 getURLProperties(Medium);
1923 try {
1924 xPropArg->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI")))
1925 >>= input.sSystemId;
1926 input.sSystemId += ::rtl::OUString::createFromAscii("/").concat(
1927 ::rtl::OUString::createFromAscii(s_metaXml));
1928 } catch (css::uno::Exception &) {
1929 input.sSystemId = ::rtl::OUString::createFromAscii(s_metaXml);
1931 css::uno::Sequence< css::uno::Any > args(1);
1932 args[0] <<= xPropArg;
1934 css::uno::Reference<css::xml::sax::XDocumentHandler> xDocHandler (
1935 xMsf->createInstanceWithArgumentsAndContext(
1936 ::rtl::OUString::createFromAscii(pServiceName), args, m_xContext),
1937 css::uno::UNO_QUERY_THROW);
1938 if (!xDocHandler.is()) throw css::uno::RuntimeException(
1939 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::loadFromStorage:"
1940 " cannot create XMLOasisMetaImporter service"), *this);
1941 css::uno::Reference<css::document::XImporter> xImp (xDocHandler,
1942 css::uno::UNO_QUERY_THROW);
1943 xImp->setTargetDocument(css::uno::Reference<css::lang::XComponent>(this));
1944 xParser->setDocumentHandler(xDocHandler);
1945 try {
1946 xParser->parseStream(input);
1947 } catch (css::xml::sax::SAXException &) {
1948 throw css::io::WrongFormatException(::rtl::OUString::createFromAscii(
1949 "SfxDocumentMetaData::loadFromStorage:"
1950 " XML parsing exception"), *this);
1952 // NB: the implementation of XMLOasisMetaImporter calls initialize
1953 // init(xDocBuilder->getDocument());
1954 checkInit();
1957 void SAL_CALL
1958 SfxDocumentMetaData::storeToStorage(
1959 const css::uno::Reference< css::embed::XStorage > & xStorage,
1960 const css::uno::Sequence< css::beans::PropertyValue > & Medium)
1961 throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
1962 css::lang::WrappedTargetException, css::io::IOException,
1963 css::uno::Exception)
1965 if (!xStorage.is()) throw css::lang::IllegalArgumentException(
1966 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::storeToStorage:"
1967 " argument is null"), *this, 0);
1968 ::osl::MutexGuard g(m_aMutex);
1969 checkInit();
1971 // update user-defined meta data in DOM tree
1972 // updateUserDefinedAndAttributes(); // this will be done in serialize!
1974 // write into storage
1975 css::uno::Reference<css::io::XStream> xStream =
1976 xStorage->openStreamElement(::rtl::OUString::createFromAscii(s_metaXml),
1977 css::embed::ElementModes::WRITE
1978 | css::embed::ElementModes::TRUNCATE);
1979 if (!xStream.is()) throw css::lang::NullPointerException();
1980 css::uno::Reference< css::beans::XPropertySet > xStreamProps(xStream,
1981 css::uno::UNO_QUERY_THROW);
1982 xStreamProps->setPropertyValue(
1983 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MediaType")),
1984 css::uno::makeAny(::rtl::OUString::createFromAscii("text/xml")));
1985 xStreamProps->setPropertyValue(
1986 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Compressed")),
1987 css::uno::makeAny(static_cast<sal_Bool> (sal_False)));
1988 xStreamProps->setPropertyValue(
1989 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption")),
1990 css::uno::makeAny(static_cast<sal_Bool> (sal_False)));
1991 css::uno::Reference<css::io::XOutputStream> xOutStream =
1992 xStream->getOutputStream();
1993 if (!xOutStream.is()) throw css::lang::NullPointerException();
1994 css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1995 m_xContext->getServiceManager());
1996 css::uno::Reference<css::io::XActiveDataSource> xSaxWriter(
1997 xMsf->createInstanceWithContext(::rtl::OUString::createFromAscii(
1998 "com.sun.star.xml.sax.Writer"), m_xContext),
1999 css::uno::UNO_QUERY_THROW);
2000 xSaxWriter->setOutputStream(xOutStream);
2001 css::uno::Reference<css::xml::sax::XDocumentHandler> xDocHandler (
2002 xSaxWriter, css::uno::UNO_QUERY_THROW);
2004 const sal_uInt64 version = SotStorage::GetVersion( xStorage );
2005 // Oasis is also the default (0)
2006 const sal_Bool bOasis = ( version > SOFFICE_FILEFORMAT_60 || version == 0 );
2007 const sal_Char *pServiceName = bOasis
2008 ? "com.sun.star.document.XMLOasisMetaExporter"
2009 : "com.sun.star.document.XMLMetaExporter";
2011 // set base URL
2012 css::uno::Reference<css::beans::XPropertySet> xPropArg =
2013 getURLProperties(Medium);
2014 css::uno::Sequence< css::uno::Any > args(2);
2015 args[0] <<= xDocHandler;
2016 args[1] <<= xPropArg;
2018 css::uno::Reference<css::document::XExporter> xExp(
2019 xMsf->createInstanceWithArgumentsAndContext(
2020 ::rtl::OUString::createFromAscii(pServiceName), args, m_xContext),
2021 css::uno::UNO_QUERY_THROW);
2022 xExp->setSourceDocument(css::uno::Reference<css::lang::XComponent>(this));
2023 css::uno::Reference<css::document::XFilter> xFilter(xExp,
2024 css::uno::UNO_QUERY_THROW);
2025 if (xFilter->filter(css::uno::Sequence< css::beans::PropertyValue >())) {
2026 css::uno::Reference<css::embed::XTransactedObject> xTransaction(
2027 xStorage, css::uno::UNO_QUERY);
2028 if (xTransaction.is()) {
2029 xTransaction->commit();
2031 } else {
2032 throw css::io::IOException(::rtl::OUString::createFromAscii(
2033 "SfxDocumentMetaData::storeToStorage: cannot filter"), *this);
2037 void SAL_CALL
2038 SfxDocumentMetaData::loadFromMedium(const ::rtl::OUString & URL,
2039 const css::uno::Sequence< css::beans::PropertyValue > & Medium)
2040 throw (css::uno::RuntimeException, css::io::WrongFormatException,
2041 css::lang::WrappedTargetException, css::io::IOException,
2042 css::uno::Exception)
2044 css::uno::Reference<css::io::XInputStream> xIn;
2045 ::comphelper::MediaDescriptor md(Medium);
2046 // if we have an URL parameter, it replaces the one in the media descriptor
2047 if (!URL.equalsAscii("")) {
2048 md[ ::comphelper::MediaDescriptor::PROP_URL() ] <<= URL;
2050 if (sal_True == md.addInputStream()) {
2051 md[ ::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] >>= xIn;
2053 css::uno::Reference<css::embed::XStorage> xStorage;
2054 css::uno::Reference<css::lang::XMultiServiceFactory> xMsf (
2055 m_xContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
2056 try {
2057 if (xIn.is()) {
2058 xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream(
2059 xIn, xMsf);
2060 } else { // fallback to url parameter
2061 xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
2062 URL, css::embed::ElementModes::READ, xMsf);
2064 } catch (css::uno::RuntimeException &) {
2065 throw;
2066 } catch (css::io::IOException &) {
2067 throw;
2068 } catch (css::uno::Exception & e) {
2069 throw css::lang::WrappedTargetException(
2070 ::rtl::OUString::createFromAscii(
2071 "SfxDocumentMetaData::loadFromMedium: exception"),
2072 css::uno::Reference<css::uno::XInterface>(*this),
2073 css::uno::makeAny(e));
2075 if (!xStorage.is()) {
2076 throw css::lang::NullPointerException(::rtl::OUString::createFromAscii(
2077 "SfxDocumentMetaData::loadFromMedium: cannot get Storage"),
2078 *this);
2080 loadFromStorage(xStorage, md.getAsConstPropertyValueList());
2083 void SAL_CALL
2084 SfxDocumentMetaData::storeToMedium(const ::rtl::OUString & URL,
2085 const css::uno::Sequence< css::beans::PropertyValue > & Medium)
2086 throw (css::uno::RuntimeException,
2087 css::lang::WrappedTargetException, css::io::IOException,
2088 css::uno::Exception)
2090 ::comphelper::MediaDescriptor md(Medium);
2091 if (!URL.equalsAscii("")) {
2092 md[ ::comphelper::MediaDescriptor::PROP_URL() ] <<= URL;
2094 SfxMedium aMedium(md.getAsConstPropertyValueList());
2095 css::uno::Reference<css::embed::XStorage> xStorage
2096 = aMedium.GetOutputStorage();
2099 if (!xStorage.is()) {
2100 throw css::lang::NullPointerException(::rtl::OUString::createFromAscii(
2101 "SfxDocumentMetaData::storeToMedium: cannot get Storage"),
2102 *this);
2104 // set MIME type of the storage
2105 ::comphelper::MediaDescriptor::const_iterator iter
2106 = md.find(::comphelper::MediaDescriptor::PROP_MEDIATYPE());
2107 if (iter != md.end()) {
2108 css::uno::Reference< css::beans::XPropertySet > xProps(xStorage,
2109 css::uno::UNO_QUERY_THROW);
2110 xProps->setPropertyValue(
2111 ::comphelper::MediaDescriptor::PROP_MEDIATYPE(),
2112 iter->second);
2114 storeToStorage(xStorage, md.getAsConstPropertyValueList());
2117 const sal_Bool bOk = aMedium.Commit();
2118 aMedium.Close();
2119 if ( !bOk ) {
2120 sal_uInt32 nError = aMedium.GetError();
2121 if ( nError == ERRCODE_NONE ) {
2122 nError = ERRCODE_IO_GENERAL;
2125 throw css::task::ErrorCodeIOException( ::rtl::OUString(),
2126 css::uno::Reference< css::uno::XInterface >(), nError);
2131 // ::com::sun::star::lang::XInitialization:
2132 void SAL_CALL
2133 SfxDocumentMetaData::initialize(
2134 const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments)
2135 throw (css::uno::RuntimeException, css::uno::Exception)
2137 // possible arguments:
2138 // - no argument: default initialization (empty DOM)
2139 // - 1 argument, XDocument: initialize with given DOM and empty base URL
2140 // NB: links in document must be absolute
2142 ::osl::MutexGuard g(m_aMutex);
2143 css::uno::Reference<css::xml::dom::XDocument> xDoc;
2145 for (sal_Int32 i = 0; i < aArguments.getLength(); ++i) {
2146 const css::uno::Any any = aArguments[i];
2147 if (any >>= xDoc) {
2148 if (!xDoc.is()) {
2149 throw css::lang::IllegalArgumentException(
2150 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::"
2151 "initialize: argument is null"),
2152 *this, static_cast<sal_Int16>(i));
2154 } else {
2155 throw css::lang::IllegalArgumentException(
2156 ::rtl::OUString::createFromAscii("SfxDocumentMetaData::"
2157 "initialize: argument must be XDocument"),
2158 *this, static_cast<sal_Int16>(i));
2162 if (!xDoc.is()) {
2163 // For a new document, we create a new DOM tree here.
2164 xDoc = createDOM();
2167 init(xDoc);
2170 // ::com::sun::star::util::XCloneable:
2171 css::uno::Reference<css::util::XCloneable> SAL_CALL
2172 SfxDocumentMetaData::createClone()
2173 throw (css::uno::RuntimeException)
2175 ::osl::MutexGuard g(m_aMutex);
2176 checkInit();
2178 SfxDocumentMetaData *pNew = createMe(m_xContext);
2180 // NB: do not copy the modification listeners, only DOM
2181 css::uno::Reference<css::xml::dom::XDocument> xDoc = createDOM();
2182 try {
2183 updateUserDefinedAndAttributes();
2184 // deep copy of root node
2185 css::uno::Reference<css::xml::dom::XNode> xRoot(
2186 m_xDoc->getDocumentElement(), css::uno::UNO_QUERY_THROW);
2187 css::uno::Reference<css::xml::dom::XNode> xRootNew(
2188 xDoc->importNode(xRoot, true));
2189 xDoc->appendChild(xRootNew);
2190 pNew->init(xDoc);
2191 } catch (css::uno::RuntimeException &) {
2192 throw;
2193 } catch (css::uno::Exception & e) {
2194 css::uno::Any a(e);
2195 throw css::lang::WrappedTargetRuntimeException(
2196 ::rtl::OUString::createFromAscii(
2197 "SfxDocumentMetaData::createClone: exception"),
2198 css::uno::Reference<css::uno::XInterface>(*this), a);
2200 // return static_cast< ::cppu::OWeakObject * > (pNew);
2201 return css::uno::Reference<css::util::XCloneable> (pNew);
2204 // ::com::sun::star::util::XModifiable:
2205 ::sal_Bool SAL_CALL SfxDocumentMetaData::isModified( )
2206 throw (css::uno::RuntimeException)
2208 ::osl::MutexGuard g(m_aMutex);
2209 checkInit();
2210 css::uno::Reference<css::util::XModifiable> xMB(m_xUserDefined,
2211 css::uno::UNO_QUERY);
2212 return m_isModified || (xMB.is() ? xMB->isModified() : sal_False);
2215 void SAL_CALL SfxDocumentMetaData::setModified( ::sal_Bool bModified )
2216 throw (css::beans::PropertyVetoException, css::uno::RuntimeException)
2218 css::uno::Reference<css::util::XModifiable> xMB;
2219 { // do not lock mutex while notifying (#i93514#) to prevent deadlock
2220 ::osl::MutexGuard g(m_aMutex);
2221 checkInit();
2222 m_isModified = bModified;
2223 if ( !bModified )
2225 xMB.set(m_xUserDefined, css::uno::UNO_QUERY);
2226 DBG_ASSERT(xMB.is(),
2227 "SfxDocumentMetaData::setModified: PropertyBag not Modifiable?");
2230 if (bModified) {
2231 try {
2232 css::uno::Reference<css::uno::XInterface> xThis(*this);
2233 css::lang::EventObject event(xThis);
2234 m_NotifyListeners.notifyEach(&css::util::XModifyListener::modified,
2235 event);
2236 } catch (css::uno::RuntimeException &) {
2237 throw;
2238 } catch (css::uno::Exception & e) {
2239 // ignore
2240 DBG_WARNING1("SfxDocumentMetaData::setModified: exception:\n%s",
2241 OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
2242 (void) e;
2244 } else {
2245 if (xMB.is()) {
2246 xMB->setModified(false);
2251 // ::com::sun::star::util::XModifyBroadcaster:
2252 void SAL_CALL SfxDocumentMetaData::addModifyListener(
2253 const css::uno::Reference< css::util::XModifyListener > & xListener)
2254 throw (css::uno::RuntimeException)
2256 ::osl::MutexGuard g(m_aMutex);
2257 checkInit();
2258 m_NotifyListeners.addInterface(xListener);
2259 css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
2260 css::uno::UNO_QUERY);
2261 if (xMB.is()) {
2262 xMB->addModifyListener(xListener);
2266 void SAL_CALL SfxDocumentMetaData::removeModifyListener(
2267 const css::uno::Reference< css::util::XModifyListener > & xListener)
2268 throw (css::uno::RuntimeException)
2270 ::osl::MutexGuard g(m_aMutex);
2271 checkInit();
2272 m_NotifyListeners.removeInterface(xListener);
2273 css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
2274 css::uno::UNO_QUERY);
2275 if (xMB.is()) {
2276 xMB->removeModifyListener(xListener);
2280 // ::com::sun::star::xml::sax::XSAXSerializable
2281 void SAL_CALL SfxDocumentMetaData::serialize(
2282 const css::uno::Reference<css::xml::sax::XDocumentHandler>& i_xHandler,
2283 const css::uno::Sequence< css::beans::StringPair >& i_rNamespaces)
2284 throw (css::uno::RuntimeException, css::xml::sax::SAXException)
2286 ::osl::MutexGuard g(m_aMutex);
2287 checkInit();
2288 updateUserDefinedAndAttributes();
2289 css::uno::Reference<css::xml::sax::XSAXSerializable> xSAXable(m_xDoc,
2290 css::uno::UNO_QUERY_THROW);
2291 xSAXable->serialize(i_xHandler, i_rNamespaces);
2294 void SfxDocumentMetaData::createUserDefined()
2296 if ( !m_xUserDefined.is() )
2298 css::uno::Sequence<css::uno::Type> types(10);
2299 types[0] = ::cppu::UnoType<bool>::get();
2300 types[1] = ::cppu::UnoType< ::rtl::OUString>::get();
2301 types[2] = ::cppu::UnoType<css::util::DateTime>::get();
2302 types[3] = ::cppu::UnoType<css::util::Date>::get();
2303 types[4] = ::cppu::UnoType<css::util::Time>::get();
2304 types[5] = ::cppu::UnoType<float>::get();
2305 types[6] = ::cppu::UnoType<double>::get();
2306 types[7] = ::cppu::UnoType<sal_Int16>::get();
2307 types[8] = ::cppu::UnoType<sal_Int32>::get();
2308 types[9] = ::cppu::UnoType<sal_Int64>::get();
2309 css::uno::Sequence<css::uno::Any> args(2);
2310 args[0] <<= css::beans::NamedValue(
2311 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AllowedTypes")),
2312 css::uno::makeAny(types));
2313 // #i94175#: ODF 1.1 allows empty user-defined property names!
2314 args[1] <<= css::beans::NamedValue(
2315 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AllowEmptyPropertyName")),
2316 css::uno::makeAny(sal_True));
2318 css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (m_xContext->getServiceManager());
2319 m_xUserDefined.set(
2320 xMsf->createInstanceWithContext(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.PropertyBag")), m_xContext),
2321 css::uno::UNO_QUERY_THROW);
2322 css::uno::Reference<css::lang::XInitialization> xInit(m_xUserDefined,
2323 css::uno::UNO_QUERY);
2324 if (xInit.is()) {
2325 xInit->initialize(args);
2328 css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,css::uno::UNO_QUERY);
2329 if (xMB.is())
2331 css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aListener = m_NotifyListeners.getElements();
2332 const css::uno::Reference< css::uno::XInterface >* pIter = aListener.getConstArray();
2333 const css::uno::Reference< css::uno::XInterface >* pEnd = pIter + aListener.getLength();
2334 for(;pIter != pEnd;++pIter )
2335 xMB->addModifyListener(css::uno::Reference< css::util::XModifyListener >(*pIter,css::uno::UNO_QUERY));
2340 } // closing anonymous implementation namespace
2343 // component helper namespace
2344 namespace comp_CompatWriterDocProps {
2346 ::rtl::OUString SAL_CALL _getImplementationName() {
2347 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2348 "CompatWriterDocPropsImpl"));
2351 css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
2353 static css::uno::Sequence< rtl::OUString > aServiceNames;
2354 if ( aServiceNames.getLength() == 0 )
2356 aServiceNames.realloc( 1 );
2357 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.writer.DocumentProperties" ) );
2359 return aServiceNames;
2361 css::uno::Reference< css::uno::XInterface > SAL_CALL _create(
2362 const css::uno::Reference< css::uno::XComponentContext > & context)
2363 SAL_THROW((css::uno::Exception))
2365 return static_cast< ::cppu::OWeakObject * >
2366 (new CompatWriterDocPropsImpl(context));
2370 namespace comp_SfxDocumentMetaData {
2372 ::rtl::OUString SAL_CALL _getImplementationName() {
2373 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2374 "SfxDocumentMetaData"));
2377 css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
2379 css::uno::Sequence< ::rtl::OUString > s(1);
2380 s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2381 "com.sun.star.document.DocumentProperties"));
2382 return s;
2385 css::uno::Reference< css::uno::XInterface > SAL_CALL _create(
2386 const css::uno::Reference< css::uno::XComponentContext > & context)
2387 SAL_THROW((css::uno::Exception))
2389 return static_cast< ::cppu::OWeakObject * >
2390 (new SfxDocumentMetaData(context));
2393 } // closing component helper namespace
2395 static ::cppu::ImplementationEntry const entries[] = {
2396 { &comp_SfxDocumentMetaData::_create,
2397 &comp_SfxDocumentMetaData::_getImplementationName,
2398 &comp_SfxDocumentMetaData::_getSupportedServiceNames,
2399 &::cppu::createSingleComponentFactory, 0, 0 },
2400 { 0, 0, 0, 0, 0, 0 }
2403 #if 0
2404 extern "C" void SAL_CALL component_getImplementationEnvironment(
2405 const char ** envTypeName, uno_Environment **)
2407 *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
2410 extern "C" void * SAL_CALL component_getFactory(
2411 const char * implName, void * serviceManager, void * registryKey)
2413 return ::cppu::component_getFactoryHelper(
2414 implName, serviceManager, registryKey, entries);
2417 extern "C" sal_Bool SAL_CALL component_writeInfo(
2418 void * serviceManager, void * registryKey)
2420 return ::cppu::component_writeInfoHelper(serviceManager, registryKey,
2421 entries);
2423 #endif