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-27 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         646 :     virtual ~SfxDocumentMetaData() {}
     291          55 :     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           1 : 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           1 :         && 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         507 : bool isValidDateTime(const css::util::DateTime & i_rDateTime)
     498             : {
     499         507 :     return i_rDateTime.Month > 0;
     500             : }
     501             : 
     502             : std::pair< ::rtl::OUString, ::rtl::OUString > SAL_CALL
     503        8166 : getQualifier(const char* i_name) {
     504        8166 :     ::rtl::OUString nm = ::rtl::OUString::createFromAscii(i_name);
     505        8166 :     sal_Int32 ix = nm.indexOf(static_cast<sal_Unicode> (':'));
     506        8166 :     if (ix == -1) {
     507           0 :         return std::make_pair(::rtl::OUString(), nm);
     508             :     } else {
     509        8166 :         return std::make_pair(nm.copy(0,ix), nm.copy(ix+1));
     510        8166 :     }
     511             : }
     512             : 
     513             : // get namespace for standard qualified names
     514             : // NB: only call this with statically known strings!
     515        5076 : ::rtl::OUString SAL_CALL getNameSpace(const char* i_qname) throw ()
     516             : {
     517             :     DBG_ASSERT(i_qname, "SfxDocumentMetaData: getNameSpace: argument is null");
     518        5076 :     const char * ns = "";
     519        5076 :     ::rtl::OUString n = getQualifier(i_qname).first;
     520        5076 :     if ( n == "xlink" ) ns = s_nsXLink;
     521        5076 :     if ( n == "dc" ) ns = s_nsDC;
     522        5076 :     if ( n == "office" ) ns = s_nsODF;
     523        5076 :     if ( n == "meta" ) ns = s_nsODFMeta;
     524             :     DBG_ASSERT(*ns, "SfxDocumentMetaData: unknown namespace prefix");
     525        5076 :     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        1294 : textToDateTime(css::util::DateTime & io_rdt, ::rtl::OUString i_text) throw ()
     545             : {
     546        1294 :     if (::sax::Converter::convertDateTime(io_rdt, i_text)) {
     547          44 :         return true;
     548             :     } else {
     549             :         DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
     550             :             OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr());
     551        1250 :         return false;
     552             :     }
     553             : }
     554             : 
     555             : // convert string to date/time with default return value
     556             : css::util::DateTime SAL_CALL
     557        1294 : textToDateTimeDefault(::rtl::OUString i_text) throw ()
     558             : {
     559        1294 :     css::util::DateTime dt;
     560        1294 :     static_cast<void> (textToDateTime(dt, i_text));
     561             :     // on conversion error: return default value (unchanged)
     562        1294 :     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         448 : dateTimeToText(css::util::DateTime const& i_rdt) throw ()
     582             : {
     583         448 :     if (isValidDateTime(i_rdt)) {
     584         298 :         ::rtl::OUStringBuffer buf;
     585         298 :         ::sax::Converter::convertDateTime(buf, i_rdt, true);
     586         298 :         return buf.makeStringAndClear();
     587             :     } else {
     588         150 :         return ::rtl::OUString();
     589             :     }
     590             : }
     591             : 
     592             : // convert string to duration
     593             : bool
     594        1157 : textToDuration(css::util::Duration& io_rDur, ::rtl::OUString const& i_rText)
     595             : throw ()
     596             : {
     597        1157 :     if (::sax::Converter::convertDuration(io_rDur, i_rText)) {
     598          23 :         return true;
     599             :     } else {
     600             :         DBG_WARNING1("SfxDocumentMetaData: invalid duration: %s",
     601             :             OUStringToOString(i_rText, RTL_TEXTENCODING_UTF8).getStr());
     602        1134 :         return false;
     603             :     }
     604             : }
     605             : 
     606        1157 : sal_Int32 textToDuration(::rtl::OUString const& i_rText) throw ()
     607             : {
     608        1157 :     css::util::Duration d;
     609        1157 :     if (textToDuration(d, i_rText)) {
     610             :         // #i107372#: approximate years/months
     611          23 :         const sal_Int32 days( (d.Years * 365) + (d.Months * 30) + d.Days );
     612             :         return  (days * (24*3600))
     613          23 :                 + (d.Hours * 3600) + (d.Minutes * 60) + d.Seconds;
     614             :     } else {
     615        1134 :         return 0; // default
     616             :     }
     617             : }
     618             : 
     619             : // convert duration to string
     620         140 : ::rtl::OUString durationToText(css::util::Duration const& i_rDur) throw ()
     621             : {
     622         140 :     ::rtl::OUStringBuffer buf;
     623         140 :     ::sax::Converter::convertDuration(buf, i_rDur);
     624         140 :     return buf.makeStringAndClear();
     625             : }
     626             : 
     627             : // convert duration to string
     628         140 : ::rtl::OUString SAL_CALL durationToText(sal_Int32 i_value) throw ()
     629             : {
     630         140 :     css::util::Duration ud;
     631         140 :     ud.Days    = static_cast<sal_Int16>(i_value / (24 * 3600));
     632         140 :     ud.Hours   = static_cast<sal_Int16>((i_value % (24 * 3600)) / 3600);
     633         140 :     ud.Minutes = static_cast<sal_Int16>((i_value % 3600) / 60);
     634         140 :     ud.Seconds = static_cast<sal_Int16>(i_value % 60);
     635         140 :     ud.MilliSeconds = 0;
     636         140 :     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         392 : getNodeText(css::uno::Reference<css::xml::dom::XNode> i_xNode)
     682             :         throw (css::uno::RuntimeException)
     683             : {
     684         392 :     if (!i_xNode.is()) throw css::uno::RuntimeException(
     685             :         ::rtl::OUString(
     686           0 :                 "SfxDocumentMetaData::getNodeText: argument is null"), i_xNode);
     687         784 :     for (css::uno::Reference<css::xml::dom::XNode> c = i_xNode->getFirstChild();
     688         392 :             c.is();
     689           0 :             c = c->getNextSibling()) {
     690         381 :         if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
     691             :             try {
     692         381 :                 return c->getNodeValue();
     693           0 :             } catch (const css::xml::dom::DOMException &) { // too big?
     694           0 :                 return ::rtl::OUString();
     695             :             }
     696             :         }
     697         392 :     }
     698          11 :     return ::rtl::OUString();
     699             : }
     700             : 
     701             : ::rtl::OUString SAL_CALL
     702        1144 : SfxDocumentMetaData::getMetaText(const char* i_name) const
     703             : //        throw (css::uno::RuntimeException)
     704             : {
     705        1144 :     checkInit();
     706             : 
     707        1144 :     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        1144 :     css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
     711        1144 :     return (xNode.is()) ? getNodeText(xNode) : ::rtl::OUString();
     712             : }
     713             : 
     714             : bool SAL_CALL
     715        1504 : SfxDocumentMetaData::setMetaText(const char* i_name,
     716             :         const ::rtl::OUString & i_rValue)
     717             :     // throw (css::uno::RuntimeException)
     718             : {
     719        1504 :     checkInit();
     720             : 
     721        1504 :     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        1504 :     css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
     725             : 
     726             :     try {
     727        1504 :         if (i_rValue.isEmpty()) {
     728         275 :             if (xNode.is()) { // delete
     729           4 :                 m_xParent->removeChild(xNode);
     730           4 :                 xNode.clear();
     731           4 :                 m_meta[name] = xNode;
     732           4 :                 return true;
     733             :             } else {
     734         271 :                 return false;
     735             :             }
     736             :         } else {
     737        1229 :             if (xNode.is()) { // update
     738         376 :                 for (css::uno::Reference<css::xml::dom::XNode> c =
     739         188 :                             xNode->getFirstChild();
     740         188 :                         c.is();
     741           0 :                         c = c->getNextSibling()) {
     742         188 :                     if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
     743         188 :                         if (!c->getNodeValue().equals(i_rValue)) {
     744          41 :                             c->setNodeValue(i_rValue);
     745          41 :                             return true;
     746             :                         } else {
     747         147 :                             return false;
     748             :                         }
     749             :                     }
     750         188 :                 }
     751             :             } else { // insert
     752        1041 :                 xNode.set(m_xDoc->createElementNS(getNameSpace(i_name), name),
     753        1041 :                             css::uno::UNO_QUERY_THROW);
     754        1041 :                 m_xParent->appendChild(xNode);
     755        1041 :                 m_meta[name] = xNode;
     756             :             }
     757             :             css::uno::Reference<css::xml::dom::XNode> xTextNode(
     758        1041 :                 m_xDoc->createTextNode(i_rValue), css::uno::UNO_QUERY_THROW);
     759        1041 :             xNode->appendChild(xTextNode);
     760        1041 :             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        1504 :     }
     769             : }
     770             : 
     771             : void SAL_CALL
     772        1496 : SfxDocumentMetaData::setMetaTextAndNotify(const char* i_name,
     773             :         const ::rtl::OUString & i_rValue)
     774             :     // throw (css::uno::RuntimeException)
     775             : {
     776        1496 :     ::osl::ClearableMutexGuard g(m_aMutex);
     777        1496 :     if (setMetaText(i_name, i_rValue)) {
     778        1081 :         g.clear();
     779        1081 :         setModified(true);
     780        1496 :     }
     781        1496 : }
     782             : 
     783             : ::rtl::OUString SAL_CALL
     784       10857 : SfxDocumentMetaData::getMetaAttr(const char* i_name, const char* i_attr) const
     785             : //        throw (css::uno::RuntimeException)
     786             : {
     787       10857 :     ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
     788             :     DBG_ASSERT(m_meta.find(name) != m_meta.end(),
     789             :         "SfxDocumentMetaData::getMetaAttr: not found");
     790       10857 :     css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
     791       10857 :     if (xNode.is()) {
     792             :         css::uno::Reference<css::xml::dom::XElement> xElem(xNode,
     793        3090 :             css::uno::UNO_QUERY_THROW);
     794        3090 :         return xElem->getAttributeNS(getNameSpace(i_attr),
     795        3090 :                     getQualifier(i_attr).second);
     796             :     } else {
     797        7767 :         return ::rtl::OUString();
     798       10857 :     }
     799             : }
     800             : 
     801             : css::uno::Sequence< ::rtl::OUString> SAL_CALL
     802          56 : SfxDocumentMetaData::getMetaList(const char* i_name) const
     803             : //        throw (css::uno::RuntimeException)
     804             : {
     805          56 :     checkInit();
     806          56 :     ::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          56 :         m_metaList.find(name)->second;
     811          56 :     css::uno::Sequence< ::rtl::OUString> ret(vec.size());
     812          62 :     for (size_t i = 0; i < vec.size(); ++i) {
     813           6 :         ret[i] = getNodeText(vec.at(i));
     814             :     }
     815          56 :     return ret;
     816             : }
     817             : 
     818             : bool SAL_CALL
     819          83 : 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          83 :     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          83 :         ::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          83 :             m_metaList[name];
     835             : 
     836             :         // if nothing changed, do nothing
     837             :         // alas, this does not check for permutations, or attributes...
     838          83 :         if ((0 == i_pAttrs)) {
     839          24 :             if (static_cast<size_t>(i_rValue.getLength()) == vec.size()) {
     840          22 :                 bool isEqual(true);
     841          22 :                 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          22 :                 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          61 :                 ::reverse_iterator it(vec.rbegin());
     859             :             try {
     860          73 :                 for ( ;it != vec.rend(); ++it)
     861             :                 {
     862          12 :                     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          61 :             vec.clear();
     872             :         }
     873             : 
     874             :         // insert new meta data nodes into DOM tree
     875         113 :         for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
     876             :             css::uno::Reference<css::xml::dom::XElement> xElem(
     877          52 :                 m_xDoc->createElementNS(getNameSpace(i_name), name),
     878          52 :                 css::uno::UNO_QUERY_THROW);
     879             :             css::uno::Reference<css::xml::dom::XNode> xNode(xElem,
     880          52 :                 css::uno::UNO_QUERY_THROW);
     881             :             css::uno::Reference<css::xml::dom::XNode> xTextNode(
     882          52 :                 m_xDoc->createTextNode(i_rValue[i]), css::uno::UNO_QUERY_THROW);
     883             :             // set attributes
     884          52 :             if (i_pAttrs != 0) {
     885         408 :                 for (std::vector<std::pair<const char*, ::rtl::OUString> >
     886          48 :                                 ::const_iterator it = (*i_pAttrs)[i].begin();
     887         272 :                         it != (*i_pAttrs)[i].end(); ++it) {
     888         176 :                     xElem->setAttributeNS(getNameSpace(it->first),
     889          88 :                         ::rtl::OUString::createFromAscii(it->first),
     890         264 :                         it->second);
     891             :                 }
     892             :             }
     893          52 :             xNode->appendChild(xTextNode);
     894          52 :             m_xParent->appendChild(xNode);
     895          52 :             vec.push_back(xNode);
     896          52 :         }
     897             : 
     898          61 :         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          59 : propsToStrings(css::uno::Reference<css::beans::XPropertySet> const & i_xPropSet)
     911             : {
     912          59 :     ::comphelper::SequenceAsVector< ::rtl::OUString > values;
     913          59 :     AttrVector attrs;
     914             : 
     915             :     css::uno::Reference<css::beans::XPropertySetInfo> xSetInfo
     916          59 :         = i_xPropSet->getPropertySetInfo();
     917          59 :     css::uno::Sequence<css::beans::Property> props = xSetInfo->getProperties();
     918             : 
     919         107 :     for (sal_Int32 i = 0; i < props.getLength(); ++i) {
     920          48 :         if (props[i].Attributes & css::beans::PropertyAttribute::TRANSIENT) {
     921           0 :             continue;
     922             :         }
     923          48 :         const ::rtl::OUString name = props[i].Name;
     924          48 :         css::uno::Any any;
     925             :         try {
     926          48 :             any = i_xPropSet->getPropertyValue(name);
     927           0 :         } catch (const css::uno::Exception &) {
     928             :             // ignore
     929             :         }
     930          48 :         const css::uno::Type & type = any.getValueType();
     931          48 :         std::vector<std::pair<const char*, ::rtl::OUString> > as;
     932             :         as.push_back(std::make_pair(static_cast<const char*>("meta:name"),
     933          48 :                                         name));
     934          48 :         const char* vt = "meta:value-type";
     935             : 
     936             :         // convert according to type
     937          48 :         if (type == ::cppu::UnoType<bool>::get()) {
     938          32 :             bool b = false;
     939          32 :             any >>= b;
     940          32 :             ::rtl::OUStringBuffer buf;
     941          32 :             ::sax::Converter::convertBool(buf, b);
     942          32 :             values.push_back(buf.makeStringAndClear());
     943             :             as.push_back(std::make_pair(vt,
     944          32 :                 ::rtl::OUString("boolean")));
     945          16 :         } else if (type == ::cppu::UnoType< ::rtl::OUString>::get()) {
     946           8 :             ::rtl::OUString s;
     947           8 :             any >>= s;
     948           8 :             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           8 :             if (4 <= i)
     954             :             {
     955             :                 as.push_back(std::make_pair(vt,
     956           0 :                     ::rtl::OUString("string")));
     957           8 :             }
     958           8 :         } 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           8 :         } 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           8 :         } 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           8 :         } 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           8 :         } else if (::cppu::UnoType<double>::get().isAssignableFrom(type)) {
     990             :             // support not just double, but anything that can be converted
     991           8 :             double d = 0;
     992           8 :             any >>= d;
     993           8 :             ::rtl::OUStringBuffer buf;
     994           8 :             ::sax::Converter::convertDouble(buf, d);
     995           8 :             values.push_back(buf.makeStringAndClear());
     996             :             as.push_back(std::make_pair(vt,
     997           8 :                 ::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          48 :         attrs.push_back(as);
    1005          48 :     }
    1006             : 
    1007          59 :     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         388 : SfxDocumentMetaData::updateElement(const char *i_name,
    1013             :         std::vector<std::pair<const char *, ::rtl::OUString> >* i_pAttrs)
    1014             : {
    1015         388 :     ::rtl::OUString name = ::rtl::OUString::createFromAscii(i_name);
    1016             :     try {
    1017             :         // remove old element
    1018             :         css::uno::Reference<css::xml::dom::XNode> xNode =
    1019         388 :             m_meta.find(name)->second;
    1020         388 :         if (xNode.is()) {
    1021         158 :             m_xParent->removeChild(xNode);
    1022         158 :             xNode.clear();
    1023             :         }
    1024             :         // add new element
    1025         388 :         if (0 != i_pAttrs) {
    1026             :             css::uno::Reference<css::xml::dom::XElement> xElem(
    1027         219 :                 m_xDoc->createElementNS(getNameSpace(i_name), name),
    1028         219 :                     css::uno::UNO_QUERY_THROW);
    1029         219 :             xNode.set(xElem, css::uno::UNO_QUERY_THROW);
    1030             :             // set attributes
    1031        2415 :             for (std::vector<std::pair<const char *, ::rtl::OUString> >
    1032         219 :                     ::const_iterator it = i_pAttrs->begin();
    1033        1610 :                     it != i_pAttrs->end(); ++it) {
    1034        1172 :                 xElem->setAttributeNS(getNameSpace(it->first),
    1035        1172 :                     ::rtl::OUString::createFromAscii(it->first), it->second);
    1036             :             }
    1037         219 :             m_xParent->appendChild(xNode);
    1038             :         }
    1039         388 :         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         388 :     }
    1047         388 : }
    1048             : 
    1049             : // update user-defined meta data in DOM tree
    1050          59 : void SAL_CALL SfxDocumentMetaData::updateUserDefinedAndAttributes()
    1051             : {
    1052          59 :     createUserDefined();
    1053             :     const css::uno::Reference<css::beans::XPropertySet> xPSet(m_xUserDefined,
    1054          59 :             css::uno::UNO_QUERY_THROW);
    1055             :     const std::pair<css::uno::Sequence< ::rtl::OUString>, AttrVector>
    1056          59 :         udStringsAttrs( propsToStrings(xPSet) );
    1057             :     (void) setMetaList("meta:user-defined", udStringsAttrs.first,
    1058          59 :             &udStringsAttrs.second);
    1059             : 
    1060             :     // update elements with attributes
    1061          59 :     std::vector<std::pair<const char *, ::rtl::OUString> > attributes;
    1062         110 :     if (!m_TemplateName.isEmpty() || !m_TemplateURL.isEmpty()
    1063          51 :             || isValidDateTime(m_TemplateDate)) {
    1064             :         attributes.push_back(std::make_pair(
    1065             :                 static_cast<const char*>("xlink:type"),
    1066           8 :                 ::rtl::OUString("simple")));
    1067             :         attributes.push_back(std::make_pair(
    1068             :                 static_cast<const char*>("xlink:actuate"),
    1069           8 :                 ::rtl::OUString("onRequest")));
    1070             :         attributes.push_back(std::make_pair(
    1071           8 :                 static_cast<const char*>("xlink:title"), m_TemplateName));
    1072             :         attributes.push_back(std::make_pair(
    1073           8 :                 static_cast<const char*>("xlink:href" ), m_TemplateURL ));
    1074           8 :         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           8 :         updateElement("meta:template", &attributes);
    1080             :     } else {
    1081          51 :         updateElement("meta:template");
    1082             :     }
    1083          59 :     attributes.clear();
    1084             : 
    1085          59 :     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          59 :         updateElement("meta:auto-reload");
    1094             :     }
    1095          59 :     attributes.clear();
    1096             : 
    1097          59 :     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          59 :         updateElement("meta:hyperlink-behaviour");
    1109             :     }
    1110          59 :     attributes.clear();
    1111          59 : }
    1112             : 
    1113             : // create empty DOM tree (XDocument)
    1114             : css::uno::Reference<css::xml::dom::XDocument> SAL_CALL
    1115        1090 : SfxDocumentMetaData::createDOM() const // throw (css::uno::RuntimeException)
    1116             : {
    1117        1090 :     css::uno::Reference<css::lang::XMultiComponentFactory> xMsf ( m_xContext->getServiceManager());
    1118        1090 :     css::uno::Reference<css::xml::dom::XDocumentBuilder> xBuilder( css::xml::dom::DocumentBuilder::create(m_xContext) );
    1119        1090 :     css::uno::Reference<css::xml::dom::XDocument> xDoc = xBuilder->newDocument();
    1120        1090 :     if (!xDoc.is()) throw css::uno::RuntimeException(
    1121             :         ::rtl::OUString("SfxDocumentMetaData::createDOM: "
    1122             :                 "cannot create new document"),
    1123           0 :                 *const_cast<SfxDocumentMetaData*>(this));
    1124        1090 :     return xDoc;
    1125             : }
    1126             : 
    1127             : void SAL_CALL
    1128        6949 : SfxDocumentMetaData::checkInit() const // throw (css::uno::RuntimeException)
    1129             : {
    1130        6949 :     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        6949 : }
    1138             : 
    1139             : // initialize state from DOM tree
    1140        1132 : void SAL_CALL SfxDocumentMetaData::init(
    1141             :         css::uno::Reference<css::xml::dom::XDocument> i_xDoc)
    1142             : {
    1143        1132 :     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        1132 :         m_xContext->getServiceManager());
    1149             :     css::uno::Reference<css::xml::xpath::XXPathAPI> xPath(
    1150        1132 :         xMsf->createInstanceWithContext(::rtl::OUString(
    1151        1132 :                 "com.sun.star.xml.xpath.XPathAPI"), m_xContext),
    1152        1132 :         css::uno::UNO_QUERY_THROW );
    1153        1132 :     if (!xPath.is()) throw css::uno::RuntimeException(
    1154             :         ::rtl::OUString("SfxDocumentMetaData::init:"
    1155           0 :                 " cannot create XPathAPI service"), *this);
    1156             : 
    1157        1132 :     m_isInitialized = false;
    1158        1132 :     m_xDoc = i_xDoc;
    1159             : 
    1160             :     // select nodes for standard meta data stuff
    1161        1132 :     xPath->registerNS(::rtl::OUString("xlink"),
    1162        1132 :         ::rtl::OUString::createFromAscii(s_nsXLink));
    1163        1132 :     xPath->registerNS(::rtl::OUString("dc"),
    1164        1132 :         ::rtl::OUString::createFromAscii(s_nsDC));
    1165        1132 :     xPath->registerNS(::rtl::OUString("office"),
    1166        1132 :         ::rtl::OUString::createFromAscii(s_nsODF));
    1167        1132 :     xPath->registerNS(::rtl::OUString("meta"),
    1168        1132 :         ::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        1132 :         "/child::office:document-meta/child::office:meta");
    1174             :     css::uno::Reference<css::xml::dom::XNode> xDocNode(
    1175        1132 :         m_xDoc, css::uno::UNO_QUERY_THROW);
    1176        1132 :     m_xParent.clear();
    1177             :     try {
    1178        1132 :         m_xParent = xPath->selectSingleNode(xDocNode, prefix);
    1179        1035 :     } catch (const com::sun::star::uno::Exception &) {
    1180             :     }
    1181             : 
    1182        1132 :     if (!m_xParent.is()) {
    1183             :         // all this create/append stuff may throw DOMException
    1184             :         try {
    1185        1035 :             css::uno::Reference<css::xml::dom::XElement> xRElem;
    1186             :             css::uno::Reference<css::xml::dom::XNode> xNode(
    1187        1035 :                 i_xDoc->getFirstChild());
    1188        2070 :             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        1035 :             if (!xRElem.is()) {
    1210        1035 :                 xRElem = i_xDoc->createElementNS(
    1211             :                     ::rtl::OUString::createFromAscii(s_nsODF),
    1212        1035 :                     ::rtl::OUString("office:document-meta"));
    1213             :                 css::uno::Reference<css::xml::dom::XNode> xRNode(xRElem,
    1214        1035 :                     css::uno::UNO_QUERY_THROW);
    1215        1035 :                 i_xDoc->appendChild(xRNode);
    1216             :             }
    1217        1035 :             xRElem->setAttributeNS(::rtl::OUString::createFromAscii(s_nsODF),
    1218             :                         ::rtl::OUString("office:version"),
    1219        1035 :                         ::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        1035 :                 i_xDoc->createElementNS(
    1223             :                     ::rtl::OUString::createFromAscii(s_nsODF),
    1224        1035 :                     ::rtl::OUString("office:meta")),
    1225        1035 :             css::uno::UNO_QUERY_THROW);
    1226        1035 :             xRElem->appendChild(xParent);
    1227        1035 :             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       20376 :     for (const char **pName = s_stdMeta; *pName != 0; ++pName) {
    1240       19244 :         ::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       19244 :             xPath->selectSingleNode(m_xParent,
    1249       19244 :                 ::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       19244 :         m_meta[name] = xNode;
    1253       19244 :     }
    1254             : 
    1255             :     // select nodes for elements of which we handle all occurrences
    1256        3396 :     for (const char **pName = s_stdMetaList; *pName != 0; ++pName) {
    1257        2264 :         ::rtl::OUString name = ::rtl::OUString::createFromAscii(*pName);
    1258             :         css::uno::Reference<css::xml::dom::XNodeList> nodes =
    1259        2264 :             xPath->selectNodeList(m_xParent,
    1260        2264 :                 ::rtl::OUString("child::") + name);
    1261        2264 :         std::vector<css::uno::Reference<css::xml::dom::XNode> > v;
    1262        2342 :         for (sal_Int32 i = 0; i < nodes->getLength(); ++i) {
    1263          78 :             v.push_back(nodes->item(i));
    1264             :         }
    1265        2264 :         m_metaList[name] = v;
    1266        2264 :     }
    1267             : 
    1268             :     // initialize members corresponding to attributes from DOM nodes
    1269        1132 :     m_TemplateName  = getMetaAttr("meta:template", "xlink:title");
    1270        1132 :     m_TemplateURL   = getMetaAttr("meta:template", "xlink:href");
    1271             :     m_TemplateDate  =
    1272        1132 :         textToDateTimeDefault(getMetaAttr("meta:template", "meta:date"));
    1273        1132 :     m_AutoloadURL   = getMetaAttr("meta:auto-reload", "xlink:href");
    1274             :     m_AutoloadSecs  =
    1275        1132 :         textToDuration(getMetaAttr("meta:auto-reload", "meta:delay"));
    1276             :     m_DefaultTarget =
    1277        1132 :         getMetaAttr("meta:hyperlink-behaviour", "office:target-frame-name");
    1278             : 
    1279             : 
    1280             :     std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
    1281        1132 :         m_metaList[::rtl::OUString("meta:user-defined")];
    1282        1132 :     m_xUserDefined.clear(); // #i105826#: reset (may be re-initialization)
    1283        1132 :     if ( !vec.empty() )
    1284             :     {
    1285          13 :         createUserDefined();
    1286             :     }
    1287             : 
    1288             :     // user-defined meta data: initialize PropertySet from DOM nodes
    1289        3615 :     for (std::vector<css::uno::Reference<css::xml::dom::XNode> >::iterator
    1290        3542 :             it = vec.begin(); it != vec.end(); ++it) {
    1291          73 :         css::uno::Reference<css::xml::dom::XElement> xElem(*it,
    1292          73 :             css::uno::UNO_QUERY_THROW);
    1293          73 :         css::uno::Any any;
    1294          73 :         ::rtl::OUString name = xElem->getAttributeNS(
    1295             :                 ::rtl::OUString::createFromAscii(s_nsODFMeta),
    1296          73 :                 ::rtl::OUString("name"));
    1297          73 :         ::rtl::OUString type = xElem->getAttributeNS(
    1298             :                 ::rtl::OUString::createFromAscii(s_nsODFMeta),
    1299          73 :                 ::rtl::OUString("value-type"));
    1300          73 :         ::rtl::OUString text = getNodeText(*it);
    1301          73 :         if ( type == "float" ) {
    1302             :             double d;
    1303          10 :             if (::sax::Converter::convertDouble(d, text)) {
    1304          10 :                 any <<= d;
    1305             :             } else {
    1306             :                 DBG_WARNING1("SfxDocumentMetaData: invalid float: %s",
    1307             :                     OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
    1308           0 :                 continue;
    1309             :             }
    1310          63 :         } 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          63 :         } 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          63 :         } else if ( type == "boolean" ) {
    1335             :             bool b;
    1336          40 :             if (::sax::Converter::convertBool(b, text)) {
    1337          40 :                 any <<= b;
    1338             :             } else {
    1339             :                 DBG_WARNING1("SfxDocumentMetaData: invalid boolean: %s",
    1340             :                     OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
    1341           0 :                 continue;
    1342             :             }
    1343          23 :         } else if ( type == "string" || true) { // default
    1344          23 :             any <<= text;
    1345             :         }
    1346             :         try {
    1347          73 :             m_xUserDefined->addProperty(name,
    1348          73 :                 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          73 :     }
    1361             : 
    1362        1132 :     m_isModified = false;
    1363        1132 :     m_isInitialized = true;
    1364        1132 : }
    1365             : 
    1366             : 
    1367             : 
    1368         547 : 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         547 :     , 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         547 :     init(createDOM());
    1382         547 : }
    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         323 : void SAL_CALL SfxDocumentMetaData::dispose() throw (css::uno::RuntimeException)
    1414             : {
    1415         323 :     ::osl::MutexGuard g(m_aMutex);
    1416         323 :     if (!m_isInitialized) {
    1417         323 :         return;
    1418             :     }
    1419         323 :     WeakComponentImplHelperBase::dispose(); // superclass
    1420             :     m_NotifyListeners.disposeAndClear(css::lang::EventObject(
    1421         323 :             static_cast< ::cppu::OWeakObject* >(this)));
    1422         323 :     m_isInitialized = false;
    1423         323 :     m_meta.clear();
    1424         323 :     m_metaList.clear();
    1425         323 :     m_xParent.clear();
    1426         323 :     m_xDoc.clear();
    1427         323 :     m_xUserDefined.clear();
    1428             : }
    1429             : 
    1430             : 
    1431             : // ::com::sun::star::document::XDocumentProperties:
    1432             : ::rtl::OUString SAL_CALL
    1433         290 : SfxDocumentMetaData::getAuthor() throw (css::uno::RuntimeException)
    1434             : {
    1435         290 :     ::osl::MutexGuard g(m_aMutex);
    1436         290 :     return getMetaText("meta:initial-creator");
    1437             : }
    1438             : 
    1439         112 : void SAL_CALL SfxDocumentMetaData::setAuthor(const ::rtl::OUString & the_value)
    1440             :         throw (css::uno::RuntimeException)
    1441             : {
    1442         112 :     setMetaTextAndNotify("meta:initial-creator", the_value);
    1443         112 : }
    1444             : 
    1445             : 
    1446             : ::rtl::OUString SAL_CALL
    1447          89 : SfxDocumentMetaData::getGenerator() throw (css::uno::RuntimeException)
    1448             : {
    1449          89 :     ::osl::MutexGuard g(m_aMutex);
    1450          89 :     return getMetaText("meta:generator");
    1451             : }
    1452             : 
    1453             : void SAL_CALL
    1454         425 : SfxDocumentMetaData::setGenerator(const ::rtl::OUString & the_value)
    1455             :         throw (css::uno::RuntimeException)
    1456             : {
    1457         425 :     setMetaTextAndNotify("meta:generator", the_value);
    1458         425 : }
    1459             : 
    1460             : css::util::DateTime SAL_CALL
    1461          54 : SfxDocumentMetaData::getCreationDate() throw (css::uno::RuntimeException)
    1462             : {
    1463          54 :     ::osl::MutexGuard g(m_aMutex);
    1464          54 :     return textToDateTimeDefault(getMetaText("meta:creation-date"));
    1465             : }
    1466             : 
    1467             : void SAL_CALL
    1468         184 : SfxDocumentMetaData::setCreationDate(const css::util::DateTime & the_value)
    1469             :         throw (css::uno::RuntimeException)
    1470             : {
    1471         184 :     setMetaTextAndNotify("meta:creation-date", dateTimeToText(the_value));
    1472         184 : }
    1473             : 
    1474             : ::rtl::OUString SAL_CALL
    1475         126 : SfxDocumentMetaData::getTitle() throw (css::uno::RuntimeException)
    1476             : {
    1477         126 :     ::osl::MutexGuard g(m_aMutex);
    1478         126 :     return getMetaText("dc:title");
    1479             : }
    1480             : 
    1481          29 : void SAL_CALL SfxDocumentMetaData::setTitle(const ::rtl::OUString & the_value)
    1482             :         throw (css::uno::RuntimeException)
    1483             : {
    1484          29 :     setMetaTextAndNotify("dc:title", the_value);
    1485          29 : }
    1486             : 
    1487             : ::rtl::OUString SAL_CALL
    1488          56 : SfxDocumentMetaData::getSubject() throw (css::uno::RuntimeException)
    1489             : {
    1490          56 :     ::osl::MutexGuard g(m_aMutex);
    1491          56 :     return getMetaText("dc:subject");
    1492             : }
    1493             : 
    1494             : void SAL_CALL
    1495          26 : SfxDocumentMetaData::setSubject(const ::rtl::OUString & the_value)
    1496             :         throw (css::uno::RuntimeException)
    1497             : {
    1498          26 :     setMetaTextAndNotify("dc:subject", the_value);
    1499          26 : }
    1500             : 
    1501             : ::rtl::OUString SAL_CALL
    1502          56 : SfxDocumentMetaData::getDescription() throw (css::uno::RuntimeException)
    1503             : {
    1504          56 :     ::osl::MutexGuard g(m_aMutex);
    1505          56 :     return getMetaText("dc:description");
    1506             : }
    1507             : 
    1508             : void SAL_CALL
    1509          21 : SfxDocumentMetaData::setDescription(const ::rtl::OUString & the_value)
    1510             :         throw (css::uno::RuntimeException)
    1511             : {
    1512          21 :     setMetaTextAndNotify("dc:description", the_value);
    1513          21 : }
    1514             : 
    1515             : css::uno::Sequence< ::rtl::OUString >
    1516          56 : SAL_CALL SfxDocumentMetaData::getKeywords() throw (css::uno::RuntimeException)
    1517             : {
    1518          56 :     ::osl::MutexGuard g(m_aMutex);
    1519          56 :     return getMetaList("meta:keyword");
    1520             : }
    1521             : 
    1522             : void SAL_CALL
    1523          24 : SfxDocumentMetaData::setKeywords(
    1524             :         const css::uno::Sequence< ::rtl::OUString > & the_value)
    1525             :         throw (css::uno::RuntimeException)
    1526             : {
    1527          24 :     ::osl::ClearableMutexGuard g(m_aMutex);
    1528          24 :     if (setMetaList("meta:keyword", the_value)) {
    1529           2 :         g.clear();
    1530           2 :         setModified(true);
    1531          24 :     }
    1532          24 : }
    1533             : 
    1534             : css::lang::Locale SAL_CALL
    1535          25 :         SfxDocumentMetaData::getLanguage() throw (css::uno::RuntimeException)
    1536             : {
    1537          25 :     ::osl::MutexGuard g(m_aMutex);
    1538          25 :     css::lang::Locale loc;
    1539          25 :     ::rtl::OUString text = getMetaText("dc:language");
    1540          25 :     sal_Int32 ix = text.indexOf(static_cast<sal_Unicode> ('-'));
    1541          25 :     if (ix == -1) {
    1542          25 :         loc.Language = text;
    1543             :     } else {
    1544           0 :         loc.Language = text.copy(0, ix);
    1545           0 :         loc.Country = text.copy(ix+1);
    1546             :     }
    1547          25 :     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         290 : SfxDocumentMetaData::getModifiedBy() throw (css::uno::RuntimeException)
    1563             : {
    1564         290 :     ::osl::MutexGuard g(m_aMutex);
    1565         290 :     return getMetaText("dc:creator");
    1566             : }
    1567             : 
    1568             : void SAL_CALL
    1569         112 : SfxDocumentMetaData::setModifiedBy(const ::rtl::OUString & the_value)
    1570             :         throw (css::uno::RuntimeException)
    1571             : {
    1572         112 :     setMetaTextAndNotify("dc:creator", the_value);
    1573         112 : }
    1574             : 
    1575             : css::util::DateTime SAL_CALL
    1576          54 : SfxDocumentMetaData::getModificationDate() throw (css::uno::RuntimeException)
    1577             : {
    1578          54 :     ::osl::MutexGuard g(m_aMutex);
    1579          54 :     return textToDateTimeDefault(getMetaText("dc:date"));
    1580             : }
    1581             : 
    1582             : void SAL_CALL
    1583         149 : SfxDocumentMetaData::setModificationDate(const css::util::DateTime & the_value)
    1584             :         throw (css::uno::RuntimeException)
    1585             : {
    1586         149 :     setMetaTextAndNotify("dc:date", dateTimeToText(the_value));
    1587         149 : }
    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          50 : SfxDocumentMetaData::setPrintedBy(const ::rtl::OUString & the_value)
    1598             :         throw (css::uno::RuntimeException)
    1599             : {
    1600          50 :     setMetaTextAndNotify("meta:printed-by", the_value);
    1601          50 : }
    1602             : 
    1603             : css::util::DateTime SAL_CALL
    1604          54 : SfxDocumentMetaData::getPrintDate() throw (css::uno::RuntimeException)
    1605             : {
    1606          54 :     ::osl::MutexGuard g(m_aMutex);
    1607          54 :     return textToDateTimeDefault(getMetaText("meta:print-date"));
    1608             : }
    1609             : 
    1610             : void SAL_CALL
    1611         112 : SfxDocumentMetaData::setPrintDate(const css::util::DateTime & the_value)
    1612             :         throw (css::uno::RuntimeException)
    1613             : {
    1614         112 :     setMetaTextAndNotify("meta:print-date", dateTimeToText(the_value));
    1615         112 : }
    1616             : 
    1617             : ::rtl::OUString SAL_CALL
    1618          40 : SfxDocumentMetaData::getTemplateName() throw (css::uno::RuntimeException)
    1619             : {
    1620          40 :     ::osl::MutexGuard g(m_aMutex);
    1621          40 :     checkInit();
    1622          40 :     return m_TemplateName;
    1623             : }
    1624             : 
    1625             : void SAL_CALL
    1626          89 : SfxDocumentMetaData::setTemplateName(const ::rtl::OUString & the_value)
    1627             :         throw (css::uno::RuntimeException)
    1628             : {
    1629          89 :     ::osl::ClearableMutexGuard g(m_aMutex);
    1630          89 :     checkInit();
    1631          89 :     if (m_TemplateName != the_value) {
    1632          84 :         m_TemplateName = the_value;
    1633          84 :         g.clear();
    1634          84 :         setModified(true);
    1635          89 :     }
    1636          89 : }
    1637             : 
    1638             : ::rtl::OUString SAL_CALL
    1639          88 : SfxDocumentMetaData::getTemplateURL() throw (css::uno::RuntimeException)
    1640             : {
    1641          88 :     ::osl::MutexGuard g(m_aMutex);
    1642          88 :     checkInit();
    1643          88 :     return m_TemplateURL;
    1644             : }
    1645             : 
    1646             : void SAL_CALL
    1647          71 : SfxDocumentMetaData::setTemplateURL(const ::rtl::OUString & the_value)
    1648             :         throw (css::uno::RuntimeException)
    1649             : {
    1650          71 :     ::osl::ClearableMutexGuard g(m_aMutex);
    1651          71 :     checkInit();
    1652          71 :     if (m_TemplateURL != the_value) {
    1653           0 :         m_TemplateURL = the_value;
    1654           0 :         g.clear();
    1655           0 :         setModified(true);
    1656          71 :     }
    1657          71 : }
    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           1 : SfxDocumentMetaData::setTemplateDate(const css::util::DateTime & the_value)
    1669             :         throw (css::uno::RuntimeException)
    1670             : {
    1671           1 :     ::osl::ClearableMutexGuard g(m_aMutex);
    1672           1 :     checkInit();
    1673           1 :     if (!(m_TemplateDate == the_value)) {
    1674           0 :         m_TemplateDate = the_value;
    1675           0 :         g.clear();
    1676           0 :         setModified(true);
    1677           1 :     }
    1678           1 : }
    1679             : 
    1680             : ::rtl::OUString SAL_CALL
    1681         535 : SfxDocumentMetaData::getAutoloadURL() throw (css::uno::RuntimeException)
    1682             : {
    1683         535 :     ::osl::MutexGuard g(m_aMutex);
    1684         535 :     checkInit();
    1685         535 :     return m_AutoloadURL;
    1686             : }
    1687             : 
    1688             : void SAL_CALL
    1689          42 : SfxDocumentMetaData::setAutoloadURL(const ::rtl::OUString & the_value)
    1690             :         throw (css::uno::RuntimeException)
    1691             : {
    1692          42 :     ::osl::ClearableMutexGuard g(m_aMutex);
    1693          42 :     checkInit();
    1694          42 :     if (m_AutoloadURL != the_value) {
    1695           0 :         m_AutoloadURL = the_value;
    1696           0 :         g.clear();
    1697           0 :         setModified(true);
    1698          42 :     }
    1699          42 : }
    1700             : 
    1701             : ::sal_Int32 SAL_CALL
    1702         493 : SfxDocumentMetaData::getAutoloadSecs() throw (css::uno::RuntimeException)
    1703             : {
    1704         493 :     ::osl::MutexGuard g(m_aMutex);
    1705         493 :     checkInit();
    1706         493 :     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         271 : SfxDocumentMetaData::getDocumentStatistics() throw (css::uno::RuntimeException)
    1749             : {
    1750         271 :     ::osl::MutexGuard g(m_aMutex);
    1751         271 :     checkInit();
    1752         271 :     ::comphelper::SequenceAsVector<css::beans::NamedValue> stats;
    1753        4336 :     for (size_t i = 0; s_stdStats[i] != 0; ++i) {
    1754        4065 :         const char * aName = s_stdStatAttrs[i];
    1755        4065 :         ::rtl::OUString text = getMetaAttr("meta:document-statistic", aName);
    1756        4065 :         if (text.isEmpty()) continue;
    1757         562 :         css::beans::NamedValue stat;
    1758         562 :         stat.Name = ::rtl::OUString::createFromAscii(s_stdStats[i]);
    1759             :         sal_Int32 val;
    1760         562 :         css::uno::Any any;
    1761         562 :         if (!::sax::Converter::convertNumber(val, text, 0,
    1762         562 :                 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         562 :         any <<= val;
    1768         562 :         stat.Value = any;
    1769         562 :         stats.push_back(stat);
    1770         562 :     }
    1771             : 
    1772         271 :     return stats.getAsConstList();
    1773             : }
    1774             : 
    1775             : void SAL_CALL
    1776         211 : SfxDocumentMetaData::setDocumentStatistics(
    1777             :         const css::uno::Sequence< css::beans::NamedValue > & the_value)
    1778             :         throw (css::uno::RuntimeException)
    1779             : {
    1780         211 :     ::osl::ClearableMutexGuard g(m_aMutex);
    1781         211 :     checkInit();
    1782         211 :     std::vector<std::pair<const char *, ::rtl::OUString> > attributes;
    1783         765 :     for (sal_Int32 i = 0; i < the_value.getLength(); ++i) {
    1784         554 :         const ::rtl::OUString name = the_value[i].Name;
    1785             :         // inefficently search for matching attribute
    1786        3002 :         for (size_t j = 0; s_stdStats[j] != 0; ++j) {
    1787        3002 :             if (name.equalsAscii(s_stdStats[j])) {
    1788         554 :                 const css::uno::Any any = the_value[i].Value;
    1789         554 :                 sal_Int32 val = 0;
    1790         554 :                 if (any >>= val) {
    1791         554 :                     ::rtl::OUStringBuffer buf;
    1792         554 :                     ::sax::Converter::convertNumber(buf, val);
    1793             :                     attributes.push_back(std::make_pair(s_stdStatAttrs[j],
    1794         554 :                                 buf.makeStringAndClear()));
    1795             :                 } else {
    1796             :                     DBG_WARNING1("SfxDocumentMetaData: invalid statistic: %s",
    1797             :                         OUStringToOString(name, RTL_TEXTENCODING_UTF8)
    1798             :                             .getStr());
    1799             :                 }
    1800         554 :                 break;
    1801             :             }
    1802             :         }
    1803         554 :     }
    1804         211 :     updateElement("meta:document-statistic", &attributes);
    1805         211 :     g.clear();
    1806         211 :     setModified(true);
    1807         211 : }
    1808             : 
    1809             : ::sal_Int16 SAL_CALL
    1810          25 : SfxDocumentMetaData::getEditingCycles() throw (css::uno::RuntimeException)
    1811             : {
    1812          25 :     ::osl::MutexGuard g(m_aMutex);
    1813          25 :     ::rtl::OUString text = getMetaText("meta:editing-cycles");
    1814             :     sal_Int32 ret;
    1815          25 :     if (::sax::Converter::convertNumber(ret, text,
    1816          25 :             0, std::numeric_limits<sal_Int16>::max())) {
    1817          25 :         return static_cast<sal_Int16>(ret);
    1818             :     } else {
    1819           0 :         return 0;
    1820          25 :     }
    1821             : }
    1822             : 
    1823             : void SAL_CALL
    1824         137 : SfxDocumentMetaData::setEditingCycles(::sal_Int16 the_value)
    1825             :         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
    1826             : {
    1827         137 :     if (the_value < 0) throw css::lang::IllegalArgumentException(
    1828             :         ::rtl::OUString(
    1829             :                 "SfxDocumentMetaData::setEditingCycles: argument is negative"),
    1830           0 :                 *this, 0);
    1831         137 :     ::rtl::OUStringBuffer buf;
    1832         137 :     ::sax::Converter::convertNumber(buf, the_value);
    1833         137 :     setMetaTextAndNotify("meta:editing-cycles", buf.makeStringAndClear());
    1834         137 : }
    1835             : 
    1836             : ::sal_Int32 SAL_CALL
    1837          25 : SfxDocumentMetaData::getEditingDuration() throw (css::uno::RuntimeException)
    1838             : {
    1839          25 :     ::osl::MutexGuard g(m_aMutex);
    1840          25 :     return textToDuration(getMetaText("meta:editing-duration"));
    1841             : }
    1842             : 
    1843             : void SAL_CALL
    1844         139 : SfxDocumentMetaData::setEditingDuration(::sal_Int32 the_value)
    1845             :         throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
    1846             : {
    1847         139 :     if (the_value < 0) throw css::lang::IllegalArgumentException(
    1848             :         ::rtl::OUString(
    1849             :             "SfxDocumentMetaData::setEditingDuration: argument is negative"),
    1850           0 :             *this, 0);
    1851         139 :     setMetaTextAndNotify("meta:editing-duration", durationToText(the_value));
    1852         139 : }
    1853             : 
    1854             : void SAL_CALL
    1855           1 : SfxDocumentMetaData::resetUserData(const ::rtl::OUString & the_value)
    1856             :     throw (css::uno::RuntimeException)
    1857             : {
    1858           1 :     ::osl::ClearableMutexGuard g(m_aMutex);
    1859             : 
    1860           1 :     bool bModified( false );
    1861           1 :     bModified |= setMetaText("meta:initial-creator", the_value);
    1862           1 :     ::DateTime now( ::DateTime::SYSTEM );
    1863           3 :     css::util::DateTime uDT(now.Get100Sec(), now.GetSec(), now.GetMin(),
    1864           4 :         now.GetHour(), now.GetDay(), now.GetMonth(), now.GetYear());
    1865           1 :     bModified |= setMetaText("meta:creation-date", dateTimeToText(uDT));
    1866           1 :     bModified |= setMetaText("dc:creator", ::rtl::OUString());
    1867           1 :     bModified |= setMetaText("meta:printed-by", ::rtl::OUString());
    1868           1 :     bModified |= setMetaText("dc:date", dateTimeToText(css::util::DateTime()));
    1869             :     bModified |= setMetaText("meta:print-date",
    1870           1 :         dateTimeToText(css::util::DateTime()));
    1871           1 :     bModified |= setMetaText("meta:editing-duration", durationToText(0));
    1872             :     bModified |= setMetaText("meta:editing-cycles",
    1873           1 :         ::rtl::OUString("1"));
    1874             : 
    1875           1 :     if (bModified) {
    1876           1 :         g.clear();
    1877           1 :         setModified(true);
    1878           1 :     }
    1879           1 : }
    1880             : 
    1881             : 
    1882             : css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
    1883         395 : SfxDocumentMetaData::getUserDefinedProperties()
    1884             :         throw (css::uno::RuntimeException)
    1885             : {
    1886         395 :     ::osl::MutexGuard g(m_aMutex);
    1887         395 :     checkInit();
    1888         395 :     createUserDefined();
    1889         395 :     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         530 : 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         530 :     ::osl::MutexGuard g(m_aMutex);
    2143         530 :     css::uno::Reference<css::xml::dom::XDocument> xDoc;
    2144             : 
    2145         572 :     for (sal_Int32 i = 0; i < aArguments.getLength(); ++i) {
    2146          42 :         const css::uno::Any any = aArguments[i];
    2147          42 :         if (any >>= xDoc) {
    2148          42 :             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          42 :     }
    2161             : 
    2162         530 :     if (!xDoc.is()) {
    2163             :         // For a new document, we create a new DOM tree here.
    2164         488 :         xDoc = createDOM();
    2165             :     }
    2166             : 
    2167         530 :     init(xDoc);
    2168         530 : }
    2169             : 
    2170             : // ::com::sun::star::util::XCloneable:
    2171             : css::uno::Reference<css::util::XCloneable> SAL_CALL
    2172          55 : SfxDocumentMetaData::createClone()
    2173             :     throw (css::uno::RuntimeException)
    2174             : {
    2175          55 :     ::osl::MutexGuard g(m_aMutex);
    2176          55 :     checkInit();
    2177             : 
    2178          55 :     SfxDocumentMetaData *pNew = createMe(m_xContext);
    2179             : 
    2180             :     // NB: do not copy the modification listeners, only DOM
    2181          55 :     css::uno::Reference<css::xml::dom::XDocument> xDoc = createDOM();
    2182             :     try {
    2183          55 :         updateUserDefinedAndAttributes();
    2184             :         // deep copy of root node
    2185             :         css::uno::Reference<css::xml::dom::XNode> xRoot(
    2186          55 :             m_xDoc->getDocumentElement(), css::uno::UNO_QUERY_THROW);
    2187             :         css::uno::Reference<css::xml::dom::XNode> xRootNew(
    2188          55 :             xDoc->importNode(xRoot, true));
    2189          55 :         xDoc->appendChild(xRootNew);
    2190          55 :         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          55 :     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        1379 : void SAL_CALL SfxDocumentMetaData::setModified( ::sal_Bool bModified )
    2215             :         throw (css::beans::PropertyVetoException, css::uno::RuntimeException)
    2216             : {
    2217        1379 :     css::uno::Reference<css::util::XModifiable> xMB;
    2218             :     { // do not lock mutex while notifying (#i93514#) to prevent deadlock
    2219        1379 :         ::osl::MutexGuard g(m_aMutex);
    2220        1379 :         checkInit();
    2221        1379 :         m_isModified = bModified;
    2222        1379 :         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        1379 :         }
    2228             :     }
    2229        1379 :     if (bModified) {
    2230             :         try {
    2231        1379 :             css::uno::Reference<css::uno::XInterface> xThis(*this);
    2232        1379 :             css::lang::EventObject event(xThis);
    2233             :             m_NotifyListeners.notifyEach(&css::util::XModifyListener::modified,
    2234        1379 :                 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        1379 :     }
    2248        1379 : }
    2249             : 
    2250             : // ::com::sun::star::util::XModifyBroadcaster:
    2251         488 : void SAL_CALL SfxDocumentMetaData::addModifyListener(
    2252             :         const css::uno::Reference< css::util::XModifyListener > & xListener)
    2253             :         throw (css::uno::RuntimeException)
    2254             : {
    2255         488 :     ::osl::MutexGuard g(m_aMutex);
    2256         488 :     checkInit();
    2257         488 :     m_NotifyListeners.addInterface(xListener);
    2258             :     css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
    2259         488 :         css::uno::UNO_QUERY);
    2260         488 :     if (xMB.is()) {
    2261           0 :         xMB->addModifyListener(xListener);
    2262         488 :     }
    2263         488 : }
    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           4 : 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           4 :     ::osl::MutexGuard g(m_aMutex);
    2286           4 :     checkInit();
    2287           4 :     updateUserDefinedAndAttributes();
    2288             :     css::uno::Reference<css::xml::sax::XSAXSerializable> xSAXable(m_xDoc,
    2289           4 :         css::uno::UNO_QUERY_THROW);
    2290           4 :     xSAXable->serialize(i_xHandler, i_rNamespaces);
    2291           4 : }
    2292             : 
    2293         467 : void SfxDocumentMetaData::createUserDefined()
    2294             : {
    2295             :     // user-defined meta data: create PropertyBag which only accepts property
    2296             :     // values of allowed types
    2297         467 :     if ( !m_xUserDefined.is() )
    2298             :     {
    2299         162 :         css::uno::Sequence<css::uno::Type> types(11);
    2300         162 :         types[0] = ::cppu::UnoType<bool>::get();
    2301         162 :         types[1] = ::cppu::UnoType< ::rtl::OUString>::get();
    2302         162 :         types[2] = ::cppu::UnoType<css::util::DateTime>::get();
    2303         162 :         types[3] = ::cppu::UnoType<css::util::Date>::get();
    2304         162 :         types[4] = ::cppu::UnoType<css::util::Duration>::get();
    2305         162 :         types[5] = ::cppu::UnoType<float>::get();
    2306         162 :         types[6] = ::cppu::UnoType<double>::get();
    2307         162 :         types[7] = ::cppu::UnoType<sal_Int16>::get();
    2308         162 :         types[8] = ::cppu::UnoType<sal_Int32>::get();
    2309         162 :         types[9] = ::cppu::UnoType<sal_Int64>::get();
    2310             :         // Time is supported for backward compatibility with OOo 3.x, x<=2
    2311         162 :         types[10] = ::cppu::UnoType<css::util::Time>::get();
    2312         162 :         css::uno::Sequence<css::uno::Any> args(2);
    2313         162 :         args[0] <<= css::beans::NamedValue(
    2314             :             ::rtl::OUString("AllowedTypes"),
    2315         324 :             css::uno::makeAny(types));
    2316             :         // #i94175#:  ODF allows empty user-defined property names!
    2317         162 :         args[1] <<= css::beans::NamedValue( ::rtl::OUString(
    2318             :                         "AllowEmptyPropertyName"),
    2319         324 :             css::uno::makeAny(sal_True));
    2320             : 
    2321             :         const css::uno::Reference<css::lang::XMultiComponentFactory> xMsf(
    2322         162 :                 m_xContext->getServiceManager());
    2323             :         m_xUserDefined.set(
    2324         162 :             xMsf->createInstanceWithContext(
    2325             :                 ::rtl::OUString(
    2326         162 :                     "com.sun.star.beans.PropertyBag"), m_xContext),
    2327         162 :             css::uno::UNO_QUERY_THROW);
    2328             :         const css::uno::Reference<css::lang::XInitialization> xInit(
    2329         162 :             m_xUserDefined, css::uno::UNO_QUERY);
    2330         162 :         if (xInit.is()) {
    2331         162 :             xInit->initialize(args);
    2332             :         }
    2333             : 
    2334             :         const css::uno::Reference<css::util::XModifyBroadcaster> xMB(
    2335         162 :             m_xUserDefined, css::uno::UNO_QUERY);
    2336         162 :         if (xMB.is())
    2337             :         {
    2338             :             const css::uno::Sequence<css::uno::Reference<css::uno::XInterface> >
    2339         162 :                 listeners(m_NotifyListeners.getElements());
    2340         632 :             for (css::uno::Reference< css::uno::XInterface > const * iter =
    2341         162 :                                 ::comphelper::stl_begin(listeners);
    2342         316 :                         iter != ::comphelper::stl_end(listeners); ++iter) {
    2343         154 :                 xMB->addModifyListener(
    2344             :                     css::uno::Reference< css::util::XModifyListener >(*iter,
    2345         154 :                         css::uno::UNO_QUERY));
    2346         162 :             }
    2347         162 :         }
    2348             :     }
    2349         467 : }
    2350             : 
    2351             : } // closing anonymous implementation namespace
    2352             : 
    2353             : 
    2354             : // component helper namespace
    2355             : namespace comp_CompatWriterDocProps {
    2356             : 
    2357          44 :     ::rtl::OUString SAL_CALL _getImplementationName() {
    2358             :         return ::rtl::OUString(
    2359          44 :             "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          59 : ::rtl::OUString SAL_CALL _getImplementationName() {
    2380             :     return ::rtl::OUString(
    2381          59 :         "SfxDocumentMetaData");
    2382             : }
    2383             : 
    2384          15 : css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
    2385             : {
    2386          15 :     css::uno::Sequence< ::rtl::OUString > s(1);
    2387          15 :     s[0] = ::rtl::OUString(
    2388          30 :         "com.sun.star.document.DocumentProperties");
    2389          15 :     return s;
    2390             : }
    2391             : 
    2392         492 : 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         492 :                 (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