LCOV - code coverage report
Current view: top level - libreoffice/sfx2/source/doc - SfxDocumentMetaData.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 648 1008 64.3 %
Date: 2012-12-17 Functions: 77 111 69.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10