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