xref: /aoo4110/main/sfx2/source/doc/objuno.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26 
27 #include <com/sun/star/lang/DisposedException.hpp>
28 #include <com/sun/star/util/DateTime.hpp>
29 #include <com/sun/star/util/Date.hpp>
30 #include <com/sun/star/util/Time.hpp>
31 #include <com/sun/star/beans/PropertyAttribute.hpp>
32 #include <com/sun/star/beans/NamedValue.hpp>
33 #include <com/sun/star/beans/StringPair.hpp>
34 #include <com/sun/star/embed/ElementModes.hpp>
35 #include <com/sun/star/xml/sax/XParser.hpp>
36 #include <com/sun/star/document/XImporter.hpp>
37 #include <com/sun/star/document/XExporter.hpp>
38 #include <com/sun/star/io/XActiveDataSource.hpp>
39 #include <com/sun/star/document/XFilter.hpp>
40 #include <com/sun/star/embed/XTransactedObject.hpp>
41 #include <com/sun/star/lang/Locale.hpp>
42 #include <com/sun/star/util/XModifiable.hpp>
43 #include <com/sun/star/document/XDocumentProperties.hpp>
44 
45 #include <unotools/configmgr.hxx>
46 #include <tools/inetdef.hxx>
47 #include <unotools/bootstrap.hxx>
48 #include <cppuhelper/interfacecontainer.hxx>
49 #include <osl/mutex.hxx>
50 #include <rtl/ustrbuf.hxx>
51 #include <vcl/svapp.hxx>
52 #include <vos/mutex.hxx>
53 
54 #include <tools/errcode.hxx>
55 #include <svl/cntwids.hrc>
56 #include <comphelper/string.hxx>
57 #include <comphelper/sequenceasvector.hxx>
58 #include <comphelper/storagehelper.hxx>
59 #include <sot/storage.hxx>
60 
61 #include <sfx2/objuno.hxx>
62 #include <sfx2/sfx.hrc>
63 
64 #include <vector>
65 #include <algorithm>
66 
67 #include "sfx2/sfxresid.hxx"
68 #include "doc.hrc"
69 
70 using namespace ::com::sun::star;
71 
72 // TODO/REFACTOR: provide service for MS formats
73 // TODO/REFACTOR: IsEncrypted is never set nor read
74 // Generator is not saved ATM; which value?!
75 // Generator handling must be implemented
76 // Deprecate "Theme", rework IDL
77 // AutoLoadEnabled is deprecated?!
78 // Reasonable defaults for DateTime
79 // MIMEType readonly?!
80 // Announce changes about Theme, Language, Generator, removed entries etc.
81 // IsEncrypted is necessary for binary formats!
82 // Open: When to call PrepareDocInfoForSave? Currently only called for own formats and HTML/Writer
83 // Open: How to load and save EditingTime to MS formats
84 // PPT-Export should use SavePropertySet
85 
86 //=============================================================================
87 
88 // The number of user defined fields handled by the evil XDocumentInfo
89 // interface. There are exactly 4. No more, no less.
90 #define FOUR 4
91 
92 #define PROPERTY_UNBOUND 0
93 #define PROPERTY_MAYBEVOID ::com::sun::star::beans::PropertyAttribute::MAYBEVOID
94 
lcl_GetDocInfoPropertyMap()95 const SfxItemPropertyMapEntry* lcl_GetDocInfoPropertyMap()
96 {
97     static SfxItemPropertyMapEntry aDocInfoPropertyMap_Impl[] =
98     {
99         { "Author"          , 6 , WID_FROM,           &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
100         { "AutoloadEnabled" , 15, MID_DOCINFO_AUTOLOADENABLED, &::getBooleanCppuType(),   PROPERTY_UNBOUND, 0 },
101         { "AutoloadSecs"    , 12, MID_DOCINFO_AUTOLOADSECS, &::getCppuType((const sal_Int32*)0),     PROPERTY_UNBOUND, 0 },
102         { "AutoloadURL"     , 11, MID_DOCINFO_AUTOLOADURL, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
103         { "CreationDate"    , 12, WID_DATE_CREATED,   &::getCppuType((const ::com::sun::star::util::DateTime*)0),PROPERTY_MAYBEVOID, 0 },
104         { "DefaultTarget"   , 13, MID_DOCINFO_DEFAULTTARGET, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
105         { "Description"     , 11, MID_DOCINFO_DESCRIPTION, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
106         { "DocumentStatistic", 17 , MID_DOCINFO_STATISTIC, &::getCppuType((const uno::Sequence< beans::NamedValue >*)0), PROPERTY_UNBOUND, 0 },
107         { "EditingCycles"   , 13, MID_DOCINFO_REVISION, &::getCppuType((const sal_Int16*)0),   PROPERTY_UNBOUND, 0 },
108         { "EditingDuration" , 15, MID_DOCINFO_EDITTIME, &::getCppuType((const sal_Int32*)0),   PROPERTY_UNBOUND, 0 },
109         { "Generator"       , 9,  SID_APPLICATION, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
110         { "Keywords"        , 8 , WID_KEYWORDS,       &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
111         { "Language"        , 8,  MID_DOCINFO_CHARLOCALE, &::getCppuType((const lang::Locale*)0), PROPERTY_UNBOUND, 0 },
112         { "MIMEType"        , 8 , WID_CONTENT_TYPE,   &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND | ::com::sun::star::beans::PropertyAttribute::READONLY, 0 },
113         { "ModifiedBy"      , 10, MID_DOCINFO_MODIFICATIONAUTHOR, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
114         { "ModifyDate"      , 10, WID_DATE_MODIFIED,  &::getCppuType((const ::com::sun::star::util::DateTime*)0),PROPERTY_MAYBEVOID, 0 },
115         { "PrintDate"       , 9 , MID_DOCINFO_PRINTDATE, &::getCppuType((const ::com::sun::star::util::DateTime*)0),PROPERTY_MAYBEVOID, 0 },
116         { "PrintedBy"       , 9 , MID_DOCINFO_PRINTEDBY, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
117         { "Subject"         , 7 , MID_DOCINFO_SUBJECT, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
118         { "Template"        , 8 , MID_DOCINFO_TEMPLATE, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
119         { "TemplateFileName", 16, SID_TEMPLATE_NAME, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
120         { "TemplateDate"    , 12, MID_DOCINFO_TEMPLATEDATE, &::getCppuType((const ::com::sun::star::util::DateTime*)0),PROPERTY_MAYBEVOID, 0 },
121         { "Title"           , 5 , WID_TITLE,          &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
122         {0,0,0,0,0,0}
123     };
124     return aDocInfoPropertyMap_Impl;
125 }
126 
127 static sal_uInt16 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30,
128 								   31, 31, 30, 31, 30, 31 };
129 
DaysInMonth(sal_uInt16 nMonth,sal_uInt16 nYear)130 inline sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear )
131 {
132 	if ( nMonth != 2 )
133 		return aDaysInMonth[nMonth-1];
134 	else
135 	{
136 		if ( (((nYear % 4) == 0) && ((nYear % 100) != 0)) ||
137 			 ((nYear % 400) == 0) )
138 			return aDaysInMonth[nMonth-1] + 1;
139 		else
140 			return aDaysInMonth[nMonth-1];
141 	}
142 }
143 
IsValidDateTime(const util::DateTime & rDT)144 bool IsValidDateTime( const util::DateTime& rDT )
145 {
146 	if ( !rDT.Month || (rDT.Month > 12) )
147 		return false;
148 	if ( !rDT.Day || (rDT.Day > DaysInMonth( rDT.Month, rDT.Year )) )
149 		return false;
150 	else if ( rDT.Year <= 1582 )
151 	{
152 		if ( rDT.Year < 1582 )
153 			return false;
154 		else if ( rDT.Month < 10 )
155 			return false;
156 		else if ( (rDT.Month == 10) && (rDT.Day < 15) )
157 			return false;
158 	}
159 
160 	return true;
161 }
162 
163 struct OUStringHashCode
164 {
operator ()OUStringHashCode165     size_t operator()( const ::rtl::OUString& sString ) const
166 	{
167 		return sString.hashCode();
168 	}
169 };
170 
171 struct SfxExtendedItemPropertyMap : public SfxItemPropertyMapEntry
172 {
173     ::com::sun::star::uno::Any aValue;
174 };
175 
Copy(const uno::Reference<document::XStandaloneDocumentInfo> & rSource,const uno::Reference<document::XStandaloneDocumentInfo> & rTarget)176 void Copy( const uno::Reference < document::XStandaloneDocumentInfo >& rSource, const uno::Reference < document::XStandaloneDocumentInfo >& rTarget )
177 {
178     try
179     {
180         uno::Reference< beans::XPropertySet > xSet( rSource, uno::UNO_QUERY );
181         uno::Reference< beans::XPropertySet > xTarget( rTarget, uno::UNO_QUERY );
182         uno::Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
183         uno::Reference< beans::XPropertyContainer > xContainer( rTarget, uno::UNO_QUERY );
184         uno::Sequence< beans::Property > lProps = xSetInfo->getProperties();
185         const beans::Property* pProps = lProps.getConstArray();
186         sal_Int32 c = lProps.getLength();
187         sal_Int32 i = 0;
188         for (i=0; i<c; ++i)
189         {
190             uno::Any aValue = xSet->getPropertyValue( pProps[i].Name );
191             if ( pProps[i].Attributes & ::com::sun::star::beans::PropertyAttribute::REMOVABLE )
192                 // QUESTION: DefaultValue?!
193                 xContainer->addProperty( pProps[i].Name, pProps[i].Attributes, aValue );
194             try
195             {
196                 // it is possible that the propertysets from XML and binary files differ; we shouldn't break then
197                 xTarget->setPropertyValue( pProps[i].Name, aValue );
198             }
199             catch ( uno::Exception& ) {}
200         }
201 
202         sal_Int16 nCount = rSource->getUserFieldCount();
203         sal_Int16 nSupportedCount = rTarget->getUserFieldCount();
204         for ( sal_Int16 nInd = 0; nInd < nCount && nInd < nSupportedCount; nInd++ )
205         {
206             ::rtl::OUString aPropName = rSource->getUserFieldName( nInd );
207             rTarget->setUserFieldName( nInd, aPropName );
208             ::rtl::OUString aPropVal = rSource->getUserFieldValue( nInd );
209             rTarget->setUserFieldValue( nInd, aPropVal );
210         }
211     }
212     catch ( uno::Exception& ) {}
213 }
214 
215 class MixedPropertySetInfo : public ::cppu::WeakImplHelper1< ::com::sun::star::beans::XPropertySetInfo >
216 {
217     private:
218 
219         SfxItemPropertyMap  _aPropertyMap;
220         ::rtl::OUString* _pUserKeys;
221         uno::Reference<beans::XPropertySet> _xUDProps;
222 
223     public:
224 
225         MixedPropertySetInfo( const SfxItemPropertyMapEntry* pFixProps,
226                              ::rtl::OUString* pUserKeys,
227                              uno::Reference<beans::XPropertySet> xUDProps);
228 
229         virtual ~MixedPropertySetInfo();
230 
231         virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > SAL_CALL getProperties(  ) throw (::com::sun::star::uno::RuntimeException);
232         virtual ::com::sun::star::beans::Property SAL_CALL getPropertyByName( const ::rtl::OUString& aName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
233         virtual ::sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& Name ) throw (::com::sun::star::uno::RuntimeException);
234 };
235 
236 //-----------------------------------------------------------------------------
237 
MixedPropertySetInfo(const SfxItemPropertyMapEntry * pFixProps,::rtl::OUString * pUserKeys,uno::Reference<beans::XPropertySet> xUDProps)238 MixedPropertySetInfo::MixedPropertySetInfo(const SfxItemPropertyMapEntry* pFixProps,
239                      ::rtl::OUString* pUserKeys,
240                      uno::Reference<beans::XPropertySet> xUDProps)
241     : _aPropertyMap( pFixProps )
242     , _pUserKeys(pUserKeys)
243     , _xUDProps(xUDProps)
244 {
245 }
246 
247 //-----------------------------------------------------------------------------
248 
~MixedPropertySetInfo()249 MixedPropertySetInfo::~MixedPropertySetInfo()
250 {
251 }
252 
253 //-----------------------------------------------------------------------------
254 
getProperties()255 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > SAL_CALL MixedPropertySetInfo::getProperties()
256     throw(::com::sun::star::uno::RuntimeException)
257 {
258     ::comphelper::SequenceAsVector< ::com::sun::star::beans::Property > lProps;
259 
260     // copy "fix" props
261     //todo: os: this ugly thing should be replaced
262     const SfxItemPropertyMapEntry* pFixProp = lcl_GetDocInfoPropertyMap();
263 
264     while(pFixProp && pFixProp->pName)
265     {
266         ::com::sun::star::beans::Property aProp;
267 
268         aProp.Name       = ::rtl::OUString::createFromAscii(pFixProp->pName);
269         aProp.Handle     = pFixProp->nWID;
270         aProp.Type       = *(pFixProp->pType);
271         aProp.Attributes = (sal_Int16)(pFixProp->nFlags);
272 
273         lProps.push_back(aProp);
274         ++pFixProp;
275     }
276 
277     // copy "dynamic" props
278 
279     // NB: this is really ugly:
280     // The returned properties must _not_ include the 4 user-defined fields!
281     // These are _not_ properties of the XDocumentInfo interface.
282     // Some things rely on this, e.g. Copy would break otherwise.
283     // This will have interesting consequences if someone expects to insert
284     // a property with the same name as an user-defined key, but nobody
285     // sane does that.
286     uno::Sequence<beans::Property> udProps =
287         _xUDProps->getPropertySetInfo()->getProperties();
288     for (sal_Int32 i = 0; i < udProps.getLength(); ++i) {
289         if (std::find(_pUserKeys, _pUserKeys+FOUR, udProps[i].Name)
290             == _pUserKeys+FOUR) {
291                 // #i100027#: handles from udProps are not valid here
292                 udProps[i].Handle = -1;
293                 lProps.push_back(udProps[i]);
294         }
295     }
296 
297     return lProps.getAsConstList();
298 }
299 
300 //-----------------------------------------------------------------------------
301 
getPropertyByName(const::rtl::OUString & sName)302 ::com::sun::star::beans::Property SAL_CALL MixedPropertySetInfo::getPropertyByName(
303     const ::rtl::OUString& sName )
304     throw(::com::sun::star::beans::UnknownPropertyException,
305           ::com::sun::star::uno::RuntimeException          )
306 {
307     ::com::sun::star::beans::Property aProp;
308 
309     // search it as "fix" prop
310     if( _aPropertyMap.hasPropertyByName( sName ) )
311         return _aPropertyMap.getPropertyByName( sName );
312     else
313     // search it as "dynamic" prop
314     return _xUDProps->getPropertySetInfo()->getPropertyByName(sName);
315 }
316 
317 //-----------------------------------------------------------------------------
318 
hasPropertyByName(const::rtl::OUString & sName)319 ::sal_Bool SAL_CALL MixedPropertySetInfo::hasPropertyByName(const ::rtl::OUString& sName)
320     throw(::com::sun::star::uno::RuntimeException)
321 {
322     return _aPropertyMap.hasPropertyByName( sName ) ? // "fix" prop?
323         sal_True :
324         _xUDProps->getPropertySetInfo()->hasPropertyByName(sName); // "dynamic" prop?
325 }
326 
327 //-----------------------------------------------------------------------------
328 
329 struct SfxDocumentInfoObject_Impl
330 {
331 	::osl::Mutex						_aMutex;
332 	::cppu::OInterfaceContainerHelper	_aDisposeContainer;
333 
334     sal_Bool            bDisposed;
335 
336     // this contains the names of the 4 user defined properties
337     // which are accessible via the evil XDocumentInfo interface
338     ::rtl::OUString m_UserDefined[FOUR];
339 
340     // the actual contents
341     uno::Reference<document::XDocumentProperties> m_xDocProps;
342     SfxItemPropertyMap      m_aPropertyMap;
343 
SfxDocumentInfoObject_ImplSfxDocumentInfoObject_Impl344     SfxDocumentInfoObject_Impl()
345         : _aDisposeContainer( _aMutex )
346         , bDisposed(sal_False)
347         , m_xDocProps()
348         , m_aPropertyMap( lcl_GetDocInfoPropertyMap() )
349 	{
350         // the number of user fields is not changeable from the outside
351         // we can't set it too high because every name/value pair will be written to the file (even if empty)
352         // currently our dialog has only 4 user keys so 4 is still a reasonable number
353 	}
354 
355     /// the initialization function
356     void Reset(uno::Reference<document::XDocumentProperties> xDocProps, ::rtl::OUString* pUserDefined = 0);
357 };
358 
Reset(uno::Reference<document::XDocumentProperties> xDocProps,::rtl::OUString * pUserDefined)359 void SfxDocumentInfoObject_Impl::Reset(uno::Reference<document::XDocumentProperties> xDocProps, ::rtl::OUString* pUserDefined)
360 {
361     if (pUserDefined == 0) {
362         // NB: this is an ugly hack; the "Properties" ui dialog displays
363         //     exactly 4 user-defined fields and expects these to be available
364         //     (should be redesigned), but I do not want to do this in
365         //     DocumentProperties; do it here instead
366         uno::Reference<beans::XPropertyAccess> xPropAccess(
367             xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
368         uno::Reference<beans::XPropertyContainer> xPropContainer(
369             xPropAccess, uno::UNO_QUERY_THROW);
370         uno::Sequence< beans::PropertyValue >
371             props = xPropAccess->getPropertyValues();
372         sal_Int32 oldLength = props.getLength();
373         if (oldLength < FOUR) {
374             std::vector< ::rtl::OUString > names;
375             for (sal_Int32 i = 0; i < oldLength; ++i) {
376                 names.push_back(props[i].Name);
377             }
378             const ::rtl::OUString sInfo(
379                         String( SfxResId( STR_DOCINFO_INFOFIELD ) ));
380             for (sal_Int32 i = oldLength; i < FOUR; ++i) {
381                 ::rtl::OUString sName(sInfo);
382                 sal_Int32 idx = sName.indexOfAsciiL("%1", 2);
383                 ::rtl::OUString name = (idx > 0)
384                     ? sName.replaceAt(idx, 2, ::rtl::OUString::valueOf(i+1))
385                     : sName + ::rtl::OUString::valueOf(i+1);
386                 while (std::find(names.begin(), names.end(), name)
387                        != names.end()) {
388                     name += ::rtl::OUString::createFromAscii("'");
389                 }
390                 // FIXME there is a race condition here
391                 try {
392                     xPropContainer->addProperty(name,
393                         beans::PropertyAttribute::REMOVEABLE,
394                         uno::makeAny(::rtl::OUString::createFromAscii("")));
395                 } catch (uno::RuntimeException) {
396                     throw;
397                 } catch (uno::Exception) {
398                     // ignore
399                 }
400             }
401         }
402         props = xPropAccess->getPropertyValues();
403         for (sal_Int32 i = 0; i < FOUR; ++i) {
404             m_UserDefined[i] = props[i].Name;
405         }
406     } else {
407         std::copy(pUserDefined, pUserDefined+FOUR, m_UserDefined);
408     }
409     m_xDocProps = xDocProps;
410 }
411 
412 //-----------------------------------------------------------------------------
413 
SfxDocumentInfoObject()414 SfxDocumentInfoObject::SfxDocumentInfoObject()
415     : _pImp( new SfxDocumentInfoObject_Impl() )
416 {
417 }
418 
419 //-----------------------------------------------------------------------------
420 
~SfxDocumentInfoObject()421 SfxDocumentInfoObject::~SfxDocumentInfoObject()
422 {
423 	delete _pImp;
424 }
425 
426 //-----------------------------------------------------------------------------
427 
428 // ::com::sun::star::lang::XInitialization:
429 void SAL_CALL
initialize(const uno::Sequence<uno::Any> & aArguments)430 SfxDocumentInfoObject::initialize(const uno::Sequence< uno::Any > & aArguments)
431     throw (uno::RuntimeException, uno::Exception)
432 {
433     if (aArguments.getLength() >= 1) {
434         uno::Any any = aArguments[0];
435         uno::Reference<document::XDocumentProperties> xDoc;
436         if (!(any >>= xDoc) || !xDoc.is()) throw lang::IllegalArgumentException(
437             ::rtl::OUString::createFromAscii(
438                 "SfxDocumentInfoObject::initialize: no XDocumentProperties given"),
439                 *this, 0);
440         _pImp->Reset(xDoc);
441     } else {
442         throw lang::IllegalArgumentException(
443             ::rtl::OUString::createFromAscii(
444                 "SfxDocumentInfoObject::initialize: no argument given"),
445                 *this, 0);
446     }
447 }
448 
449 // ::com::sun::star::util::XCloneable:
450 uno::Reference<util::XCloneable> SAL_CALL
createClone()451 SfxDocumentInfoObject::createClone() throw (uno::RuntimeException)
452 {
453     SfxDocumentInfoObject *pNew = new SfxDocumentInfoObject;
454     uno::Reference< util::XCloneable >
455         xCloneable(_pImp->m_xDocProps, uno::UNO_QUERY_THROW);
456     uno::Reference<document::XDocumentProperties> xDocProps(
457         xCloneable->createClone(), uno::UNO_QUERY_THROW);
458     pNew->_pImp->Reset(xDocProps, _pImp->m_UserDefined);
459     return pNew;
460 }
461 
462 // ::com::sun::star::document::XDocumentProperties:
463 uno::Reference< document::XDocumentProperties > SAL_CALL
getDocumentProperties()464 SfxDocumentInfoObject::getDocumentProperties()
465     throw(::com::sun::star::uno::RuntimeException)
466 {
467     return _pImp->m_xDocProps;
468 }
469 
470 //-----------------------------------------------------------------------------
471 
operator =(const SfxDocumentInfoObject & rOther)472 const SfxDocumentInfoObject& SfxDocumentInfoObject::operator=( const SfxDocumentInfoObject & rOther)
473 {
474     uno::Reference< util::XCloneable >
475         xCloneable(rOther._pImp->m_xDocProps, uno::UNO_QUERY_THROW);
476     uno::Reference<document::XDocumentProperties> xDocProps(
477         xCloneable->createClone(), uno::UNO_QUERY_THROW);
478     _pImp->Reset(xDocProps, rOther._pImp->m_UserDefined);
479     return *this;
480 }
481 
482 //-----------------------------------------------------------------------------
483 
dispose()484 void SAL_CALL SfxDocumentInfoObject::dispose() throw( ::com::sun::star::uno::RuntimeException )
485 {
486 	::com::sun::star::lang::EventObject aEvent( (::cppu::OWeakObject *)this );
487 	_pImp->_aDisposeContainer.disposeAndClear( aEvent );
488 	::osl::MutexGuard aGuard( _pImp->_aMutex );
489     _pImp->m_xDocProps = 0;
490     // NB: do not call m_xDocProps->dispose(), there could be other refs
491     _pImp->bDisposed = sal_True;
492 }
493 
494 //-----------------------------------------------------------------------------
495 
addEventListener(const::com::sun::star::uno::Reference<::com::sun::star::lang::XEventListener> & aListener)496 void SAL_CALL  SfxDocumentInfoObject::addEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & aListener) throw( ::com::sun::star::uno::RuntimeException )
497 {
498 	_pImp->_aDisposeContainer.addInterface( aListener );
499 }
500 
501 //-----------------------------------------------------------------------------
502 
removeEventListener(const::com::sun::star::uno::Reference<::com::sun::star::lang::XEventListener> & aListener)503 void SAL_CALL  SfxDocumentInfoObject::removeEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & aListener) throw( ::com::sun::star::uno::RuntimeException )
504 {
505 	_pImp->_aDisposeContainer.removeInterface( aListener );
506 }
507 //-----------------------------------------------------------------------------
508 
getPropertySetInfo()509 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >  SAL_CALL  SfxDocumentInfoObject::getPropertySetInfo()  throw( ::com::sun::star::uno::RuntimeException )
510 {
511     ::osl::MutexGuard aGuard( _pImp->_aMutex );
512 
513     uno::Reference<beans::XPropertySet> xPropSet(
514         _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
515     MixedPropertySetInfo* pInfo = new MixedPropertySetInfo( lcl_GetDocInfoPropertyMap(), _pImp->m_UserDefined, xPropSet);
516     uno::Reference< beans::XPropertySetInfo > xInfo(
517         static_cast< beans::XPropertySetInfo* >(pInfo), uno::UNO_QUERY_THROW);
518     return xInfo;
519 }
520 
521 //-----------------------------------------------------------------------------
522 
setPropertyValue(const::rtl::OUString & aPropertyName,const uno::Any & aValue)523 void SAL_CALL  SfxDocumentInfoObject::setPropertyValue(const ::rtl::OUString& aPropertyName, const uno::Any& aValue) throw (
524         uno::RuntimeException, beans::UnknownPropertyException,
525         beans::PropertyVetoException, lang::IllegalArgumentException,
526         lang::WrappedTargetException)
527 {
528     const SfxItemPropertySimpleEntry* pEntry = _pImp->m_aPropertyMap.getByName( aPropertyName );
529     // fix prop!
530     if ( pEntry )
531         setFastPropertyValue( pEntry->nWID, aValue );
532     else
533     // dynamic prop!
534     {
535         uno::Reference<beans::XPropertySet> xPropSet(
536             _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
537         return xPropSet->setPropertyValue(aPropertyName, aValue);
538     }
539 }
540 
541 //-----------------------------------------------------------------------------
542 
getPropertyValue(const::rtl::OUString & aPropertyName)543 uno::Any  SAL_CALL  SfxDocumentInfoObject::getPropertyValue(const ::rtl::OUString& aPropertyName)  throw(
544         uno::RuntimeException, beans::UnknownPropertyException,
545         lang::WrappedTargetException)
546 {
547     const SfxItemPropertySimpleEntry* pEntry = _pImp->m_aPropertyMap.getByName( aPropertyName );
548     // fix prop!
549     if ( pEntry )
550         return getFastPropertyValue( pEntry->nWID );
551 	else
552     // dynamic prop!
553     {
554         uno::Reference<beans::XPropertySet> xPropSet(
555             _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
556         return xPropSet->getPropertyValue(aPropertyName);
557     }
558 }
559 
isModified()560 sal_Bool SAL_CALL SfxDocumentInfoObject::isModified() throw(::com::sun::star::uno::RuntimeException)
561 {
562     uno::Reference<util::XModifiable> xModif(
563             _pImp->m_xDocProps, uno::UNO_QUERY_THROW);
564     return xModif->isModified();
565 }
566 
setModified(sal_Bool bModified)567 void SAL_CALL SfxDocumentInfoObject::setModified( sal_Bool bModified )
568         throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException)
569 {
570     uno::Reference<util::XModifiable> xModif(
571             _pImp->m_xDocProps, uno::UNO_QUERY_THROW);
572     return xModif->setModified(bModified);
573 }
574 
addModifyListener(const uno::Reference<util::XModifyListener> & xListener)575 void SAL_CALL SfxDocumentInfoObject::addModifyListener( const uno::Reference< util::XModifyListener >& xListener) throw( uno::RuntimeException )
576 {
577     uno::Reference<util::XModifiable> xModif(
578             _pImp->m_xDocProps, uno::UNO_QUERY_THROW);
579     return xModif->addModifyListener(xListener);
580 }
581 
removeModifyListener(const uno::Reference<util::XModifyListener> & xListener)582 void SAL_CALL SfxDocumentInfoObject::removeModifyListener( const uno::Reference< util::XModifyListener >& xListener) throw( uno::RuntimeException )
583 {
584     uno::Reference<util::XModifiable> xModif(
585             _pImp->m_xDocProps, uno::UNO_QUERY_THROW);
586     return xModif->removeModifyListener(xListener);
587 }
588 
589 //-----------------------------------------------------------------------------
590 
addPropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)591 void SAL_CALL  SfxDocumentInfoObject::addPropertyChangeListener(const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener > & ) throw(
592         uno::RuntimeException, beans::UnknownPropertyException,
593         lang::WrappedTargetException)
594 {}
595 
596 //-----------------------------------------------------------------------------
597 
removePropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)598 void SAL_CALL  SfxDocumentInfoObject::removePropertyChangeListener(const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener > & ) throw(
599         uno::RuntimeException, beans::UnknownPropertyException,
600         lang::WrappedTargetException)
601 {}
602 
603 //-----------------------------------------------------------------------------
604 
addVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)605 void SAL_CALL  SfxDocumentInfoObject::addVetoableChangeListener(const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener > & ) throw(
606         uno::RuntimeException, beans::UnknownPropertyException,
607         lang::WrappedTargetException)
608 {}
609 
610 //-----------------------------------------------------------------------------
611 
removeVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)612 void SAL_CALL  SfxDocumentInfoObject::removeVetoableChangeListener(const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener > & ) throw(
613         uno::RuntimeException, beans::UnknownPropertyException,
614         lang::WrappedTargetException)
615 {}
616 
getPropertyValues(void)617 uno::Sequence< beans::PropertyValue > SAL_CALL  SfxDocumentInfoObject::getPropertyValues( void ) throw( uno::RuntimeException )
618 {
619 	::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >  xInfo = getPropertySetInfo();
620 	::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > aProps = xInfo->getProperties();
621 
622 	const ::com::sun::star::beans::Property* pProps  = aProps.getConstArray();
623 	sal_uInt32 nCount = aProps.getLength();
624 
625 	::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >aSeq( nCount );
626 	::com::sun::star::beans::PropertyValue*  pValues = aSeq.getArray();
627 
628 	for ( sal_uInt32 n = 0; n < nCount; ++n )
629 	{
630 		::com::sun::star::beans::PropertyValue& rCurrValue = pValues[n];
631 		const ::com::sun::star::beans::Property& rCurrProp = pProps[n];
632 
633 		rCurrValue.Name = rCurrProp.Name;
634 		rCurrValue.Handle = rCurrProp.Handle;
635 		rCurrValue.Value = getPropertyValue( rCurrProp.Name );
636 	}
637 
638 	return aSeq;
639 }
640 
setPropertyValues(const::com::sun::star::uno::Sequence<::com::sun::star::beans::PropertyValue> & aProps)641 void SAL_CALL  SfxDocumentInfoObject::setPropertyValues( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aProps )
642         throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException )
643 {
644 	const ::com::sun::star::beans::PropertyValue* pProps  = aProps.getConstArray();
645 	sal_uInt32 nCount = aProps.getLength();
646 
647 	for ( sal_uInt32 n = 0; n < nCount; ++n )
648 	{
649 		const ::com::sun::star::beans::PropertyValue& rProp = pProps[n];
650 		setPropertyValue( rProp.Name, rProp.Value );
651 	}
652 }
653 
addProperty(const::rtl::OUString & sName,sal_Int16 nAttributes,const::com::sun::star::uno::Any & aDefaultValue)654 void SAL_CALL SfxDocumentInfoObject::addProperty(const ::rtl::OUString&            sName        ,
655                                                        sal_Int16                   nAttributes  ,
656                                                  const ::com::sun::star::uno::Any& aDefaultValue)
657     throw(::com::sun::star::beans::PropertyExistException ,
658           ::com::sun::star::beans::IllegalTypeException   ,
659           ::com::sun::star::lang::IllegalArgumentException,
660           ::com::sun::star::uno::RuntimeException         )
661 {
662     // clash with "fix" properties ?
663     sal_Bool bFixProp = _pImp->m_aPropertyMap.getByName( sName ) != 0;
664     if ( bFixProp )
665     {
666         ::rtl::OUStringBuffer sMsg(256);
667         sMsg.appendAscii("The property \""   );
668         sMsg.append     (sName               );
669         sMsg.appendAscii("\" "               );
670         if ( bFixProp )
671             sMsg.appendAscii(" already exists as a fix property. Please have a look into the IDL documentation of the DocumentInfo service.");
672 
673         throw ::com::sun::star::beans::PropertyExistException(
674                 sMsg.makeStringAndClear(),
675                 static_cast< ::cppu::OWeakObject* >(this));
676     }
677 
678     uno::Reference<beans::XPropertyContainer> xPropSet(
679         _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
680     return xPropSet->addProperty(sName, nAttributes, aDefaultValue);
681 }
682 
removeProperty(const::rtl::OUString & sName)683 void SAL_CALL SfxDocumentInfoObject::removeProperty(const ::rtl::OUString& sName)
684     throw(::com::sun::star::beans::UnknownPropertyException,
685           ::com::sun::star::beans::NotRemoveableException  ,
686           ::com::sun::star::uno::RuntimeException          )
687 {
688     // clash with "fix" properties ?
689     sal_Bool bFixProp = _pImp->m_aPropertyMap.getByName( sName ) != 0;
690     if ( bFixProp )
691     {
692         ::rtl::OUStringBuffer sMsg(256);
693         sMsg.appendAscii("The property \""                                                    );
694         sMsg.append     (sName                                                                );
695         sMsg.appendAscii("\" cant be removed. Its a fix property of the DocumentInfo service.");
696 
697         throw ::com::sun::star::beans::NotRemoveableException(
698                 sMsg.makeStringAndClear(),
699                 static_cast< ::cppu::OWeakObject* >(this));
700     }
701 
702     uno::Reference<beans::XPropertyContainer> xPropSet(
703         _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
704     return xPropSet->removeProperty(sName);
705 }
706 
equalsDateTime(const util::DateTime & D1,const util::DateTime & D2)707 sal_Bool equalsDateTime( const util::DateTime& D1, const util::DateTime& D2 )
708 {
709     return D1.HundredthSeconds == D2.HundredthSeconds &&
710            D1.Seconds == D2.Seconds &&
711            D1.Minutes == D2.Minutes &&
712            D1.Hours == D2.Hours &&
713            D1.Day == D2.Day &&
714            D1.Month == D2.Month &&
715            D1.Year == D2.Year;
716 }
717 
setFastPropertyValue(sal_Int32 nHandle,const::com::sun::star::uno::Any & aValue)718 void SAL_CALL  SfxDocumentInfoObject::setFastPropertyValue(sal_Int32 nHandle, const ::com::sun::star::uno::Any& aValue) throw(
719         uno::RuntimeException, beans::UnknownPropertyException,
720         beans::PropertyVetoException, lang::IllegalArgumentException,
721         lang::WrappedTargetException)
722 {
723     // Attention: Only fix properties should be provided by this method.
724     // Dynamic properties has no handle in real ... because it cant be used inside multithreaded environments :-)
725 
726     ::osl::ClearableMutexGuard aGuard( _pImp->_aMutex );
727 
728     if ( aValue.getValueType() == ::getCppuType((const ::rtl::OUString*)0) )
729 	{
730 		::rtl::OUString sTemp ;
731 		aValue >>= sTemp ;
732 		switch ( nHandle )
733 		{
734             case SID_APPLICATION :
735                 _pImp->m_xDocProps->setGenerator(sTemp);
736                 break;
737 			case WID_FROM :
738 			{
739                 // QUESTION: do we still need this?
740                 /*
741                 // String aStrVal( sTemp );
742 				if ( aStrVal.Len() > TIMESTAMP_MAXLENGTH )
743 				{
744 					SvAddressParser aParser( aStrVal );
745 					if ( aParser.Count() > 0 )
746 					{
747 						String aEmail = aParser.GetEmailAddress(0);
748 						String aRealname = aParser.GetRealName(0);
749 
750 						if ( aRealname.Len() <= TIMESTAMP_MAXLENGTH )
751 							aStrVal = aRealname;
752 						else if ( aEmail.Len() <= TIMESTAMP_MAXLENGTH )
753 							aStrVal = aEmail;
754 					}
755                 } */
756 
757                 if ( _pImp->m_xDocProps->getAuthor() != sTemp )
758                     _pImp->m_xDocProps->setAuthor(sTemp);
759 				break;
760 			}
761             case MID_DOCINFO_PRINTEDBY:
762                 if ( _pImp->m_xDocProps->getPrintedBy() != sTemp )
763                     _pImp->m_xDocProps->setPrintedBy(sTemp);
764                 break;
765 			case MID_DOCINFO_MODIFICATIONAUTHOR:
766                 if ( _pImp->m_xDocProps->getModifiedBy() != sTemp )
767                     _pImp->m_xDocProps->setModifiedBy(sTemp);
768 				break;
769 			case WID_TITLE :
770             {
771                 if ( _pImp->m_xDocProps->getTitle() != sTemp )
772                     _pImp->m_xDocProps->setTitle(sTemp);
773 				break;
774             }
775 			case MID_DOCINFO_SUBJECT :
776                 if ( _pImp->m_xDocProps->getSubject() != sTemp )
777                     _pImp->m_xDocProps->setSubject(sTemp);
778 				break;
779 			case WID_KEYWORDS :
780                 {
781                     _pImp->m_xDocProps->setKeywords(
782                         ::comphelper::string::convertCommaSeparated(sTemp));
783                 }
784 				break;
785 			case MID_DOCINFO_TEMPLATE:
786                 if ( _pImp->m_xDocProps->getTemplateName() != sTemp )
787                     _pImp->m_xDocProps->setTemplateName(sTemp);
788 				break;
789 			case SID_TEMPLATE_NAME:
790                 if ( _pImp->m_xDocProps->getTemplateURL() != sTemp )
791                     _pImp->m_xDocProps->setTemplateURL(sTemp);
792 				break;
793 			case MID_DOCINFO_DESCRIPTION:
794                 if ( _pImp->m_xDocProps->getDescription() != sTemp )
795                     _pImp->m_xDocProps->setDescription(sTemp);
796 				break;
797 			case MID_DOCINFO_AUTOLOADURL:
798                 if ( _pImp->m_xDocProps->getAutoloadURL() != sTemp )
799                     _pImp->m_xDocProps->setAutoloadURL(sTemp);
800 				break;
801 			case MID_DOCINFO_DEFAULTTARGET:
802                 if ( _pImp->m_xDocProps->getDefaultTarget() != sTemp )
803                     _pImp->m_xDocProps->setDefaultTarget(sTemp);
804 				break;
805 //            case WID_CONTENT_TYPE : // this is readonly!
806 			default:
807 				break;
808 		}
809 	}
810     else if ( aValue.getValueType() == ::getCppuType((const ::com::sun::star::util::DateTime*)0) )
811 	{
812         com::sun::star::util::DateTime aTemp;
813         aValue >>= aTemp ;
814 		switch ( nHandle )
815 		{
816 			case WID_DATE_CREATED :
817 			{
818                 if ( !equalsDateTime(_pImp->m_xDocProps->getCreationDate(), aTemp ) )
819 				{
820 					_pImp->m_xDocProps->setCreationDate(aTemp);
821 				}
822 				break;
823 			}
824 			case WID_DATE_MODIFIED :
825 			{
826                 if ( !equalsDateTime(_pImp->m_xDocProps->getModificationDate(), aTemp ) )
827 				{
828 					_pImp->m_xDocProps->setModificationDate(aTemp);
829 				}
830 				break;
831 			}
832             case MID_DOCINFO_PRINTDATE :
833 			{
834                 if ( !equalsDateTime(_pImp->m_xDocProps->getPrintDate(), aTemp ) )
835 				{
836 					_pImp->m_xDocProps->setPrintDate(aTemp);
837 				}
838 				break;
839 			}
840             case MID_DOCINFO_TEMPLATEDATE :
841 			{
842                 if ( !equalsDateTime(_pImp->m_xDocProps->getTemplateDate(), aTemp ) )
843 				{
844 					_pImp->m_xDocProps->setTemplateDate(aTemp);
845 				}
846 				break;
847 			}
848 			default:
849 				break;
850 		}
851 	}
852 
853     else if ( aValue.getValueType() == ::getBooleanCppuType() )
854 	{
855 		sal_Bool bBoolVal = false;
856 		aValue >>= bBoolVal ;
857 		switch ( nHandle )
858 		{
859 			case MID_DOCINFO_AUTOLOADENABLED:
860                 // NB: this property does not exist any more
861                 //     it is emulated as enabled iff delay > 0
862                 if ( bBoolVal && (0 == _pImp->m_xDocProps->getAutoloadSecs()) ) {
863                     _pImp->m_xDocProps->setAutoloadSecs(60); // default
864                 } else if ( !bBoolVal && (0 != _pImp->m_xDocProps->getAutoloadSecs()) ) {
865                     _pImp->m_xDocProps->setAutoloadSecs(0);
866                     _pImp->m_xDocProps->setAutoloadURL(::rtl::OUString::createFromAscii(""));
867                 }
868 				break;
869 			default:
870 				break;
871 		}
872 	}
873     else if ( aValue.getValueType() == ::getCppuType((const sal_Int32*)0) )
874 	{
875 		sal_Int32 nIntVal = 0;
876 		aValue >>= nIntVal ;
877 		switch ( nHandle )
878 		{
879 			case MID_DOCINFO_AUTOLOADSECS:
880                 if ( nIntVal != _pImp->m_xDocProps->getAutoloadSecs())
881                     _pImp->m_xDocProps->setAutoloadSecs(nIntVal);
882 				break;
883 			case MID_DOCINFO_EDITTIME:
884                 if ( nIntVal != _pImp->m_xDocProps->getEditingDuration())
885                     _pImp->m_xDocProps->setEditingDuration(nIntVal);
886 				break;
887 			default:
888 				break;
889 		}
890 	}
891     else if ( aValue.getValueType() == ::getCppuType((const sal_Int16*)0) )
892 	{
893 		short nIntVal = 0;
894 		aValue >>= nIntVal ;
895 		switch ( nHandle )
896 		{
897             case MID_DOCINFO_REVISION:
898                 if ( nIntVal != _pImp->m_xDocProps->getEditingCycles())
899                     _pImp->m_xDocProps->setEditingCycles(nIntVal);
900 				break;
901 			default:
902 				break;
903 		}
904 	}
905 	else if ( aValue.getValueType() == ::getCppuType((const uno::Sequence< beans::NamedValue >*)0) )
906 	{
907         if ( nHandle == MID_DOCINFO_STATISTIC )
908 		{
909             uno::Sequence < beans::NamedValue > aData;
910             aValue >>= aData;
911             {
912                 _pImp->m_xDocProps->setDocumentStatistics(aData);
913             }
914 		}
915 	}
916 	else if ( aValue.getValueType() == ::getCppuType((const lang::Locale*)0) )
917 	{
918         if ( nHandle == MID_DOCINFO_CHARLOCALE )
919 		{
920             lang::Locale aLocale;
921             aValue >>= aLocale;
922             lang::Locale oldLocale = _pImp->m_xDocProps->getLanguage();
923             if ( aLocale.Language != oldLocale.Language ||
924                  aLocale.Country  != oldLocale.Country  ||
925                  aLocale.Variant  != oldLocale.Variant   )
926 			{
927 				_pImp->m_xDocProps->setLanguage(aLocale);
928 			}
929 		}
930 	}
931 }
932 
933 //-----------------------------------------------------------------------------
934 
getFastPropertyValue(sal_Int32 nHandle)935 ::com::sun::star::uno::Any SAL_CALL  SfxDocumentInfoObject::getFastPropertyValue(sal_Int32 nHandle) throw(
936         uno::RuntimeException, beans::UnknownPropertyException,
937         lang::WrappedTargetException)
938 {
939     // Attention: Only fix properties should be provided by this method.
940     // Dynamic properties has no handle in real ... because it cant be used inside multithreaded environments :-)
941 
942     ::osl::MutexGuard aGuard( _pImp->_aMutex );
943 	::com::sun::star::uno::Any aValue;
944     switch ( nHandle )
945     {
946         case SID_APPLICATION :
947             aValue <<= _pImp->m_xDocProps->getGenerator();
948             break;
949         case WID_CONTENT_TYPE :
950 // FIXME this is not available anymore
951             aValue <<= ::rtl::OUString();
952             break;
953         case MID_DOCINFO_REVISION :
954             aValue <<= _pImp->m_xDocProps->getEditingCycles();
955             break;
956         case MID_DOCINFO_EDITTIME :
957             aValue <<= _pImp->m_xDocProps->getEditingDuration();
958             break;
959         case WID_FROM :
960 			aValue <<= _pImp->m_xDocProps->getAuthor();
961             break;
962         case WID_DATE_CREATED :
963             if ( IsValidDateTime( _pImp->m_xDocProps->getCreationDate() ) )
964 	            aValue <<= _pImp->m_xDocProps->getCreationDate();
965             break;
966         case WID_TITLE :
967             aValue <<= _pImp->m_xDocProps->getTitle();
968             break;
969         case MID_DOCINFO_SUBJECT:
970             aValue <<= _pImp->m_xDocProps->getSubject();
971             break;
972         case MID_DOCINFO_MODIFICATIONAUTHOR:
973             aValue <<= _pImp->m_xDocProps->getModifiedBy();
974             break;
975         case WID_DATE_MODIFIED :
976             if ( IsValidDateTime( _pImp->m_xDocProps->getModificationDate() ) )
977 	            aValue <<= _pImp->m_xDocProps->getModificationDate();
978             break;
979         case MID_DOCINFO_PRINTEDBY:
980             aValue <<= _pImp->m_xDocProps->getPrintedBy();
981             break;
982         case MID_DOCINFO_PRINTDATE:
983             if ( IsValidDateTime( _pImp->m_xDocProps->getPrintDate() ) )
984 	            aValue <<= _pImp->m_xDocProps->getPrintDate();
985             break;
986         case WID_KEYWORDS :
987             aValue <<= ::comphelper::string::convertCommaSeparated(
988                 _pImp->m_xDocProps->getKeywords());
989             break;
990         case MID_DOCINFO_DESCRIPTION:
991             aValue <<= _pImp->m_xDocProps->getDescription();
992             break;
993         case MID_DOCINFO_TEMPLATE:
994             aValue <<= _pImp->m_xDocProps->getTemplateName();
995             break;
996         case SID_TEMPLATE_NAME:
997             aValue <<= _pImp->m_xDocProps->getTemplateURL();
998             break;
999         case MID_DOCINFO_TEMPLATEDATE:
1000             if ( IsValidDateTime( _pImp->m_xDocProps->getTemplateDate() ) )
1001 				aValue <<= _pImp->m_xDocProps->getTemplateDate();
1002             break;
1003         case MID_DOCINFO_AUTOLOADENABLED:
1004             aValue <<= static_cast<sal_Bool>
1005                         (   (_pImp->m_xDocProps->getAutoloadSecs() != 0)
1006                         || !(_pImp->m_xDocProps->getAutoloadURL().equalsAscii("")));
1007             break;
1008         case MID_DOCINFO_AUTOLOADURL:
1009             aValue <<= _pImp->m_xDocProps->getAutoloadURL();
1010             break;
1011         case MID_DOCINFO_AUTOLOADSECS:
1012             aValue <<= _pImp->m_xDocProps->getAutoloadSecs();
1013             break;
1014         case MID_DOCINFO_DEFAULTTARGET:
1015             aValue <<= _pImp->m_xDocProps->getDefaultTarget();
1016             break;
1017         case MID_DOCINFO_STATISTIC:
1018             aValue <<= _pImp->m_xDocProps->getDocumentStatistics();
1019             break;
1020         case MID_DOCINFO_CHARLOCALE:
1021             aValue <<= _pImp->m_xDocProps->getLanguage();
1022             break;
1023         default:
1024             aValue <<= ::rtl::OUString();
1025             break;
1026     }
1027 
1028 	return aValue;
1029 }
1030 
1031 //-----------------------------------------------------------------------------
1032 
getUserFieldCount()1033 sal_Int16 SAL_CALL  SfxDocumentInfoObject::getUserFieldCount() throw( ::com::sun::star::uno::RuntimeException )
1034 {
1035 //    uno::Reference<beans::XPropertyAccess> xPropSet(
1036 //        _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1037 //    return xPropSet->getPropertyValues().getLength();
1038     return FOUR;
1039 }
1040 
1041 //-----------------------------------------------------------------------------
1042 
getUserFieldName(sal_Int16 nIndex)1043 ::rtl::OUString SAL_CALL  SfxDocumentInfoObject::getUserFieldName(sal_Int16 nIndex) throw( ::com::sun::star::uno::RuntimeException )
1044 {
1045     ::osl::MutexGuard aGuard( _pImp->_aMutex );
1046     if (nIndex < FOUR)
1047         return _pImp->m_UserDefined[nIndex];
1048 	else
1049 		return ::rtl::OUString();
1050 }
1051 
1052 //-----------------------------------------------------------------------------
1053 
getUserFieldValue(sal_Int16 nIndex)1054 ::rtl::OUString SAL_CALL  SfxDocumentInfoObject::getUserFieldValue(sal_Int16 nIndex) throw( ::com::sun::star::uno::RuntimeException )
1055 {
1056     ::osl::MutexGuard aGuard( _pImp->_aMutex );
1057     if (nIndex < FOUR) {
1058         ::rtl::OUString name = _pImp->m_UserDefined[nIndex];
1059         uno::Reference<beans::XPropertySet> xPropSet(
1060             _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1061         ::rtl::OUString val;
1062         try {
1063             xPropSet->getPropertyValue(name) >>= val;
1064             return val;
1065         } catch (uno::RuntimeException &) {
1066             throw;
1067         } catch (uno::Exception &) {
1068             return ::rtl::OUString(); // ignore
1069         }
1070     } else
1071 		return ::rtl::OUString();
1072 }
1073 
1074 //-----------------------------------------------------------------------------
1075 
setUserFieldName(sal_Int16 nIndex,const::rtl::OUString & aName)1076 void  SAL_CALL SfxDocumentInfoObject::setUserFieldName(sal_Int16 nIndex, const ::rtl::OUString& aName ) throw( ::com::sun::star::uno::RuntimeException )
1077 {
1078     ::osl::ClearableMutexGuard aGuard( _pImp->_aMutex );
1079     if (nIndex < FOUR) // yes, four!
1080     {
1081         // FIXME this is full of race conditions because the PropertyBag
1082         // can be accessed from clients of the DocumentProperties!
1083         ::rtl::OUString name = _pImp->m_UserDefined[nIndex];
1084         if (name != aName) {
1085             uno::Reference<beans::XPropertySet> xPropSet(
1086                 _pImp->m_xDocProps->getUserDefinedProperties(),
1087                 uno::UNO_QUERY_THROW);
1088             uno::Reference<beans::XPropertyContainer> xPropContainer(
1089                 _pImp->m_xDocProps->getUserDefinedProperties(),
1090                 uno::UNO_QUERY_THROW);
1091             uno::Any value;
1092             try {
1093                 value = xPropSet->getPropertyValue(name);
1094                 xPropContainer->removeProperty(name);
1095                 xPropContainer->addProperty(aName,
1096                     beans::PropertyAttribute::REMOVEABLE, value);
1097                 _pImp->m_UserDefined[nIndex] = aName;
1098             } catch (beans::UnknownPropertyException) {
1099                 try {
1100                     xPropContainer->addProperty(aName,
1101                         beans::PropertyAttribute::REMOVEABLE,
1102                         uno::makeAny(::rtl::OUString::createFromAscii("")));
1103                     _pImp->m_UserDefined[nIndex] = aName;
1104                 } catch (beans::PropertyExistException) {
1105                     _pImp->m_UserDefined[nIndex] = aName;
1106                     // ignore
1107                 }
1108             } catch (beans::PropertyExistException) {
1109                 try {
1110                     xPropContainer->addProperty(name,
1111                         beans::PropertyAttribute::REMOVEABLE, value);
1112                 } catch (beans::PropertyExistException) {
1113                     // bugger...
1114                 }
1115             } catch (uno::RuntimeException &) {
1116                 throw;
1117             } catch (uno::Exception &) {
1118                 // ignore everything else; xPropSet _may_ be corrupted
1119             }
1120 		}
1121     }
1122 }
1123 
1124 //-----------------------------------------------------------------------------
1125 
setUserFieldValue(sal_Int16 nIndex,const::rtl::OUString & aValue)1126 void SAL_CALL  SfxDocumentInfoObject::setUserFieldValue( sal_Int16 nIndex, const ::rtl::OUString& aValue ) throw( ::com::sun::star::uno::RuntimeException )
1127 {
1128     ::osl::ClearableMutexGuard aGuard( _pImp->_aMutex );
1129     if (nIndex < FOUR) // yes, four!
1130     {
1131         ::rtl::OUString name = _pImp->m_UserDefined[nIndex];
1132         uno::Reference<beans::XPropertySet> xPropSet(
1133             _pImp->m_xDocProps->getUserDefinedProperties(),
1134             uno::UNO_QUERY_THROW);
1135         uno::Reference<beans::XPropertyContainer> xPropContainer(
1136             _pImp->m_xDocProps->getUserDefinedProperties(),
1137             uno::UNO_QUERY_THROW);
1138         uno::Any aAny;
1139         aAny <<= aValue;
1140         try {
1141             uno::Any value = xPropSet->getPropertyValue(name);
1142             if (value != aAny) {
1143                 xPropSet->setPropertyValue(name, aAny);
1144             }
1145         } catch (beans::UnknownPropertyException) {
1146             try {
1147                 // someone removed it, add it back again
1148                 xPropContainer->addProperty(name,
1149                     beans::PropertyAttribute::REMOVEABLE, aAny);
1150             } catch (uno::RuntimeException &) {
1151                 throw;
1152             } catch (uno::Exception &) {
1153                 // ignore everything else
1154             }
1155         } catch (uno::RuntimeException &) {
1156             throw;
1157         } catch (uno::Exception &) {
1158             // ignore everything else
1159         }
1160     }
1161 }
1162 
1163 //-----------------------------------------------------------------------------
SFX_IMPL_XINTERFACE_2(SfxStandaloneDocumentInfoObject,SfxDocumentInfoObject,::com::sun::star::lang::XServiceInfo,::com::sun::star::document::XStandaloneDocumentInfo)1164 SFX_IMPL_XINTERFACE_2( SfxStandaloneDocumentInfoObject, SfxDocumentInfoObject, ::com::sun::star::lang::XServiceInfo, ::com::sun::star::document::XStandaloneDocumentInfo  )
1165 SFX_IMPL_XTYPEPROVIDER_10( SfxStandaloneDocumentInfoObject, ::com::sun::star::document::XDocumentInfo, ::com::sun::star::lang::XComponent,
1166     ::com::sun::star::beans::XPropertySet, ::com::sun::star::beans::XFastPropertySet, ::com::sun::star::beans::XPropertyAccess,
1167     ::com::sun::star::beans::XPropertyContainer, ::com::sun::star::util::XModifiable, ::com::sun::star::util::XModifyBroadcaster,
1168     ::com::sun::star::document::XStandaloneDocumentInfo, ::com::sun::star::lang::XServiceInfo )
1169 
1170 SFX_IMPL_XSERVICEINFO( SfxStandaloneDocumentInfoObject, "com.sun.star.document.StandaloneDocumentInfo", "com.sun.star.comp.sfx2.StandaloneDocumentInfo" )
1171 SFX_IMPL_SINGLEFACTORY( SfxStandaloneDocumentInfoObject )
1172 
1173 SfxStandaloneDocumentInfoObject::SfxStandaloneDocumentInfoObject( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
1174     : SfxDocumentInfoObject()
1175     , _xFactory( xFactory )
1176 {
1177     uno::Reference< lang::XInitialization > xDocProps(
1178         _xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1179             "com.sun.star.document.DocumentProperties"))), uno::UNO_QUERY_THROW);
1180 //    xDocProps->initialize(uno::Sequence<uno::Any>());
1181     uno::Any a;
1182     a <<= xDocProps;
1183     uno::Sequence<uno::Any> args(1);
1184     args[0] = a;
1185     initialize(args);
1186 }
1187 
1188 //-----------------------------------------------------------------------------
1189 
~SfxStandaloneDocumentInfoObject()1190 SfxStandaloneDocumentInfoObject::~SfxStandaloneDocumentInfoObject()
1191 {
1192 }
1193 
1194 //-----------------------------------------------------------------------------
1195 
GetStorage_Impl(const::rtl::OUString & rName,sal_Bool bWrite,uno::Reference<lang::XMultiServiceFactory> & xFactory)1196 uno::Reference< embed::XStorage > GetStorage_Impl( const ::rtl::OUString& rName, sal_Bool bWrite, uno::Reference < lang::XMultiServiceFactory >& xFactory )
1197 {
1198     // catch unexpected exceptions under solaris
1199     // Client code checks the returned reference but is not interested on error details.
1200     try
1201     {
1202 		::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1203         return ::comphelper::OStorageHelper::GetStorageFromURL(
1204 						rName,
1205 						bWrite ? embed::ElementModes::READWRITE : embed::ElementModes::READ,
1206                         xFactory );
1207     }
1208     catch(const uno::Exception&)
1209     {}
1210 
1211     return uno::Reference< embed::XStorage >();
1212 }
1213 
1214 //-----------------------------------------------------------------------------
1215 
getUserFieldCount()1216 sal_Int16 SAL_CALL SfxStandaloneDocumentInfoObject::getUserFieldCount() throw( ::com::sun::star::uno::RuntimeException )
1217 {
1218 	return SfxDocumentInfoObject::getUserFieldCount();
1219 }
1220 
1221 //-----------------------------------------------------------------------------
1222 
getUserFieldName(sal_Int16 nIndex)1223 ::rtl::OUString SAL_CALL  SfxStandaloneDocumentInfoObject::getUserFieldName(sal_Int16 nIndex) throw( ::com::sun::star::uno::RuntimeException )
1224 {
1225 	return SfxDocumentInfoObject::getUserFieldName(nIndex);
1226 }
1227 
1228 //-----------------------------------------------------------------------------
1229 
getUserFieldValue(sal_Int16 nIndex)1230 ::rtl::OUString SAL_CALL  SfxStandaloneDocumentInfoObject::getUserFieldValue(sal_Int16 nIndex) throw( ::com::sun::star::uno::RuntimeException )
1231 {
1232 	return SfxDocumentInfoObject::getUserFieldValue(nIndex);
1233 }
1234 
1235 //-----------------------------------------------------------------------------
1236 
setUserFieldName(sal_Int16 nIndex,const::rtl::OUString & aName)1237 void  SAL_CALL SfxStandaloneDocumentInfoObject::setUserFieldName(sal_Int16 nIndex, const ::rtl::OUString& aName ) throw( ::com::sun::star::uno::RuntimeException )
1238 {
1239 	SfxDocumentInfoObject::setUserFieldName( nIndex, aName );
1240 }
1241 
1242 //-----------------------------------------------------------------------------
1243 
setUserFieldValue(sal_Int16 nIndex,const::rtl::OUString & aValue)1244 void SAL_CALL  SfxStandaloneDocumentInfoObject::setUserFieldValue( sal_Int16 nIndex, const ::rtl::OUString& aValue ) throw( ::com::sun::star::uno::RuntimeException )
1245 {
1246 	SfxDocumentInfoObject::setUserFieldValue( nIndex, aValue );
1247 }
1248 
1249 //-----------------------------------------------------------------------------
1250 
loadFromURL(const::rtl::OUString & aURL)1251 void SAL_CALL  SfxStandaloneDocumentInfoObject::loadFromURL(const ::rtl::OUString& aURL)
1252 	throw( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException )
1253 {
1254 	sal_Bool bOK = sal_False;
1255 
1256     ::osl::ClearableMutexGuard aGuard( _pImp->_aMutex );
1257     uno::Reference< document::XDocumentProperties > xDocProps(
1258         _xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1259             "com.sun.star.document.DocumentProperties"))), uno::UNO_QUERY_THROW);
1260 //    uno::Reference< lang::XInitialization > xInit(xDocProps, uno::UNO_QUERY_THROW);
1261 //    xInit->initialize(uno::Sequence<uno::Any>());
1262     _pImp->Reset(xDocProps);
1263 	aGuard.clear();
1264 
1265     uno::Reference< embed::XStorage > xStorage = GetStorage_Impl( aURL, sal_False, _xFactory );
1266     if ( xStorage.is() )
1267 	{
1268 		try
1269 		{
1270             uno::Sequence<beans::PropertyValue> medium(2);
1271             medium[0].Name = ::rtl::OUString::createFromAscii("DocumentBaseURL");
1272             medium[0].Value <<= aURL;
1273             medium[1].Name = ::rtl::OUString::createFromAscii("URL");
1274             medium[1].Value <<= aURL;
1275             _pImp->m_xDocProps->loadFromStorage(xStorage, medium);
1276             _pImp->Reset(_pImp->m_xDocProps);
1277             bOK = sal_True;
1278 		}
1279 		catch( uno::Exception& )
1280 		{
1281 		}
1282     }
1283 	else
1284 	{
1285         uno::Reference < document::XStandaloneDocumentInfo > xBinary( _xFactory->createInstance(
1286             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStandaloneDocumentInfo" ) ) ), uno::UNO_QUERY );
1287         if ( xBinary.is() )
1288         {
1289             xBinary->loadFromURL( aURL );
1290             bOK = sal_True;
1291             uno::Reference < document::XStandaloneDocumentInfo > xTarget( static_cast < document::XStandaloneDocumentInfo*> (this), uno::UNO_QUERY );
1292             Copy( xBinary, xTarget );
1293         }
1294 	}
1295 
1296 	if ( !bOK )
1297 		throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), ERRCODE_IO_CANTREAD );
1298 }
1299 
1300 //-----------------------------------------------------------------------------
1301 
storeIntoURL(const::rtl::OUString & aURL)1302 void SAL_CALL  SfxStandaloneDocumentInfoObject::storeIntoURL(const ::rtl::OUString& aURL) throw( ::com::sun::star::io::IOException )
1303 {
1304 	sal_Bool bOK = sal_False;
1305     uno::Reference< embed::XStorage > xStorage = GetStorage_Impl( aURL, sal_True, _xFactory );
1306 	if ( xStorage.is() )
1307 	{
1308 		try
1309 		{
1310             uno::Sequence<beans::PropertyValue> medium(2);
1311             medium[0].Name = ::rtl::OUString::createFromAscii("DocumentBaseURL");
1312             medium[0].Value <<= aURL;
1313             medium[1].Name = ::rtl::OUString::createFromAscii("URL");
1314             medium[1].Value <<= aURL;
1315 
1316             _pImp->m_xDocProps->storeToStorage(xStorage, medium);
1317             bOK = sal_True;
1318 		}
1319 		catch( io::IOException & )
1320 		{
1321 			throw;
1322 		}
1323 		catch( uno::RuntimeException& )
1324 		{
1325 			throw;
1326 		}
1327 		catch( uno::Exception& )
1328 		{
1329 		}
1330 	}
1331 	else
1332 	{
1333         uno::Reference < document::XStandaloneDocumentInfo > xBinary( _xFactory->createInstance(
1334 			::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStandaloneDocumentInfo" ) ) ), uno::UNO_QUERY );
1335         if ( xBinary.is() )
1336         {
1337             Copy( this, xBinary );
1338             xBinary->storeIntoURL( aURL );
1339             bOK = sal_True;
1340         }
1341 	}
1342 
1343 	if ( !bOK )
1344 		throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), ERRCODE_IO_CANTWRITE );
1345 }
1346 
1347