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