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 #include "unotools/configmgr.hxx"
31 #include "unotools/configitem.hxx"
32 #include "unotools/configpathes.hxx"
33 #include <unotools/processfactory.hxx>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
37 #include <com/sun/star/container/XNameContainer.hpp>
38 #include <com/sun/star/beans/PropertyValue.hpp>
39 #include <osl/diagnose.h>
40 #include <rtl/bootstrap.hxx>
41 #include <rtl/instance.hxx>
42 #if OSL_DEBUG_LEVEL > 0
43 #include <rtl/strbuf.hxx>
44 #endif
45 
46 #include <list>
47 
48 //-----------------------------------------------------------------------------
49 
50 using namespace utl;
51 using namespace rtl;
52 using namespace com::sun::star::uno;
53 using namespace com::sun::star::lang;
54 using namespace com::sun::star::beans;
55 using namespace com::sun::star::container;
56 
57 #define C2U(cChar) OUString::createFromAscii(cChar)
58 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
59 
60 //-----------------------------------------------------------------------------
61 const char* cConfigBaseURL = "/org.openoffice.";
62 //const char* cConfigBaseURL = "/com.sun.star.";
63 const char* cAccessSrvc = "com.sun.star.configuration.ConfigurationUpdateAccess";
64 
65 namespace
66 {
67     struct BrandName
68         : public rtl::Static< ::rtl::OUString, BrandName > {};
69     struct ProductVersion
70         : public rtl::Static< ::rtl::OUString, ProductVersion > {};
71     struct AboutBoxProductVersion
72         : public rtl::Static< ::rtl::OUString, AboutBoxProductVersion > {};
73     struct OOOVendor
74         : public rtl::Static< ::rtl::OUString, OOOVendor > {};
75     struct ProductExtension
76         : public rtl::Static< ::rtl::OUString, ProductExtension > {};
77     struct XMLFileFormatName
78         : public rtl::Static< ::rtl::OUString, XMLFileFormatName > {};
79     struct XMLFileFormatVersion
80         : public rtl::Static< ::rtl::OUString, XMLFileFormatVersion > {};
81     struct WriterCompatibilityVersionOOo11
82         : public rtl::Static< ::rtl::OUString, WriterCompatibilityVersionOOo11 > {};
83     struct OpenSourceContext : public rtl::StaticWithInit< sal_Int32, OpenSourceContext >
84     {
85         sal_Int32 operator() () { return sal_Int32( -1 ); }
86     };
87 
88 }
89 
90 //-----------------------------------------------------------------------------
91 struct ConfigItemListEntry_Impl
92 {
93 	ConfigItem* 				pConfigItem;
94 
95 	ConfigItemListEntry_Impl(ConfigItem* 	pItem ) :
96 		pConfigItem(pItem){}
97 };
98 typedef std::list<ConfigItemListEntry_Impl> ConfigItemList;
99 struct utl::ConfigMgr_Impl
100 {
101 	ConfigItemList 							aItemList;
102 };
103 
104 /* -----------------------------28.08.00 15:35--------------------------------
105 
106  ---------------------------------------------------------------------------*/
107 ConfigManager::ConfigManager() :
108 	pMgrImpl(new utl::ConfigMgr_Impl)
109 {
110 	GetConfigurationProvider(); // attempt to create the provider early
111 }
112 /* -----------------------------17.11.00 13:51--------------------------------
113 
114  ---------------------------------------------------------------------------*/
115 ConfigManager::ConfigManager(Reference< XMultiServiceFactory > xConfigProv) :
116 	xConfigurationProvider(xConfigProv),
117 	pMgrImpl(new utl::ConfigMgr_Impl)
118 {
119 }
120 /* -----------------------------28.08.00 15:35--------------------------------
121 
122  ---------------------------------------------------------------------------*/
123 ConfigManager::~ConfigManager()
124 {
125 	//check list content -> should be empty!
126 	OSL_ENSURE(pMgrImpl->aItemList.empty(), "some ConfigItems are still alive");
127 	if(!pMgrImpl->aItemList.empty())
128 	{
129 		ConfigItemList::iterator aListIter;
130 		for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter)
131 		{
132 			ConfigItemListEntry_Impl& rEntry = *aListIter;
133 			rEntry.pConfigItem->ReleaseConfigMgr();
134 		}
135 		pMgrImpl->aItemList.erase(pMgrImpl->aItemList.begin(), pMgrImpl->aItemList.end());
136 	}
137 	delete pMgrImpl;
138 
139 }
140 /* -----------------------------28.08.00 16:17--------------------------------
141 
142  ---------------------------------------------------------------------------*/
143 Reference< XMultiServiceFactory > ConfigManager::GetConfigurationProvider()
144 {
145 	if(!xConfigurationProvider.is())
146 	{
147 		Reference< XMultiServiceFactory > xMSF = ::utl::getProcessServiceFactory();
148 		if ( xMSF.is() )
149 		{
150 			try
151 			{
152 				xConfigurationProvider = Reference< XMultiServiceFactory >
153 					(xMSF->createInstance(
154 						C2U("com.sun.star.configuration.ConfigurationProvider")),
155 					 UNO_QUERY);
156 			}
157 #ifdef DBG_UTIL
158 	catch(Exception& rEx)
159 	{
160         static sal_Bool bMessage = sal_True;
161         if(bMessage)
162         {
163             bMessage = sal_False;
164             OString sMsg("CreateInstance with arguments exception: ");
165             sMsg += OString(rEx.Message.getStr(),
166                         rEx.Message.getLength(),
167                         RTL_TEXTENCODING_ASCII_US);
168             OSL_ENSURE(sal_False, sMsg.getStr());
169         }
170 	}
171 #else
172 	catch(Exception&){}
173 #endif
174 		}
175 	}
176 	return xConfigurationProvider;
177 }
178 /* -----------------------------03.12.02 -------------------------------------
179 
180  ---------------------------------------------------------------------------*/
181 namespace
182 {
183     // helper to achieve exception - safe registration of a ConfigItem under construction
184     class RegisterConfigItemHelper // : Noncopyable
185     {
186         utl::ConfigManager & rCfgMgr;
187         utl::ConfigItem* pCfgItem;
188     public:
189         RegisterConfigItemHelper(utl::ConfigManager & rMgr, utl::ConfigItem& rCfgItem)
190         : rCfgMgr(rMgr)
191         , pCfgItem(&rCfgItem)
192         {
193             rCfgMgr.RegisterConfigItem(rCfgItem);
194         }
195 
196         ~RegisterConfigItemHelper()
197         {
198             if (pCfgItem) rCfgMgr.RemoveConfigItem(*pCfgItem);
199         }
200 
201         void keep() { pCfgItem = 0; }
202     };
203 }
204 /* -----------------------------12.12.00 17:19--------------------------------
205 
206  ---------------------------------------------------------------------------*/
207 Reference< XMultiServiceFactory > ConfigManager::GetLocalConfigurationProvider()
208 {
209 	return GetConfigurationProvider();
210 }
211 /* -----------------------------29.08.00 12:35--------------------------------
212 
213  ---------------------------------------------------------------------------*/
214 Reference< XHierarchicalNameAccess > ConfigManager::AddConfigItem(utl::ConfigItem& rCfgItem)
215 {
216     RegisterConfigItemHelper registeredItem(*this,rCfgItem);
217     Reference< XHierarchicalNameAccess > xTree = AcquireTree(rCfgItem);
218     registeredItem.keep();
219     return xTree;
220 }
221 /* -----------------------------21.06.01 12:20--------------------------------
222 
223  ---------------------------------------------------------------------------*/
224 void    ConfigManager::RegisterConfigItem(utl::ConfigItem& rCfgItem)
225 {
226     ConfigItemList::iterator aListIter = pMgrImpl->aItemList.begin();
227 #ifdef DBG_UTIL
228 	for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter)
229 	{
230 		ConfigItemListEntry_Impl& rEntry = *aListIter;
231 		if(rEntry.pConfigItem == &rCfgItem)
232             OSL_ENSURE(sal_False, "RegisterConfigItem: already inserted!");
233 	}
234 #endif
235     pMgrImpl->aItemList.insert(aListIter, ConfigItemListEntry_Impl(&rCfgItem));
236 }
237 /* -----------------------------21.06.01 12:20--------------------------------
238 
239  ---------------------------------------------------------------------------*/
240 Reference< XHierarchicalNameAccess> ConfigManager::AcquireTree(utl::ConfigItem& rCfgItem)
241 {
242     ConfigItemList::iterator aListIter = pMgrImpl->aItemList.begin();
243 #ifdef DBG_UTIL
244     sal_Bool bFound = sal_False;
245     for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter)
246 	{
247 		ConfigItemListEntry_Impl& rEntry = *aListIter;
248 		if(rEntry.pConfigItem == &rCfgItem)
249         {
250             bFound = sal_True;
251             break;
252         }
253     }
254     OSL_ENSURE(bFound, "AcquireTree: ConfigItem unknown!");
255 #endif
256 	OUString sPath = C2U(cConfigBaseURL);
257 	sPath += rCfgItem.GetSubTreeName();
258     Sequence< Any > aArgs(2);
259     Any* pArgs = aArgs.getArray();
260 	PropertyValue aPath;
261 	aPath.Name = C2U("nodepath");
262 	aPath.Value <<= sPath;
263     pArgs[0] <<= aPath;
264     sal_Bool bLazy = 0 != (rCfgItem.GetMode()&CONFIG_MODE_DELAYED_UPDATE);
265     PropertyValue aUpdate;
266     aUpdate.Name = C2U("lazywrite");
267     aUpdate.Value.setValue(&bLazy, ::getBooleanCppuType());
268     pArgs[1] <<= aUpdate;
269 
270     // Initialize item with support for reading/writing more then one locales at same time!
271 	// It's neccessary for creation of a complete configuration entry without changing office locale
272 	// at runtime.
273     if((rCfgItem.GetMode() & CONFIG_MODE_ALL_LOCALES) == CONFIG_MODE_ALL_LOCALES)
274 	{
275         sal_Int32 nCount = aArgs.getLength();
276         aArgs.realloc(nCount+1);
277 
278         PropertyValue aAllLocale;
279         aAllLocale.Name  =   C2U("locale");
280         aAllLocale.Value <<= C2U("*"     );
281         aArgs[nCount]    <<= aAllLocale;
282 	}
283 
284 	Reference< XMultiServiceFactory > xCfgProvider = GetConfigurationProvider();
285 	Reference< XInterface > xIFace;
286 	if(xCfgProvider.is())
287 	{
288 		try
289 		{
290 			xIFace = xCfgProvider->createInstanceWithArguments(
291 					C2U(cAccessSrvc),
292 					aArgs);
293 		}
294 		catch(Exception& rEx)
295 		{
296             if (CONFIG_MODE_PROPAGATE_ERRORS & rCfgItem.GetMode())
297             {
298                 OSL_TRACE("ConfigItem: Propagating creation error: %s\n",
299                             OUStringToOString(rEx.Message,RTL_TEXTENCODING_ASCII_US).getStr());
300 
301                 throw;
302             }
303 #ifdef DBG_UTIL
304             if(0 == (CONFIG_MODE_IGNORE_ERRORS & rCfgItem.GetMode()))
305             {
306                 OString sMsg("CreateInstance exception: ");
307                 sMsg += OString(rEx.Message.getStr(),
308                             rEx.Message.getLength(),
309                             RTL_TEXTENCODING_ASCII_US);
310                 OSL_ENSURE(sal_False, sMsg.getStr());
311             }
312 #endif
313 		}
314     }
315 	return Reference<XHierarchicalNameAccess>(xIFace, UNO_QUERY);
316 }
317 /* -----------------------------29.08.00 12:35--------------------------------
318 
319  ---------------------------------------------------------------------------*/
320 void ConfigManager::RemoveConfigItem(utl::ConfigItem& rCfgItem)
321 {
322 	if( !pMgrImpl->aItemList.empty() )
323 	{
324 		ConfigItemList::iterator aListIter = pMgrImpl->aItemList.begin();
325 		for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter)
326 		{
327 			ConfigItemListEntry_Impl& rEntry = *aListIter;
328 			if(rEntry.pConfigItem == &rCfgItem)
329 			{
330 				pMgrImpl->aItemList.erase(aListIter);
331 				break;
332 			}
333 		}
334 	}
335 }
336 /* -----------------------------30.08.00 15:04--------------------------------
337 
338  ---------------------------------------------------------------------------*/
339 void ConfigManager::StoreConfigItems()
340 {
341 	if(!pMgrImpl->aItemList.empty())
342 	{
343 		ConfigItemList::iterator aListIter = pMgrImpl->aItemList.begin();
344 		for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter)
345 		{
346 			ConfigItemListEntry_Impl& rEntry = *aListIter;
347 			if(rEntry.pConfigItem->IsModified())
348             {
349 				rEntry.pConfigItem->Commit();
350                 rEntry.pConfigItem->ClearModified();
351             }
352 		}
353 	}
354 }
355 /* -----------------------------07.09.00 11:06--------------------------------
356 
357  ---------------------------------------------------------------------------*/
358 struct theConfigManager : public rtl::Static<ConfigManager, theConfigManager> {};
359 
360 ConfigManager* ConfigManager::GetConfigManager()
361 {
362     return &theConfigManager::get();
363 }
364 /* -----------------------------08.09.00 13:22--------------------------------
365 
366  ---------------------------------------------------------------------------*/
367 rtl::OUString ConfigManager::GetConfigBaseURL()
368 {
369 	return C2U(cConfigBaseURL);
370 }
371 /* -----------------------------25.09.00 16:34--------------------------------
372 
373  ---------------------------------------------------------------------------*/
374 Any ConfigManager::GetDirectConfigProperty(ConfigProperty eProp)
375 {
376     switch(eProp)
377     {
378         case INSTALLPATH:
379             OSL_ENSURE( false,
380                         "ConfigManager::GetDirectConfigProperty: "
381                         "INSTALLPATH no longer supported." );
382             return Any();
383         case USERINSTALLURL:
384             OSL_ENSURE( false,
385                         "ConfigManager::GetDirectConfigProperty: "
386                         "USERINSTALLURL no longer supported." );
387             return Any();
388         case OFFICEINSTALL:
389             OSL_ENSURE( false,
390                         "ConfigManager::GetDirectConfigProperty: "
391                         "OFFICEINSTALL no longer supported." );
392             return Any();
393         case OFFICEINSTALLURL:
394             OSL_ENSURE( false,
395                         "ConfigManager::GetDirectConfigProperty: "
396                         "OFFICEINSTALLURL no longer supported." );
397             return Any();
398         default:
399             break;
400     }
401 
402     Any aRet;
403     ::rtl::OUString &rBrandName = BrandName::get();
404     if ( eProp == PRODUCTNAME && rBrandName.getLength() )
405     {
406         aRet <<= rBrandName;
407         return aRet;
408     }
409 
410     rtl::OUString &rProductVersion = ProductVersion::get();
411     if ( eProp == PRODUCTVERSION && rProductVersion.getLength() )
412     {
413         aRet <<= rProductVersion;
414         return aRet;
415     }
416 
417     rtl::OUString &rAboutBoxProductVersion = AboutBoxProductVersion::get();
418     if ( eProp == ABOUTBOXPRODUCTVERSION && rAboutBoxProductVersion.getLength() )
419     {
420         aRet <<= rAboutBoxProductVersion;
421         return aRet;
422     }
423 
424     rtl::OUString &rOOOVendor = OOOVendor::get();
425     if ( eProp == OOOVENDOR && rOOOVendor.getLength() )
426     {
427         aRet <<= rOOOVendor;
428         return aRet;
429     }
430 
431 
432     rtl::OUString &rProductExtension = ProductExtension::get();
433     if ( eProp == PRODUCTEXTENSION && rProductExtension.getLength() )
434     {
435         aRet <<= rProductExtension;
436         return aRet;
437     }
438 
439     rtl::OUString &rXMLFileFormatName = XMLFileFormatName::get();
440     if ( eProp == PRODUCTXMLFILEFORMATNAME && rXMLFileFormatName.getLength() )
441     {
442         aRet <<= rXMLFileFormatName;
443         return aRet;
444     }
445 
446     rtl::OUString &rXMLFileFormatVersion = XMLFileFormatVersion::get();
447     if ( eProp == PRODUCTXMLFILEFORMATVERSION && rXMLFileFormatVersion.getLength() )
448     {
449         aRet <<= rXMLFileFormatVersion;
450         return aRet;
451     }
452 
453     sal_Int32 &rOpenSourceContext = OpenSourceContext::get();
454     if ( eProp == OPENSOURCECONTEXT && ( rOpenSourceContext >= 0 ) )
455     {
456         aRet <<= rOpenSourceContext;
457         return aRet;
458     }
459 
460     rtl::OUString &rWriterCompatibilityVersionOOo11 = WriterCompatibilityVersionOOo11::get();
461     if ( eProp == WRITERCOMPATIBILITYVERSIONOOO11 && rWriterCompatibilityVersionOOo11.getLength() )
462     {
463         aRet <<= rWriterCompatibilityVersionOOo11;
464         return aRet;
465     }
466 
467     if (eProp == PRODUCTEXTENSION) {
468         rtl::OUString name(
469             rtl::OUString(
470                 RTL_CONSTASCII_USTRINGPARAM(
471                     "${BRAND_BASE_DIR}/program/edition/edition.ini")));
472         rtl::Bootstrap::expandMacros(name);
473         if (rtl::Bootstrap(name).getFrom(
474                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EDITIONNAME")),
475                 rProductExtension))
476         {
477             return com::sun::star::uno::Any(rProductExtension);
478         }
479     }
480 
481 	OUString sPath = C2U(cConfigBaseURL);
482 	switch(eProp)
483 	{
484 		case LOCALE:						sPath += C2U("Setup/L10N"); break;
485 
486         case PRODUCTNAME:
487         case PRODUCTVERSION:
488         case PRODUCTEXTENSION:
489         case PRODUCTXMLFILEFORMATNAME :
490 		case PRODUCTXMLFILEFORMATVERSION:
491         case OPENSOURCECONTEXT:
492         case OOOVENDOR:
493         case ABOUTBOXPRODUCTVERSION:        sPath += C2U("Setup/Product"); break;
494 
495 		case DEFAULTCURRENCY:				sPath += C2U("Setup/L10N"); break;
496 
497 		case WRITERCOMPATIBILITYVERSIONOOO11:
498 			sPath += C2U("Office.Compatibility/WriterCompatibilityVersion"); break;
499         default:
500             break;
501 	}
502 	Sequence< Any > aArgs(1);
503 	aArgs[0] <<= sPath;
504 	Reference< XMultiServiceFactory > xCfgProvider = GetConfigManager()->GetConfigurationProvider();
505 	if(!xCfgProvider.is())
506 		return aRet;
507 	Reference< XInterface > xIFace;
508 	try
509 	{
510 		xIFace = xCfgProvider->createInstanceWithArguments(
511 				C2U(cAccessSrvc),
512 				aArgs);
513 
514 	}
515 	catch(Exception&){}
516 	Reference<XNameAccess> xDirectAccess(xIFace, UNO_QUERY);
517 	if(xDirectAccess.is())
518 	{
519 		OUString sProperty;
520 		switch(eProp)
521 		{
522 			case LOCALE:							sProperty = C2U("ooLocale"); break;
523             case PRODUCTNAME:						sProperty = C2U("ooName"); break;
524             case PRODUCTVERSION:					sProperty = C2U("ooSetupVersion"); break;
525             case ABOUTBOXPRODUCTVERSION: 			sProperty = C2U("ooSetupVersionAboutBox"); break;
526             case OOOVENDOR:                         sProperty = C2U("ooVendor"); break;
527             case PRODUCTEXTENSION:					sProperty = C2U("ooSetupExtension"); break;
528             case PRODUCTXMLFILEFORMATNAME:          sProperty = C2U("ooXMLFileFormatName"); break;
529             case PRODUCTXMLFILEFORMATVERSION:       sProperty = C2U("ooXMLFileFormatVersion"); break;
530             case OPENSOURCECONTEXT:                 sProperty = C2U("ooOpenSourceContext"); break;
531             case DEFAULTCURRENCY:                   sProperty = C2U("ooSetupCurrency"); break;
532 			case WRITERCOMPATIBILITYVERSIONOOO11:	sProperty = C2U("OOo11"); break;
533             default:
534                 break;
535 		}
536 		try
537 		{
538 			aRet = xDirectAccess->getByName(sProperty);
539 		}
540 		catch(Exception&)
541 		{
542             #if OSL_DEBUG_LEVEL > 0
543             rtl::OStringBuffer aBuf(256);
544             aBuf.append( "ConfigManager::GetDirectConfigProperty: could not retrieve the property \"" );
545             aBuf.append( rtl::OUStringToOString( sProperty, RTL_TEXTENCODING_ASCII_US ) );
546             aBuf.append( "\" under \"" );
547             aBuf.append( rtl::OUStringToOString( sPath, RTL_TEXTENCODING_ASCII_US ) );
548             aBuf.append( "\" (caught an exception)!" );
549 			OSL_ENSURE( sal_False, aBuf.getStr() );
550             #endif
551 		}
552 	}
553 
554     if ( eProp == PRODUCTNAME )
555         aRet >>= rBrandName;
556 
557     if ( eProp == PRODUCTXMLFILEFORMATNAME )
558         aRet >>= rXMLFileFormatName;
559 
560     if ( eProp == PRODUCTXMLFILEFORMATVERSION )
561         aRet >>= rXMLFileFormatVersion;
562 
563     if ( eProp == PRODUCTVERSION )
564         aRet >>= rProductVersion;
565 
566     if( eProp == OOOVENDOR )
567         aRet >>= rOOOVendor;
568 
569     if ( eProp == ABOUTBOXPRODUCTVERSION )
570     {
571         aRet >>= rAboutBoxProductVersion;
572         getBasisAboutBoxProductVersion( rAboutBoxProductVersion );
573         aRet <<= rAboutBoxProductVersion;
574     }
575 
576     if ( eProp == PRODUCTEXTENSION )
577         aRet >>= rProductExtension;
578 
579     if ( eProp == WRITERCOMPATIBILITYVERSIONOOO11 )
580         aRet >>= rWriterCompatibilityVersionOOo11;
581 
582     if ( eProp == OPENSOURCECONTEXT )
583         aRet >>= rOpenSourceContext;
584 
585 	return aRet;
586 }
587 
588 /*---------------------------------------------------------------------------*/
589 void ConfigManager::getBasisAboutBoxProductVersion( OUString& rVersion )
590 {
591     rtl::OUString aPackageVersion = UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":OOOPackageVersion}" );
592     rtl::Bootstrap::expandMacros( aPackageVersion );
593 
594     if ( aPackageVersion.getLength() )
595     {
596         sal_Int32 nTokIndex = 0;
597         rtl::OUString aVersionMinor = aPackageVersion.getToken( 1, '.', nTokIndex );
598         rtl::OUString aVersionMicro;
599 
600         if ( nTokIndex > 0 )
601             aVersionMicro = aPackageVersion.getToken( 0, '.', nTokIndex );
602 
603         if ( aVersionMinor.getLength() == 0 )
604             aVersionMinor = UNISTRING( "0" );
605         if ( aVersionMicro.getLength() == 0 )
606             aVersionMicro = UNISTRING( "0" );
607 
608         sal_Int32 nIndex = rVersion.indexOf( '.' );
609         if ( nIndex == -1 )
610         {
611             rVersion += UNISTRING( "." );
612             rVersion += aVersionMinor;
613         }
614         else
615         {
616             nIndex = rVersion.indexOf( '.', nIndex+1 );
617         }
618         if ( nIndex == -1 )
619         {
620             rVersion += UNISTRING( "." );
621             rVersion += aVersionMicro;
622         }
623         else
624         {
625             rVersion = rVersion.replaceAt( nIndex+1, rVersion.getLength()-nIndex-1, aVersionMicro );
626         }
627     }
628 }
629 
630 /* -----------------------------12.12.00 17:22--------------------------------
631 
632  ---------------------------------------------------------------------------*/
633 Reference< XHierarchicalNameAccess> ConfigManager::GetHierarchyAccess(const OUString& rFullPath)
634 {
635 	Sequence< Any > aArgs(1);
636 	aArgs[0] <<= rFullPath;
637 	Reference< XMultiServiceFactory > xCfgProvider = GetLocalConfigurationProvider();
638 	Reference< XInterface > xIFace;
639 	if(xCfgProvider.is())
640 	{
641 		try
642 		{
643 			xIFace = xCfgProvider->createInstanceWithArguments(
644 					C2U(cAccessSrvc),
645 					aArgs);
646 		}
647 #ifdef DBG_UTIL
648 		catch(Exception& rEx)
649 		{
650 			OString sMsg("CreateInstance exception: ");
651 			sMsg += OString(rEx.Message.getStr(),
652 						rEx.Message.getLength(),
653 				 		RTL_TEXTENCODING_ASCII_US);
654 			OSL_ENSURE(sal_False, sMsg.getStr());
655 		}
656 #else
657 		catch(Exception&){}
658 #endif
659 	}
660 	return Reference<XHierarchicalNameAccess>(xIFace, UNO_QUERY);
661 }
662 /* -----------------------------12.12.00 17:17--------------------------------
663 
664  ---------------------------------------------------------------------------*/
665 Any ConfigManager::GetLocalProperty(const OUString& rProperty)
666 {
667 	OUString sPath = C2U(cConfigBaseURL);
668 	sPath += rProperty;
669 
670 	OUString sNode, sProperty;
671     OSL_VERIFY( splitLastFromConfigurationPath(sPath, sNode, sProperty) );
672 
673 	Reference< XNameAccess> xAccess( GetHierarchyAccess(sNode), UNO_QUERY );
674 	Any aRet;
675 	try
676 	{
677 		if(xAccess.is())
678 			aRet = xAccess->getByName(sProperty);
679 	}
680 #ifdef DBG_UTIL
681 	catch(Exception& rEx)
682 	{
683 		OString sMsg("GetLocalProperty: ");
684 		sMsg += OString(rEx.Message.getStr(),
685 					rEx.Message.getLength(),
686 				 	RTL_TEXTENCODING_ASCII_US);
687 		OSL_ENSURE(sal_False, sMsg.getStr());
688 	}
689 #else
690 	catch(Exception&){}
691 #endif
692 	return aRet;
693 }
694 /* -----------------------------12.12.00 17:17--------------------------------
695 
696  ---------------------------------------------------------------------------*/
697 void ConfigManager::PutLocalProperty(const OUString& rProperty, const Any& rValue)
698 {
699 	OUString sPath = C2U(cConfigBaseURL);
700 	sPath += rProperty;
701 
702 	OUString sNode, sProperty;
703     OSL_VERIFY( splitLastFromConfigurationPath(sPath, sNode, sProperty) );
704 
705 	Reference<XNameReplace> xNodeReplace(GetHierarchyAccess(sNode), UNO_QUERY);
706 	if(xNodeReplace.is())
707 	{
708 		try
709 		{
710 			xNodeReplace->replaceByName(sProperty, rValue);
711 		}
712 #ifdef DBG_UTIL
713 		catch(Exception& rEx)
714 		{
715 			OString sMsg("PutLocalProperty: ");
716 			sMsg += OString(rEx.Message.getStr(),
717 						rEx.Message.getLength(),
718 				 		RTL_TEXTENCODING_ASCII_US);
719 			OSL_ENSURE(sal_False, sMsg.getStr());
720 		}
721 #else
722 		catch(Exception& ){}
723 #endif
724 	}
725 }
726 /* -----------------------------13.12.00 08:47--------------------------------
727 
728  ---------------------------------------------------------------------------*/
729 sal_Bool	ConfigManager::IsLocalConfigProvider()
730 {
731 	return false;
732 }
733 
734