xref: /trunk/main/sfx2/source/doc/objuno.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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(  );
232         virtual ::com::sun::star::beans::Property SAL_CALL getPropertyByName( const ::rtl::OUString& aName );
233         virtual ::sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& Name );
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 {
257     ::comphelper::SequenceAsVector< ::com::sun::star::beans::Property > lProps;
258 
259     // copy "fix" props
260     //todo: os: this ugly thing should be replaced
261     const SfxItemPropertyMapEntry* pFixProp = lcl_GetDocInfoPropertyMap();
262 
263     while(pFixProp && pFixProp->pName)
264     {
265         ::com::sun::star::beans::Property aProp;
266 
267         aProp.Name       = ::rtl::OUString::createFromAscii(pFixProp->pName);
268         aProp.Handle     = pFixProp->nWID;
269         aProp.Type       = *(pFixProp->pType);
270         aProp.Attributes = (sal_Int16)(pFixProp->nFlags);
271 
272         lProps.push_back(aProp);
273         ++pFixProp;
274     }
275 
276     // copy "dynamic" props
277 
278     // NB: this is really ugly:
279     // The returned properties must _not_ include the 4 user-defined fields!
280     // These are _not_ properties of the XDocumentInfo interface.
281     // Some things rely on this, e.g. Copy would break otherwise.
282     // This will have interesting consequences if someone expects to insert
283     // a property with the same name as an user-defined key, but nobody
284     // sane does that.
285     uno::Sequence<beans::Property> udProps =
286         _xUDProps->getPropertySetInfo()->getProperties();
287     for (sal_Int32 i = 0; i < udProps.getLength(); ++i) {
288         if (std::find(_pUserKeys, _pUserKeys+FOUR, udProps[i].Name)
289             == _pUserKeys+FOUR) {
290                 // #i100027#: handles from udProps are not valid here
291                 udProps[i].Handle = -1;
292                 lProps.push_back(udProps[i]);
293         }
294     }
295 
296     return lProps.getAsConstList();
297 }
298 
299 //-----------------------------------------------------------------------------
300 
getPropertyByName(const::rtl::OUString & sName)301 ::com::sun::star::beans::Property SAL_CALL MixedPropertySetInfo::getPropertyByName(
302     const ::rtl::OUString& sName )
303 {
304     ::com::sun::star::beans::Property aProp;
305 
306     // search it as "fix" prop
307     if( _aPropertyMap.hasPropertyByName( sName ) )
308         return _aPropertyMap.getPropertyByName( sName );
309     else
310     // search it as "dynamic" prop
311     return _xUDProps->getPropertySetInfo()->getPropertyByName(sName);
312 }
313 
314 //-----------------------------------------------------------------------------
315 
hasPropertyByName(const::rtl::OUString & sName)316 ::sal_Bool SAL_CALL MixedPropertySetInfo::hasPropertyByName(const ::rtl::OUString& sName)
317 {
318     return _aPropertyMap.hasPropertyByName( sName ) ? // "fix" prop?
319         sal_True :
320         _xUDProps->getPropertySetInfo()->hasPropertyByName(sName); // "dynamic" prop?
321 }
322 
323 //-----------------------------------------------------------------------------
324 
325 struct SfxDocumentInfoObject_Impl
326 {
327     ::osl::Mutex                        _aMutex;
328     ::cppu::OInterfaceContainerHelper   _aDisposeContainer;
329 
330     sal_Bool            bDisposed;
331 
332     // this contains the names of the 4 user defined properties
333     // which are accessible via the evil XDocumentInfo interface
334     ::rtl::OUString m_UserDefined[FOUR];
335 
336     // the actual contents
337     uno::Reference<document::XDocumentProperties> m_xDocProps;
338     SfxItemPropertyMap      m_aPropertyMap;
339 
SfxDocumentInfoObject_ImplSfxDocumentInfoObject_Impl340     SfxDocumentInfoObject_Impl()
341         : _aDisposeContainer( _aMutex )
342         , bDisposed(sal_False)
343         , m_xDocProps()
344         , m_aPropertyMap( lcl_GetDocInfoPropertyMap() )
345     {
346         // the number of user fields is not changeable from the outside
347         // we can't set it too high because every name/value pair will be written to the file (even if empty)
348         // currently our dialog has only 4 user keys so 4 is still a reasonable number
349     }
350 
351     /// the initialization function
352     void Reset(uno::Reference<document::XDocumentProperties> xDocProps, ::rtl::OUString* pUserDefined = 0);
353 };
354 
Reset(uno::Reference<document::XDocumentProperties> xDocProps,::rtl::OUString * pUserDefined)355 void SfxDocumentInfoObject_Impl::Reset(uno::Reference<document::XDocumentProperties> xDocProps, ::rtl::OUString* pUserDefined)
356 {
357     if (pUserDefined == 0) {
358         // NB: this is an ugly hack; the "Properties" ui dialog displays
359         //     exactly 4 user-defined fields and expects these to be available
360         //     (should be redesigned), but I do not want to do this in
361         //     DocumentProperties; do it here instead
362         uno::Reference<beans::XPropertyAccess> xPropAccess(
363             xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
364         uno::Reference<beans::XPropertyContainer> xPropContainer(
365             xPropAccess, uno::UNO_QUERY_THROW);
366         uno::Sequence< beans::PropertyValue >
367             props = xPropAccess->getPropertyValues();
368         sal_Int32 oldLength = props.getLength();
369         if (oldLength < FOUR) {
370             std::vector< ::rtl::OUString > names;
371             for (sal_Int32 i = 0; i < oldLength; ++i) {
372                 names.push_back(props[i].Name);
373             }
374             const ::rtl::OUString sInfo(
375                         String( SfxResId( STR_DOCINFO_INFOFIELD ) ));
376             for (sal_Int32 i = oldLength; i < FOUR; ++i) {
377                 ::rtl::OUString sName(sInfo);
378                 sal_Int32 idx = sName.indexOfAsciiL("%1", 2);
379                 ::rtl::OUString name = (idx > 0)
380                     ? sName.replaceAt(idx, 2, ::rtl::OUString::valueOf(i+1))
381                     : sName + ::rtl::OUString::valueOf(i+1);
382                 while (std::find(names.begin(), names.end(), name)
383                        != names.end()) {
384                     name += ::rtl::OUString::createFromAscii("'");
385                 }
386                 // FIXME there is a race condition here
387                 try {
388                     xPropContainer->addProperty(name,
389                         beans::PropertyAttribute::REMOVEABLE,
390                         uno::makeAny(::rtl::OUString::createFromAscii("")));
391                 } catch (uno::RuntimeException) {
392                     throw;
393                 } catch (uno::Exception) {
394                     // ignore
395                 }
396             }
397         }
398         props = xPropAccess->getPropertyValues();
399         for (sal_Int32 i = 0; i < FOUR; ++i) {
400             m_UserDefined[i] = props[i].Name;
401         }
402     } else {
403         std::copy(pUserDefined, pUserDefined+FOUR, m_UserDefined);
404     }
405     m_xDocProps = xDocProps;
406 }
407 
408 //-----------------------------------------------------------------------------
409 
SfxDocumentInfoObject()410 SfxDocumentInfoObject::SfxDocumentInfoObject()
411     : _pImp( new SfxDocumentInfoObject_Impl() )
412 {
413 }
414 
415 //-----------------------------------------------------------------------------
416 
~SfxDocumentInfoObject()417 SfxDocumentInfoObject::~SfxDocumentInfoObject()
418 {
419     delete _pImp;
420 }
421 
422 //-----------------------------------------------------------------------------
423 
424 // ::com::sun::star::lang::XInitialization:
425 void SAL_CALL
initialize(const uno::Sequence<uno::Any> & aArguments)426 SfxDocumentInfoObject::initialize(const uno::Sequence< uno::Any > & aArguments)
427 {
428     if (aArguments.getLength() >= 1) {
429         uno::Any any = aArguments[0];
430         uno::Reference<document::XDocumentProperties> xDoc;
431         if (!(any >>= xDoc) || !xDoc.is()) throw lang::IllegalArgumentException(
432             ::rtl::OUString::createFromAscii(
433                 "SfxDocumentInfoObject::initialize: no XDocumentProperties given"),
434                 *this, 0);
435         _pImp->Reset(xDoc);
436     } else {
437         throw lang::IllegalArgumentException(
438             ::rtl::OUString::createFromAscii(
439                 "SfxDocumentInfoObject::initialize: no argument given"),
440                 *this, 0);
441     }
442 }
443 
444 // ::com::sun::star::util::XCloneable:
445 uno::Reference<util::XCloneable> SAL_CALL
createClone()446 SfxDocumentInfoObject::createClone()
447 {
448     SfxDocumentInfoObject *pNew = new SfxDocumentInfoObject;
449     uno::Reference< util::XCloneable >
450         xCloneable(_pImp->m_xDocProps, uno::UNO_QUERY_THROW);
451     uno::Reference<document::XDocumentProperties> xDocProps(
452         xCloneable->createClone(), uno::UNO_QUERY_THROW);
453     pNew->_pImp->Reset(xDocProps, _pImp->m_UserDefined);
454     return pNew;
455 }
456 
457 // ::com::sun::star::document::XDocumentProperties:
458 uno::Reference< document::XDocumentProperties > SAL_CALL
getDocumentProperties()459 SfxDocumentInfoObject::getDocumentProperties()
460 {
461     return _pImp->m_xDocProps;
462 }
463 
464 //-----------------------------------------------------------------------------
465 
operator =(const SfxDocumentInfoObject & rOther)466 const SfxDocumentInfoObject& SfxDocumentInfoObject::operator=( const SfxDocumentInfoObject & rOther)
467 {
468     uno::Reference< util::XCloneable >
469         xCloneable(rOther._pImp->m_xDocProps, uno::UNO_QUERY_THROW);
470     uno::Reference<document::XDocumentProperties> xDocProps(
471         xCloneable->createClone(), uno::UNO_QUERY_THROW);
472     _pImp->Reset(xDocProps, rOther._pImp->m_UserDefined);
473     return *this;
474 }
475 
476 //-----------------------------------------------------------------------------
477 
dispose()478 void SAL_CALL SfxDocumentInfoObject::dispose()
479 {
480     ::com::sun::star::lang::EventObject aEvent( (::cppu::OWeakObject *)this );
481     _pImp->_aDisposeContainer.disposeAndClear( aEvent );
482     ::osl::MutexGuard aGuard( _pImp->_aMutex );
483     _pImp->m_xDocProps = 0;
484     // NB: do not call m_xDocProps->dispose(), there could be other refs
485     _pImp->bDisposed = sal_True;
486 }
487 
488 //-----------------------------------------------------------------------------
489 
addEventListener(const::com::sun::star::uno::Reference<::com::sun::star::lang::XEventListener> & aListener)490 void SAL_CALL  SfxDocumentInfoObject::addEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & aListener)
491 {
492     _pImp->_aDisposeContainer.addInterface( aListener );
493 }
494 
495 //-----------------------------------------------------------------------------
496 
removeEventListener(const::com::sun::star::uno::Reference<::com::sun::star::lang::XEventListener> & aListener)497 void SAL_CALL  SfxDocumentInfoObject::removeEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & aListener)
498 {
499     _pImp->_aDisposeContainer.removeInterface( aListener );
500 }
501 //-----------------------------------------------------------------------------
502 
getPropertySetInfo()503 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >  SAL_CALL  SfxDocumentInfoObject::getPropertySetInfo()
504 {
505     ::osl::MutexGuard aGuard( _pImp->_aMutex );
506 
507     uno::Reference<beans::XPropertySet> xPropSet(
508         _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
509     MixedPropertySetInfo* pInfo = new MixedPropertySetInfo( lcl_GetDocInfoPropertyMap(), _pImp->m_UserDefined, xPropSet);
510     uno::Reference< beans::XPropertySetInfo > xInfo(
511         static_cast< beans::XPropertySetInfo* >(pInfo), uno::UNO_QUERY_THROW);
512     return xInfo;
513 }
514 
515 //-----------------------------------------------------------------------------
516 
setPropertyValue(const::rtl::OUString & aPropertyName,const uno::Any & aValue)517 void SAL_CALL  SfxDocumentInfoObject::setPropertyValue(const ::rtl::OUString& aPropertyName, const uno::Any& aValue)
518 {
519     const SfxItemPropertySimpleEntry* pEntry = _pImp->m_aPropertyMap.getByName( aPropertyName );
520     // fix prop!
521     if ( pEntry )
522         setFastPropertyValue( pEntry->nWID, aValue );
523     else
524     // dynamic prop!
525     {
526         uno::Reference<beans::XPropertySet> xPropSet(
527             _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
528         return xPropSet->setPropertyValue(aPropertyName, aValue);
529     }
530 }
531 
532 //-----------------------------------------------------------------------------
533 
getPropertyValue(const::rtl::OUString & aPropertyName)534 uno::Any  SAL_CALL  SfxDocumentInfoObject::getPropertyValue(const ::rtl::OUString& aPropertyName)
535 {
536     const SfxItemPropertySimpleEntry* pEntry = _pImp->m_aPropertyMap.getByName( aPropertyName );
537     // fix prop!
538     if ( pEntry )
539         return getFastPropertyValue( pEntry->nWID );
540     else
541     // dynamic prop!
542     {
543         uno::Reference<beans::XPropertySet> xPropSet(
544             _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
545         return xPropSet->getPropertyValue(aPropertyName);
546     }
547 }
548 
isModified()549 sal_Bool SAL_CALL SfxDocumentInfoObject::isModified()
550 {
551     uno::Reference<util::XModifiable> xModif(
552             _pImp->m_xDocProps, uno::UNO_QUERY_THROW);
553     return xModif->isModified();
554 }
555 
setModified(sal_Bool bModified)556 void SAL_CALL SfxDocumentInfoObject::setModified( sal_Bool bModified )
557 {
558     uno::Reference<util::XModifiable> xModif(
559             _pImp->m_xDocProps, uno::UNO_QUERY_THROW);
560     return xModif->setModified(bModified);
561 }
562 
addModifyListener(const uno::Reference<util::XModifyListener> & xListener)563 void SAL_CALL SfxDocumentInfoObject::addModifyListener( const uno::Reference< util::XModifyListener >& xListener)
564 {
565     uno::Reference<util::XModifiable> xModif(
566             _pImp->m_xDocProps, uno::UNO_QUERY_THROW);
567     return xModif->addModifyListener(xListener);
568 }
569 
removeModifyListener(const uno::Reference<util::XModifyListener> & xListener)570 void SAL_CALL SfxDocumentInfoObject::removeModifyListener( const uno::Reference< util::XModifyListener >& xListener)
571 {
572     uno::Reference<util::XModifiable> xModif(
573             _pImp->m_xDocProps, uno::UNO_QUERY_THROW);
574     return xModif->removeModifyListener(xListener);
575 }
576 
577 //-----------------------------------------------------------------------------
578 
addPropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)579 void SAL_CALL  SfxDocumentInfoObject::addPropertyChangeListener(const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener > & )
580 {}
581 
582 //-----------------------------------------------------------------------------
583 
removePropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)584 void SAL_CALL  SfxDocumentInfoObject::removePropertyChangeListener(const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener > & )
585 {}
586 
587 //-----------------------------------------------------------------------------
588 
addVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)589 void SAL_CALL  SfxDocumentInfoObject::addVetoableChangeListener(const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener > & )
590 {}
591 
592 //-----------------------------------------------------------------------------
593 
removeVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)594 void SAL_CALL  SfxDocumentInfoObject::removeVetoableChangeListener(const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener > & )
595 {}
596 
getPropertyValues(void)597 uno::Sequence< beans::PropertyValue > SAL_CALL  SfxDocumentInfoObject::getPropertyValues( void )
598 {
599     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >  xInfo = getPropertySetInfo();
600     ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > aProps = xInfo->getProperties();
601 
602     const ::com::sun::star::beans::Property* pProps  = aProps.getConstArray();
603     sal_uInt32 nCount = aProps.getLength();
604 
605     ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >aSeq( nCount );
606     ::com::sun::star::beans::PropertyValue*  pValues = aSeq.getArray();
607 
608     for ( sal_uInt32 n = 0; n < nCount; ++n )
609     {
610         ::com::sun::star::beans::PropertyValue& rCurrValue = pValues[n];
611         const ::com::sun::star::beans::Property& rCurrProp = pProps[n];
612 
613         rCurrValue.Name = rCurrProp.Name;
614         rCurrValue.Handle = rCurrProp.Handle;
615         rCurrValue.Value = getPropertyValue( rCurrProp.Name );
616     }
617 
618     return aSeq;
619 }
620 
setPropertyValues(const::com::sun::star::uno::Sequence<::com::sun::star::beans::PropertyValue> & aProps)621 void SAL_CALL  SfxDocumentInfoObject::setPropertyValues( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aProps )
622 {
623     const ::com::sun::star::beans::PropertyValue* pProps  = aProps.getConstArray();
624     sal_uInt32 nCount = aProps.getLength();
625 
626     for ( sal_uInt32 n = 0; n < nCount; ++n )
627     {
628         const ::com::sun::star::beans::PropertyValue& rProp = pProps[n];
629         setPropertyValue( rProp.Name, rProp.Value );
630     }
631 }
632 
addProperty(const::rtl::OUString & sName,sal_Int16 nAttributes,const::com::sun::star::uno::Any & aDefaultValue)633 void SAL_CALL SfxDocumentInfoObject::addProperty(const ::rtl::OUString&            sName        ,
634                                                        sal_Int16                   nAttributes  ,
635                                                  const ::com::sun::star::uno::Any& aDefaultValue)
636 {
637     // clash with "fix" properties ?
638     sal_Bool bFixProp = _pImp->m_aPropertyMap.getByName( sName ) != 0;
639     if ( bFixProp )
640     {
641         ::rtl::OUStringBuffer sMsg(256);
642         sMsg.appendAscii("The property \""   );
643         sMsg.append     (sName               );
644         sMsg.appendAscii("\" "               );
645         if ( bFixProp )
646             sMsg.appendAscii(" already exists as a fix property. Please have a look into the IDL documentation of the DocumentInfo service.");
647 
648         throw ::com::sun::star::beans::PropertyExistException(
649                 sMsg.makeStringAndClear(),
650                 static_cast< ::cppu::OWeakObject* >(this));
651     }
652 
653     uno::Reference<beans::XPropertyContainer> xPropSet(
654         _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
655     return xPropSet->addProperty(sName, nAttributes, aDefaultValue);
656 }
657 
removeProperty(const::rtl::OUString & sName)658 void SAL_CALL SfxDocumentInfoObject::removeProperty(const ::rtl::OUString& sName)
659 {
660     // clash with "fix" properties ?
661     sal_Bool bFixProp = _pImp->m_aPropertyMap.getByName( sName ) != 0;
662     if ( bFixProp )
663     {
664         ::rtl::OUStringBuffer sMsg(256);
665         sMsg.appendAscii("The property \""                                                    );
666         sMsg.append     (sName                                                                );
667         sMsg.appendAscii("\" can't be removed. Its a fix property of the DocumentInfo service.");
668 
669         throw ::com::sun::star::beans::NotRemoveableException(
670                 sMsg.makeStringAndClear(),
671                 static_cast< ::cppu::OWeakObject* >(this));
672     }
673 
674     uno::Reference<beans::XPropertyContainer> xPropSet(
675         _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
676     return xPropSet->removeProperty(sName);
677 }
678 
equalsDateTime(const util::DateTime & D1,const util::DateTime & D2)679 sal_Bool equalsDateTime( const util::DateTime& D1, const util::DateTime& D2 )
680 {
681     return D1.HundredthSeconds == D2.HundredthSeconds &&
682            D1.Seconds == D2.Seconds &&
683            D1.Minutes == D2.Minutes &&
684            D1.Hours == D2.Hours &&
685            D1.Day == D2.Day &&
686            D1.Month == D2.Month &&
687            D1.Year == D2.Year;
688 }
689 
setFastPropertyValue(sal_Int32 nHandle,const::com::sun::star::uno::Any & aValue)690 void SAL_CALL  SfxDocumentInfoObject::setFastPropertyValue(sal_Int32 nHandle, const ::com::sun::star::uno::Any& aValue)
691 {
692     // Attention: Only fix properties should be provided by this method.
693     // Dynamic properties has no handle in real ... because it can't be used inside multithreaded environments :-)
694 
695     ::osl::ClearableMutexGuard aGuard( _pImp->_aMutex );
696 
697     if ( aValue.getValueType() == ::getCppuType((const ::rtl::OUString*)0) )
698     {
699         ::rtl::OUString sTemp ;
700         aValue >>= sTemp ;
701         switch ( nHandle )
702         {
703             case SID_APPLICATION :
704                 _pImp->m_xDocProps->setGenerator(sTemp);
705                 break;
706             case WID_FROM :
707             {
708                 // QUESTION: do we still need this?
709                 /*
710                 // String aStrVal( sTemp );
711                 if ( aStrVal.Len() > TIMESTAMP_MAXLENGTH )
712                 {
713                     SvAddressParser aParser( aStrVal );
714                     if ( aParser.Count() > 0 )
715                     {
716                         String aEmail = aParser.GetEmailAddress(0);
717                         String aRealname = aParser.GetRealName(0);
718 
719                         if ( aRealname.Len() <= TIMESTAMP_MAXLENGTH )
720                             aStrVal = aRealname;
721                         else if ( aEmail.Len() <= TIMESTAMP_MAXLENGTH )
722                             aStrVal = aEmail;
723                     }
724                 } */
725 
726                 if ( _pImp->m_xDocProps->getAuthor() != sTemp )
727                     _pImp->m_xDocProps->setAuthor(sTemp);
728                 break;
729             }
730             case MID_DOCINFO_PRINTEDBY:
731                 if ( _pImp->m_xDocProps->getPrintedBy() != sTemp )
732                     _pImp->m_xDocProps->setPrintedBy(sTemp);
733                 break;
734             case MID_DOCINFO_MODIFICATIONAUTHOR:
735                 if ( _pImp->m_xDocProps->getModifiedBy() != sTemp )
736                     _pImp->m_xDocProps->setModifiedBy(sTemp);
737                 break;
738             case WID_TITLE :
739             {
740                 if ( _pImp->m_xDocProps->getTitle() != sTemp )
741                     _pImp->m_xDocProps->setTitle(sTemp);
742                 break;
743             }
744             case MID_DOCINFO_SUBJECT :
745                 if ( _pImp->m_xDocProps->getSubject() != sTemp )
746                     _pImp->m_xDocProps->setSubject(sTemp);
747                 break;
748             case WID_KEYWORDS :
749                 {
750                     _pImp->m_xDocProps->setKeywords(
751                         ::comphelper::string::convertCommaSeparated(sTemp));
752                 }
753                 break;
754             case MID_DOCINFO_TEMPLATE:
755                 if ( _pImp->m_xDocProps->getTemplateName() != sTemp )
756                     _pImp->m_xDocProps->setTemplateName(sTemp);
757                 break;
758             case SID_TEMPLATE_NAME:
759                 if ( _pImp->m_xDocProps->getTemplateURL() != sTemp )
760                     _pImp->m_xDocProps->setTemplateURL(sTemp);
761                 break;
762             case MID_DOCINFO_DESCRIPTION:
763                 if ( _pImp->m_xDocProps->getDescription() != sTemp )
764                     _pImp->m_xDocProps->setDescription(sTemp);
765                 break;
766             case MID_DOCINFO_AUTOLOADURL:
767                 if ( _pImp->m_xDocProps->getAutoloadURL() != sTemp )
768                     _pImp->m_xDocProps->setAutoloadURL(sTemp);
769                 break;
770             case MID_DOCINFO_DEFAULTTARGET:
771                 if ( _pImp->m_xDocProps->getDefaultTarget() != sTemp )
772                     _pImp->m_xDocProps->setDefaultTarget(sTemp);
773                 break;
774 //            case WID_CONTENT_TYPE : // this is readonly!
775             default:
776                 break;
777         }
778     }
779     else if ( aValue.getValueType() == ::getCppuType((const ::com::sun::star::util::DateTime*)0) )
780     {
781         com::sun::star::util::DateTime aTemp;
782         aValue >>= aTemp ;
783         switch ( nHandle )
784         {
785             case WID_DATE_CREATED :
786             {
787                 if ( !equalsDateTime(_pImp->m_xDocProps->getCreationDate(), aTemp ) )
788                 {
789                     _pImp->m_xDocProps->setCreationDate(aTemp);
790                 }
791                 break;
792             }
793             case WID_DATE_MODIFIED :
794             {
795                 if ( !equalsDateTime(_pImp->m_xDocProps->getModificationDate(), aTemp ) )
796                 {
797                     _pImp->m_xDocProps->setModificationDate(aTemp);
798                 }
799                 break;
800             }
801             case MID_DOCINFO_PRINTDATE :
802             {
803                 if ( !equalsDateTime(_pImp->m_xDocProps->getPrintDate(), aTemp ) )
804                 {
805                     _pImp->m_xDocProps->setPrintDate(aTemp);
806                 }
807                 break;
808             }
809             case MID_DOCINFO_TEMPLATEDATE :
810             {
811                 if ( !equalsDateTime(_pImp->m_xDocProps->getTemplateDate(), aTemp ) )
812                 {
813                     _pImp->m_xDocProps->setTemplateDate(aTemp);
814                 }
815                 break;
816             }
817             default:
818                 break;
819         }
820     }
821 
822     else if ( aValue.getValueType() == ::getBooleanCppuType() )
823     {
824         sal_Bool bBoolVal = false;
825         aValue >>= bBoolVal ;
826         switch ( nHandle )
827         {
828             case MID_DOCINFO_AUTOLOADENABLED:
829                 // NB: this property does not exist any more
830                 //     it is emulated as enabled iff delay > 0
831                 if ( bBoolVal && (0 == _pImp->m_xDocProps->getAutoloadSecs()) ) {
832                     _pImp->m_xDocProps->setAutoloadSecs(60); // default
833                 } else if ( !bBoolVal && (0 != _pImp->m_xDocProps->getAutoloadSecs()) ) {
834                     _pImp->m_xDocProps->setAutoloadSecs(0);
835                     _pImp->m_xDocProps->setAutoloadURL(::rtl::OUString::createFromAscii(""));
836                 }
837                 break;
838             default:
839                 break;
840         }
841     }
842     else if ( aValue.getValueType() == ::getCppuType((const sal_Int32*)0) )
843     {
844         sal_Int32 nIntVal = 0;
845         aValue >>= nIntVal ;
846         switch ( nHandle )
847         {
848             case MID_DOCINFO_AUTOLOADSECS:
849                 if ( nIntVal != _pImp->m_xDocProps->getAutoloadSecs())
850                     _pImp->m_xDocProps->setAutoloadSecs(nIntVal);
851                 break;
852             case MID_DOCINFO_EDITTIME:
853                 if ( nIntVal != _pImp->m_xDocProps->getEditingDuration())
854                     _pImp->m_xDocProps->setEditingDuration(nIntVal);
855                 break;
856             default:
857                 break;
858         }
859     }
860     else if ( aValue.getValueType() == ::getCppuType((const sal_Int16*)0) )
861     {
862         short nIntVal = 0;
863         aValue >>= nIntVal ;
864         switch ( nHandle )
865         {
866             case MID_DOCINFO_REVISION:
867                 if ( nIntVal != _pImp->m_xDocProps->getEditingCycles())
868                     _pImp->m_xDocProps->setEditingCycles(nIntVal);
869                 break;
870             default:
871                 break;
872         }
873     }
874     else if ( aValue.getValueType() == ::getCppuType((const uno::Sequence< beans::NamedValue >*)0) )
875     {
876         if ( nHandle == MID_DOCINFO_STATISTIC )
877         {
878             uno::Sequence < beans::NamedValue > aData;
879             aValue >>= aData;
880             {
881                 _pImp->m_xDocProps->setDocumentStatistics(aData);
882             }
883         }
884     }
885     else if ( aValue.getValueType() == ::getCppuType((const lang::Locale*)0) )
886     {
887         if ( nHandle == MID_DOCINFO_CHARLOCALE )
888         {
889             lang::Locale aLocale;
890             aValue >>= aLocale;
891             lang::Locale oldLocale = _pImp->m_xDocProps->getLanguage();
892             if ( aLocale.Language != oldLocale.Language ||
893                  aLocale.Country  != oldLocale.Country  ||
894                  aLocale.Variant  != oldLocale.Variant   )
895             {
896                 _pImp->m_xDocProps->setLanguage(aLocale);
897             }
898         }
899     }
900 }
901 
902 //-----------------------------------------------------------------------------
903 
getFastPropertyValue(sal_Int32 nHandle)904 ::com::sun::star::uno::Any SAL_CALL  SfxDocumentInfoObject::getFastPropertyValue(sal_Int32 nHandle)
905 {
906     // Attention: Only fix properties should be provided by this method.
907     // Dynamic properties has no handle in real ... because it can't be used inside multithreaded environments :-)
908 
909     ::osl::MutexGuard aGuard( _pImp->_aMutex );
910     ::com::sun::star::uno::Any aValue;
911     switch ( nHandle )
912     {
913         case SID_APPLICATION :
914             aValue <<= _pImp->m_xDocProps->getGenerator();
915             break;
916         case WID_CONTENT_TYPE :
917 // FIXME this is not available anymore
918             aValue <<= ::rtl::OUString();
919             break;
920         case MID_DOCINFO_REVISION :
921             aValue <<= _pImp->m_xDocProps->getEditingCycles();
922             break;
923         case MID_DOCINFO_EDITTIME :
924             aValue <<= _pImp->m_xDocProps->getEditingDuration();
925             break;
926         case WID_FROM :
927             aValue <<= _pImp->m_xDocProps->getAuthor();
928             break;
929         case WID_DATE_CREATED :
930             if ( IsValidDateTime( _pImp->m_xDocProps->getCreationDate() ) )
931                 aValue <<= _pImp->m_xDocProps->getCreationDate();
932             break;
933         case WID_TITLE :
934             aValue <<= _pImp->m_xDocProps->getTitle();
935             break;
936         case MID_DOCINFO_SUBJECT:
937             aValue <<= _pImp->m_xDocProps->getSubject();
938             break;
939         case MID_DOCINFO_MODIFICATIONAUTHOR:
940             aValue <<= _pImp->m_xDocProps->getModifiedBy();
941             break;
942         case WID_DATE_MODIFIED :
943             if ( IsValidDateTime( _pImp->m_xDocProps->getModificationDate() ) )
944                 aValue <<= _pImp->m_xDocProps->getModificationDate();
945             break;
946         case MID_DOCINFO_PRINTEDBY:
947             aValue <<= _pImp->m_xDocProps->getPrintedBy();
948             break;
949         case MID_DOCINFO_PRINTDATE:
950             if ( IsValidDateTime( _pImp->m_xDocProps->getPrintDate() ) )
951                 aValue <<= _pImp->m_xDocProps->getPrintDate();
952             break;
953         case WID_KEYWORDS :
954             aValue <<= ::comphelper::string::convertCommaSeparated(
955                 _pImp->m_xDocProps->getKeywords());
956             break;
957         case MID_DOCINFO_DESCRIPTION:
958             aValue <<= _pImp->m_xDocProps->getDescription();
959             break;
960         case MID_DOCINFO_TEMPLATE:
961             aValue <<= _pImp->m_xDocProps->getTemplateName();
962             break;
963         case SID_TEMPLATE_NAME:
964             aValue <<= _pImp->m_xDocProps->getTemplateURL();
965             break;
966         case MID_DOCINFO_TEMPLATEDATE:
967             if ( IsValidDateTime( _pImp->m_xDocProps->getTemplateDate() ) )
968                 aValue <<= _pImp->m_xDocProps->getTemplateDate();
969             break;
970         case MID_DOCINFO_AUTOLOADENABLED:
971             aValue <<= static_cast<sal_Bool>
972                         (   (_pImp->m_xDocProps->getAutoloadSecs() != 0)
973                         || !(_pImp->m_xDocProps->getAutoloadURL().equalsAscii("")));
974             break;
975         case MID_DOCINFO_AUTOLOADURL:
976             aValue <<= _pImp->m_xDocProps->getAutoloadURL();
977             break;
978         case MID_DOCINFO_AUTOLOADSECS:
979             aValue <<= _pImp->m_xDocProps->getAutoloadSecs();
980             break;
981         case MID_DOCINFO_DEFAULTTARGET:
982             aValue <<= _pImp->m_xDocProps->getDefaultTarget();
983             break;
984         case MID_DOCINFO_STATISTIC:
985             aValue <<= _pImp->m_xDocProps->getDocumentStatistics();
986             break;
987         case MID_DOCINFO_CHARLOCALE:
988             aValue <<= _pImp->m_xDocProps->getLanguage();
989             break;
990         default:
991             aValue <<= ::rtl::OUString();
992             break;
993     }
994 
995     return aValue;
996 }
997 
998 //-----------------------------------------------------------------------------
999 
getUserFieldCount()1000 sal_Int16 SAL_CALL  SfxDocumentInfoObject::getUserFieldCount()
1001 {
1002 //    uno::Reference<beans::XPropertyAccess> xPropSet(
1003 //        _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1004 //    return xPropSet->getPropertyValues().getLength();
1005     return FOUR;
1006 }
1007 
1008 //-----------------------------------------------------------------------------
1009 
getUserFieldName(sal_Int16 nIndex)1010 ::rtl::OUString SAL_CALL  SfxDocumentInfoObject::getUserFieldName(sal_Int16 nIndex)
1011 {
1012     ::osl::MutexGuard aGuard( _pImp->_aMutex );
1013     if (nIndex < FOUR)
1014         return _pImp->m_UserDefined[nIndex];
1015     else
1016         return ::rtl::OUString();
1017 }
1018 
1019 //-----------------------------------------------------------------------------
1020 
getUserFieldValue(sal_Int16 nIndex)1021 ::rtl::OUString SAL_CALL  SfxDocumentInfoObject::getUserFieldValue(sal_Int16 nIndex)
1022 {
1023     ::osl::MutexGuard aGuard( _pImp->_aMutex );
1024     if (nIndex < FOUR) {
1025         ::rtl::OUString name = _pImp->m_UserDefined[nIndex];
1026         uno::Reference<beans::XPropertySet> xPropSet(
1027             _pImp->m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1028         ::rtl::OUString val;
1029         try {
1030             xPropSet->getPropertyValue(name) >>= val;
1031             return val;
1032         } catch (uno::RuntimeException &) {
1033             throw;
1034         } catch (uno::Exception &) {
1035             return ::rtl::OUString(); // ignore
1036         }
1037     } else
1038         return ::rtl::OUString();
1039 }
1040 
1041 //-----------------------------------------------------------------------------
1042 
setUserFieldName(sal_Int16 nIndex,const::rtl::OUString & aName)1043 void  SAL_CALL SfxDocumentInfoObject::setUserFieldName(sal_Int16 nIndex, const ::rtl::OUString& aName )
1044 {
1045     ::osl::ClearableMutexGuard aGuard( _pImp->_aMutex );
1046     if (nIndex < FOUR) // yes, four!
1047     {
1048         // FIXME this is full of race conditions because the PropertyBag
1049         // can be accessed from clients of the DocumentProperties!
1050         ::rtl::OUString name = _pImp->m_UserDefined[nIndex];
1051         if (name != aName) {
1052             uno::Reference<beans::XPropertySet> xPropSet(
1053                 _pImp->m_xDocProps->getUserDefinedProperties(),
1054                 uno::UNO_QUERY_THROW);
1055             uno::Reference<beans::XPropertyContainer> xPropContainer(
1056                 _pImp->m_xDocProps->getUserDefinedProperties(),
1057                 uno::UNO_QUERY_THROW);
1058             uno::Any value;
1059             try {
1060                 value = xPropSet->getPropertyValue(name);
1061                 xPropContainer->removeProperty(name);
1062                 xPropContainer->addProperty(aName,
1063                     beans::PropertyAttribute::REMOVEABLE, value);
1064                 _pImp->m_UserDefined[nIndex] = aName;
1065             } catch (beans::UnknownPropertyException) {
1066                 try {
1067                     xPropContainer->addProperty(aName,
1068                         beans::PropertyAttribute::REMOVEABLE,
1069                         uno::makeAny(::rtl::OUString::createFromAscii("")));
1070                     _pImp->m_UserDefined[nIndex] = aName;
1071                 } catch (beans::PropertyExistException) {
1072                     _pImp->m_UserDefined[nIndex] = aName;
1073                     // ignore
1074                 }
1075             } catch (beans::PropertyExistException) {
1076                 try {
1077                     xPropContainer->addProperty(name,
1078                         beans::PropertyAttribute::REMOVEABLE, value);
1079                 } catch (beans::PropertyExistException) {
1080                     // bugger...
1081                 }
1082             } catch (uno::RuntimeException &) {
1083                 throw;
1084             } catch (uno::Exception &) {
1085                 // ignore everything else; xPropSet _may_ be corrupted
1086             }
1087         }
1088     }
1089 }
1090 
1091 //-----------------------------------------------------------------------------
1092 
setUserFieldValue(sal_Int16 nIndex,const::rtl::OUString & aValue)1093 void SAL_CALL  SfxDocumentInfoObject::setUserFieldValue( sal_Int16 nIndex, const ::rtl::OUString& aValue )
1094 {
1095     ::osl::ClearableMutexGuard aGuard( _pImp->_aMutex );
1096     if (nIndex < FOUR) // yes, four!
1097     {
1098         ::rtl::OUString name = _pImp->m_UserDefined[nIndex];
1099         uno::Reference<beans::XPropertySet> xPropSet(
1100             _pImp->m_xDocProps->getUserDefinedProperties(),
1101             uno::UNO_QUERY_THROW);
1102         uno::Reference<beans::XPropertyContainer> xPropContainer(
1103             _pImp->m_xDocProps->getUserDefinedProperties(),
1104             uno::UNO_QUERY_THROW);
1105         uno::Any aAny;
1106         aAny <<= aValue;
1107         try {
1108             uno::Any value = xPropSet->getPropertyValue(name);
1109             if (value != aAny) {
1110                 xPropSet->setPropertyValue(name, aAny);
1111             }
1112         } catch (beans::UnknownPropertyException) {
1113             try {
1114                 // someone removed it, add it back again
1115                 xPropContainer->addProperty(name,
1116                     beans::PropertyAttribute::REMOVEABLE, aAny);
1117             } catch (uno::RuntimeException &) {
1118                 throw;
1119             } catch (uno::Exception &) {
1120                 // ignore everything else
1121             }
1122         } catch (uno::RuntimeException &) {
1123             throw;
1124         } catch (uno::Exception &) {
1125             // ignore everything else
1126         }
1127     }
1128 }
1129 
1130 //-----------------------------------------------------------------------------
SFX_IMPL_XINTERFACE_2(SfxStandaloneDocumentInfoObject,SfxDocumentInfoObject,::com::sun::star::lang::XServiceInfo,::com::sun::star::document::XStandaloneDocumentInfo)1131 SFX_IMPL_XINTERFACE_2( SfxStandaloneDocumentInfoObject, SfxDocumentInfoObject, ::com::sun::star::lang::XServiceInfo, ::com::sun::star::document::XStandaloneDocumentInfo  )
1132 SFX_IMPL_XTYPEPROVIDER_10( SfxStandaloneDocumentInfoObject, ::com::sun::star::document::XDocumentInfo, ::com::sun::star::lang::XComponent,
1133     ::com::sun::star::beans::XPropertySet, ::com::sun::star::beans::XFastPropertySet, ::com::sun::star::beans::XPropertyAccess,
1134     ::com::sun::star::beans::XPropertyContainer, ::com::sun::star::util::XModifiable, ::com::sun::star::util::XModifyBroadcaster,
1135     ::com::sun::star::document::XStandaloneDocumentInfo, ::com::sun::star::lang::XServiceInfo )
1136 
1137 SFX_IMPL_XSERVICEINFO( SfxStandaloneDocumentInfoObject, "com.sun.star.document.StandaloneDocumentInfo", "com.sun.star.comp.sfx2.StandaloneDocumentInfo" )
1138 SFX_IMPL_SINGLEFACTORY( SfxStandaloneDocumentInfoObject )
1139 
1140 SfxStandaloneDocumentInfoObject::SfxStandaloneDocumentInfoObject( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
1141     : SfxDocumentInfoObject()
1142     , _xFactory( xFactory )
1143 {
1144     uno::Reference< lang::XInitialization > xDocProps(
1145         _xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1146             "com.sun.star.document.DocumentProperties"))), uno::UNO_QUERY_THROW);
1147 //    xDocProps->initialize(uno::Sequence<uno::Any>());
1148     uno::Any a;
1149     a <<= xDocProps;
1150     uno::Sequence<uno::Any> args(1);
1151     args[0] = a;
1152     initialize(args);
1153 }
1154 
1155 //-----------------------------------------------------------------------------
1156 
~SfxStandaloneDocumentInfoObject()1157 SfxStandaloneDocumentInfoObject::~SfxStandaloneDocumentInfoObject()
1158 {
1159 }
1160 
1161 //-----------------------------------------------------------------------------
1162 
GetStorage_Impl(const::rtl::OUString & rName,sal_Bool bWrite,uno::Reference<lang::XMultiServiceFactory> & xFactory)1163 uno::Reference< embed::XStorage > GetStorage_Impl( const ::rtl::OUString& rName, sal_Bool bWrite, uno::Reference < lang::XMultiServiceFactory >& xFactory )
1164 {
1165     // catch unexpected exceptions under solaris
1166     // Client code checks the returned reference but is not interested on error details.
1167     try
1168     {
1169         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1170         return ::comphelper::OStorageHelper::GetStorageFromURL(
1171                         rName,
1172                         bWrite ? embed::ElementModes::READWRITE : embed::ElementModes::READ,
1173                         xFactory );
1174     }
1175     catch(const uno::Exception&)
1176     {}
1177 
1178     return uno::Reference< embed::XStorage >();
1179 }
1180 
1181 //-----------------------------------------------------------------------------
1182 
getUserFieldCount()1183 sal_Int16 SAL_CALL SfxStandaloneDocumentInfoObject::getUserFieldCount()
1184 {
1185     return SfxDocumentInfoObject::getUserFieldCount();
1186 }
1187 
1188 //-----------------------------------------------------------------------------
1189 
getUserFieldName(sal_Int16 nIndex)1190 ::rtl::OUString SAL_CALL  SfxStandaloneDocumentInfoObject::getUserFieldName(sal_Int16 nIndex)
1191 {
1192     return SfxDocumentInfoObject::getUserFieldName(nIndex);
1193 }
1194 
1195 //-----------------------------------------------------------------------------
1196 
getUserFieldValue(sal_Int16 nIndex)1197 ::rtl::OUString SAL_CALL  SfxStandaloneDocumentInfoObject::getUserFieldValue(sal_Int16 nIndex)
1198 {
1199     return SfxDocumentInfoObject::getUserFieldValue(nIndex);
1200 }
1201 
1202 //-----------------------------------------------------------------------------
1203 
setUserFieldName(sal_Int16 nIndex,const::rtl::OUString & aName)1204 void  SAL_CALL SfxStandaloneDocumentInfoObject::setUserFieldName(sal_Int16 nIndex, const ::rtl::OUString& aName )
1205 {
1206     SfxDocumentInfoObject::setUserFieldName( nIndex, aName );
1207 }
1208 
1209 //-----------------------------------------------------------------------------
1210 
setUserFieldValue(sal_Int16 nIndex,const::rtl::OUString & aValue)1211 void SAL_CALL  SfxStandaloneDocumentInfoObject::setUserFieldValue( sal_Int16 nIndex, const ::rtl::OUString& aValue )
1212 {
1213     SfxDocumentInfoObject::setUserFieldValue( nIndex, aValue );
1214 }
1215 
1216 //-----------------------------------------------------------------------------
1217 
loadFromURL(const::rtl::OUString & aURL)1218 void SAL_CALL  SfxStandaloneDocumentInfoObject::loadFromURL(const ::rtl::OUString& aURL)
1219 {
1220     sal_Bool bOK = sal_False;
1221 
1222     ::osl::ClearableMutexGuard aGuard( _pImp->_aMutex );
1223     uno::Reference< document::XDocumentProperties > xDocProps(
1224         _xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1225             "com.sun.star.document.DocumentProperties"))), uno::UNO_QUERY_THROW);
1226 //    uno::Reference< lang::XInitialization > xInit(xDocProps, uno::UNO_QUERY_THROW);
1227 //    xInit->initialize(uno::Sequence<uno::Any>());
1228     _pImp->Reset(xDocProps);
1229     aGuard.clear();
1230 
1231     uno::Reference< embed::XStorage > xStorage = GetStorage_Impl( aURL, sal_False, _xFactory );
1232     if ( xStorage.is() )
1233     {
1234         try
1235         {
1236             uno::Sequence<beans::PropertyValue> medium(2);
1237             medium[0].Name = ::rtl::OUString::createFromAscii("DocumentBaseURL");
1238             medium[0].Value <<= aURL;
1239             medium[1].Name = ::rtl::OUString::createFromAscii("URL");
1240             medium[1].Value <<= aURL;
1241             _pImp->m_xDocProps->loadFromStorage(xStorage, medium);
1242             _pImp->Reset(_pImp->m_xDocProps);
1243             bOK = sal_True;
1244         }
1245         catch( uno::Exception& )
1246         {
1247         }
1248     }
1249     else
1250     {
1251         uno::Reference < document::XStandaloneDocumentInfo > xBinary( _xFactory->createInstance(
1252             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStandaloneDocumentInfo" ) ) ), uno::UNO_QUERY );
1253         if ( xBinary.is() )
1254         {
1255             xBinary->loadFromURL( aURL );
1256             bOK = sal_True;
1257             uno::Reference < document::XStandaloneDocumentInfo > xTarget( static_cast < document::XStandaloneDocumentInfo*> (this), uno::UNO_QUERY );
1258             Copy( xBinary, xTarget );
1259         }
1260     }
1261 
1262     if ( !bOK )
1263         throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), ERRCODE_IO_CANTREAD );
1264 }
1265 
1266 //-----------------------------------------------------------------------------
1267 
storeIntoURL(const::rtl::OUString & aURL)1268 void SAL_CALL  SfxStandaloneDocumentInfoObject::storeIntoURL(const ::rtl::OUString& aURL)
1269 {
1270     sal_Bool bOK = sal_False;
1271     uno::Reference< embed::XStorage > xStorage = GetStorage_Impl( aURL, sal_True, _xFactory );
1272     if ( xStorage.is() )
1273     {
1274         try
1275         {
1276             uno::Sequence<beans::PropertyValue> medium(2);
1277             medium[0].Name = ::rtl::OUString::createFromAscii("DocumentBaseURL");
1278             medium[0].Value <<= aURL;
1279             medium[1].Name = ::rtl::OUString::createFromAscii("URL");
1280             medium[1].Value <<= aURL;
1281 
1282             _pImp->m_xDocProps->storeToStorage(xStorage, medium);
1283             bOK = sal_True;
1284         }
1285         catch( io::IOException & )
1286         {
1287             throw;
1288         }
1289         catch( uno::RuntimeException& )
1290         {
1291             throw;
1292         }
1293         catch( uno::Exception& )
1294         {
1295         }
1296     }
1297     else
1298     {
1299         uno::Reference < document::XStandaloneDocumentInfo > xBinary( _xFactory->createInstance(
1300             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStandaloneDocumentInfo" ) ) ), uno::UNO_QUERY );
1301         if ( xBinary.is() )
1302         {
1303             Copy( this, xBinary );
1304             xBinary->storeIntoURL( aURL );
1305             bOK = sal_True;
1306         }
1307     }
1308 
1309     if ( !bOK )
1310         throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), ERRCODE_IO_CANTWRITE );
1311 }
1312