1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <unotools/historyoptions.hxx>
22 #include <unotools/configmgr.hxx>
23 #include <unotools/configitem.hxx>
24 #include <com/sun/star/uno/Any.hxx>
25 #include <com/sun/star/uno/Sequence.hxx>
31 #include <rtl/logfile.hxx>
32 #include "itemholder1.hxx"
34 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
38 #include <com/sun/star/container/XNameContainer.hpp>
40 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
42 #include <comphelper/configurationhelper.hxx>
44 #include <comphelper/processfactory.hxx>
46 using namespace ::std
;
47 using namespace ::utl
;
48 using namespace ::rtl
;
49 using namespace ::osl
;
50 using namespace ::com::sun::star::uno
;
51 using namespace ::com::sun::star::beans
;
54 static const ::sal_Int32 s_nOffsetURL
= 0;
55 static const ::sal_Int32 s_nOffsetFilter
= 1;
56 static const ::sal_Int32 s_nOffsetTitle
= 2;
57 static const ::sal_Int32 s_nOffsetPassword
= 3;
59 const char s_sCommonHistory
[] = "org.openoffice.Office.Common/History";
60 const char s_sHistories
[] = "org.openoffice.Office.Histories/Histories";
61 const char s_sPickListSize
[] = "PickListSize";
62 const char s_sURLHistorySize
[] = "Size";
63 const char s_sHelpBookmarksSize
[] = "HelpBookmarkSize";
64 const char s_sPickList
[] = "PickList";
65 const char s_sURLHistory
[] = "URLHistory";
66 const char s_sHelpBookmarks
[] = "HelpBookmarks";
67 const char s_sItemList
[] = "ItemList";
68 const char s_sOrderList
[] = "OrderList";
69 const char s_sHistoryItemRef
[] = "HistoryItemRef";
70 const char s_sFilter
[] = "Filter";
71 const char s_sTitle
[] = "Title";
72 const char s_sPassword
[] = "Password";
75 struct IMPL_THistoryItem
81 IMPL_THistoryItem( const OUString
& sNewURL
,
82 const OUString
& sNewFilter
,
83 const OUString
& sNewTitle
,
84 const OUString
& sNewPassword
)
87 sFilter
= sNewFilter
;
89 sPassword
= sNewPassword
;
92 sal_Bool
operator==( const OUString
& sSearchedURL
) const
94 return( sURL
== sSearchedURL
);
103 //*****************************************************************************************************************
104 // class SvtHistoryOptions_Impl
106 //*****************************************************************************************************************
107 class SvtHistoryOptions_Impl
110 SvtHistoryOptions_Impl();
111 ~SvtHistoryOptions_Impl();
113 sal_uInt32
GetSize( EHistoryType eHistory
);
114 void Clear( EHistoryType eHistory
);
115 Sequence
< Sequence
< PropertyValue
> > GetList( EHistoryType eHistory
);
116 void AppendItem( EHistoryType eHistory
,
117 const OUString
& sURL
,
118 const OUString
& sFilter
,
119 const OUString
& sTitle
,
120 const OUString
& sPassword
);
123 void impl_truncateList (EHistoryType eHistory
, sal_uInt32 nSize
);
126 css::uno::Reference
< css::container::XNameAccess
> m_xCfg
;
127 css::uno::Reference
< css::container::XNameAccess
> m_xCommonXCU
;
130 //*****************************************************************************************************************
132 //*****************************************************************************************************************
133 SvtHistoryOptions_Impl::SvtHistoryOptions_Impl()
137 m_xCfg
= Reference
< css::container::XNameAccess
> (
138 ::comphelper::ConfigurationHelper::openConfig(
139 ::comphelper::getProcessComponentContext(),
140 rtl::OUString(s_sHistories
),
141 ::comphelper::ConfigurationHelper::E_STANDARD
),
142 css::uno::UNO_QUERY
);
144 m_xCommonXCU
= Reference
< css::container::XNameAccess
> (
145 ::comphelper::ConfigurationHelper::openConfig(
146 ::comphelper::getProcessComponentContext(),
147 rtl::OUString(s_sCommonHistory
),
148 ::comphelper::ConfigurationHelper::E_STANDARD
),
149 css::uno::UNO_QUERY
);
151 catch(const css::uno::Exception
& ex
)
154 m_xCommonXCU
.clear();
156 SAL_WARN("unotools", "Caught unexpected: " << ex
.Message
);
160 //*****************************************************************************************************************
162 //*****************************************************************************************************************
163 SvtHistoryOptions_Impl::~SvtHistoryOptions_Impl()
167 //*****************************************************************************************************************
169 // Attention: We return the max. size of our internal lists - That is the capacity not the size!
170 //*****************************************************************************************************************
171 sal_uInt32
SvtHistoryOptions_Impl::GetSize( EHistoryType eHistory
)
173 css::uno::Reference
< css::beans::XPropertySet
> xListAccess(m_xCommonXCU
, css::uno::UNO_QUERY
);
175 if (!xListAccess
.is())
178 sal_uInt32 nSize
= 0 ;
185 xListAccess
->getPropertyValue(rtl::OUString(s_sPickListSize
)) >>= nSize
;
189 xListAccess
->getPropertyValue(rtl::OUString(s_sURLHistorySize
)) >>= nSize
;
193 xListAccess
->getPropertyValue(rtl::OUString(s_sHelpBookmarksSize
)) >>= nSize
;
200 catch(const css::uno::Exception
& ex
)
202 SAL_WARN("unotools", "Caught unexpected: " << ex
.Message
);
208 //*****************************************************************************************************************
209 void SvtHistoryOptions_Impl::impl_truncateList ( EHistoryType eHistory
, sal_uInt32 nSize
)
211 css::uno::Reference
< css::container::XNameAccess
> xList
;
212 css::uno::Reference
< css::container::XNameContainer
> xItemList
;
213 css::uno::Reference
< css::container::XNameContainer
> xOrderList
;
214 css::uno::Reference
< css::beans::XPropertySet
> xSet
;
221 m_xCfg
->getByName(rtl::OUString(s_sPickList
)) >>= xList
;
225 m_xCfg
->getByName(rtl::OUString(s_sURLHistory
)) >>= xList
;
229 m_xCfg
->getByName(rtl::OUString(s_sHelpBookmarks
)) >>= xList
;
236 // If too much items in current list ...
237 // truncate the oldest items BEFORE you set the new one.
241 xList
->getByName(rtl::OUString(s_sOrderList
)) >>= xOrderList
;
242 xList
->getByName(rtl::OUString(s_sItemList
)) >>= xItemList
;
244 const sal_uInt32 nLength
= xOrderList
->getElementNames().getLength();
247 for (sal_uInt32 i
=nLength
-1; i
>=nSize
; --i
)
249 ::rtl::OUString sTmp
;
250 const ::rtl::OUString sRemove
= ::rtl::OUString::valueOf((sal_Int32
)i
);
251 xOrderList
->getByName(sRemove
) >>= xSet
;
252 xSet
->getPropertyValue(rtl::OUString(s_sHistoryItemRef
)) >>= sTmp
;
253 xItemList
->removeByName(sTmp
);
254 xOrderList
->removeByName(sRemove
);
257 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
260 catch(const css::uno::Exception
& ex
)
262 SAL_WARN("unotools", "Caught unexpected: " << ex
.Message
);
266 //*****************************************************************************************************************
268 // Clear specified history list
269 //*****************************************************************************************************************
270 void SvtHistoryOptions_Impl::Clear( EHistoryType eHistory
)
272 css::uno::Reference
< css::container::XNameAccess
> xListAccess
;
273 css::uno::Reference
< css::container::XNameContainer
> xNode
;
274 Sequence
< ::rtl::OUString
> lOrders
;
282 m_xCfg
->getByName(rtl::OUString(s_sPickList
)) >>= xListAccess
;
288 m_xCfg
->getByName(rtl::OUString(s_sURLHistory
)) >>= xListAccess
;
294 m_xCfg
->getByName(rtl::OUString(s_sHelpBookmarks
)) >>= xListAccess
;
302 if (xListAccess
.is())
305 xListAccess
->getByName(rtl::OUString(s_sItemList
)) >>= xNode
;
306 lOrders
= xNode
->getElementNames();
307 const sal_Int32 nLength
= lOrders
.getLength();
308 for(sal_Int32 i
=0; i
<nLength
; ++i
)
309 xNode
->removeByName(lOrders
[i
]);
312 xListAccess
->getByName(rtl::OUString(s_sOrderList
)) >>= xNode
;
313 lOrders
= xNode
->getElementNames();
314 for(sal_Int32 j
=0; j
<nLength
; ++j
)
315 xNode
->removeByName(lOrders
[j
]);
317 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
320 catch(const css::uno::Exception
& ex
)
322 SAL_WARN("unotools", "Caught unexpected: " << ex
.Message
);
326 //*****************************************************************************************************************
328 // get a sequence list from the items
329 //*****************************************************************************************************************
330 Sequence
< Sequence
< PropertyValue
> > SvtHistoryOptions_Impl::GetList( EHistoryType eHistory
)
332 impl_truncateList (eHistory
, GetSize (eHistory
));
334 Sequence
< Sequence
< PropertyValue
> > seqReturn
; // Set default return value.
335 Sequence
< PropertyValue
> seqProperties( 4 );
336 Sequence
< ::rtl::OUString
> lOrders
;
338 css::uno::Reference
< css::container::XNameAccess
> xListAccess
;
339 css::uno::Reference
< css::container::XNameAccess
> xItemList
;
340 css::uno::Reference
< css::container::XNameAccess
> xOrderList
;
341 css::uno::Reference
< css::beans::XPropertySet
> xSet
;
343 seqProperties
[s_nOffsetURL
].Name
= HISTORY_PROPERTYNAME_URL
;
344 seqProperties
[s_nOffsetFilter
].Name
= HISTORY_PROPERTYNAME_FILTER
;
345 seqProperties
[s_nOffsetTitle
].Name
= HISTORY_PROPERTYNAME_TITLE
;
346 seqProperties
[s_nOffsetPassword
].Name
= HISTORY_PROPERTYNAME_PASSWORD
;
354 m_xCfg
->getByName(rtl::OUString(s_sPickList
)) >>= xListAccess
;
360 m_xCfg
->getByName(rtl::OUString(s_sURLHistory
)) >>= xListAccess
;
366 m_xCfg
->getByName(rtl::OUString(s_sHelpBookmarks
)) >>= xListAccess
;
374 if (xListAccess
.is())
376 xListAccess
->getByName(rtl::OUString(s_sItemList
)) >>= xItemList
;
377 xListAccess
->getByName(rtl::OUString(s_sOrderList
)) >>= xOrderList
;
379 const sal_Int32 nLength
= xOrderList
->getElementNames().getLength();
380 Sequence
< Sequence
< PropertyValue
> > aRet(nLength
);
381 sal_Int32 nCount
= 0;
383 for(sal_Int32 nItem
=0; nItem
<nLength
; ++nItem
)
387 ::rtl::OUString sUrl
;
388 xOrderList
->getByName(::rtl::OUString::valueOf(nItem
)) >>= xSet
;
389 xSet
->getPropertyValue(rtl::OUString(s_sHistoryItemRef
)) >>= sUrl
;
391 xItemList
->getByName(sUrl
) >>= xSet
;
392 seqProperties
[s_nOffsetURL
].Value
<<= sUrl
;
393 xSet
->getPropertyValue(rtl::OUString(s_sFilter
)) >>= seqProperties
[s_nOffsetFilter
].Value
;
394 xSet
->getPropertyValue(rtl::OUString(s_sTitle
)) >>= seqProperties
[s_nOffsetTitle
].Value
;
395 xSet
->getPropertyValue(rtl::OUString(s_sPassword
)) >>= seqProperties
[s_nOffsetPassword
].Value
;
396 aRet
[nCount
++] = seqProperties
;
398 catch(const css::uno::Exception
& ex
)
400 // <https://bugs.freedesktop.org/show_bug.cgi?id=46074>
401 // "FILEOPEN: No Recent Documents..." discusses a problem
402 // with corrupted /org.openoffice.Office/Histories/Histories
403 // configuration items; to work around that problem, simply
404 // ignore such corrupted individual items here, so that at
405 // least newly added items are successfully reported back
406 // from this function:
407 SAL_WARN("unotools", "Caught unexpected: " << ex
.Message
);
410 assert(nCount
<= nLength
);
411 aRet
.realloc(nCount
);
415 catch(const css::uno::Exception
& ex
)
417 SAL_WARN("unotools", "Caught unexpected: " << ex
.Message
);
423 //*****************************************************************************************************************
425 // implements a deque in XML
426 //*****************************************************************************************************************
427 void SvtHistoryOptions_Impl::AppendItem( EHistoryType eHistory
,
428 const OUString
& sURL
,
429 const OUString
& sFilter
,
430 const OUString
& sTitle
,
431 const OUString
& sPassword
)
433 impl_truncateList (eHistory
, GetSize (eHistory
));
435 css::uno::Reference
< css::container::XNameAccess
> xListAccess
;
436 sal_Int32 nMaxSize
= 0;
442 m_xCfg
->getByName(rtl::OUString(s_sPickList
)) >>= xListAccess
;
443 nMaxSize
= GetSize(ePICKLIST
);
448 m_xCfg
->getByName(rtl::OUString(s_sURLHistory
)) >>= xListAccess
;
449 nMaxSize
= GetSize(eHISTORY
);
454 m_xCfg
->getByName(rtl::OUString(s_sHelpBookmarks
)) >>= xListAccess
;
455 nMaxSize
= GetSize(eHELPBOOKMARKS
);
465 css::uno::Reference
< css::container::XNameContainer
> xItemList
;
466 css::uno::Reference
< css::container::XNameContainer
> xOrderList
;
467 css::uno::Reference
< css::beans::XPropertySet
> xSet
;
471 xListAccess
->getByName(rtl::OUString(s_sItemList
)) >>= xItemList
;
472 xListAccess
->getByName(rtl::OUString(s_sOrderList
)) >>= xOrderList
;
473 sal_Int32 nLength
= xOrderList
->getElementNames().getLength();
475 rtl::OUString
sHistoryItemRef(s_sHistoryItemRef
);
476 // The item to be appended is already existing!
477 if (xItemList
->hasByName(sURL
))
479 for (sal_Int32 i
=0; i
<nLength
; ++i
)
481 ::rtl::OUString sTmp
;
482 xOrderList
->getByName(::rtl::OUString::valueOf(i
)) >>= xSet
;
483 xSet
->getPropertyValue(sHistoryItemRef
) >>= sTmp
;
487 ::rtl::OUString sFind
;
488 xOrderList
->getByName( ::rtl::OUString::valueOf(i
) ) >>= xSet
;
489 xSet
->getPropertyValue(sHistoryItemRef
) >>= sFind
;
490 for (sal_Int32 j
=i
-1; j
>=0; --j
)
492 css::uno::Reference
< css::beans::XPropertySet
> xPrevSet
;
493 css::uno::Reference
< css::beans::XPropertySet
> xNextSet
;
494 xOrderList
->getByName( ::rtl::OUString::valueOf(j
+1) ) >>= xPrevSet
;
495 xOrderList
->getByName( ::rtl::OUString::valueOf(j
) ) >>= xNextSet
;
497 ::rtl::OUString sTemp
;
498 xNextSet
->getPropertyValue(sHistoryItemRef
) >>= sTemp
;
499 xPrevSet
->setPropertyValue(sHistoryItemRef
, css::uno::makeAny(sTemp
));
501 xOrderList
->getByName( ::rtl::OUString::valueOf((sal_Int32
)0) ) >>= xSet
;
502 xSet
->setPropertyValue(sHistoryItemRef
, css::uno::makeAny(sFind
));
504 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
510 // The item to be appended is not existing!
513 css::uno::Reference
< css::lang::XSingleServiceFactory
> xFac
;
514 css::uno::Reference
< css::uno::XInterface
> xInst
;
515 css::uno::Reference
< css::beans::XPropertySet
> xPrevSet
;
516 css::uno::Reference
< css::beans::XPropertySet
> xNextSet
;
518 // Append new item to OrderList.
519 if ( nLength
== nMaxSize
)
521 ::rtl::OUString sRemove
;
522 xOrderList
->getByName(::rtl::OUString::valueOf(nLength
-1)) >>= xSet
;
523 xSet
->getPropertyValue(sHistoryItemRef
) >>= sRemove
;
526 xItemList
->removeByName(sRemove
);
528 catch (css::container::NoSuchElementException
&)
530 // <https://bugs.freedesktop.org/show_bug.cgi?id=46074>
531 // "FILEOPEN: No Recent Documents..." discusses a problem
532 // with corrupted /org.openoffice.Office/Histories/Histories
533 // configuration items; to work around that problem, simply
534 // ignore such corrupted individual items here, so that at
535 // least newly added items are successfully added:
536 if (!sRemove
.isEmpty())
542 if ( nLength
!= nMaxSize
)
544 xFac
= css::uno::Reference
< css::lang::XSingleServiceFactory
>(xOrderList
, css::uno::UNO_QUERY
);
545 xInst
= xFac
->createInstance();
546 ::rtl::OUString sPush
= ::rtl::OUString::valueOf(nLength
++);
547 xOrderList
->insertByName(sPush
, css::uno::makeAny(xInst
));
549 for (sal_Int32 j
=nLength
-1; j
>0; --j
)
551 xOrderList
->getByName( ::rtl::OUString::valueOf(j
) ) >>= xPrevSet
;
552 xOrderList
->getByName( ::rtl::OUString::valueOf(j
-1) ) >>= xNextSet
;
553 ::rtl::OUString sTemp
;
554 xNextSet
->getPropertyValue(sHistoryItemRef
) >>= sTemp
;
555 xPrevSet
->setPropertyValue(sHistoryItemRef
, css::uno::makeAny(sTemp
));
557 xOrderList
->getByName( ::rtl::OUString::valueOf((sal_Int32
)0) ) >>= xSet
;
558 xSet
->setPropertyValue(sHistoryItemRef
, css::uno::makeAny(sURL
));
560 // Append the item to ItemList.
561 xFac
= css::uno::Reference
< css::lang::XSingleServiceFactory
>(xItemList
, css::uno::UNO_QUERY
);
562 xInst
= xFac
->createInstance();
563 xItemList
->insertByName(sURL
, css::uno::makeAny(xInst
));
564 xSet
= css::uno::Reference
< css::beans::XPropertySet
>(xInst
, css::uno::UNO_QUERY
);
565 xSet
->setPropertyValue(rtl::OUString(s_sFilter
), css::uno::makeAny(sFilter
));
566 xSet
->setPropertyValue(rtl::OUString(s_sTitle
), css::uno::makeAny(sTitle
));
567 xSet
->setPropertyValue(rtl::OUString(s_sPassword
), css::uno::makeAny(sPassword
));
569 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
572 catch(const css::uno::Exception
& ex
)
574 SAL_WARN("unotools", "Caught unexpected: " << ex
.Message
);
578 //*****************************************************************************************************************
579 // initialize static member
580 // DON'T DO IT IN YOUR HEADER!
581 // see definition for further informations
582 //*****************************************************************************************************************
583 SvtHistoryOptions_Impl
* SvtHistoryOptions::m_pDataContainer
= NULL
;
584 sal_Int32
SvtHistoryOptions::m_nRefCount
= 0 ;
586 //*****************************************************************************************************************
588 //*****************************************************************************************************************
589 SvtHistoryOptions::SvtHistoryOptions()
591 // Global access, must be guarded (multithreading!).
592 MutexGuard
aGuard( GetOwnStaticMutex() );
593 // Increase ouer refcount ...
595 // ... and initialize ouer data container only if it not already exist!
596 if( m_pDataContainer
== NULL
)
598 RTL_LOGFILE_CONTEXT(aLog
, "unotools ( ??? ) ::SvtHistoryOptions_Impl::ctor()");
599 m_pDataContainer
= new SvtHistoryOptions_Impl
;
601 ItemHolder1::holdConfigItem(E_HISTORYOPTIONS
);
605 //*****************************************************************************************************************
607 //*****************************************************************************************************************
608 SvtHistoryOptions::~SvtHistoryOptions()
610 // Global access, must be guarded (multithreading!)
611 MutexGuard
aGuard( GetOwnStaticMutex() );
612 // Decrease ouer refcount.
614 // If last instance was deleted ...
615 // we must destroy ouer static data container!
616 if( m_nRefCount
<= 0 )
618 delete m_pDataContainer
;
619 m_pDataContainer
= NULL
;
623 //*****************************************************************************************************************
625 //*****************************************************************************************************************
626 sal_uInt32
SvtHistoryOptions::GetSize( EHistoryType eHistory
) const
628 MutexGuard
aGuard( GetOwnStaticMutex() );
629 return m_pDataContainer
->GetSize( eHistory
);
632 //*****************************************************************************************************************
634 //*****************************************************************************************************************
635 void SvtHistoryOptions::Clear( EHistoryType eHistory
)
637 MutexGuard
aGuard( GetOwnStaticMutex() );
638 m_pDataContainer
->Clear( eHistory
);
641 //*****************************************************************************************************************
643 //*****************************************************************************************************************
644 Sequence
< Sequence
< PropertyValue
> > SvtHistoryOptions::GetList( EHistoryType eHistory
) const
646 MutexGuard
aGuard( GetOwnStaticMutex() );
647 return m_pDataContainer
->GetList( eHistory
);
650 //*****************************************************************************************************************
652 //*****************************************************************************************************************
653 void SvtHistoryOptions::AppendItem( EHistoryType eHistory
,
654 const OUString
& sURL
,
655 const OUString
& sFilter
,
656 const OUString
& sTitle
,
657 const OUString
& sPassword
)
659 MutexGuard
aGuard( GetOwnStaticMutex() );
660 m_pDataContainer
->AppendItem( eHistory
, sURL
, sFilter
, sTitle
, sPassword
);
665 class theHistoryOptionsMutex
: public rtl::Static
<osl::Mutex
, theHistoryOptionsMutex
>{};
668 //*****************************************************************************************************************
670 //*****************************************************************************************************************
671 Mutex
& SvtHistoryOptions::GetOwnStaticMutex()
673 return theHistoryOptionsMutex::get();
676 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */