1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_unotools.hxx"
30 #ifndef GCC
31 #endif
32 
33 //_________________________________________________________________________________________________________________
34 // includes
35 //_________________________________________________________________________________________________________________
36 
37 #include <unotools/historyoptions.hxx>
38 #include <unotools/historyoptions_const.hxx>
39 #include <unotools/configmgr.hxx>
40 #include <unotools/configitem.hxx>
41 #include <tools/debug.hxx>
42 #include <com/sun/star/uno/Any.hxx>
43 #include <com/sun/star/uno/Sequence.hxx>
44 
45 #ifndef __SGI_STL_DEQUE
46 #include <deque>
47 #endif
48 
49 #ifndef __SGI_STL_ALGORITHM
50 #include <algorithm>
51 #endif
52 
53 #include <rtl/logfile.hxx>
54 #include "itemholder1.hxx"
55 
56 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
57 #include <com/sun/star/beans/XPropertySet.hpp>
58 #endif
59 
60 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
61 #include <com/sun/star/container/XNameAccess.hpp>
62 #endif
63 
64 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
65 #include <com/sun/star/container/XNameContainer.hpp>
66 #endif
67 
68 #ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
69 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
70 #endif
71 
72 #ifndef _COMPHELPER_CONFIGURATIONHELPER_HXX_
73 #include <comphelper/configurationhelper.hxx>
74 #endif
75 
76 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX_
77 #include <unotools/processfactory.hxx>
78 #endif
79 
80 #ifndef _SVT_LOGHELPER_HXX
81 #include <unotools/loghelper.hxx>
82 #endif
83 
84 //_________________________________________________________________________________________________________________
85 // namespaces
86 //_________________________________________________________________________________________________________________
87 
88 using namespace ::std     ;
89 using namespace ::utl     ;
90 using namespace ::rtl     ;
91 using namespace ::osl     ;
92 using namespace ::com::sun::star::uno ;
93 using namespace ::com::sun::star::beans ;
94 
95 namespace css = ::com::sun::star;
96 
97 //_________________________________________________________________________________________________________________
98 // const
99 //_________________________________________________________________________________________________________________
100 
101 namespace {
102 	static const ::sal_Int32 s_nOffsetURL               = 0;
103 	static const ::sal_Int32 s_nOffsetFilter            = 1;
104 	static const ::sal_Int32 s_nOffsetTitle             = 2;
105 	static const ::sal_Int32 s_nOffsetPassword          = 3;
106 }
107 
108 //_________________________________________________________________________________________________________________
109 // private declarations!
110 //_________________________________________________________________________________________________________________
111 
112 struct IMPL_THistoryItem
113 {
114 	IMPL_THistoryItem()
115 	{
116 	}
117 
118 	IMPL_THistoryItem( const OUString& sNewURL   ,
119 		const OUString& sNewFilter  ,
120 		const OUString& sNewTitle  ,
121 		const OUString& sNewPassword )
122 	{
123 		sURL  = sNewURL  ;
124 		sFilter  = sNewFilter ;
125 		sTitle  = sNewTitle  ;
126 		sPassword = sNewPassword ;
127 	}
128 
129 	sal_Bool operator==( const OUString& sSearchedURL )
130 	{
131 		return( sURL == sSearchedURL );
132 	}
133 
134 	OUString sURL  ;
135 	OUString sFilter  ;
136 	OUString sTitle  ;
137 	OUString sPassword ;
138 };
139 
140 //*****************************************************************************************************************
141 //  class SvtHistoryOptions_Impl
142 //  redesigned
143 //*****************************************************************************************************************
144 class SvtHistoryOptions_Impl
145 {
146 public:
147 	SvtHistoryOptions_Impl();
148 	~SvtHistoryOptions_Impl();
149 
150 	sal_uInt32 GetSize( EHistoryType eHistory );
151 	void SetSize( EHistoryType eHistory, sal_uInt32 nSize );
152 	void Clear( EHistoryType eHistory );
153 	Sequence< Sequence< PropertyValue > > GetList( EHistoryType eHistory );
154 	void                                  AppendItem(       EHistoryType eHistory ,
155 		const OUString&    sURL     ,
156 		const OUString&    sFilter  ,
157 		const OUString&    sTitle   ,
158 		const OUString&    sPassword );
159 
160 private:
161     void impl_truncateList (EHistoryType eHistory, sal_uInt32 nSize);
162 
163 private:
164 	css::uno::Reference< css::container::XNameAccess > m_xCfg;
165 	css::uno::Reference< css::container::XNameAccess > m_xCommonXCU;
166 };
167 
168 //*****************************************************************************************************************
169 //  constructor
170 //*****************************************************************************************************************
171 SvtHistoryOptions_Impl::SvtHistoryOptions_Impl()
172 {
173 	try
174 	{
175 		m_xCfg = Reference< css::container::XNameAccess > (
176 			::comphelper::ConfigurationHelper::openConfig(
177 			utl::getProcessServiceFactory(),
178 			s_sHistories,
179 			::comphelper::ConfigurationHelper::E_STANDARD),
180 			css::uno::UNO_QUERY );
181 
182 		m_xCommonXCU = Reference< css::container::XNameAccess > (
183 			::comphelper::ConfigurationHelper::openConfig(
184 			utl::getProcessServiceFactory(),
185 			s_sCommonHistory,
186 			::comphelper::ConfigurationHelper::E_STANDARD),
187 			css::uno::UNO_QUERY );
188 	}
189 	catch(const css::uno::Exception& ex)
190 	{
191 		m_xCfg.clear();
192 		m_xCommonXCU.clear();
193 
194 		LogHelper::logIt(ex);
195 	}
196 }
197 
198 //*****************************************************************************************************************
199 //  destructor
200 //*****************************************************************************************************************
201 SvtHistoryOptions_Impl::~SvtHistoryOptions_Impl()
202 {
203 }
204 
205 //*****************************************************************************************************************
206 //  public method
207 //  Attention: We return the max. size of our internal lists - That is the capacity not the size!
208 //*****************************************************************************************************************
209 sal_uInt32 SvtHistoryOptions_Impl::GetSize( EHistoryType eHistory )
210 {
211 	sal_uInt32                                       nSize = 0  ;
212 	css::uno::Reference< css::beans::XPropertySet >  xListAccess(m_xCommonXCU, css::uno::UNO_QUERY);
213 
214 	try
215 	{
216 		switch( eHistory )
217 		{
218 		case ePICKLIST:
219 			xListAccess->getPropertyValue(s_sPickListSize) >>= nSize;
220 			break;
221 
222 		case eHISTORY:
223 			xListAccess->getPropertyValue(s_sURLHistorySize) >>= nSize;
224 			break;
225 
226 		case eHELPBOOKMARKS:
227 			xListAccess->getPropertyValue(s_sHelpBookmarksSize) >>= nSize;
228 			break;
229 
230 		default:
231 			break;
232 		}
233 	}
234 	catch(const css::uno::Exception& ex)
235 	{
236 		LogHelper::logIt(ex);
237 	}
238 
239 	return nSize;
240 }
241 
242 //*****************************************************************************************************************
243 //  public method
244 //  Attention: We return the max. size of our internal lists - That is the capacity not the size!
245 //*****************************************************************************************************************
246 void SvtHistoryOptions_Impl::SetSize( EHistoryType eHistory, sal_uInt32 nSize )
247 {
248 	css::uno::Reference< css::beans::XPropertySet > xListAccess(m_xCommonXCU, css::uno::UNO_QUERY);
249     if (! xListAccess.is ())
250         return;
251 
252 	try
253 	{
254 		switch( eHistory )
255 		{
256 		case ePICKLIST:
257 			if(nSize!=GetSize(ePICKLIST))
258 			{
259 				xListAccess->setPropertyValue(s_sPickListSize, css::uno::makeAny(nSize));
260 				::comphelper::ConfigurationHelper::flush(m_xCommonXCU);
261 			}
262 			break;
263 
264 		case eHISTORY:
265 			if(nSize!=GetSize(eHISTORY))
266 			{
267 				xListAccess->setPropertyValue(s_sURLHistorySize, css::uno::makeAny(nSize));
268 				::comphelper::ConfigurationHelper::flush(m_xCommonXCU);
269 			}
270 			break;
271 
272 		case eHELPBOOKMARKS:
273 			if(nSize!=GetSize(eHELPBOOKMARKS))
274 			{
275 				xListAccess->setPropertyValue(s_sHelpBookmarksSize, css::uno::makeAny(nSize));
276 				::comphelper::ConfigurationHelper::flush(m_xCommonXCU);
277 			}
278 			break;
279 
280 		default:
281 			break;
282 		}
283 
284         impl_truncateList (eHistory, nSize);
285 	}
286 	catch(const css::uno::Exception& ex)
287 	{
288 		LogHelper::logIt(ex);
289 	}
290 }
291 
292 //*****************************************************************************************************************
293 void SvtHistoryOptions_Impl::impl_truncateList ( EHistoryType eHistory, sal_uInt32 nSize )
294 {
295 	css::uno::Reference< css::container::XNameAccess >    xList;
296 	css::uno::Reference< css::container::XNameContainer > xItemList;
297 	css::uno::Reference< css::container::XNameContainer > xOrderList;
298 	css::uno::Reference< css::beans::XPropertySet >       xSet;
299 
300 	try
301 	{
302 		switch( eHistory )
303 		{
304 		case ePICKLIST:
305             m_xCfg->getByName(s_sPickList) >>= xList;
306 			break;
307 
308 		case eHISTORY:
309             m_xCfg->getByName(s_sURLHistory) >>= xList;
310 			break;
311 
312 		case eHELPBOOKMARKS:
313             m_xCfg->getByName(s_sHelpBookmarks) >>= xList;
314 			break;
315 
316 		default:
317 			break;
318 		}
319 
320 		// If too much items in current list ...
321 		// truncate the oldest items BEFORE you set the new one.
322 		if ( ! xList.is())
323             return;
324 
325         xList->getByName(s_sOrderList) >>= xOrderList;
326         xList->getByName(s_sItemList)  >>= xItemList;
327 
328         const sal_uInt32 nLength = xOrderList->getElementNames().getLength();
329         if (nSize < nLength)
330         {
331             for (sal_uInt32 i=nLength-1; i>=nSize; --i)
332             {
333                 ::rtl::OUString sTmp;
334                 const ::rtl::OUString sRemove = ::rtl::OUString::valueOf((sal_Int32)i);
335                 xOrderList->getByName(sRemove) >>= xSet;
336                 xSet->getPropertyValue(s_sHistoryItemRef) >>= sTmp;
337                 xItemList->removeByName(sTmp);
338                 xOrderList->removeByName(sRemove);
339             }
340 
341             ::comphelper::ConfigurationHelper::flush(m_xCfg);
342         }
343 	}
344 	catch(const css::uno::Exception& ex)
345 	{
346 		LogHelper::logIt(ex);
347 	}
348 }
349 
350 //*****************************************************************************************************************
351 //  public method
352 //  Clear specified history list
353 //*****************************************************************************************************************
354 void SvtHistoryOptions_Impl::Clear( EHistoryType eHistory )
355 {
356 	css::uno::Reference< css::container::XNameAccess >    xListAccess;
357 	css::uno::Reference< css::container::XNameContainer > xNode;
358 	Sequence< ::rtl::OUString >                           lOrders;
359 
360 	try
361 	{
362 		switch( eHistory )
363 		{
364 		case ePICKLIST:
365 			{
366 				m_xCfg->getByName(s_sPickList) >>= xListAccess;
367 				break;
368 			}
369 
370 		case eHISTORY:
371 			{
372 				m_xCfg->getByName(s_sURLHistory) >>= xListAccess;
373 				break;
374 			}
375 
376 		case eHELPBOOKMARKS:
377 			{
378 				m_xCfg->getByName(s_sHelpBookmarks) >>= xListAccess;
379 				break;
380 			}
381 
382 		default:
383 			break;
384 		}
385 
386 		if (xListAccess.is())
387 		{
388 			// clear ItemList
389 			xListAccess->getByName(s_sItemList)  >>= xNode  ;
390 			lOrders = xNode->getElementNames();
391 			const sal_Int32 nLength = lOrders.getLength();
392 			for(sal_Int32 i=0; i<nLength; ++i)
393 				xNode->removeByName(lOrders[i]);
394 
395 			// clear OrderList
396 			xListAccess->getByName(s_sOrderList) >>= xNode ;
397 			lOrders = xNode->getElementNames();
398 			for(sal_Int32 j=0; j<nLength; ++j)
399 				xNode->removeByName(lOrders[j]);
400 
401 			::comphelper::ConfigurationHelper::flush(m_xCfg);
402 		}
403 	}
404 	catch(const css::uno::Exception& ex)
405 	{
406 		LogHelper::logIt(ex);
407 	}
408 }
409 
410 //*****************************************************************************************************************
411 //  public method
412 //  get a sequence list from the items
413 //*****************************************************************************************************************
414 Sequence< Sequence< PropertyValue > > SvtHistoryOptions_Impl::GetList( EHistoryType eHistory )
415 {
416     impl_truncateList (eHistory, GetSize (eHistory));
417 
418 	Sequence< Sequence< PropertyValue > > seqReturn; // Set default return value.
419 	Sequence< PropertyValue >             seqProperties( 4 );
420 	Sequence< ::rtl::OUString >           lOrders;
421 
422 	css::uno::Reference< css::container::XNameAccess > xListAccess;
423 	css::uno::Reference< css::container::XNameAccess > xItemList;
424 	css::uno::Reference< css::container::XNameAccess > xOrderList;
425 	css::uno::Reference< css::beans::XPropertySet >    xSet;
426 
427 	seqProperties[s_nOffsetURL       ].Name = HISTORY_PROPERTYNAME_URL;
428 	seqProperties[s_nOffsetFilter    ].Name = HISTORY_PROPERTYNAME_FILTER;
429 	seqProperties[s_nOffsetTitle     ].Name = HISTORY_PROPERTYNAME_TITLE;
430 	seqProperties[s_nOffsetPassword  ].Name = HISTORY_PROPERTYNAME_PASSWORD;
431 
432 	try
433 	{
434 		switch( eHistory )
435 		{
436 		case ePICKLIST:
437 			{
438 				m_xCfg->getByName(s_sPickList) >>= xListAccess;
439 				break;
440 			}
441 
442 		case eHISTORY:
443 			{
444 				m_xCfg->getByName(s_sURLHistory) >>= xListAccess;
445 				break;
446 			}
447 
448 		case eHELPBOOKMARKS:
449 			{
450 				m_xCfg->getByName(s_sHelpBookmarks) >>= xListAccess;
451 				break;
452 			}
453 
454 		default:
455 			break;
456 		}
457 
458 		if (xListAccess.is())
459 		{
460 			xListAccess->getByName(s_sItemList)  >>= xItemList;
461 			xListAccess->getByName(s_sOrderList) >>= xOrderList;
462 
463 			const sal_Int32 nLength = xOrderList->getElementNames().getLength();
464 			Sequence< Sequence< PropertyValue > > aRet(nLength);
465 
466 			for(sal_Int32 nItem=0; nItem<nLength; ++nItem)
467 			{
468 				::rtl::OUString sUrl;
469 				xOrderList->getByName(::rtl::OUString::valueOf(nItem)) >>= xSet;
470 				xSet->getPropertyValue(s_sHistoryItemRef) >>= sUrl;
471 
472 				xItemList->getByName(sUrl) >>= xSet;
473 				seqProperties[s_nOffsetURL  ].Value <<= sUrl;
474 				xSet->getPropertyValue(s_sFilter)   >>= seqProperties[s_nOffsetFilter   ].Value;
475 				xSet->getPropertyValue(s_sTitle)    >>= seqProperties[s_nOffsetTitle    ].Value;
476 				xSet->getPropertyValue(s_sPassword) >>= seqProperties[s_nOffsetPassword ].Value;
477 				aRet[nItem] = seqProperties;
478 			}
479 			seqReturn = aRet;
480 		}
481 	}
482 	catch(const css::uno::Exception& ex)
483 	{
484 		LogHelper::logIt(ex);
485 	}
486 
487 	return seqReturn;
488 }
489 
490 //*****************************************************************************************************************
491 //  public method
492 //  implements a deque in XML
493 //*****************************************************************************************************************
494 void SvtHistoryOptions_Impl::AppendItem(       EHistoryType eHistory ,
495 										const OUString& sURL        ,
496 										const OUString& sFilter     ,
497 										const OUString& sTitle      ,
498 										const OUString& sPassword   )
499 {
500     impl_truncateList (eHistory, GetSize (eHistory));
501 
502 	css::uno::Reference< css::container::XNameAccess > xListAccess;
503 	sal_Int32             nMaxSize = 0;
504 
505 	switch(eHistory)
506 	{
507 	case ePICKLIST:
508 		{
509 			m_xCfg->getByName(s_sPickList) >>= xListAccess;
510 			nMaxSize = GetSize(ePICKLIST);
511 		}
512 		break;
513 	case eHISTORY:
514 		{
515 			m_xCfg->getByName(s_sURLHistory) >>= xListAccess;
516 			nMaxSize = GetSize(eHISTORY);
517 		}
518 		break;
519 	case eHELPBOOKMARKS:
520 		{
521 			m_xCfg->getByName(s_sHelpBookmarks) >>= xListAccess;
522 			nMaxSize = GetSize(eHELPBOOKMARKS);
523 		}
524 		break;
525 	default:
526 		break;
527 	}
528 
529 	if (nMaxSize==0)
530 		return;
531 
532 	css::uno::Reference< css::container::XNameContainer > xItemList;
533 	css::uno::Reference< css::container::XNameContainer > xOrderList;
534 	css::uno::Reference< css::beans::XPropertySet >       xSet;
535 
536 	try
537 	{
538 		xListAccess->getByName(s_sItemList)  >>= xItemList;
539 		xListAccess->getByName(s_sOrderList) >>= xOrderList;
540 		sal_Int32 nLength = xOrderList->getElementNames().getLength();
541 
542 		// The item to be appended is already existing!
543 		if (xItemList->hasByName(sURL))
544 		{
545 			for (sal_Int32 i=0; i<nLength; ++i)
546 			{
547 				::rtl::OUString sTmp;
548 				xOrderList->getByName(::rtl::OUString::valueOf(i)) >>= xSet;
549 				xSet->getPropertyValue(s_sHistoryItemRef) >>= sTmp;
550 
551 				if(sURL == sTmp)
552 				{
553 					::rtl::OUString sFind;
554 					xOrderList->getByName( ::rtl::OUString::valueOf(i) ) >>= xSet;
555 					xSet->getPropertyValue(s_sHistoryItemRef) >>= sFind;
556 					for (sal_Int32 j=i-1; j>=0; --j)
557 					{
558 						css::uno::Reference< css::beans::XPropertySet > xPrevSet;
559 						css::uno::Reference< css::beans::XPropertySet > xNextSet;
560 						xOrderList->getByName( ::rtl::OUString::valueOf(j+1) )   >>= xPrevSet;
561 						xOrderList->getByName( ::rtl::OUString::valueOf(j) )     >>= xNextSet;
562 
563 						::rtl::OUString sTemp;
564 						xNextSet->getPropertyValue(s_sHistoryItemRef) >>= sTemp;
565 						xPrevSet->setPropertyValue(s_sHistoryItemRef, css::uno::makeAny(sTemp));
566 					}
567 					xOrderList->getByName( ::rtl::OUString::valueOf((sal_Int32)0) ) >>= xSet;
568 					xSet->setPropertyValue(s_sHistoryItemRef, css::uno::makeAny(sFind));
569 
570 					::comphelper::ConfigurationHelper::flush(m_xCfg);
571 					break;
572 				}
573 			}
574 		}
575 
576 		// The item to be appended is not existing!
577 		else
578 		{
579 			css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
580 			css::uno::Reference< css::uno::XInterface >             xInst;
581 			css::uno::Reference< css::beans::XPropertySet > xPrevSet;
582 			css::uno::Reference< css::beans::XPropertySet > xNextSet;
583 
584 			// Append new item to OrderList.
585 			if ( nLength == nMaxSize )
586 			{
587 				::rtl::OUString sRemove;
588 				xOrderList->getByName(::rtl::OUString::valueOf(nLength-1)) >>= xSet;
589 				xSet->getPropertyValue(s_sHistoryItemRef) >>= sRemove;
590 				xItemList->removeByName(sRemove);
591 			}
592 			if ( nLength != nMaxSize )
593 			{
594 				xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xOrderList, css::uno::UNO_QUERY);
595 				xInst = xFac->createInstance();
596 				::rtl::OUString sPush = ::rtl::OUString::valueOf(nLength++);
597 				xOrderList->insertByName(sPush, css::uno::makeAny(xInst));
598 			}
599 			for (sal_Int32 j=nLength-1; j>0; --j)
600 			{
601 				xOrderList->getByName( ::rtl::OUString::valueOf(j) )   >>= xPrevSet;
602 				xOrderList->getByName( ::rtl::OUString::valueOf(j-1) ) >>= xNextSet;
603 				::rtl::OUString sTemp;
604 				xNextSet->getPropertyValue(s_sHistoryItemRef) >>= sTemp;
605 				xPrevSet->setPropertyValue(s_sHistoryItemRef, css::uno::makeAny(sTemp));
606 			}
607 			xOrderList->getByName( ::rtl::OUString::valueOf((sal_Int32)0) ) >>= xSet;
608 			xSet->setPropertyValue(s_sHistoryItemRef, css::uno::makeAny(sURL));
609 
610 			// Append the item to ItemList.
611 			xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xItemList, css::uno::UNO_QUERY);
612 			xInst = xFac->createInstance();
613 			xItemList->insertByName(sURL, css::uno::makeAny(xInst));
614 			xSet = css::uno::Reference< css::beans::XPropertySet >(xInst, css::uno::UNO_QUERY);
615 			xSet->setPropertyValue(s_sFilter, css::uno::makeAny(sFilter));
616 			xSet->setPropertyValue(s_sTitle, css::uno::makeAny(sTitle));
617 			xSet->setPropertyValue(s_sPassword, css::uno::makeAny(sPassword));
618 
619 			::comphelper::ConfigurationHelper::flush(m_xCfg);
620 		}
621 	}
622 	catch(const css::uno::Exception& ex)
623 	{
624 		LogHelper::logIt(ex);
625 	}
626 }
627 
628 //*****************************************************************************************************************
629 // initialize static member
630 // DON'T DO IT IN YOUR HEADER!
631 // see definition for further informations
632 //*****************************************************************************************************************
633 SvtHistoryOptions_Impl*  SvtHistoryOptions::m_pDataContainer = NULL ;
634 sal_Int32     SvtHistoryOptions::m_nRefCount  = 0  ;
635 
636 //*****************************************************************************************************************
637 // constructor
638 //*****************************************************************************************************************
639 SvtHistoryOptions::SvtHistoryOptions()
640 {
641 	// Global access, must be guarded (multithreading!).
642 	MutexGuard aGuard( GetOwnStaticMutex() );
643 	// Increase ouer refcount ...
644 	++m_nRefCount;
645 	// ... and initialize ouer data container only if it not already exist!
646 	if( m_pDataContainer == NULL )
647 	{
648 		RTL_LOGFILE_CONTEXT(aLog, "unotools ( ??? ) ::SvtHistoryOptions_Impl::ctor()");
649 		m_pDataContainer = new SvtHistoryOptions_Impl;
650 
651 		ItemHolder1::holdConfigItem(E_HISTORYOPTIONS);
652 	}
653 }
654 
655 //*****************************************************************************************************************
656 // destructor
657 //*****************************************************************************************************************
658 SvtHistoryOptions::~SvtHistoryOptions()
659 {
660 	// Global access, must be guarded (multithreading!)
661 	MutexGuard aGuard( GetOwnStaticMutex() );
662 	// Decrease ouer refcount.
663 	--m_nRefCount;
664 	// If last instance was deleted ...
665 	// we must destroy ouer static data container!
666 	if( m_nRefCount <= 0 )
667 	{
668 		delete m_pDataContainer;
669 		m_pDataContainer = NULL;
670 	}
671 }
672 
673 //*****************************************************************************************************************
674 // public method
675 //*****************************************************************************************************************
676 sal_uInt32 SvtHistoryOptions::GetSize( EHistoryType eHistory ) const
677 {
678 	MutexGuard aGuard( GetOwnStaticMutex() );
679 	return m_pDataContainer->GetSize( eHistory );
680 }
681 
682 //*****************************************************************************************************************
683 // public method
684 //*****************************************************************************************************************
685 void SvtHistoryOptions::SetSize( EHistoryType eHistory, sal_uInt32 nSize )
686 {
687 	MutexGuard aGuard( GetOwnStaticMutex() );
688 	m_pDataContainer->SetSize( eHistory, nSize );
689 }
690 
691 //*****************************************************************************************************************
692 // public method
693 //*****************************************************************************************************************
694 void SvtHistoryOptions::Clear( EHistoryType eHistory )
695 {
696 	MutexGuard aGuard( GetOwnStaticMutex() );
697 	m_pDataContainer->Clear( eHistory );
698 }
699 
700 //*****************************************************************************************************************
701 // public method
702 //*****************************************************************************************************************
703 Sequence< Sequence< PropertyValue > > SvtHistoryOptions::GetList( EHistoryType eHistory ) const
704 {
705 	MutexGuard aGuard( GetOwnStaticMutex() );
706 	return m_pDataContainer->GetList( eHistory );
707 }
708 
709 //*****************************************************************************************************************
710 // public method
711 //*****************************************************************************************************************
712 void SvtHistoryOptions::AppendItem(   EHistoryType eHistory ,
713 								   const OUString&  sURL  ,
714 								   const OUString&  sFilter  ,
715 								   const OUString&  sTitle  ,
716 								   const OUString&  sPassword )
717 {
718 	MutexGuard aGuard( GetOwnStaticMutex() );
719 	m_pDataContainer->AppendItem( eHistory, sURL, sFilter, sTitle, sPassword );
720 }
721 
722 //*****************************************************************************************************************
723 // private method
724 //*****************************************************************************************************************
725 Mutex& SvtHistoryOptions::GetOwnStaticMutex()
726 {
727 	// Initialize static mutex only for one time!
728 	static Mutex* pMutex = NULL;
729 	// If these method first called (Mutex not already exist!) ...
730 	if( pMutex == NULL )
731 	{
732 		// ... we must create a new one. Protect follow code with the global mutex -
733 		// It must be - we create a static variable!
734 		MutexGuard aGuard( Mutex::getGlobalMutex() );
735 		// We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
736 		if( pMutex == NULL )
737 		{
738 			// Create the new mutex and set it for return on static variable.
739 			static Mutex aMutex;
740 			pMutex = &aMutex;
741 		}
742 	}
743 	// Return new created or already existing mutex object.
744 	return *pMutex;
745 }
746