forked from amazingfate/loongoffice
For some functions and all kinds of Exceptions. CannotConvertException CloseVetoException DisposedException EmptyUndoStackException ErrorCodeIOException Exception GridInvalidDataException GridInvalidModelException IOException IllegalAccessException IllegalArgumentException IllegalTypeException IndexOutOfBoundsException NoMasterException NoSuchElementException NoSupportException PropertyVetoException RuntimeException SAXException ScannerException StorageWrappedTargetException UnsupportedFlavorException VetoException WrappedTargetException ZipIOException throwGenericSQLException throwIllegallArgumentException createInstance createInstanceWithContext forName getByName getPackageManager getPropertyValue getUnpackedValueOrDefault getValueByName hasPropertyByName openKey setName setPropertyValue supportsService bash command: for i in `cat list`; do git grep "$i\s*(\s*OUString(\s*\"" -- '*.[hc]xx' | cut -d ':' -f1 | sort -u | xargs sed -i -e "s/\(\<$i\s*(\)\s*OUString(\s*\(\"[^\")\\]*\"\)\s*)\s*/\1\2/g" -e "s/\($i.*\)\"+ /\1\" + /g"; done Change-Id: Iaf8e641b0abf28c082906014f87a183517630535 Reviewed-on: https://gerrit.libreoffice.org/4624 Tested-by: LibreOffice gerrit bot <gerrit@libreoffice.org> Reviewed-by: Thomas Arnhold <thomas@arnhold.org> Tested-by: Thomas Arnhold <thomas@arnhold.org>
2367 lines
87 KiB
C++
2367 lines
87 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
|
|
#include "sal/config.h"
|
|
#include "cppuhelper/factory.hxx"
|
|
#include "cppuhelper/implementationentry.hxx"
|
|
#include "cppuhelper/compbase6.hxx"
|
|
#include "com/sun/star/lang/XServiceInfo.hpp"
|
|
#include "com/sun/star/document/XDocumentProperties.hpp"
|
|
#include "com/sun/star/lang/XInitialization.hpp"
|
|
#include "com/sun/star/util/XCloneable.hpp"
|
|
#include "com/sun/star/util/XModifiable.hpp"
|
|
#include "com/sun/star/xml/sax/XSAXSerializable.hpp"
|
|
|
|
#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
|
|
#include "com/sun/star/lang/EventObject.hpp"
|
|
#include "com/sun/star/beans/XPropertySet.hpp"
|
|
#include "com/sun/star/beans/XPropertySetInfo.hpp"
|
|
#include "com/sun/star/beans/PropertyAttribute.hpp"
|
|
#include "com/sun/star/task/ErrorCodeIOException.hpp"
|
|
#include "com/sun/star/embed/XStorage.hpp"
|
|
#include "com/sun/star/embed/XTransactedObject.hpp"
|
|
#include "com/sun/star/embed/ElementModes.hpp"
|
|
#include "com/sun/star/io/XActiveDataControl.hpp"
|
|
#include "com/sun/star/io/XActiveDataSource.hpp"
|
|
#include "com/sun/star/io/XStream.hpp"
|
|
#include "com/sun/star/document/XImporter.hpp"
|
|
#include "com/sun/star/document/XExporter.hpp"
|
|
#include "com/sun/star/document/XFilter.hpp"
|
|
#include "com/sun/star/xml/sax/Parser.hpp"
|
|
#include "com/sun/star/xml/sax/Writer.hpp"
|
|
#include "com/sun/star/xml/dom/XDocument.hpp"
|
|
#include "com/sun/star/xml/dom/XElement.hpp"
|
|
#include "com/sun/star/xml/dom/DocumentBuilder.hpp"
|
|
#include "com/sun/star/xml/dom/XSAXDocumentBuilder.hpp"
|
|
#include "com/sun/star/xml/dom/NodeType.hpp"
|
|
#include "com/sun/star/xml/xpath/XPathAPI.hpp"
|
|
#include "com/sun/star/util/Date.hpp"
|
|
#include "com/sun/star/util/Time.hpp"
|
|
#include "com/sun/star/util/Duration.hpp"
|
|
|
|
#include "SfxDocumentMetaData.hxx"
|
|
#include "rtl/ustrbuf.hxx"
|
|
#include "tools/debug.hxx"
|
|
#include "tools/datetime.hxx"
|
|
#include "osl/mutex.hxx"
|
|
#include "cppuhelper/basemutex.hxx"
|
|
#include "cppuhelper/interfacecontainer.hxx"
|
|
#include "comphelper/storagehelper.hxx"
|
|
#include "comphelper/mediadescriptor.hxx"
|
|
#include "comphelper/sequenceasvector.hxx"
|
|
#include "comphelper/stlunosequence.hxx"
|
|
#include "sot/storage.hxx"
|
|
#include "sfx2/docfile.hxx"
|
|
#include "sax/tools/converter.hxx"
|
|
|
|
#include <utility>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <cstring>
|
|
#include <limits>
|
|
|
|
|
|
#include <cppuhelper/implbase1.hxx>
|
|
#include <com/sun/star/document/XCompatWriterDocProperties.hpp>
|
|
#include <com/sun/star/beans/PropertyBag.hpp>
|
|
|
|
/**
|
|
* This file contains the implementation of the service
|
|
* com.sun.star.document.DocumentProperties.
|
|
* This service enables access to the meta-data stored in documents.
|
|
* Currently, this service only handles documents in ODF format.
|
|
*
|
|
* The implementation uses an XML DOM to store the properties.
|
|
* This approach was taken because it allows for preserving arbitrary XML data
|
|
* in loaded documents, which will be stored unmodified when saving the
|
|
* document again.
|
|
*
|
|
* Upon access, some properties are directly read from and updated in the DOM.
|
|
* Exception: it seems impossible to get notified upon addition of a property
|
|
* to a com.sun.star.beans.PropertyBag, which is used for storing user-defined
|
|
* properties; because of this, user-defined properties are updated in the
|
|
* XML DOM only when storing the document.
|
|
* Exception 2: when setting certain properties which correspond to attributes
|
|
* in the XML DOM, we want to remove the corresponding XML element. Detecting
|
|
* this condition can get messy, so we store all such properties as members,
|
|
* and update the DOM tree only when storing the document (in
|
|
* <method>updateUserDefinedAndAttributes</method>).
|
|
*
|
|
* @author mst
|
|
*/
|
|
|
|
/// anonymous implementation namespace
|
|
namespace {
|
|
|
|
/// a list of attribute-lists, where attribute means name and content
|
|
typedef std::vector<std::vector<std::pair<const char*, OUString> > >
|
|
AttrVector;
|
|
|
|
typedef ::cppu::WeakComponentImplHelper6<
|
|
css::lang::XServiceInfo,
|
|
css::document::XDocumentProperties,
|
|
css::lang::XInitialization,
|
|
css::util::XCloneable,
|
|
css::util::XModifiable,
|
|
css::xml::sax::XSAXSerializable>
|
|
SfxDocumentMetaData_Base;
|
|
|
|
class SfxDocumentMetaData:
|
|
private ::cppu::BaseMutex,
|
|
public SfxDocumentMetaData_Base
|
|
{
|
|
public:
|
|
explicit SfxDocumentMetaData(
|
|
css::uno::Reference< css::uno::XComponentContext > const & context);
|
|
|
|
// ::com::sun::star::lang::XServiceInfo:
|
|
virtual OUString SAL_CALL getImplementationName()
|
|
throw (css::uno::RuntimeException);
|
|
virtual ::sal_Bool SAL_CALL supportsService(
|
|
const OUString & ServiceName) throw (css::uno::RuntimeException);
|
|
virtual css::uno::Sequence< OUString > SAL_CALL
|
|
getSupportedServiceNames() throw (css::uno::RuntimeException);
|
|
|
|
// ::com::sun::star::lang::XComponent:
|
|
virtual void SAL_CALL dispose() throw (css::uno::RuntimeException);
|
|
|
|
// ::com::sun::star::document::XDocumentProperties:
|
|
virtual OUString SAL_CALL getAuthor()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setAuthor(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getGenerator()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setGenerator(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual css::util::DateTime SAL_CALL getCreationDate()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setCreationDate(const css::util::DateTime & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getTitle()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setTitle(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getSubject()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setSubject(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getDescription()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setDescription(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual css::uno::Sequence< OUString > SAL_CALL getKeywords()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setKeywords(
|
|
const css::uno::Sequence< OUString > & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual css::lang::Locale SAL_CALL getLanguage()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setLanguage(const css::lang::Locale & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getModifiedBy()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setModifiedBy(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual css::util::DateTime SAL_CALL getModificationDate()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setModificationDate(
|
|
const css::util::DateTime & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getPrintedBy()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setPrintedBy(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual css::util::DateTime SAL_CALL getPrintDate()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setPrintDate(const css::util::DateTime & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getTemplateName()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setTemplateName(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getTemplateURL()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setTemplateURL(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual css::util::DateTime SAL_CALL getTemplateDate()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setTemplateDate(const css::util::DateTime & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual OUString SAL_CALL getAutoloadURL()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setAutoloadURL(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual ::sal_Int32 SAL_CALL getAutoloadSecs()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setAutoloadSecs(::sal_Int32 the_value)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
|
|
virtual OUString SAL_CALL getDefaultTarget()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setDefaultTarget(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL
|
|
getDocumentStatistics() throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setDocumentStatistics(
|
|
const css::uno::Sequence< css::beans::NamedValue > & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual ::sal_Int16 SAL_CALL getEditingCycles()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setEditingCycles(::sal_Int16 the_value)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
|
|
virtual ::sal_Int32 SAL_CALL getEditingDuration()
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setEditingDuration(::sal_Int32 the_value)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException);
|
|
virtual void SAL_CALL resetUserData(const OUString & the_value)
|
|
throw (css::uno::RuntimeException);
|
|
virtual css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
|
|
getUserDefinedProperties() throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL loadFromStorage(
|
|
const css::uno::Reference< css::embed::XStorage > & Storage,
|
|
const css::uno::Sequence< css::beans::PropertyValue > & Medium)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
|
|
css::io::WrongFormatException,
|
|
css::lang::WrappedTargetException, css::io::IOException);
|
|
virtual void SAL_CALL loadFromMedium(const OUString & URL,
|
|
const css::uno::Sequence< css::beans::PropertyValue > & Medium)
|
|
throw (css::uno::RuntimeException,
|
|
css::io::WrongFormatException,
|
|
css::lang::WrappedTargetException, css::io::IOException);
|
|
virtual void SAL_CALL storeToStorage(
|
|
const css::uno::Reference< css::embed::XStorage > & Storage,
|
|
const css::uno::Sequence< css::beans::PropertyValue > & Medium)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
|
|
css::lang::WrappedTargetException, css::io::IOException);
|
|
virtual void SAL_CALL storeToMedium(const OUString & URL,
|
|
const css::uno::Sequence< css::beans::PropertyValue > & Medium)
|
|
throw (css::uno::RuntimeException,
|
|
css::lang::WrappedTargetException, css::io::IOException);
|
|
|
|
// ::com::sun::star::lang::XInitialization:
|
|
virtual void SAL_CALL initialize(
|
|
const css::uno::Sequence< css::uno::Any > & aArguments)
|
|
throw (css::uno::RuntimeException, css::uno::Exception);
|
|
|
|
// ::com::sun::star::util::XCloneable:
|
|
virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone()
|
|
throw (css::uno::RuntimeException);
|
|
|
|
// ::com::sun::star::util::XModifiable:
|
|
virtual ::sal_Bool SAL_CALL isModified( )
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL setModified( ::sal_Bool bModified )
|
|
throw (css::beans::PropertyVetoException, css::uno::RuntimeException);
|
|
|
|
// ::com::sun::star::util::XModifyBroadcaster:
|
|
virtual void SAL_CALL addModifyListener(
|
|
const css::uno::Reference< css::util::XModifyListener > & xListener)
|
|
throw (css::uno::RuntimeException);
|
|
virtual void SAL_CALL removeModifyListener(
|
|
const css::uno::Reference< css::util::XModifyListener > & xListener)
|
|
throw (css::uno::RuntimeException);
|
|
|
|
// ::com::sun::star::xml::sax::XSAXSerializable
|
|
virtual void SAL_CALL serialize(
|
|
const css::uno::Reference<css::xml::sax::XDocumentHandler>& i_xHandler,
|
|
const css::uno::Sequence< css::beans::StringPair >& i_rNamespaces)
|
|
throw (css::uno::RuntimeException, css::xml::sax::SAXException);
|
|
|
|
protected:
|
|
SfxDocumentMetaData(SfxDocumentMetaData &); // not defined
|
|
SfxDocumentMetaData& operator =(SfxDocumentMetaData &); // not defined
|
|
|
|
virtual ~SfxDocumentMetaData() {}
|
|
virtual SfxDocumentMetaData* createMe( css::uno::Reference< css::uno::XComponentContext > const & context ) { return new SfxDocumentMetaData( context ); };
|
|
const css::uno::Reference< css::uno::XComponentContext > m_xContext;
|
|
|
|
/// for notification
|
|
::cppu::OInterfaceContainerHelper m_NotifyListeners;
|
|
/// flag: false means not initialized yet, or disposed
|
|
bool m_isInitialized;
|
|
/// flag
|
|
bool m_isModified;
|
|
/// meta-data DOM tree
|
|
css::uno::Reference< css::xml::dom::XDocument > m_xDoc;
|
|
/// meta-data super node in the meta-data DOM tree
|
|
css::uno::Reference< css::xml::dom::XNode> m_xParent;
|
|
/// standard meta data (single occurrence)
|
|
std::map< OUString, css::uno::Reference<css::xml::dom::XNode> >
|
|
m_meta;
|
|
/// standard meta data (multiple occurrences)
|
|
std::map< OUString,
|
|
std::vector<css::uno::Reference<css::xml::dom::XNode> > > m_metaList;
|
|
/// user-defined meta data (meta:user-defined) @ATTENTION may be null!
|
|
css::uno::Reference<css::beans::XPropertyContainer> m_xUserDefined;
|
|
// now for some meta-data attributes; these are not updated directly in the
|
|
// DOM because updates (detecting "empty" elements) would be quite messy
|
|
OUString m_TemplateName;
|
|
OUString m_TemplateURL;
|
|
css::util::DateTime m_TemplateDate;
|
|
OUString m_AutoloadURL;
|
|
sal_Int32 m_AutoloadSecs;
|
|
OUString m_DefaultTarget;
|
|
|
|
/// check if we are initialized properly
|
|
void SAL_CALL checkInit() const;
|
|
/// initialize state from given DOM tree
|
|
void SAL_CALL init(css::uno::Reference<css::xml::dom::XDocument> i_xDom);
|
|
/// update element in DOM tree
|
|
void SAL_CALL updateElement(const char *i_name,
|
|
std::vector<std::pair<const char *, OUString> >* i_pAttrs = 0);
|
|
/// update user-defined meta data and attributes in DOM tree
|
|
void SAL_CALL updateUserDefinedAndAttributes();
|
|
/// create empty DOM tree (XDocument)
|
|
css::uno::Reference<css::xml::dom::XDocument> SAL_CALL createDOM() const;
|
|
/// extract base URL (necessary for converting relative links)
|
|
css::uno::Reference<css::beans::XPropertySet> SAL_CALL getURLProperties(
|
|
const css::uno::Sequence<css::beans::PropertyValue> & i_rMedium) const;
|
|
/// get text of standard meta data element
|
|
OUString SAL_CALL getMetaText(const char* i_name) const;
|
|
/// set text of standard meta data element iff not equal to existing text
|
|
bool SAL_CALL setMetaText(const char* i_name,
|
|
const OUString & i_rValue);
|
|
/// set text of standard meta data element iff not equal to existing text
|
|
void SAL_CALL setMetaTextAndNotify(const char* i_name,
|
|
const OUString & i_rValue);
|
|
/// get text of standard meta data element's attribute
|
|
OUString SAL_CALL getMetaAttr(const char* i_name,
|
|
const char* i_attr) const;
|
|
/// get text of a list of standard meta data elements (multiple occ.)
|
|
css::uno::Sequence< OUString > SAL_CALL getMetaList(
|
|
const char* i_name) const;
|
|
/// set text of a list of standard meta data elements (multiple occ.)
|
|
bool SAL_CALL setMetaList(const char* i_name,
|
|
const css::uno::Sequence< OUString > & i_rValue,
|
|
AttrVector const* = 0);
|
|
void createUserDefined();
|
|
};
|
|
|
|
typedef ::cppu::ImplInheritanceHelper1< SfxDocumentMetaData, css::document::XCompatWriterDocProperties > CompatWriterDocPropsImpl_BASE;
|
|
|
|
class CompatWriterDocPropsImpl : public CompatWriterDocPropsImpl_BASE
|
|
{
|
|
OUString msManager;
|
|
OUString msCategory;
|
|
OUString msCompany;
|
|
protected:
|
|
virtual SfxDocumentMetaData* createMe( css::uno::Reference< css::uno::XComponentContext > const & context ) { return new CompatWriterDocPropsImpl( context ); };
|
|
public:
|
|
CompatWriterDocPropsImpl( css::uno::Reference< css::uno::XComponentContext > const & context) : CompatWriterDocPropsImpl_BASE( context ) {}
|
|
// XCompatWriterDocPropsImpl
|
|
virtual OUString SAL_CALL getManager() throw (::com::sun::star::uno::RuntimeException) { return msManager; }
|
|
virtual void SAL_CALL setManager( const OUString& _manager ) throw (::com::sun::star::uno::RuntimeException) { msManager = _manager; }
|
|
virtual OUString SAL_CALL getCategory() throw (::com::sun::star::uno::RuntimeException){ return msCategory; }
|
|
virtual void SAL_CALL setCategory( const OUString& _category ) throw (::com::sun::star::uno::RuntimeException){ msCategory = _category; }
|
|
virtual OUString SAL_CALL getCompany() throw (::com::sun::star::uno::RuntimeException){ return msCompany; }
|
|
virtual void SAL_CALL setCompany( const OUString& _company ) throw (::com::sun::star::uno::RuntimeException){ msCompany = _company; }
|
|
|
|
// XServiceInfo
|
|
virtual OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
return comp_CompatWriterDocProps::_getImplementationName();
|
|
}
|
|
|
|
virtual ::sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
css::uno::Sequence< OUString > sServiceNames= getSupportedServiceNames();
|
|
sal_Int32 nLen = sServiceNames.getLength();
|
|
OUString* pIt = sServiceNames.getArray();
|
|
OUString* pEnd = ( pIt + nLen );
|
|
sal_Bool bRes = sal_False;
|
|
for ( ; pIt != pEnd; ++pIt )
|
|
{
|
|
if ( pIt->equals( ServiceName ) )
|
|
{
|
|
bRes = sal_True;
|
|
break;
|
|
}
|
|
}
|
|
return bRes;
|
|
}
|
|
|
|
virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
return comp_CompatWriterDocProps::_getSupportedServiceNames();
|
|
}
|
|
};
|
|
|
|
bool operator== (const css::util::DateTime &i_rLeft,
|
|
const css::util::DateTime &i_rRight)
|
|
{
|
|
return i_rLeft.Year == i_rRight.Year
|
|
&& i_rLeft.Month == i_rRight.Month
|
|
&& i_rLeft.Day == i_rRight.Day
|
|
&& i_rLeft.Hours == i_rRight.Hours
|
|
&& i_rLeft.Minutes == i_rRight.Minutes
|
|
&& i_rLeft.Seconds == i_rRight.Seconds
|
|
&& i_rLeft.NanoSeconds == i_rRight.NanoSeconds;
|
|
}
|
|
|
|
// NB: keep these two arrays in sync!
|
|
const char* s_stdStatAttrs[] = {
|
|
"meta:page-count",
|
|
"meta:table-count",
|
|
"meta:draw-count",
|
|
"meta:image-count",
|
|
"meta:object-count",
|
|
"meta:ole-object-count",
|
|
"meta:paragraph-count",
|
|
"meta:word-count",
|
|
"meta:character-count",
|
|
"meta:row-count",
|
|
"meta:frame-count",
|
|
"meta:sentence-count",
|
|
"meta:syllable-count",
|
|
"meta:non-whitespace-character-count",
|
|
"meta:cell-count",
|
|
0
|
|
};
|
|
|
|
// NB: keep these two arrays in sync!
|
|
const char* s_stdStats[] = {
|
|
"PageCount",
|
|
"TableCount",
|
|
"DrawCount",
|
|
"ImageCount",
|
|
"ObjectCount",
|
|
"OLEObjectCount",
|
|
"ParagraphCount",
|
|
"WordCount",
|
|
"CharacterCount",
|
|
"RowCount",
|
|
"FrameCount",
|
|
"SentenceCount",
|
|
"SyllableCount",
|
|
"NonWhitespaceCharacterCount",
|
|
"CellCount",
|
|
0
|
|
};
|
|
|
|
const char* s_stdMeta[] = {
|
|
"meta:generator", // string
|
|
"dc:title", // string
|
|
"dc:description", // string
|
|
"dc:subject", // string
|
|
"meta:initial-creator", // string
|
|
"dc:creator", // string
|
|
"meta:printed-by", // string
|
|
"meta:creation-date", // dateTime
|
|
"dc:date", // dateTime
|
|
"meta:print-date", // dateTime
|
|
"meta:template", // XLink
|
|
"meta:auto-reload", // ...
|
|
"meta:hyperlink-behaviour", // ...
|
|
"dc:language", // language
|
|
"meta:editing-cycles", // nonNegativeInteger
|
|
"meta:editing-duration", // duration
|
|
"meta:document-statistic", // ... // note: statistic is singular, no s!
|
|
0
|
|
};
|
|
|
|
const char* s_stdMetaList[] = {
|
|
"meta:keyword", // string*
|
|
"meta:user-defined", // ...*
|
|
0
|
|
};
|
|
|
|
const char* s_nsXLink = "http://www.w3.org/1999/xlink";
|
|
const char* s_nsDC = "http://purl.org/dc/elements/1.1/";
|
|
const char* s_nsODF = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
|
|
const char* s_nsODFMeta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0";
|
|
// const char* s_nsOOo = "http://openoffice.org/2004/office"; // not used (yet?)
|
|
|
|
static const char s_meta [] = "meta.xml";
|
|
|
|
bool isValidDate(const css::util::Date & i_rDate)
|
|
{
|
|
return i_rDate.Month > 0;
|
|
}
|
|
|
|
bool isValidDateTime(const css::util::DateTime & i_rDateTime)
|
|
{
|
|
return i_rDateTime.Month > 0;
|
|
}
|
|
|
|
std::pair< OUString, OUString > SAL_CALL
|
|
getQualifier(const char* i_name) {
|
|
OUString nm = OUString::createFromAscii(i_name);
|
|
sal_Int32 ix = nm.indexOf(static_cast<sal_Unicode> (':'));
|
|
if (ix == -1) {
|
|
return std::make_pair(OUString(), nm);
|
|
} else {
|
|
return std::make_pair(nm.copy(0,ix), nm.copy(ix+1));
|
|
}
|
|
}
|
|
|
|
// get namespace for standard qualified names
|
|
// NB: only call this with statically known strings!
|
|
OUString SAL_CALL getNameSpace(const char* i_qname) throw ()
|
|
{
|
|
DBG_ASSERT(i_qname, "SfxDocumentMetaData: getNameSpace: argument is null");
|
|
const char * ns = "";
|
|
OUString n = getQualifier(i_qname).first;
|
|
if ( n == "xlink" ) ns = s_nsXLink;
|
|
if ( n == "dc" ) ns = s_nsDC;
|
|
if ( n == "office" ) ns = s_nsODF;
|
|
if ( n == "meta" ) ns = s_nsODFMeta;
|
|
DBG_ASSERT(*ns, "SfxDocumentMetaData: unknown namespace prefix");
|
|
return OUString::createFromAscii(ns);
|
|
}
|
|
|
|
bool SAL_CALL
|
|
textToDateOrDateTime(css::util::Date & io_rd, css::util::DateTime & io_rdt,
|
|
bool & o_rIsDateTime, OUString i_text) throw ()
|
|
{
|
|
if (::sax::Converter::convertDateOrDateTime(
|
|
io_rd, io_rdt, o_rIsDateTime, i_text)) {
|
|
return true;
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
|
|
OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// convert string to date/time
|
|
bool SAL_CALL
|
|
textToDateTime(css::util::DateTime & io_rdt, OUString i_text) throw ()
|
|
{
|
|
if (::sax::Converter::convertDateTime(io_rdt, i_text)) {
|
|
return true;
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
|
|
OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// convert string to date/time with default return value
|
|
css::util::DateTime SAL_CALL
|
|
textToDateTimeDefault(OUString i_text) throw ()
|
|
{
|
|
css::util::DateTime dt;
|
|
static_cast<void> (textToDateTime(dt, i_text));
|
|
// on conversion error: return default value (unchanged)
|
|
return dt;
|
|
}
|
|
|
|
// convert date to string
|
|
OUString SAL_CALL
|
|
dateToText(css::util::Date const& i_rd) throw ()
|
|
{
|
|
if (isValidDate(i_rd)) {
|
|
OUStringBuffer buf;
|
|
::sax::Converter::convertDate(buf, i_rd);
|
|
return buf.makeStringAndClear();
|
|
} else {
|
|
return OUString();
|
|
}
|
|
}
|
|
|
|
|
|
// convert date/time to string
|
|
OUString SAL_CALL
|
|
dateTimeToText(css::util::DateTime const& i_rdt) throw ()
|
|
{
|
|
if (isValidDateTime(i_rdt)) {
|
|
OUStringBuffer buf;
|
|
::sax::Converter::convertDateTime(buf, i_rdt, true);
|
|
return buf.makeStringAndClear();
|
|
} else {
|
|
return OUString();
|
|
}
|
|
}
|
|
|
|
// convert string to duration
|
|
bool
|
|
textToDuration(css::util::Duration& io_rDur, OUString const& i_rText)
|
|
throw ()
|
|
{
|
|
if (::sax::Converter::convertDuration(io_rDur, i_rText)) {
|
|
return true;
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid duration: %s",
|
|
OUStringToOString(i_rText, RTL_TEXTENCODING_UTF8).getStr());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
sal_Int32 textToDuration(OUString const& i_rText) throw ()
|
|
{
|
|
css::util::Duration d;
|
|
if (textToDuration(d, i_rText)) {
|
|
// #i107372#: approximate years/months
|
|
const sal_Int32 days( (d.Years * 365) + (d.Months * 30) + d.Days );
|
|
return (days * (24*3600))
|
|
+ (d.Hours * 3600) + (d.Minutes * 60) + d.Seconds;
|
|
} else {
|
|
return 0; // default
|
|
}
|
|
}
|
|
|
|
// convert duration to string
|
|
OUString durationToText(css::util::Duration const& i_rDur) throw ()
|
|
{
|
|
OUStringBuffer buf;
|
|
::sax::Converter::convertDuration(buf, i_rDur);
|
|
return buf.makeStringAndClear();
|
|
}
|
|
|
|
// convert duration to string
|
|
OUString SAL_CALL durationToText(sal_Int32 i_value) throw ()
|
|
{
|
|
css::util::Duration ud;
|
|
ud.Days = static_cast<sal_Int16>(i_value / (24 * 3600));
|
|
ud.Hours = static_cast<sal_Int16>((i_value % (24 * 3600)) / 3600);
|
|
ud.Minutes = static_cast<sal_Int16>((i_value % 3600) / 60);
|
|
ud.Seconds = static_cast<sal_Int16>(i_value % 60);
|
|
ud.NanoSeconds = 0;
|
|
return durationToText(ud);
|
|
}
|
|
|
|
// extract base URL (necessary for converting relative links)
|
|
css::uno::Reference< css::beans::XPropertySet > SAL_CALL
|
|
SfxDocumentMetaData::getURLProperties(
|
|
const css::uno::Sequence< css::beans::PropertyValue > & i_rMedium) const
|
|
{
|
|
css::uno::Reference< css::beans::XPropertyBag> xPropArg = css::beans::PropertyBag::createDefault( m_xContext );
|
|
try {
|
|
OUString dburl("DocumentBaseURL");
|
|
OUString hdn("HierarchicalDocumentName");
|
|
for (sal_Int32 i = 0; i < i_rMedium.getLength(); ++i) {
|
|
if (i_rMedium[i].Name.equals(dburl)) {
|
|
xPropArg->addProperty(
|
|
OUString("BaseURI"),
|
|
css::beans::PropertyAttribute::MAYBEVOID,
|
|
i_rMedium[i].Value);
|
|
} else if (i_rMedium[i].Name.equals(hdn)) {
|
|
xPropArg->addProperty(
|
|
OUString("StreamRelPath"),
|
|
css::beans::PropertyAttribute::MAYBEVOID,
|
|
i_rMedium[i].Value);
|
|
}
|
|
}
|
|
xPropArg->addProperty(OUString("StreamName"),
|
|
css::beans::PropertyAttribute::MAYBEVOID,
|
|
css::uno::makeAny(OUString(s_meta)));
|
|
} catch (const css::uno::Exception &) {
|
|
// ignore
|
|
}
|
|
return css::uno::Reference< css::beans::XPropertySet>(xPropArg,
|
|
css::uno::UNO_QUERY_THROW);
|
|
}
|
|
|
|
// return the text of the (hopefully unique, i.e., normalize first!) text
|
|
// node _below_ the given node
|
|
OUString SAL_CALL
|
|
getNodeText(css::uno::Reference<css::xml::dom::XNode> i_xNode)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
if (!i_xNode.is()) throw css::uno::RuntimeException(
|
|
OUString("SfxDocumentMetaData::getNodeText: argument is null"), i_xNode);
|
|
for (css::uno::Reference<css::xml::dom::XNode> c = i_xNode->getFirstChild();
|
|
c.is();
|
|
c = c->getNextSibling()) {
|
|
if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
|
|
try {
|
|
return c->getNodeValue();
|
|
} catch (const css::xml::dom::DOMException &) { // too big?
|
|
return OUString();
|
|
}
|
|
}
|
|
}
|
|
return OUString();
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getMetaText(const char* i_name) const
|
|
// throw (css::uno::RuntimeException)
|
|
{
|
|
checkInit();
|
|
|
|
const OUString name( OUString::createFromAscii(i_name) );
|
|
DBG_ASSERT(m_meta.find(name) != m_meta.end(),
|
|
"SfxDocumentMetaData::getMetaText: not found");
|
|
css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
|
|
return (xNode.is()) ? getNodeText(xNode) : OUString();
|
|
}
|
|
|
|
bool SAL_CALL
|
|
SfxDocumentMetaData::setMetaText(const char* i_name,
|
|
const OUString & i_rValue)
|
|
// throw (css::uno::RuntimeException)
|
|
{
|
|
checkInit();
|
|
|
|
const OUString name( OUString::createFromAscii(i_name) );
|
|
DBG_ASSERT(m_meta.find(name) != m_meta.end(),
|
|
"SfxDocumentMetaData::setMetaText: not found");
|
|
css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
|
|
|
|
try {
|
|
if (i_rValue.isEmpty()) {
|
|
if (xNode.is()) { // delete
|
|
m_xParent->removeChild(xNode);
|
|
xNode.clear();
|
|
m_meta[name] = xNode;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (xNode.is()) { // update
|
|
for (css::uno::Reference<css::xml::dom::XNode> c =
|
|
xNode->getFirstChild();
|
|
c.is();
|
|
c = c->getNextSibling()) {
|
|
if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
|
|
if (!c->getNodeValue().equals(i_rValue)) {
|
|
c->setNodeValue(i_rValue);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
} else { // insert
|
|
xNode.set(m_xDoc->createElementNS(getNameSpace(i_name), name),
|
|
css::uno::UNO_QUERY_THROW);
|
|
m_xParent->appendChild(xNode);
|
|
m_meta[name] = xNode;
|
|
}
|
|
css::uno::Reference<css::xml::dom::XNode> xTextNode(
|
|
m_xDoc->createTextNode(i_rValue), css::uno::UNO_QUERY_THROW);
|
|
xNode->appendChild(xTextNode);
|
|
return true;
|
|
}
|
|
} catch (const css::xml::dom::DOMException & e) {
|
|
css::uno::Any a(e);
|
|
throw css::lang::WrappedTargetRuntimeException(
|
|
OUString("SfxDocumentMetaData::setMetaText: DOM exception"),
|
|
css::uno::Reference<css::uno::XInterface>(*this), a);
|
|
}
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setMetaTextAndNotify(const char* i_name,
|
|
const OUString & i_rValue)
|
|
// throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
if (setMetaText(i_name, i_rValue)) {
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getMetaAttr(const char* i_name, const char* i_attr) const
|
|
// throw (css::uno::RuntimeException)
|
|
{
|
|
OUString name = OUString::createFromAscii(i_name);
|
|
DBG_ASSERT(m_meta.find(name) != m_meta.end(),
|
|
"SfxDocumentMetaData::getMetaAttr: not found");
|
|
css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
|
|
if (xNode.is()) {
|
|
css::uno::Reference<css::xml::dom::XElement> xElem(xNode,
|
|
css::uno::UNO_QUERY_THROW);
|
|
return xElem->getAttributeNS(getNameSpace(i_attr),
|
|
getQualifier(i_attr).second);
|
|
} else {
|
|
return OUString();
|
|
}
|
|
}
|
|
|
|
css::uno::Sequence< OUString> SAL_CALL
|
|
SfxDocumentMetaData::getMetaList(const char* i_name) const
|
|
// throw (css::uno::RuntimeException)
|
|
{
|
|
checkInit();
|
|
OUString name = OUString::createFromAscii(i_name);
|
|
DBG_ASSERT(m_metaList.find(name) != m_metaList.end(),
|
|
"SfxDocumentMetaData::getMetaList: not found");
|
|
std::vector<css::uno::Reference<css::xml::dom::XNode> > const & vec =
|
|
m_metaList.find(name)->second;
|
|
css::uno::Sequence< OUString> ret(vec.size());
|
|
for (size_t i = 0; i < vec.size(); ++i) {
|
|
ret[i] = getNodeText(vec.at(i));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool SAL_CALL
|
|
SfxDocumentMetaData::setMetaList(const char* i_name,
|
|
const css::uno::Sequence< OUString> & i_rValue,
|
|
AttrVector const* i_pAttrs)
|
|
// throw (css::uno::RuntimeException)
|
|
{
|
|
checkInit();
|
|
DBG_ASSERT((i_pAttrs == 0) ||
|
|
(static_cast<size_t>(i_rValue.getLength()) == i_pAttrs->size()),
|
|
"SfxDocumentMetaData::setMetaList: invalid args");
|
|
|
|
try {
|
|
OUString name = OUString::createFromAscii(i_name);
|
|
DBG_ASSERT(m_metaList.find(name) != m_metaList.end(),
|
|
"SfxDocumentMetaData::setMetaList: not found");
|
|
std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
|
|
m_metaList[name];
|
|
|
|
// if nothing changed, do nothing
|
|
// alas, this does not check for permutations, or attributes...
|
|
if ((0 == i_pAttrs)) {
|
|
if (static_cast<size_t>(i_rValue.getLength()) == vec.size()) {
|
|
bool isEqual(true);
|
|
for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
|
|
css::uno::Reference<css::xml::dom::XNode> xNode(vec.at(i));
|
|
if (xNode.is()) {
|
|
OUString val = getNodeText(xNode);
|
|
if (!val.equals(i_rValue[i])) {
|
|
isEqual = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (isEqual) return false;
|
|
}
|
|
}
|
|
|
|
// remove old meta data nodes
|
|
{
|
|
std::vector<css::uno::Reference<css::xml::dom::XNode> >
|
|
::reverse_iterator it(vec.rbegin());
|
|
try {
|
|
for ( ;it != vec.rend(); ++it)
|
|
{
|
|
m_xParent->removeChild(*it);
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
// Clean up already removed nodes
|
|
vec.erase(it.base(), vec.end());
|
|
throw;
|
|
}
|
|
vec.clear();
|
|
}
|
|
|
|
// insert new meta data nodes into DOM tree
|
|
for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
|
|
css::uno::Reference<css::xml::dom::XElement> xElem(
|
|
m_xDoc->createElementNS(getNameSpace(i_name), name),
|
|
css::uno::UNO_QUERY_THROW);
|
|
css::uno::Reference<css::xml::dom::XNode> xNode(xElem,
|
|
css::uno::UNO_QUERY_THROW);
|
|
css::uno::Reference<css::xml::dom::XNode> xTextNode(
|
|
m_xDoc->createTextNode(i_rValue[i]), css::uno::UNO_QUERY_THROW);
|
|
// set attributes
|
|
if (i_pAttrs != 0) {
|
|
for (std::vector<std::pair<const char*, OUString> >
|
|
::const_iterator it = (*i_pAttrs)[i].begin();
|
|
it != (*i_pAttrs)[i].end(); ++it) {
|
|
xElem->setAttributeNS(getNameSpace(it->first),
|
|
OUString::createFromAscii(it->first),
|
|
it->second);
|
|
}
|
|
}
|
|
xNode->appendChild(xTextNode);
|
|
m_xParent->appendChild(xNode);
|
|
vec.push_back(xNode);
|
|
}
|
|
|
|
return true;
|
|
} catch (const css::xml::dom::DOMException & e) {
|
|
css::uno::Any a(e);
|
|
throw css::lang::WrappedTargetRuntimeException(
|
|
OUString("SfxDocumentMetaData::setMetaList: DOM exception"),
|
|
css::uno::Reference<css::uno::XInterface>(*this), a);
|
|
}
|
|
}
|
|
|
|
// convert property list to string list and attribute list
|
|
std::pair<css::uno::Sequence< OUString>, AttrVector> SAL_CALL
|
|
propsToStrings(css::uno::Reference<css::beans::XPropertySet> const & i_xPropSet)
|
|
{
|
|
::comphelper::SequenceAsVector< OUString > values;
|
|
AttrVector attrs;
|
|
|
|
css::uno::Reference<css::beans::XPropertySetInfo> xSetInfo
|
|
= i_xPropSet->getPropertySetInfo();
|
|
css::uno::Sequence<css::beans::Property> props = xSetInfo->getProperties();
|
|
|
|
for (sal_Int32 i = 0; i < props.getLength(); ++i) {
|
|
if (props[i].Attributes & css::beans::PropertyAttribute::TRANSIENT) {
|
|
continue;
|
|
}
|
|
const OUString name = props[i].Name;
|
|
css::uno::Any any;
|
|
try {
|
|
any = i_xPropSet->getPropertyValue(name);
|
|
} catch (const css::uno::Exception &) {
|
|
// ignore
|
|
}
|
|
const css::uno::Type & type = any.getValueType();
|
|
std::vector<std::pair<const char*, OUString> > as;
|
|
as.push_back(std::make_pair(static_cast<const char*>("meta:name"),
|
|
name));
|
|
const char* vt = "meta:value-type";
|
|
|
|
// convert according to type
|
|
if (type == ::cppu::UnoType<bool>::get()) {
|
|
bool b = false;
|
|
any >>= b;
|
|
OUStringBuffer buf;
|
|
::sax::Converter::convertBool(buf, b);
|
|
values.push_back(buf.makeStringAndClear());
|
|
as.push_back(std::make_pair(vt,
|
|
OUString("boolean")));
|
|
} else if (type == ::cppu::UnoType< OUString>::get()) {
|
|
OUString s;
|
|
any >>= s;
|
|
values.push_back(s);
|
|
// #i90847# OOo 2.x does stupid things if value-type="string";
|
|
// fortunately string is default anyway, so we can just omit it
|
|
// #i107502#: however, OOo 2.x only reads 4 user-defined without @value-type
|
|
// => best backward compatibility: first 4 without @value-type, rest with
|
|
if (4 <= i)
|
|
{
|
|
as.push_back(std::make_pair(vt,
|
|
OUString("string")));
|
|
}
|
|
} else if (type == ::cppu::UnoType<css::util::DateTime>::get()) {
|
|
css::util::DateTime dt;
|
|
any >>= dt;
|
|
values.push_back(dateTimeToText(dt));
|
|
as.push_back(std::make_pair(vt,
|
|
OUString("date")));
|
|
} else if (type == ::cppu::UnoType<css::util::Date>::get()) {
|
|
css::util::Date d;
|
|
any >>= d;
|
|
values.push_back(dateToText(d));
|
|
as.push_back(std::make_pair(vt,
|
|
OUString("date")));
|
|
} else if (type == ::cppu::UnoType<css::util::Time>::get()) {
|
|
// #i97029#: replaced by Duration
|
|
// Time is supported for backward compatibility with OOo 3.x, x<=2
|
|
css::util::Time ut;
|
|
any >>= ut;
|
|
css::util::Duration ud;
|
|
ud.Hours = ut.Hours;
|
|
ud.Minutes = ut.Minutes;
|
|
ud.Seconds = ut.Seconds;
|
|
ud.NanoSeconds = ut.NanoSeconds;
|
|
values.push_back(durationToText(ud));
|
|
as.push_back(std::make_pair(vt,
|
|
OUString("time")));
|
|
} else if (type == ::cppu::UnoType<css::util::Duration>::get()) {
|
|
css::util::Duration ud;
|
|
any >>= ud;
|
|
values.push_back(durationToText(ud));
|
|
as.push_back(std::make_pair(vt,
|
|
OUString("time")));
|
|
} else if (::cppu::UnoType<double>::get().isAssignableFrom(type)) {
|
|
// support not just double, but anything that can be converted
|
|
double d = 0;
|
|
any >>= d;
|
|
OUStringBuffer buf;
|
|
::sax::Converter::convertDouble(buf, d);
|
|
values.push_back(buf.makeStringAndClear());
|
|
as.push_back(std::make_pair(vt,
|
|
OUString("float")));
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: unsupported property type: %s",
|
|
OUStringToOString(any.getValueTypeName(),
|
|
RTL_TEXTENCODING_UTF8).getStr());
|
|
continue;
|
|
}
|
|
attrs.push_back(as);
|
|
}
|
|
|
|
return std::make_pair(values.getAsConstList(), attrs);
|
|
}
|
|
|
|
// remove the given element from the DOM, and iff i_pAttrs != 0 insert new one
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::updateElement(const char *i_name,
|
|
std::vector<std::pair<const char *, OUString> >* i_pAttrs)
|
|
{
|
|
OUString name = OUString::createFromAscii(i_name);
|
|
try {
|
|
// remove old element
|
|
css::uno::Reference<css::xml::dom::XNode> xNode =
|
|
m_meta.find(name)->second;
|
|
if (xNode.is()) {
|
|
m_xParent->removeChild(xNode);
|
|
xNode.clear();
|
|
}
|
|
// add new element
|
|
if (0 != i_pAttrs) {
|
|
css::uno::Reference<css::xml::dom::XElement> xElem(
|
|
m_xDoc->createElementNS(getNameSpace(i_name), name),
|
|
css::uno::UNO_QUERY_THROW);
|
|
xNode.set(xElem, css::uno::UNO_QUERY_THROW);
|
|
// set attributes
|
|
for (std::vector<std::pair<const char *, OUString> >
|
|
::const_iterator it = i_pAttrs->begin();
|
|
it != i_pAttrs->end(); ++it) {
|
|
xElem->setAttributeNS(getNameSpace(it->first),
|
|
OUString::createFromAscii(it->first), it->second);
|
|
}
|
|
m_xParent->appendChild(xNode);
|
|
}
|
|
m_meta[name] = xNode;
|
|
} catch (const css::xml::dom::DOMException & e) {
|
|
css::uno::Any a(e);
|
|
throw css::lang::WrappedTargetRuntimeException(
|
|
OUString("SfxDocumentMetaData::updateElement: DOM exception"),
|
|
css::uno::Reference<css::uno::XInterface>(*this), a);
|
|
}
|
|
}
|
|
|
|
// update user-defined meta data in DOM tree
|
|
void SAL_CALL SfxDocumentMetaData::updateUserDefinedAndAttributes()
|
|
{
|
|
createUserDefined();
|
|
const css::uno::Reference<css::beans::XPropertySet> xPSet(m_xUserDefined,
|
|
css::uno::UNO_QUERY_THROW);
|
|
const std::pair<css::uno::Sequence< OUString>, AttrVector>
|
|
udStringsAttrs( propsToStrings(xPSet) );
|
|
(void) setMetaList("meta:user-defined", udStringsAttrs.first,
|
|
&udStringsAttrs.second);
|
|
|
|
// update elements with attributes
|
|
std::vector<std::pair<const char *, OUString> > attributes;
|
|
if (!m_TemplateName.isEmpty() || !m_TemplateURL.isEmpty()
|
|
|| isValidDateTime(m_TemplateDate)) {
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("xlink:type"),
|
|
OUString("simple")));
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("xlink:actuate"),
|
|
OUString("onRequest")));
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("xlink:title"), m_TemplateName));
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("xlink:href" ), m_TemplateURL ));
|
|
if (isValidDateTime(m_TemplateDate)) {
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("meta:date" ),
|
|
dateTimeToText(m_TemplateDate)));
|
|
}
|
|
updateElement("meta:template", &attributes);
|
|
} else {
|
|
updateElement("meta:template");
|
|
}
|
|
attributes.clear();
|
|
|
|
if (!m_AutoloadURL.isEmpty() || (0 != m_AutoloadSecs)) {
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("xlink:href" ), m_AutoloadURL ));
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("meta:delay" ),
|
|
durationToText(m_AutoloadSecs)));
|
|
updateElement("meta:auto-reload", &attributes);
|
|
} else {
|
|
updateElement("meta:auto-reload");
|
|
}
|
|
attributes.clear();
|
|
|
|
if (!m_DefaultTarget.isEmpty()) {
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("office:target-frame-name"),
|
|
m_DefaultTarget));
|
|
// xlink:show: _blank -> new, any other value -> replace
|
|
const sal_Char* show = m_DefaultTarget == "_blank" ? "new" : "replace";
|
|
attributes.push_back(std::make_pair(
|
|
static_cast<const char*>("xlink:show"),
|
|
OUString::createFromAscii(show)));
|
|
updateElement("meta:hyperlink-behaviour", &attributes);
|
|
} else {
|
|
updateElement("meta:hyperlink-behaviour");
|
|
}
|
|
attributes.clear();
|
|
}
|
|
|
|
// create empty DOM tree (XDocument)
|
|
css::uno::Reference<css::xml::dom::XDocument> SAL_CALL
|
|
SfxDocumentMetaData::createDOM() const // throw (css::uno::RuntimeException)
|
|
{
|
|
css::uno::Reference<css::lang::XMultiComponentFactory> xMsf ( m_xContext->getServiceManager());
|
|
css::uno::Reference<css::xml::dom::XDocumentBuilder> xBuilder( css::xml::dom::DocumentBuilder::create(m_xContext) );
|
|
css::uno::Reference<css::xml::dom::XDocument> xDoc = xBuilder->newDocument();
|
|
if (!xDoc.is()) throw css::uno::RuntimeException(
|
|
OUString("SfxDocumentMetaData::createDOM: "
|
|
"cannot create new document"),
|
|
*const_cast<SfxDocumentMetaData*>(this));
|
|
return xDoc;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::checkInit() const // throw (css::uno::RuntimeException)
|
|
{
|
|
if (!m_isInitialized) {
|
|
throw css::uno::RuntimeException(OUString(
|
|
"SfxDocumentMetaData::checkInit: not initialized"),
|
|
*const_cast<SfxDocumentMetaData*>(this));
|
|
}
|
|
DBG_ASSERT((m_xDoc.is() && m_xParent.is() ),
|
|
"SfxDocumentMetaData::checkInit: reference is null");
|
|
}
|
|
|
|
// initialize state from DOM tree
|
|
void SAL_CALL SfxDocumentMetaData::init(
|
|
css::uno::Reference<css::xml::dom::XDocument> i_xDoc)
|
|
{
|
|
if (!i_xDoc.is()) throw css::uno::RuntimeException(
|
|
OUString("SfxDocumentMetaData::init: no DOM tree given"), *this);
|
|
|
|
css::uno::Reference<css::xml::xpath::XXPathAPI> xPath = css::xml::xpath::XPathAPI::create(m_xContext);
|
|
|
|
m_isInitialized = false;
|
|
m_xDoc = i_xDoc;
|
|
|
|
// select nodes for standard meta data stuff
|
|
xPath->registerNS(OUString("xlink"),
|
|
OUString::createFromAscii(s_nsXLink));
|
|
xPath->registerNS(OUString("dc"),
|
|
OUString::createFromAscii(s_nsDC));
|
|
xPath->registerNS(OUString("office"),
|
|
OUString::createFromAscii(s_nsODF));
|
|
xPath->registerNS(OUString("meta"),
|
|
OUString::createFromAscii(s_nsODFMeta));
|
|
// NB: we do not handle the single-XML-file ODF variant, which would
|
|
// have the root element office:document.
|
|
// The root of such documents must be converted in the importer!
|
|
OUString prefix(
|
|
"/child::office:document-meta/child::office:meta");
|
|
css::uno::Reference<css::xml::dom::XNode> xDocNode(
|
|
m_xDoc, css::uno::UNO_QUERY_THROW);
|
|
m_xParent.clear();
|
|
try {
|
|
m_xParent = xPath->selectSingleNode(xDocNode, prefix);
|
|
} catch (const com::sun::star::uno::Exception &) {
|
|
}
|
|
|
|
if (!m_xParent.is()) {
|
|
// all this create/append stuff may throw DOMException
|
|
try {
|
|
css::uno::Reference<css::xml::dom::XElement> xRElem;
|
|
css::uno::Reference<css::xml::dom::XNode> xNode(
|
|
i_xDoc->getFirstChild());
|
|
while (xNode.is()) {
|
|
if (css::xml::dom::NodeType_ELEMENT_NODE ==xNode->getNodeType())
|
|
{
|
|
if ( xNode->getNamespaceURI().equalsAscii(s_nsODF) && xNode->getLocalName() == "document-meta" )
|
|
{
|
|
xRElem.set(xNode, css::uno::UNO_QUERY_THROW);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
OSL_TRACE("SfxDocumentMetaData::init(): "
|
|
"deleting unexpected root element: %s",
|
|
OUStringToOString(xNode->getLocalName(),
|
|
RTL_TEXTENCODING_UTF8).getStr());
|
|
i_xDoc->removeChild(xNode);
|
|
xNode = i_xDoc->getFirstChild(); // start over
|
|
}
|
|
} else {
|
|
xNode = xNode->getNextSibling();
|
|
}
|
|
}
|
|
if (!xRElem.is()) {
|
|
xRElem = i_xDoc->createElementNS(
|
|
OUString::createFromAscii(s_nsODF),
|
|
OUString("office:document-meta"));
|
|
css::uno::Reference<css::xml::dom::XNode> xRNode(xRElem,
|
|
css::uno::UNO_QUERY_THROW);
|
|
i_xDoc->appendChild(xRNode);
|
|
}
|
|
xRElem->setAttributeNS(OUString::createFromAscii(s_nsODF),
|
|
OUString("office:version"),
|
|
OUString("1.0"));
|
|
// does not exist, otherwise m_xParent would not be null
|
|
css::uno::Reference<css::xml::dom::XNode> xParent (
|
|
i_xDoc->createElementNS(
|
|
OUString::createFromAscii(s_nsODF),
|
|
OUString("office:meta")),
|
|
css::uno::UNO_QUERY_THROW);
|
|
xRElem->appendChild(xParent);
|
|
m_xParent = xParent;
|
|
} catch (const css::xml::dom::DOMException & e) {
|
|
css::uno::Any a(e);
|
|
throw css::lang::WrappedTargetRuntimeException(
|
|
OUString("SfxDocumentMetaData::init: DOM exception"),
|
|
css::uno::Reference<css::uno::XInterface>(*this), a);
|
|
}
|
|
}
|
|
|
|
|
|
// select nodes for elements of which we only handle one occurrence
|
|
for (const char **pName = s_stdMeta; *pName != 0; ++pName) {
|
|
OUString name = OUString::createFromAscii(*pName);
|
|
// NB: If a document contains more than one occurrence of a
|
|
// meta-data element, we arbitrarily pick one of them here.
|
|
// We do not remove the others, i.e., when we write the
|
|
// document, it will contain the duplicates unchanged.
|
|
// The ODF spec says that handling multiple occurrences is
|
|
// application-specific.
|
|
css::uno::Reference<css::xml::dom::XNode> xNode =
|
|
xPath->selectSingleNode(m_xParent,
|
|
OUString("child::") + name);
|
|
// Do not create an empty element if it is missing;
|
|
// for certain elements, such as dateTime, this would be invalid
|
|
m_meta[name] = xNode;
|
|
}
|
|
|
|
// select nodes for elements of which we handle all occurrences
|
|
for (const char **pName = s_stdMetaList; *pName != 0; ++pName) {
|
|
OUString name = OUString::createFromAscii(*pName);
|
|
css::uno::Reference<css::xml::dom::XNodeList> nodes =
|
|
xPath->selectNodeList(m_xParent,
|
|
OUString("child::") + name);
|
|
std::vector<css::uno::Reference<css::xml::dom::XNode> > v;
|
|
for (sal_Int32 i = 0; i < nodes->getLength(); ++i) {
|
|
v.push_back(nodes->item(i));
|
|
}
|
|
m_metaList[name] = v;
|
|
}
|
|
|
|
// initialize members corresponding to attributes from DOM nodes
|
|
m_TemplateName = getMetaAttr("meta:template", "xlink:title");
|
|
m_TemplateURL = getMetaAttr("meta:template", "xlink:href");
|
|
m_TemplateDate =
|
|
textToDateTimeDefault(getMetaAttr("meta:template", "meta:date"));
|
|
m_AutoloadURL = getMetaAttr("meta:auto-reload", "xlink:href");
|
|
m_AutoloadSecs =
|
|
textToDuration(getMetaAttr("meta:auto-reload", "meta:delay"));
|
|
m_DefaultTarget =
|
|
getMetaAttr("meta:hyperlink-behaviour", "office:target-frame-name");
|
|
|
|
|
|
std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
|
|
m_metaList[OUString("meta:user-defined")];
|
|
m_xUserDefined.clear(); // #i105826#: reset (may be re-initialization)
|
|
if ( !vec.empty() )
|
|
{
|
|
createUserDefined();
|
|
}
|
|
|
|
// user-defined meta data: initialize PropertySet from DOM nodes
|
|
for (std::vector<css::uno::Reference<css::xml::dom::XNode> >::iterator
|
|
it = vec.begin(); it != vec.end(); ++it) {
|
|
css::uno::Reference<css::xml::dom::XElement> xElem(*it,
|
|
css::uno::UNO_QUERY_THROW);
|
|
css::uno::Any any;
|
|
OUString name = xElem->getAttributeNS(
|
|
OUString::createFromAscii(s_nsODFMeta),
|
|
OUString("name"));
|
|
OUString type = xElem->getAttributeNS(
|
|
OUString::createFromAscii(s_nsODFMeta),
|
|
OUString("value-type"));
|
|
OUString text = getNodeText(*it);
|
|
if ( type == "float" ) {
|
|
double d;
|
|
if (::sax::Converter::convertDouble(d, text)) {
|
|
any <<= d;
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid float: %s",
|
|
OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
|
|
continue;
|
|
}
|
|
} else if ( type == "date" ) {
|
|
bool isDateTime;
|
|
css::util::Date d;
|
|
css::util::DateTime dt;
|
|
if (textToDateOrDateTime(d, dt, isDateTime, text)) {
|
|
if (isDateTime) {
|
|
any <<= dt;
|
|
} else {
|
|
any <<= d;
|
|
}
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid date: %s",
|
|
OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
|
|
continue;
|
|
}
|
|
} else if ( type == "time" ) {
|
|
css::util::Duration ud;
|
|
if (textToDuration(ud, text)) {
|
|
any <<= ud;
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid time: %s",
|
|
OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
|
|
continue;
|
|
}
|
|
} else if ( type == "boolean" ) {
|
|
bool b;
|
|
if (::sax::Converter::convertBool(b, text)) {
|
|
any <<= b;
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid boolean: %s",
|
|
OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
|
|
continue;
|
|
}
|
|
} else if ( type == "string" || true) { // default
|
|
any <<= text;
|
|
}
|
|
try {
|
|
m_xUserDefined->addProperty(name,
|
|
css::beans::PropertyAttribute::REMOVABLE, any);
|
|
} catch (const css::beans::PropertyExistException &) {
|
|
DBG_WARNING1("SfxDocumentMetaData: duplicate: %s",
|
|
OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
|
|
// ignore; duplicate
|
|
} catch (const css::beans::IllegalTypeException &) {
|
|
OSL_TRACE("SfxDocumentMetaData: illegal type: %s",
|
|
OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
|
|
} catch (const css::lang::IllegalArgumentException &) {
|
|
OSL_TRACE("SfxDocumentMetaData: illegal arg: %s",
|
|
OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
|
|
}
|
|
}
|
|
|
|
m_isModified = false;
|
|
m_isInitialized = true;
|
|
}
|
|
|
|
|
|
|
|
SfxDocumentMetaData::SfxDocumentMetaData(
|
|
css::uno::Reference< css::uno::XComponentContext > const & context)
|
|
: BaseMutex()
|
|
, SfxDocumentMetaData_Base(m_aMutex)
|
|
, m_xContext(context)
|
|
, m_NotifyListeners(m_aMutex)
|
|
, m_isInitialized(false)
|
|
, m_isModified(false)
|
|
, m_AutoloadSecs(0)
|
|
{
|
|
DBG_ASSERT(context.is(), "SfxDocumentMetaData: context is null");
|
|
DBG_ASSERT(context->getServiceManager().is(),
|
|
"SfxDocumentMetaData: context has no service manager");
|
|
init(createDOM());
|
|
}
|
|
|
|
// com.sun.star.uno.XServiceInfo:
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getImplementationName() throw (css::uno::RuntimeException)
|
|
{
|
|
return comp_SfxDocumentMetaData::_getImplementationName();
|
|
}
|
|
|
|
::sal_Bool SAL_CALL
|
|
SfxDocumentMetaData::supportsService(OUString const & serviceName)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
css::uno::Sequence< OUString > serviceNames =
|
|
comp_SfxDocumentMetaData::_getSupportedServiceNames();
|
|
for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
|
|
if (serviceNames[i] == serviceName)
|
|
return sal_True;
|
|
}
|
|
return sal_False;
|
|
}
|
|
|
|
css::uno::Sequence< OUString > SAL_CALL
|
|
SfxDocumentMetaData::getSupportedServiceNames()
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
return comp_SfxDocumentMetaData::_getSupportedServiceNames();
|
|
}
|
|
|
|
|
|
// ::com::sun::star::lang::XComponent:
|
|
void SAL_CALL SfxDocumentMetaData::dispose() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
if (!m_isInitialized) {
|
|
return;
|
|
}
|
|
WeakComponentImplHelperBase::dispose(); // superclass
|
|
m_NotifyListeners.disposeAndClear(css::lang::EventObject(
|
|
static_cast< ::cppu::OWeakObject* >(this)));
|
|
m_isInitialized = false;
|
|
m_meta.clear();
|
|
m_metaList.clear();
|
|
m_xParent.clear();
|
|
m_xDoc.clear();
|
|
m_xUserDefined.clear();
|
|
}
|
|
|
|
|
|
// ::com::sun::star::document::XDocumentProperties:
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getAuthor() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return getMetaText("meta:initial-creator");
|
|
}
|
|
|
|
void SAL_CALL SfxDocumentMetaData::setAuthor(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("meta:initial-creator", the_value);
|
|
}
|
|
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getGenerator() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return getMetaText("meta:generator");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setGenerator(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("meta:generator", the_value);
|
|
}
|
|
|
|
css::util::DateTime SAL_CALL
|
|
SfxDocumentMetaData::getCreationDate() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return textToDateTimeDefault(getMetaText("meta:creation-date"));
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setCreationDate(const css::util::DateTime & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("meta:creation-date", dateTimeToText(the_value));
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getTitle() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return getMetaText("dc:title");
|
|
}
|
|
|
|
void SAL_CALL SfxDocumentMetaData::setTitle(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("dc:title", the_value);
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getSubject() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return getMetaText("dc:subject");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setSubject(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("dc:subject", the_value);
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getDescription() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return getMetaText("dc:description");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setDescription(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("dc:description", the_value);
|
|
}
|
|
|
|
css::uno::Sequence< OUString >
|
|
SAL_CALL SfxDocumentMetaData::getKeywords() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return getMetaList("meta:keyword");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setKeywords(
|
|
const css::uno::Sequence< OUString > & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
if (setMetaList("meta:keyword", the_value)) {
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
css::lang::Locale SAL_CALL
|
|
SfxDocumentMetaData::getLanguage() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
css::lang::Locale loc;
|
|
OUString text = getMetaText("dc:language");
|
|
sal_Int32 ix = text.indexOf(static_cast<sal_Unicode> ('-'));
|
|
if (ix == -1) {
|
|
loc.Language = text;
|
|
} else {
|
|
loc.Language = text.copy(0, ix);
|
|
loc.Country = text.copy(ix+1);
|
|
}
|
|
return loc;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setLanguage(const css::lang::Locale & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
OUString text = the_value.Language;
|
|
if (!the_value.Country.isEmpty()) {
|
|
text += OUString("-").concat(the_value.Country);
|
|
}
|
|
setMetaTextAndNotify("dc:language", text);
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getModifiedBy() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return getMetaText("dc:creator");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setModifiedBy(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("dc:creator", the_value);
|
|
}
|
|
|
|
css::util::DateTime SAL_CALL
|
|
SfxDocumentMetaData::getModificationDate() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return textToDateTimeDefault(getMetaText("dc:date"));
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setModificationDate(const css::util::DateTime & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("dc:date", dateTimeToText(the_value));
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getPrintedBy() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return getMetaText("meta:printed-by");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setPrintedBy(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("meta:printed-by", the_value);
|
|
}
|
|
|
|
css::util::DateTime SAL_CALL
|
|
SfxDocumentMetaData::getPrintDate() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return textToDateTimeDefault(getMetaText("meta:print-date"));
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setPrintDate(const css::util::DateTime & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
setMetaTextAndNotify("meta:print-date", dateTimeToText(the_value));
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getTemplateName() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
return m_TemplateName;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setTemplateName(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
checkInit();
|
|
if (m_TemplateName != the_value) {
|
|
m_TemplateName = the_value;
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getTemplateURL() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
return m_TemplateURL;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setTemplateURL(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
checkInit();
|
|
if (m_TemplateURL != the_value) {
|
|
m_TemplateURL = the_value;
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
css::util::DateTime SAL_CALL
|
|
SfxDocumentMetaData::getTemplateDate() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
return m_TemplateDate;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setTemplateDate(const css::util::DateTime & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
checkInit();
|
|
if (!(m_TemplateDate == the_value)) {
|
|
m_TemplateDate = the_value;
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getAutoloadURL() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
return m_AutoloadURL;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setAutoloadURL(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
checkInit();
|
|
if (m_AutoloadURL != the_value) {
|
|
m_AutoloadURL = the_value;
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
::sal_Int32 SAL_CALL
|
|
SfxDocumentMetaData::getAutoloadSecs() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
return m_AutoloadSecs;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setAutoloadSecs(::sal_Int32 the_value)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
|
|
{
|
|
if (the_value < 0) throw css::lang::IllegalArgumentException(
|
|
OUString("SfxDocumentMetaData::setAutoloadSecs: argument is negative"),
|
|
*this, 0);
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
checkInit();
|
|
if (m_AutoloadSecs != the_value) {
|
|
m_AutoloadSecs = the_value;
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SfxDocumentMetaData::getDefaultTarget() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
return m_DefaultTarget;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setDefaultTarget(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
checkInit();
|
|
if (m_DefaultTarget != the_value) {
|
|
m_DefaultTarget = the_value;
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
css::uno::Sequence< css::beans::NamedValue > SAL_CALL
|
|
SfxDocumentMetaData::getDocumentStatistics() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
::comphelper::SequenceAsVector<css::beans::NamedValue> stats;
|
|
for (size_t i = 0; s_stdStats[i] != 0; ++i) {
|
|
const char * aName = s_stdStatAttrs[i];
|
|
OUString text = getMetaAttr("meta:document-statistic", aName);
|
|
if (text.isEmpty()) continue;
|
|
css::beans::NamedValue stat;
|
|
stat.Name = OUString::createFromAscii(s_stdStats[i]);
|
|
sal_Int32 val;
|
|
css::uno::Any any;
|
|
if (!::sax::Converter::convertNumber(val, text, 0,
|
|
std::numeric_limits<sal_Int32>::max()) || (val < 0)) {
|
|
val = 0;
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid number: %s",
|
|
OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr());
|
|
}
|
|
any <<= val;
|
|
stat.Value = any;
|
|
stats.push_back(stat);
|
|
}
|
|
|
|
return stats.getAsConstList();
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setDocumentStatistics(
|
|
const css::uno::Sequence< css::beans::NamedValue > & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
checkInit();
|
|
std::vector<std::pair<const char *, OUString> > attributes;
|
|
for (sal_Int32 i = 0; i < the_value.getLength(); ++i) {
|
|
const OUString name = the_value[i].Name;
|
|
// inefficently search for matching attribute
|
|
for (size_t j = 0; s_stdStats[j] != 0; ++j) {
|
|
if (name.equalsAscii(s_stdStats[j])) {
|
|
const css::uno::Any any = the_value[i].Value;
|
|
sal_Int32 val = 0;
|
|
if (any >>= val) {
|
|
OUStringBuffer buf;
|
|
::sax::Converter::convertNumber(buf, val);
|
|
attributes.push_back(std::make_pair(s_stdStatAttrs[j],
|
|
buf.makeStringAndClear()));
|
|
} else {
|
|
DBG_WARNING1("SfxDocumentMetaData: invalid statistic: %s",
|
|
OUStringToOString(name, RTL_TEXTENCODING_UTF8)
|
|
.getStr());
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
updateElement("meta:document-statistic", &attributes);
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
|
|
::sal_Int16 SAL_CALL
|
|
SfxDocumentMetaData::getEditingCycles() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
OUString text = getMetaText("meta:editing-cycles");
|
|
sal_Int32 ret;
|
|
if (::sax::Converter::convertNumber(ret, text,
|
|
0, std::numeric_limits<sal_Int16>::max())) {
|
|
return static_cast<sal_Int16>(ret);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setEditingCycles(::sal_Int16 the_value)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
|
|
{
|
|
if (the_value < 0) throw css::lang::IllegalArgumentException(
|
|
OUString("SfxDocumentMetaData::setEditingCycles: argument is negative"),
|
|
*this, 0);
|
|
OUStringBuffer buf;
|
|
::sax::Converter::convertNumber(buf, the_value);
|
|
setMetaTextAndNotify("meta:editing-cycles", buf.makeStringAndClear());
|
|
}
|
|
|
|
::sal_Int32 SAL_CALL
|
|
SfxDocumentMetaData::getEditingDuration() throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
return textToDuration(getMetaText("meta:editing-duration"));
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::setEditingDuration(::sal_Int32 the_value)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
|
|
{
|
|
if (the_value < 0) throw css::lang::IllegalArgumentException(
|
|
OUString("SfxDocumentMetaData::setEditingDuration: argument is negative"),
|
|
*this, 0);
|
|
setMetaTextAndNotify("meta:editing-duration", durationToText(the_value));
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::resetUserData(const OUString & the_value)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard g(m_aMutex);
|
|
|
|
bool bModified( false );
|
|
bModified |= setMetaText("meta:initial-creator", the_value);
|
|
::DateTime now( ::DateTime::SYSTEM );
|
|
css::util::DateTime uDT(now.GetNanoSec(), now.GetSec(), now.GetMin(),
|
|
now.GetHour(), now.GetDay(), now.GetMonth(), now.GetYear());
|
|
bModified |= setMetaText("meta:creation-date", dateTimeToText(uDT));
|
|
bModified |= setMetaText("dc:creator", OUString());
|
|
bModified |= setMetaText("meta:printed-by", OUString());
|
|
bModified |= setMetaText("dc:date", dateTimeToText(css::util::DateTime()));
|
|
bModified |= setMetaText("meta:print-date",
|
|
dateTimeToText(css::util::DateTime()));
|
|
bModified |= setMetaText("meta:editing-duration", durationToText(0));
|
|
bModified |= setMetaText("meta:editing-cycles",
|
|
OUString("1"));
|
|
|
|
if (bModified) {
|
|
g.clear();
|
|
setModified(true);
|
|
}
|
|
}
|
|
|
|
|
|
css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
|
|
SfxDocumentMetaData::getUserDefinedProperties()
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
createUserDefined();
|
|
return m_xUserDefined;
|
|
}
|
|
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::loadFromStorage(
|
|
const css::uno::Reference< css::embed::XStorage > & xStorage,
|
|
const css::uno::Sequence< css::beans::PropertyValue > & Medium)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
|
|
css::io::WrongFormatException,
|
|
css::lang::WrappedTargetException, css::io::IOException)
|
|
{
|
|
if (!xStorage.is()) throw css::lang::IllegalArgumentException(
|
|
OUString("SfxDocumentMetaData::loadFromStorage: argument is null"), *this, 0);
|
|
::osl::MutexGuard g(m_aMutex);
|
|
|
|
// open meta data file
|
|
css::uno::Reference<css::io::XStream> xStream(
|
|
xStorage->openStreamElement(
|
|
OUString(s_meta),
|
|
css::embed::ElementModes::READ) );
|
|
if (!xStream.is()) throw css::uno::RuntimeException();
|
|
css::uno::Reference<css::io::XInputStream> xInStream =
|
|
xStream->getInputStream();
|
|
if (!xInStream.is()) throw css::uno::RuntimeException();
|
|
|
|
// create DOM parser service
|
|
css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
|
|
m_xContext->getServiceManager());
|
|
css::uno::Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(m_xContext);
|
|
css::xml::sax::InputSource input;
|
|
input.aInputStream = xInStream;
|
|
|
|
sal_uInt64 version = SotStorage::GetVersion( xStorage );
|
|
// Oasis is also the default (0)
|
|
sal_Bool bOasis = ( version > SOFFICE_FILEFORMAT_60 || version == 0 );
|
|
const sal_Char *pServiceName = bOasis
|
|
? "com.sun.star.document.XMLOasisMetaImporter"
|
|
: "com.sun.star.document.XMLMetaImporter";
|
|
|
|
// set base URL
|
|
css::uno::Reference<css::beans::XPropertySet> xPropArg =
|
|
getURLProperties(Medium);
|
|
try {
|
|
xPropArg->getPropertyValue("BaseURI")
|
|
>>= input.sSystemId;
|
|
input.sSystemId += OUString("/").concat(
|
|
OUString(s_meta));
|
|
} catch (const css::uno::Exception &) {
|
|
input.sSystemId = OUString(s_meta);
|
|
}
|
|
css::uno::Sequence< css::uno::Any > args(1);
|
|
args[0] <<= xPropArg;
|
|
|
|
css::uno::Reference<css::xml::sax::XDocumentHandler> xDocHandler (
|
|
xMsf->createInstanceWithArgumentsAndContext(
|
|
OUString::createFromAscii(pServiceName), args, m_xContext),
|
|
css::uno::UNO_QUERY_THROW);
|
|
if (!xDocHandler.is()) throw css::uno::RuntimeException(
|
|
OUString("SfxDocumentMetaData::loadFromStorage:"
|
|
" cannot create XMLOasisMetaImporter service"), *this);
|
|
css::uno::Reference<css::document::XImporter> xImp (xDocHandler,
|
|
css::uno::UNO_QUERY_THROW);
|
|
xImp->setTargetDocument(css::uno::Reference<css::lang::XComponent>(this));
|
|
xParser->setDocumentHandler(xDocHandler);
|
|
try {
|
|
xParser->parseStream(input);
|
|
} catch (const css::xml::sax::SAXException &) {
|
|
throw css::io::WrongFormatException(OUString(
|
|
"SfxDocumentMetaData::loadFromStorage:"
|
|
" XML parsing exception"), *this);
|
|
}
|
|
// NB: the implementation of XMLOasisMetaImporter calls initialize
|
|
checkInit();
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::storeToStorage(
|
|
const css::uno::Reference< css::embed::XStorage > & xStorage,
|
|
const css::uno::Sequence< css::beans::PropertyValue > & Medium)
|
|
throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
|
|
css::lang::WrappedTargetException, css::io::IOException)
|
|
{
|
|
if (!xStorage.is()) throw css::lang::IllegalArgumentException(
|
|
OUString("SfxDocumentMetaData::storeToStorage:"
|
|
" argument is null"), *this, 0);
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
|
|
// update user-defined meta data in DOM tree
|
|
// updateUserDefinedAndAttributes(); // this will be done in serialize!
|
|
|
|
// write into storage
|
|
css::uno::Reference<css::io::XStream> xStream =
|
|
xStorage->openStreamElement(OUString(s_meta),
|
|
css::embed::ElementModes::WRITE
|
|
| css::embed::ElementModes::TRUNCATE);
|
|
if (!xStream.is()) throw css::uno::RuntimeException();
|
|
css::uno::Reference< css::beans::XPropertySet > xStreamProps(xStream,
|
|
css::uno::UNO_QUERY_THROW);
|
|
xStreamProps->setPropertyValue(
|
|
OUString("MediaType"),
|
|
css::uno::makeAny(OUString("text/xml")));
|
|
xStreamProps->setPropertyValue(
|
|
OUString("Compressed"),
|
|
css::uno::makeAny(static_cast<sal_Bool> (sal_False)));
|
|
xStreamProps->setPropertyValue(
|
|
OUString("UseCommonStoragePasswordEncryption"),
|
|
css::uno::makeAny(static_cast<sal_Bool> (sal_False)));
|
|
css::uno::Reference<css::io::XOutputStream> xOutStream =
|
|
xStream->getOutputStream();
|
|
if (!xOutStream.is()) throw css::uno::RuntimeException();
|
|
css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
|
|
m_xContext->getServiceManager());
|
|
css::uno::Reference<css::xml::sax::XWriter> xSaxWriter(
|
|
css::xml::sax::Writer::create(m_xContext));
|
|
xSaxWriter->setOutputStream(xOutStream);
|
|
|
|
const sal_uInt64 version = SotStorage::GetVersion( xStorage );
|
|
// Oasis is also the default (0)
|
|
const sal_Bool bOasis = ( version > SOFFICE_FILEFORMAT_60 || version == 0 );
|
|
const sal_Char *pServiceName = bOasis
|
|
? "com.sun.star.document.XMLOasisMetaExporter"
|
|
: "com.sun.star.document.XMLMetaExporter";
|
|
|
|
// set base URL
|
|
css::uno::Reference<css::beans::XPropertySet> xPropArg =
|
|
getURLProperties(Medium);
|
|
css::uno::Sequence< css::uno::Any > args(2);
|
|
args[0] <<= xSaxWriter;
|
|
args[1] <<= xPropArg;
|
|
|
|
css::uno::Reference<css::document::XExporter> xExp(
|
|
xMsf->createInstanceWithArgumentsAndContext(
|
|
OUString::createFromAscii(pServiceName), args, m_xContext),
|
|
css::uno::UNO_QUERY_THROW);
|
|
xExp->setSourceDocument(css::uno::Reference<css::lang::XComponent>(this));
|
|
css::uno::Reference<css::document::XFilter> xFilter(xExp,
|
|
css::uno::UNO_QUERY_THROW);
|
|
if (xFilter->filter(css::uno::Sequence< css::beans::PropertyValue >())) {
|
|
css::uno::Reference<css::embed::XTransactedObject> xTransaction(
|
|
xStorage, css::uno::UNO_QUERY);
|
|
if (xTransaction.is()) {
|
|
xTransaction->commit();
|
|
}
|
|
} else {
|
|
throw css::io::IOException(OUString(
|
|
"SfxDocumentMetaData::storeToStorage: cannot filter"), *this);
|
|
}
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::loadFromMedium(const OUString & URL,
|
|
const css::uno::Sequence< css::beans::PropertyValue > & Medium)
|
|
throw (css::uno::RuntimeException, css::io::WrongFormatException,
|
|
css::lang::WrappedTargetException, css::io::IOException)
|
|
{
|
|
css::uno::Reference<css::io::XInputStream> xIn;
|
|
::comphelper::MediaDescriptor md(Medium);
|
|
// if we have an URL parameter, it replaces the one in the media descriptor
|
|
if (!URL.isEmpty()) {
|
|
md[ ::comphelper::MediaDescriptor::PROP_URL() ] <<= URL;
|
|
}
|
|
if (sal_True == md.addInputStream()) {
|
|
md[ ::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] >>= xIn;
|
|
}
|
|
css::uno::Reference<css::embed::XStorage> xStorage;
|
|
try {
|
|
if (xIn.is()) {
|
|
xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream(
|
|
xIn, m_xContext);
|
|
} else { // fallback to url parameter
|
|
xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
|
|
URL, css::embed::ElementModes::READ, m_xContext);
|
|
}
|
|
} catch (const css::uno::RuntimeException &) {
|
|
throw;
|
|
} catch (const css::io::IOException &) {
|
|
throw;
|
|
} catch (const css::uno::Exception & e) {
|
|
throw css::lang::WrappedTargetException(
|
|
OUString("SfxDocumentMetaData::loadFromMedium: exception"),
|
|
css::uno::Reference<css::uno::XInterface>(*this),
|
|
css::uno::makeAny(e));
|
|
}
|
|
if (!xStorage.is()) {
|
|
throw css::uno::RuntimeException(OUString(
|
|
"SfxDocumentMetaData::loadFromMedium: cannot get Storage"),
|
|
*this);
|
|
}
|
|
loadFromStorage(xStorage, md.getAsConstPropertyValueList());
|
|
}
|
|
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::storeToMedium(const OUString & URL,
|
|
const css::uno::Sequence< css::beans::PropertyValue > & Medium)
|
|
throw (css::uno::RuntimeException,
|
|
css::lang::WrappedTargetException, css::io::IOException)
|
|
{
|
|
::comphelper::MediaDescriptor md(Medium);
|
|
if (!URL.isEmpty()) {
|
|
md[ ::comphelper::MediaDescriptor::PROP_URL() ] <<= URL;
|
|
}
|
|
SfxMedium aMedium(md.getAsConstPropertyValueList());
|
|
css::uno::Reference<css::embed::XStorage> xStorage
|
|
= aMedium.GetOutputStorage();
|
|
|
|
|
|
if (!xStorage.is()) {
|
|
throw css::uno::RuntimeException(OUString(
|
|
"SfxDocumentMetaData::storeToMedium: cannot get Storage"),
|
|
*this);
|
|
}
|
|
// set MIME type of the storage
|
|
::comphelper::MediaDescriptor::const_iterator iter
|
|
= md.find(::comphelper::MediaDescriptor::PROP_MEDIATYPE());
|
|
if (iter != md.end()) {
|
|
css::uno::Reference< css::beans::XPropertySet > xProps(xStorage,
|
|
css::uno::UNO_QUERY_THROW);
|
|
xProps->setPropertyValue(
|
|
::comphelper::MediaDescriptor::PROP_MEDIATYPE(),
|
|
iter->second);
|
|
}
|
|
storeToStorage(xStorage, md.getAsConstPropertyValueList());
|
|
|
|
|
|
const sal_Bool bOk = aMedium.Commit();
|
|
aMedium.Close();
|
|
if ( !bOk ) {
|
|
sal_uInt32 nError = aMedium.GetError();
|
|
if ( nError == ERRCODE_NONE ) {
|
|
nError = ERRCODE_IO_GENERAL;
|
|
}
|
|
|
|
throw css::task::ErrorCodeIOException( OUString(),
|
|
css::uno::Reference< css::uno::XInterface >(), nError);
|
|
|
|
}
|
|
}
|
|
|
|
// ::com::sun::star::lang::XInitialization:
|
|
void SAL_CALL
|
|
SfxDocumentMetaData::initialize(
|
|
const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments)
|
|
throw (css::uno::RuntimeException, css::uno::Exception)
|
|
{
|
|
// possible arguments:
|
|
// - no argument: default initialization (empty DOM)
|
|
// - 1 argument, XDocument: initialize with given DOM and empty base URL
|
|
// NB: links in document must be absolute
|
|
|
|
::osl::MutexGuard g(m_aMutex);
|
|
css::uno::Reference<css::xml::dom::XDocument> xDoc;
|
|
|
|
for (sal_Int32 i = 0; i < aArguments.getLength(); ++i) {
|
|
const css::uno::Any any = aArguments[i];
|
|
if (any >>= xDoc) {
|
|
if (!xDoc.is()) {
|
|
throw css::lang::IllegalArgumentException(
|
|
OUString("SfxDocumentMetaData::"
|
|
"initialize: argument is null"),
|
|
*this, static_cast<sal_Int16>(i));
|
|
}
|
|
} else {
|
|
throw css::lang::IllegalArgumentException(
|
|
OUString("SfxDocumentMetaData::"
|
|
"initialize: argument must be XDocument"),
|
|
*this, static_cast<sal_Int16>(i));
|
|
}
|
|
}
|
|
|
|
if (!xDoc.is()) {
|
|
// For a new document, we create a new DOM tree here.
|
|
xDoc = createDOM();
|
|
}
|
|
|
|
init(xDoc);
|
|
}
|
|
|
|
// ::com::sun::star::util::XCloneable:
|
|
css::uno::Reference<css::util::XCloneable> SAL_CALL
|
|
SfxDocumentMetaData::createClone()
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
|
|
SfxDocumentMetaData *pNew = createMe(m_xContext);
|
|
|
|
// NB: do not copy the modification listeners, only DOM
|
|
css::uno::Reference<css::xml::dom::XDocument> xDoc = createDOM();
|
|
try {
|
|
updateUserDefinedAndAttributes();
|
|
// deep copy of root node
|
|
css::uno::Reference<css::xml::dom::XNode> xRoot(
|
|
m_xDoc->getDocumentElement(), css::uno::UNO_QUERY_THROW);
|
|
css::uno::Reference<css::xml::dom::XNode> xRootNew(
|
|
xDoc->importNode(xRoot, true));
|
|
xDoc->appendChild(xRootNew);
|
|
pNew->init(xDoc);
|
|
} catch (const css::uno::RuntimeException &) {
|
|
throw;
|
|
} catch (const css::uno::Exception & e) {
|
|
css::uno::Any a(e);
|
|
throw css::lang::WrappedTargetRuntimeException(
|
|
OUString("SfxDocumentMetaData::createClone: exception"),
|
|
css::uno::Reference<css::uno::XInterface>(*this), a);
|
|
}
|
|
return css::uno::Reference<css::util::XCloneable> (pNew);
|
|
}
|
|
|
|
// ::com::sun::star::util::XModifiable:
|
|
::sal_Bool SAL_CALL SfxDocumentMetaData::isModified( )
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
css::uno::Reference<css::util::XModifiable> xMB(m_xUserDefined,
|
|
css::uno::UNO_QUERY);
|
|
return m_isModified || (xMB.is() ? xMB->isModified() : sal_False);
|
|
}
|
|
|
|
void SAL_CALL SfxDocumentMetaData::setModified( ::sal_Bool bModified )
|
|
throw (css::beans::PropertyVetoException, css::uno::RuntimeException)
|
|
{
|
|
css::uno::Reference<css::util::XModifiable> xMB;
|
|
{ // do not lock mutex while notifying (#i93514#) to prevent deadlock
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
m_isModified = bModified;
|
|
if ( !bModified && m_xUserDefined.is() )
|
|
{
|
|
xMB.set(m_xUserDefined, css::uno::UNO_QUERY);
|
|
DBG_ASSERT(xMB.is(),
|
|
"SfxDocumentMetaData::setModified: PropertyBag not Modifiable?");
|
|
}
|
|
}
|
|
if (bModified) {
|
|
try {
|
|
css::uno::Reference<css::uno::XInterface> xThis(*this);
|
|
css::lang::EventObject event(xThis);
|
|
m_NotifyListeners.notifyEach(&css::util::XModifyListener::modified,
|
|
event);
|
|
} catch (const css::uno::RuntimeException &) {
|
|
throw;
|
|
} catch (const css::uno::Exception & e) {
|
|
// ignore
|
|
DBG_WARNING1("SfxDocumentMetaData::setModified: exception:\n%s",
|
|
OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
|
|
(void) e;
|
|
}
|
|
} else {
|
|
if (xMB.is()) {
|
|
xMB->setModified(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ::com::sun::star::util::XModifyBroadcaster:
|
|
void SAL_CALL SfxDocumentMetaData::addModifyListener(
|
|
const css::uno::Reference< css::util::XModifyListener > & xListener)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
m_NotifyListeners.addInterface(xListener);
|
|
css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
|
|
css::uno::UNO_QUERY);
|
|
if (xMB.is()) {
|
|
xMB->addModifyListener(xListener);
|
|
}
|
|
}
|
|
|
|
void SAL_CALL SfxDocumentMetaData::removeModifyListener(
|
|
const css::uno::Reference< css::util::XModifyListener > & xListener)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
m_NotifyListeners.removeInterface(xListener);
|
|
css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
|
|
css::uno::UNO_QUERY);
|
|
if (xMB.is()) {
|
|
xMB->removeModifyListener(xListener);
|
|
}
|
|
}
|
|
|
|
// ::com::sun::star::xml::sax::XSAXSerializable
|
|
void SAL_CALL SfxDocumentMetaData::serialize(
|
|
const css::uno::Reference<css::xml::sax::XDocumentHandler>& i_xHandler,
|
|
const css::uno::Sequence< css::beans::StringPair >& i_rNamespaces)
|
|
throw (css::uno::RuntimeException, css::xml::sax::SAXException)
|
|
{
|
|
::osl::MutexGuard g(m_aMutex);
|
|
checkInit();
|
|
updateUserDefinedAndAttributes();
|
|
css::uno::Reference<css::xml::sax::XSAXSerializable> xSAXable(m_xDoc,
|
|
css::uno::UNO_QUERY_THROW);
|
|
xSAXable->serialize(i_xHandler, i_rNamespaces);
|
|
}
|
|
|
|
void SfxDocumentMetaData::createUserDefined()
|
|
{
|
|
// user-defined meta data: create PropertyBag which only accepts property
|
|
// values of allowed types
|
|
if ( !m_xUserDefined.is() )
|
|
{
|
|
css::uno::Sequence<css::uno::Type> types(11);
|
|
types[0] = ::cppu::UnoType<bool>::get();
|
|
types[1] = ::cppu::UnoType< OUString>::get();
|
|
types[2] = ::cppu::UnoType<css::util::DateTime>::get();
|
|
types[3] = ::cppu::UnoType<css::util::Date>::get();
|
|
types[4] = ::cppu::UnoType<css::util::Duration>::get();
|
|
types[5] = ::cppu::UnoType<float>::get();
|
|
types[6] = ::cppu::UnoType<double>::get();
|
|
types[7] = ::cppu::UnoType<sal_Int16>::get();
|
|
types[8] = ::cppu::UnoType<sal_Int32>::get();
|
|
types[9] = ::cppu::UnoType<sal_Int64>::get();
|
|
// Time is supported for backward compatibility with OOo 3.x, x<=2
|
|
types[10] = ::cppu::UnoType<css::util::Time>::get();
|
|
// #i94175#: ODF allows empty user-defined property names!
|
|
m_xUserDefined.set(
|
|
css::beans::PropertyBag::createWithTypes( m_xContext, types, sal_True/*AllowEmptyPropertyName*/, sal_False/*AutomaticAddition*/ ),
|
|
css::uno::UNO_QUERY_THROW);
|
|
|
|
const css::uno::Reference<css::util::XModifyBroadcaster> xMB(
|
|
m_xUserDefined, css::uno::UNO_QUERY);
|
|
if (xMB.is())
|
|
{
|
|
const css::uno::Sequence<css::uno::Reference<css::uno::XInterface> >
|
|
listeners(m_NotifyListeners.getElements());
|
|
for (css::uno::Reference< css::uno::XInterface > const * iter =
|
|
::comphelper::stl_begin(listeners);
|
|
iter != ::comphelper::stl_end(listeners); ++iter) {
|
|
xMB->addModifyListener(
|
|
css::uno::Reference< css::util::XModifyListener >(*iter,
|
|
css::uno::UNO_QUERY));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // closing anonymous implementation namespace
|
|
|
|
|
|
// component helper namespace
|
|
namespace comp_CompatWriterDocProps {
|
|
|
|
OUString SAL_CALL _getImplementationName() {
|
|
return OUString("CompatWriterDocPropsImpl");
|
|
}
|
|
|
|
css::uno::Sequence< OUString > SAL_CALL _getSupportedServiceNames()
|
|
{
|
|
css::uno::Sequence< OUString > aServiceNames(1);
|
|
aServiceNames[ 0 ] = OUString( "com.sun.star.writer.DocumentProperties" );
|
|
return aServiceNames;
|
|
}
|
|
|
|
css::uno::Reference< css::uno::XInterface > SAL_CALL _create(
|
|
const css::uno::Reference< css::uno::XComponentContext > & context)
|
|
SAL_THROW((css::uno::Exception))
|
|
{
|
|
return static_cast< ::cppu::OWeakObject * >
|
|
(new CompatWriterDocPropsImpl(context));
|
|
}
|
|
|
|
}
|
|
|
|
namespace comp_SfxDocumentMetaData {
|
|
|
|
OUString SAL_CALL _getImplementationName() {
|
|
return OUString("SfxDocumentMetaData");
|
|
}
|
|
|
|
css::uno::Sequence< OUString > SAL_CALL _getSupportedServiceNames()
|
|
{
|
|
css::uno::Sequence< OUString > s(1);
|
|
s[0] = OUString("com.sun.star.document.DocumentProperties");
|
|
return s;
|
|
}
|
|
|
|
css::uno::Reference< css::uno::XInterface > SAL_CALL _create(
|
|
const css::uno::Reference< css::uno::XComponentContext > & context)
|
|
SAL_THROW((css::uno::Exception))
|
|
{
|
|
return static_cast< ::cppu::OWeakObject * >
|
|
(new SfxDocumentMetaData(context));
|
|
}
|
|
|
|
} // closing component helper namespace
|
|
|
|
static ::cppu::ImplementationEntry const entries[] = {
|
|
{ &comp_SfxDocumentMetaData::_create,
|
|
&comp_SfxDocumentMetaData::_getImplementationName,
|
|
&comp_SfxDocumentMetaData::_getSupportedServiceNames,
|
|
&::cppu::createSingleComponentFactory, 0, 0 },
|
|
{ 0, 0, 0, 0, 0, 0 }
|
|
};
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|