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_stoc.hxx"
30 #include <stdlib.h>
31 #include <string.h>
32 #include <list>
33 
34 #include <unistd.h>
35 #include <cppuhelper/queryinterface.hxx>
36 #include <cppuhelper/factory.hxx>
37 #include <cppuhelper/weak.hxx>
38 #include <cppuhelper/servicefactory.hxx>
39 #ifndef _CPPUHELPER_IMPLBASE3_HXX
40 #include <cppuhelper/implbase3.hxx>
41 #endif
42 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
43 #include <cppuhelper/implementationentry.hxx>
44 #endif
45 
46 #include <uno/mapping.hxx>
47 #include <osl/thread.h>
48 
49 #include <rtl/ustring.hxx>
50 #include <rtl/ustrbuf.hxx>
51 #include <rtl/strbuf.hxx>
52 #include <osl/process.h>
53 
54 #include <com/sun/star/lang/XServiceInfo.hpp>
55 #include <com/sun/star/lang/XInitialization.hpp>
56 #include <com/sun/star/loader/XImplementationLoader.hpp>
57 #include <com/sun/star/registry/XImplementationRegistration2.hpp>
58 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
59 #include <com/sun/star/reflection/XServiceTypeDescription.hpp>
60 #include <com/sun/star/beans/XPropertySet.hpp>
61 #include "com/sun/star/uno/RuntimeException.hpp"
62 
63 #include "mergekeys.hxx"
64 
65 #if defined(SAL_W32) || defined(SAL_OS2)
66 #include <io.h>
67 #endif
68 
69 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
70 
71 
72 using namespace com::sun::star;
73 using namespace com::sun::star::uno;
74 using namespace com::sun::star::loader;
75 using namespace com::sun::star::beans;
76 using namespace com::sun::star::lang;
77 using namespace com::sun::star::registry;
78 using namespace cppu;
79 using namespace rtl;
80 using namespace osl;
81 
82 
83 #define IMPLNAME "com.sun.star.comp.stoc.ImplementationRegistration"
84 #define SERVICENAME 		"com.sun.star.registry.ImplementationRegistration"
85 namespace stoc_impreg
86 {
87 struct StringPool
88 {
89     OUString sImplementationName;
90     OUString sServiceName;
91     OUString TMP;
92     OUString TEMP;
93     OUString slash_UNO_slash_REGISTRY_LINKS;
94     OUString slash_IMPLEMENTATIONS;
95     OUString slash_UNO;
96     OUString slash_UNO_slash_SERVICES;
97     OUString slash_UNO_slash_SINGLETONS;
98     OUString slash_SERVICES;
99     OUString slash_UNO_slash_LOCATION;
100     OUString slash_UNO_slash_ACTIVATOR;
101     OUString colon_old;
102     OUString com_sun_star_registry_SimpleRegistry;
103     OUString Registry;
104     StringPool()
105         : sImplementationName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) )
106         , sServiceName( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME ) )
107         , TMP( RTL_CONSTASCII_USTRINGPARAM( "TMP" ) )
108         , TEMP( RTL_CONSTASCII_USTRINGPARAM( "TEMP" ) )
109         , slash_UNO_slash_REGISTRY_LINKS( RTL_CONSTASCII_USTRINGPARAM("/UNO/REGISTRY_LINKS"))
110         , slash_IMPLEMENTATIONS( RTL_CONSTASCII_USTRINGPARAM( "/IMPLEMENTATIONS" ) )
111         , slash_UNO( RTL_CONSTASCII_USTRINGPARAM("/UNO"))
112         , slash_UNO_slash_SERVICES( RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES"))
113         , slash_UNO_slash_SINGLETONS( RTL_CONSTASCII_USTRINGPARAM("/UNO/SINGLETONS"))
114         , slash_SERVICES( RTL_CONSTASCII_USTRINGPARAM("/SERVICES/") )
115         , slash_UNO_slash_LOCATION( RTL_CONSTASCII_USTRINGPARAM("/UNO/LOCATION") )
116         , slash_UNO_slash_ACTIVATOR( RTL_CONSTASCII_USTRINGPARAM("/UNO/ACTIVATOR") )
117         , colon_old( RTL_CONSTASCII_USTRINGPARAM(":old"))
118         , com_sun_star_registry_SimpleRegistry(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.SimpleRegistry") )
119         , Registry( RTL_CONSTASCII_USTRINGPARAM("Registry") )
120         {}
121 private:
122     StringPool( const StringPool & );
123 };
124 
125 const StringPool &spool()
126 {
127     static StringPool *pPool = 0;
128     if( ! pPool )
129     {
130         MutexGuard guard( Mutex::getGlobalMutex() );
131         if( ! pPool )
132         {
133             static StringPool pool;
134             pPool = &pool;
135         }
136     }
137     return *pPool;
138 }
139 }
140 
141 extern rtl_StandardModuleCount g_moduleCount;
142 
143 namespace stoc_bootstrap
144 {
145 Sequence< OUString > impreg_getSupportedServiceNames()
146 {
147 	static Sequence < OUString > *pNames = 0;
148 	if( ! pNames )
149 	{
150 		MutexGuard guard( Mutex::getGlobalMutex() );
151 		if( !pNames )
152 		{
153 			static Sequence< OUString > seqNames(1);
154 			seqNames.getArray()[0] = stoc_impreg::spool().sServiceName;
155 			pNames = &seqNames;
156 		}
157 	}
158 	return *pNames;
159 }
160 
161 OUString impreg_getImplementationName()
162 {
163     return stoc_impreg::spool().sImplementationName;
164 }
165 }
166 
167 namespace stoc_impreg
168 {
169 //*************************************************************************
170 //	static deleteAllLinkReferences()
171 //
172 static void deleteAllLinkReferences(const Reference < XSimpleRegistry >& xReg,
173 									const Reference < XRegistryKey >& xSource)
174     // throw ( InvalidRegistryException, RuntimeException )
175 {
176     Reference < XRegistryKey > xKey = xSource->openKey(
177         spool().slash_UNO_slash_REGISTRY_LINKS );
178 
179     if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCIILIST))
180     {
181         Sequence<OUString> linkNames = xKey->getAsciiListValue();
182 
183         if (linkNames.getLength())
184         {
185             const OUString* pLinkNames = linkNames.getConstArray();
186 
187             OUString			aLinkName;
188             OUString			aLinkParent;
189             Reference < XRegistryKey >	xLinkParent;
190             const sal_Unicode*	pTmpName = NULL;
191             const sal_Unicode*	pShortName = NULL;
192             sal_Int32		   	sEnd = 0;
193 
194             for (sal_Int32 i = 0; i < linkNames.getLength(); i++)
195             {
196                 aLinkName = pLinkNames[i];
197 
198                 pTmpName = aLinkName.getStr();
199 
200                 if (pTmpName[0] != L'/')
201                     continue;
202 
203                 sal_Int32 nIndex = rtl_ustr_indexOfChar( pTmpName, '%' );
204                 if ( nIndex == -1 )
205                     pShortName = 0;
206                 else
207                     pShortName = pTmpName+nIndex;
208 
209                 while (pShortName && pShortName[1] == L'%')
210                 {
211                     nIndex = rtl_ustr_indexOfChar( pShortName+2, '%' );
212                     if ( nIndex == -1 )
213                         pShortName = 0;
214                     else
215                         pShortName += nIndex+2;
216                 }
217 
218                 if (pShortName)
219                 {
220                     aLinkName = aLinkName.copy(0, pShortName - pTmpName);
221                 }
222 
223                 xReg->getRootKey()->deleteLink(aLinkName);
224 
225                 sEnd = rtl_ustr_lastIndexOfChar( aLinkName.getStr(), '/' );
226 
227                 aLinkParent = aLinkName.copy(0, sEnd);
228 
229                 while(aLinkParent.getLength())
230                 {
231                     xLinkParent = xReg->getRootKey()->openKey(aLinkParent);
232 
233                     if (xLinkParent.is() && (xLinkParent->getKeyNames().getLength() == 0))
234                     {
235                         aLinkName = aLinkParent;
236 
237                         xReg->getRootKey()->deleteKey(aLinkParent);
238 
239                         sEnd = rtl_ustr_lastIndexOfChar( aLinkName.getStr(), '/' );
240 
241                         aLinkParent = aLinkName.copy(0, sEnd);
242                     } else
243                     {
244                         break;
245                     }
246                 }
247             }
248         }
249     }
250 }
251 
252 //*************************************************************************
253 //	static prepareLink
254 //
255 static void prepareLink( const Reference < XSimpleRegistry > & xDest,
256 						 const Reference < XRegistryKey > & xSource,
257 						 const OUString& link)
258     // throw ( InvalidRegistryException, RuntimeException )
259 {
260     OUString linkRefName = xSource->getKeyName();
261     OUString linkName(link);
262     sal_Bool	isRelativ = sal_False;
263 
264     const sal_Unicode*	pTmpName = link.getStr();
265     const sal_Unicode*	pShortName;
266     sal_Int32           nIndex = rtl_ustr_indexOfChar( pTmpName, '%' );
267     if ( nIndex == -1 )
268         pShortName = 0;
269     else
270         pShortName = pTmpName+nIndex;
271 
272     if (pTmpName[0] != L'/')
273         isRelativ = sal_True;
274 
275     while (pShortName && pShortName[1] == L'%')
276     {
277         nIndex = rtl_ustr_indexOfChar( pShortName+2, '%' );
278         if ( nIndex == -1 )
279             pShortName = 0;
280         else
281             pShortName += nIndex+2;
282     }
283 
284     if (pShortName)
285     {
286         linkRefName = linkRefName + link.copy(pShortName - pTmpName + 1);
287         linkName = link.copy(0, pShortName - pTmpName);
288     }
289 
290     if (isRelativ)
291         xSource->createLink(linkName, linkRefName);
292     else
293         xDest->getRootKey()->createLink(linkName, linkRefName);
294 }
295 
296 //*************************************************************************
297 //	static searchImplForLink
298 //
299 static OUString searchImplForLink(
300     const Reference < XRegistryKey > & xRootKey,
301     const OUString& linkName,
302     const OUString& implName )
303     // throw ( InvalidRegistryException, RuntimeException )
304 {
305     const StringPool & pool = spool();
306     Reference < XRegistryKey > xKey = xRootKey->openKey( pool.slash_IMPLEMENTATIONS );
307     if (xKey.is())
308     {
309         Sequence< Reference < XRegistryKey > > subKeys( xKey->openKeys() );
310         const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray();
311         OUString key_name( pool.slash_UNO + linkName );
312 
313         for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
314         {
315             try
316             {
317                 Reference < XRegistryKey > xImplKey( pSubKeys[i] );
318                 if (xImplKey->getKeyType( key_name ) == RegistryKeyType_LINK)
319                 {
320                     OUString oldImplName = xImplKey->getKeyName().copy(strlen("/IMPLEMENTATIONS/"));
321                     if (implName != oldImplName)
322                     {
323                         return oldImplName;
324                     }
325                 }
326             }
327             catch(InvalidRegistryException&)
328             {
329             }
330         }
331     }
332 
333 	return OUString();
334 }
335 
336 //*************************************************************************
337 //	static searchLinkTargetForImpl
338 //
339 static OUString searchLinkTargetForImpl(const Reference < XRegistryKey >& xRootKey,
340                                         const OUString& linkName,
341                                         const OUString& implName)
342     // throw ( InvalidRegistryException, RuntimeException )
343 {
344 	OUString ret;
345 
346 //  	try
347 //  	{
348         const StringPool & pool = spool();
349 		Reference < XRegistryKey > xKey = xRootKey->openKey( pool.slash_IMPLEMENTATIONS );
350 
351 		if (xKey.is())
352 		{
353 			Sequence< Reference < XRegistryKey > > subKeys = xKey->openKeys();
354 
355 			const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray();
356 			Reference < XRegistryKey > xImplKey;
357 
358 			for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
359 			{
360 				xImplKey = pSubKeys[i];
361 
362 				OUString tmpImplName = xImplKey->getKeyName().copy(strlen("/IMPLEMENTATIONS/"));
363                 OUString qualifiedLinkName( pool.slash_UNO );
364                 qualifiedLinkName += linkName;
365 				if (tmpImplName == implName &&
366 					xImplKey->getKeyType( qualifiedLinkName ) == RegistryKeyType_LINK)
367 				{
368 					return xImplKey->getLinkTarget( qualifiedLinkName );
369 				}
370 			}
371 		}
372 //  	}
373 //  	catch(InvalidRegistryException&)
374 //  	{
375 //  	}
376 
377 	return ret;
378 }
379 
380 //*************************************************************************
381 //	static createUniqueSubEntry
382 //
383 static void createUniqueSubEntry(const Reference < XRegistryKey > & xSuperKey,
384 								 const OUString& value)
385     // throw ( InvalidRegistryException, RuntimeException )
386 {
387 	if (xSuperKey.is())
388 	{
389 //  		try
390 //  		{
391         if (xSuperKey->getValueType() == RegistryValueType_ASCIILIST)
392         {
393             sal_Int32 length = 0;
394             sal_Bool bReady = sal_False;
395 
396             Sequence<OUString> implEntries = xSuperKey->getAsciiListValue();
397             length = implEntries.getLength();
398 
399             for (sal_Int32 i = 0; !bReady && (i < length); i++)
400             {
401                 bReady = (implEntries.getConstArray()[i] == value);
402             }
403 
404             if (bReady)
405             {
406                 Sequence<OUString> implEntriesNew(length);
407                 implEntriesNew.getArray()[0] = value;
408 
409                 for (sal_Int32 i=0, j=1; i < length; i++)
410                 {
411                     if (implEntries.getConstArray()[i] != value)
412                         implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i];
413                 }
414                 xSuperKey->setAsciiListValue(implEntriesNew);
415             } else
416             {
417                 Sequence<OUString> implEntriesNew(length+1);
418                 implEntriesNew.getArray()[0] = value;
419 
420                 for (sal_Int32 i = 0; i < length; i++)
421                 {
422                     implEntriesNew.getArray()[i+1] = implEntries.getConstArray()[i];
423                 }
424                 xSuperKey->setAsciiListValue(implEntriesNew);
425             }
426         } else
427         {
428             Sequence<OUString> implEntriesNew(1);
429 
430             implEntriesNew.getArray()[0] = value;
431 
432             xSuperKey->setAsciiListValue(implEntriesNew);
433         }
434 //  		}
435 //  		catch(InvalidRegistryException&)
436 //  		{
437 //  		}
438 	}
439 }
440 
441 //*************************************************************************
442 //	static deleteSubEntry
443 //
444 static sal_Bool deleteSubEntry(const Reference < XRegistryKey >& xSuperKey, const OUString& value)
445     // throw ( InvalidRegistryException, RuntimeException )
446 {
447     if (xSuperKey->getValueType() == RegistryValueType_ASCIILIST)
448     {
449         Sequence<OUString> implEntries = xSuperKey->getAsciiListValue();
450         sal_Int32 length = implEntries.getLength();
451         sal_Int32 equals = 0;
452         sal_Bool hasNoImplementations = sal_False;
453 
454         for (sal_Int32 i = 0; i < length; i++)
455         {
456             if (implEntries.getConstArray()[i] == value)
457                 equals++;
458         }
459 
460         if (equals == length)
461         {
462             hasNoImplementations = sal_True;
463         } else
464         {
465             Sequence<OUString> implEntriesNew(length - equals);
466 
467             sal_Int32 j = 0;
468             for (sal_Int32 i = 0; i < length; i++)
469             {
470                 if (implEntries.getConstArray()[i] != value)
471                 {
472                         implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i];
473                 }
474             }
475             xSuperKey->setAsciiListValue(implEntriesNew);
476         }
477 
478         if (hasNoImplementations)
479         {
480             return sal_True;
481         }
482     }
483 	return sal_False;
484 }
485 
486 //*************************************************************************
487 //	static prepareUserLink
488 //
489 static void	prepareUserLink(const Reference < XSimpleRegistry >& xDest,
490                                 const OUString& linkName,
491                                 const OUString& linkTarget,
492                                 const OUString& implName)
493     // throw ( InvalidRegistryException, RuntimeException )
494 {
495 	sal_Bool ret = sal_False;
496 
497 	Reference < XRegistryKey > xRootKey;
498 
499 //  	try
500 //  	{
501     xRootKey = xDest->getRootKey();
502 
503     if (xRootKey->getKeyType(linkName) == RegistryKeyType_LINK)
504     {
505         OUString oldImplName(searchImplForLink(xRootKey, linkName, implName));
506 
507         if (oldImplName.getLength())
508         {
509             createUniqueSubEntry(xDest->getRootKey()->createKey(
510                 linkName + spool().colon_old ), oldImplName);
511         }
512     }
513 //  	}
514 //  	catch (InvalidRegistryException&)
515 //  	{
516 //  	}
517 
518 //  	try
519 //  	{
520     if (xRootKey->isValid())
521     {
522         ret = xRootKey->createLink(linkName, linkTarget);
523     }
524 //  	}
525 //  	catch(InvalidRegistryException&)
526 //  	{
527 //  	}
528 
529 //  	return ret;
530 }
531 
532 //*************************************************************************
533 //	static deleteUserLink
534 //
535 static void	deletePathIfPossible(const Reference < XRegistryKey >& xRootKey,
536 								 const OUString& path)
537 {
538 	try
539 	{
540 		Sequence<OUString> keyNames(xRootKey->openKey(path)->getKeyNames());
541 
542 		if (keyNames.getLength() == 0 &&
543 			xRootKey->openKey(path)->getValueType() == RegistryValueType_NOT_DEFINED)
544 		{
545 			xRootKey->deleteKey(path);
546 
547 			OUString tmpPath(path);
548 			OUString newPath = tmpPath.copy(0, tmpPath.lastIndexOf('/'));
549 
550 			if (newPath.getLength() > 1)
551 				deletePathIfPossible(xRootKey, newPath);
552 		}
553 	}
554 	catch(InvalidRegistryException&)
555 	{
556 	}
557 }
558 
559 
560 //*************************************************************************
561 //	static deleteUserLink
562 //
563 static void	deleteUserLink(const Reference < XRegistryKey >& xRootKey,
564                                const OUString& linkName,
565                                const OUString& linkTarget,
566                                const OUString& implName)
567     // throw ( InvalidRegistryException, RuntimeException )
568 {
569     sal_Bool bClean = sal_False;
570 
571     if (xRootKey->getKeyType(linkName) == RegistryKeyType_LINK)
572     {
573         OUString tmpTarget = xRootKey->getLinkTarget(linkName);
574 
575         if (tmpTarget == linkTarget)
576         {
577             xRootKey->deleteLink(linkName);
578         }
579     }
580 
581     Reference < XRegistryKey > xOldKey = xRootKey->openKey(
582         linkName + spool().colon_old );
583     if (xOldKey.is())
584     {
585         sal_Bool hasNoImplementations = sal_False;
586 
587         if (xOldKey->getValueType() == RegistryValueType_ASCIILIST)
588         {
589             Sequence<OUString> implEntries = xOldKey->getAsciiListValue();
590             sal_Int32 length = implEntries.getLength();
591             sal_Int32 equals = 0;
592 
593             for (sal_Int32 i = 0; i < length; i++)
594             {
595                 if (implEntries.getConstArray()[i] == implName)
596                     equals++;
597             }
598 
599             if (equals == length)
600             {
601                 hasNoImplementations = sal_True;
602             } else
603             {
604                 OUString oldImpl;
605 
606                 if (length > equals + 1)
607                 {
608                     Sequence<OUString> implEntriesNew(length - equals - 1);
609 
610                     sal_Int32 j = 0;
611                     sal_Bool first = sal_True;
612                     for (sal_Int32 i = 0; i < length; i++)
613                     {
614                         if (implEntries.getConstArray()[i] != implName)
615                         {
616                             if (first)
617                             {
618                                 oldImpl = implEntries.getConstArray()[i];
619                                 first = sal_False;
620                             } else
621                             {
622                                 implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i];
623                             }
624                         }
625                     }
626 
627                     xOldKey->setAsciiListValue(implEntriesNew);
628                 } else
629                 {
630                     oldImpl = implEntries.getConstArray()[0];
631                     rtl::OUString path(xOldKey->getKeyName());
632                     xOldKey->closeKey();
633                     xRootKey->deleteKey(path);
634                 }
635 
636                 OUString oldTarget = searchLinkTargetForImpl(xRootKey, linkName, oldImpl);
637                 if (oldTarget.getLength())
638                 {
639                     xRootKey->createLink(linkName, oldTarget);
640                 }
641             }
642 
643             if (hasNoImplementations)
644             {
645                 bClean = sal_True;
646                 hasNoImplementations = sal_False;
647                 rtl::OUString path(xOldKey->getKeyName());
648                 xOldKey->closeKey();
649                 xRootKey->deleteKey(path);
650             }
651         }
652     } else
653     {
654         bClean = sal_True;
655     }
656 
657     if (bClean)
658     {
659         OUString tmpName(linkName);
660         OUString path = tmpName.copy(0, tmpName.lastIndexOf('/'));
661         deletePathIfPossible(xRootKey, path);
662     }
663 }
664 
665 //*************************************************************************
666 //	static prepareUserKeys
667 //
668 static void	prepareUserKeys(const Reference < XSimpleRegistry >& xDest,
669                                 const Reference < XRegistryKey >& xUnoKey,
670                                 const Reference < XRegistryKey >& xKey,
671                                 const OUString& implName,
672                                 sal_Bool bRegister)
673     // throw ( InvalidRegistryException, RuntimeException )
674 {
675 	sal_Bool hasSubKeys = sal_False;
676 
677     Sequence<OUString> keyNames = xKey->getKeyNames();
678 
679     OUString relativKey;
680     if (keyNames.getLength())
681         relativKey = keyNames.getConstArray()[0].copy(xKey->getKeyName().getLength()+1);
682 
683     if (keyNames.getLength() == 1 &&
684         xKey->getKeyType(relativKey) == RegistryKeyType_LINK)
685     {
686         hasSubKeys = sal_True;
687 
688         OUString linkTarget = xKey->getLinkTarget(relativKey);
689         OUString linkName(xKey->getKeyName().copy(xUnoKey->getKeyName().getLength()));
690 
691         linkName = linkName + OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + relativKey;
692 
693         if (bRegister)
694         {
695             prepareUserLink(xDest, linkName, linkTarget, implName);
696         } else
697         {
698             deleteUserLink(xDest->getRootKey(), linkName, linkTarget, implName);
699         }
700     } else
701     {
702         Sequence< Reference < XRegistryKey> > subKeys = xKey->openKeys();
703 
704         if (subKeys.getLength())
705         {
706             hasSubKeys = sal_True;
707             const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray();
708 
709             for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
710             {
711                 prepareUserKeys(xDest, xUnoKey, pSubKeys[i], implName, bRegister);
712             }
713         }
714     }
715 
716     if (! hasSubKeys)
717     {
718         OUString keyName(xKey->getKeyName().copy(xUnoKey->getKeyName().getLength()));
719 
720         Reference < XRegistryKey > xRootKey = xDest->getRootKey();
721         if (bRegister)
722         {
723             createUniqueSubEntry(xRootKey->createKey(keyName), implName);
724         }
725         else
726         {
727             Reference< XRegistryKey > rKey = xRootKey->openKey(keyName);
728             if( rKey.is() )
729             {
730                 deleteSubEntry(rKey, implName);
731                 xRootKey->deleteKey(keyName);
732             }
733 
734             OUString path = keyName.copy(0, keyName.lastIndexOf('/'));
735             if( path.getLength() )
736             {
737                 deletePathIfPossible(xRootKey, path);
738             }
739         }
740     }
741 	return;
742 }
743 
744 //*************************************************************************
745 //	static deleteAllImplementations
746 //
747 static void deleteAllImplementations(	const Reference < XSimpleRegistry >& xReg,
748 										const Reference < XRegistryKey >& xSource,
749 										const OUString& locationUrl,
750 										std::list<OUString> & implNames)
751     // throw (InvalidRegistryException, RuntimeException)
752 {
753     Sequence < Reference < XRegistryKey > > subKeys = xSource->openKeys();
754 
755     if (subKeys.getLength() > 0)
756     {
757         const Reference < XRegistryKey> * pSubKeys = subKeys.getConstArray();
758         Reference < XRegistryKey > xImplKey;
759         sal_Bool hasLocationUrl = sal_False;
760 
761         const StringPool &pool = spool();
762         for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
763         {
764             xImplKey = pSubKeys[i];
765             Reference < XRegistryKey > xKey = xImplKey->openKey(
766                 pool.slash_UNO_slash_LOCATION );
767 
768             if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCII))
769             {
770                 if (xKey->getAsciiValue() == locationUrl)
771                 {
772                     hasLocationUrl = sal_True;
773 
774                     OUString implName(xImplKey->getKeyName().getStr() + 1);
775                     sal_Int32 firstDot = implName.indexOf('/');
776 
777                     if (firstDot >= 0)
778                         implName = implName.copy(firstDot + 1);
779 
780                     implNames.push_back(implName);
781 
782                     deleteAllLinkReferences(xReg, xImplKey);
783 
784                     xKey = xImplKey->openKey( pool.slash_UNO );
785                     if (xKey.is())
786                     {
787                         Sequence< Reference < XRegistryKey > > subKeys2 = xKey->openKeys();
788 
789                         if (subKeys2.getLength())
790                         {
791                             const Reference < XRegistryKey > * pSubKeys2 = subKeys2.getConstArray();
792 
793                             for (sal_Int32 j = 0; j < subKeys2.getLength(); j++)
794                             {
795                                 if (pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SERVICES ) &&
796                                     pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_REGISTRY_LINKS ) &&
797                                     pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_ACTIVATOR ) &&
798                                     pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SINGLETONS ) &&
799                                     pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_LOCATION) )
800                                 {
801                                     prepareUserKeys(xReg, xKey, pSubKeys2[j], implName, sal_False);
802                                 }
803                             }
804                         }
805                     }
806                 }
807             }
808 
809             if (hasLocationUrl)
810             {
811                 hasLocationUrl = sal_False;
812                 rtl::OUString path(xImplKey->getKeyName());
813                 xImplKey->closeKey();
814                 xReg->getRootKey()->deleteKey(path);
815             }
816         }
817 
818         subKeys = xSource->openKeys();
819         if (subKeys.getLength() == 0)
820         {
821             rtl::OUString path(xSource->getKeyName());
822             xSource->closeKey();
823             xReg->getRootKey()->deleteKey(path);
824         }
825     } else
826     {
827         rtl::OUString path(xSource->getKeyName());
828         xSource->closeKey();
829         xReg->getRootKey()->deleteKey(path);
830     }
831 }
832 
833 //==================================================================================================
834 static void delete_all_singleton_entries(
835 	Reference < registry::XRegistryKey > const & xSingletons_section,
836     ::std::list< OUString > const & impl_names )
837     // throw (InvalidRegistryException, RuntimeException)
838 {
839     Sequence< Reference< registry::XRegistryKey > > singletons( xSingletons_section->openKeys() );
840     Reference< registry::XRegistryKey > const * subkeys = singletons.getConstArray();
841     for ( sal_Int32 nPos = singletons.getLength(); nPos--; )
842     {
843         Reference< registry::XRegistryKey > const & xSingleton = subkeys[ nPos ];
844         Reference< registry::XRegistryKey > xRegisteredImplNames(
845             xSingleton->openKey( OUSTR("REGISTERED_BY") ) );
846         if (xRegisteredImplNames.is() && xRegisteredImplNames->isValid())
847         {
848             Sequence< OUString > registered_implnames;
849             try
850             {
851                 registered_implnames = xRegisteredImplNames->getAsciiListValue();
852             }
853             catch (registry::InvalidValueException &)
854             {
855             }
856             OUString const * p = registered_implnames.getConstArray();
857             sal_Int32 nOrigRegLength = registered_implnames.getLength();
858             sal_Int32 nNewLength = nOrigRegLength;
859             for ( sal_Int32 n = nOrigRegLength; n--; )
860             {
861                 OUString const & registered_implname = p[ n ];
862 
863                 ::std::list< OUString >::const_iterator iPos( impl_names.begin() );
864                 ::std::list< OUString >::const_iterator const iEnd( impl_names.end() );
865                 for ( ; iPos != iEnd; ++iPos )
866                 {
867                     if (iPos->equals( registered_implname ))
868                     {
869                         registered_implnames[ n ] = p[ nNewLength -1 ];
870                         --nNewLength;
871                     }
872                 }
873             }
874 
875             if (nNewLength != nOrigRegLength)
876             {
877                 if (0 == nNewLength)
878                 {
879                     // remove whole entry
880                     xRegisteredImplNames->closeKey();
881                     xSingleton->deleteKey( OUSTR("REGISTERED_BY") );
882                     // registry key cannot provide its relative name, only absolute :(
883                     OUString abs( xSingleton->getKeyName() );
884                     xSingletons_section->deleteKey( abs.copy( abs.lastIndexOf( '/' ) +1 ) );
885                 }
886                 else
887                 {
888                     registered_implnames.realloc( nNewLength );
889                     xRegisteredImplNames->setAsciiListValue( registered_implnames );
890                 }
891             }
892         }
893     }
894 }
895 
896 //*************************************************************************
897 //	static deleteAllServiceEntries
898 //
899 static void deleteAllServiceEntries(	const Reference < XSimpleRegistry >& xReg,
900 										const Reference < XRegistryKey >& xSource,
901 										const OUString& implName)
902     // throw ( InvalidRegistryException, RuntimeException )
903 {
904     Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys();
905 
906     if (subKeys.getLength() > 0)
907     {
908         const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray();
909         Reference < XRegistryKey > xServiceKey;
910         sal_Bool hasNoImplementations = sal_False;
911 
912         for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
913         {
914             xServiceKey = pSubKeys[i];
915 
916             if (xServiceKey->getValueType() == RegistryValueType_ASCIILIST)
917             {
918                 Sequence<OUString> implEntries = xServiceKey->getAsciiListValue();
919                 sal_Int32 length = implEntries.getLength();
920                 sal_Int32 equals = 0;
921 
922                 for (sal_Int32 j = 0; j < length; j++)
923                 {
924                     if (implEntries.getConstArray()[j] == implName)
925                         equals++;
926                 }
927 
928                 if (equals == length)
929                 {
930                     hasNoImplementations = sal_True;
931                 } else
932                 {
933                     if (equals > 0)
934                     {
935                         Sequence<OUString> implEntriesNew(length-equals);
936 
937                         sal_Int32 j = 0;
938                         for (sal_Int32 k = 0; k < length; k++)
939                         {
940                             if (implEntries.getConstArray()[k] != implName)
941                             {
942                                 implEntriesNew.getArray()[j++] = implEntries.getConstArray()[k];
943                             }
944                         }
945 
946                         xServiceKey->setAsciiListValue(implEntriesNew);
947                     }
948                 }
949             }
950 
951             if (hasNoImplementations)
952             {
953                 hasNoImplementations = sal_False;
954                 rtl::OUString path(xServiceKey->getKeyName());
955                 xServiceKey->closeKey();
956                 xReg->getRootKey()->deleteKey(path);
957             }
958         }
959 
960         subKeys = xSource->openKeys();
961         if (subKeys.getLength() == 0)
962         {
963             rtl::OUString path(xSource->getKeyName());
964             xSource->closeKey();
965             xReg->getRootKey()->deleteKey(path);
966         }
967     } else
968     {
969         rtl::OUString path(xSource->getKeyName());
970         xSource->closeKey();
971         xReg->getRootKey()->deleteKey(path);
972     }
973 }
974 
975 //--------------------------------------------------------------------------------------------------
976 static bool is_supported_service(
977     OUString const & service_name,
978     Reference< reflection::XServiceTypeDescription > const & xService_td )
979 {
980     if (xService_td->getName().equals( service_name ))
981         return true;
982     Sequence< Reference< reflection::XServiceTypeDescription > > seq(
983         xService_td->getMandatoryServices() );
984     Reference< reflection::XServiceTypeDescription > const * p = seq.getConstArray();
985     for ( sal_Int32 nPos = seq.getLength(); nPos--; )
986     {
987         if (is_supported_service( service_name, p[ nPos ] ))
988             return true;
989     }
990     return false;
991 }
992 
993 //--------------------------------------------------------------------------------------------------
994 static void insert_singletons(
995     Reference< registry::XSimpleRegistry > const & xDest,
996     Reference< registry::XRegistryKey > const & xImplKey,
997     Reference< XComponentContext > const & xContext )
998     // throw( registry::InvalidRegistryException, registry::CannotRegisterImplementationException, RuntimeException )
999 {
1000     // singletons
1001     Reference< registry::XRegistryKey > xKey( xImplKey->openKey( OUSTR("UNO/SINGLETONS") ) );
1002     if (xKey.is() && xKey->isValid())
1003     {
1004         OUString implname( xImplKey->getKeyName().copy( sizeof ("/IMPLEMENTATIONS/") -1 ) );
1005         // singleton entries
1006         Sequence< Reference< registry::XRegistryKey > > xSingletons_section( xKey->openKeys() );
1007         Reference< registry::XRegistryKey > const * p = xSingletons_section.getConstArray();
1008         for ( sal_Int32 nPos = xSingletons_section.getLength(); nPos--; )
1009         {
1010             Reference< registry::XRegistryKey > const & xSingleton = p[ nPos ];
1011             OUString singleton_name(
1012                 xSingleton->getKeyName().copy(
1013                     implname.getLength() + sizeof ("/IMPLEMENTATIONS//UNO/SINGLETONS/") -1 ) );
1014             OUString service_name( xSingleton->getStringValue() );
1015 
1016             OUString keyname( OUSTR("/SINGLETONS/") + singleton_name );
1017             Reference< registry::XRegistryKey > xKey2( xDest->getRootKey()->openKey( keyname ) );
1018             if (xKey2.is() && xKey2->isValid())
1019             {
1020                 try
1021                 {
1022                     OUString existing_name( xKey2->getStringValue() );
1023                     if (! existing_name.equals( service_name ))
1024                     {
1025                         Reference< container::XHierarchicalNameAccess > xTDMgr;
1026                         OUString the_tdmgr =
1027                             OUSTR("/singletons/com.sun.star.reflection.theTypeDescriptionManager");
1028                         xContext->getValueByName( the_tdmgr ) >>= xTDMgr;
1029                         if (! xTDMgr.is())
1030                         {
1031                             throw RuntimeException(
1032                                 OUSTR("cannot get singleton ") + the_tdmgr,
1033                                 Reference< XInterface >() );
1034                         }
1035                         try
1036                         {
1037                             Reference< reflection::XServiceTypeDescription > xExistingService_td;
1038                             xTDMgr->getByHierarchicalName( existing_name ) >>= xExistingService_td;
1039                             if (! xExistingService_td.is())
1040                             {
1041                                 throw RuntimeException(
1042                                     OUSTR("cannot get service type description: ") + existing_name,
1043                                     Reference< XInterface >() );
1044                             }
1045 
1046                             // everything's fine if existing service entry supports the one
1047                             // to be registered
1048                             if (! is_supported_service( service_name, xExistingService_td ))
1049                             {
1050                                 OUStringBuffer buf( 64 );
1051                                 buf.appendAscii(
1052                                     RTL_CONSTASCII_STRINGPARAM("existing singleton service (") );
1053                                 buf.append( singleton_name );
1054                                 buf.append( (sal_Unicode)'=' );
1055                                 buf.append( existing_name );
1056                                 buf.appendAscii(
1057                                     RTL_CONSTASCII_STRINGPARAM(") does not support given one: ") );
1058                                 buf.append( service_name );
1059                                 throw registry::CannotRegisterImplementationException(
1060                                     buf.makeStringAndClear(), Reference< XInterface >() );
1061                             }
1062                         }
1063                         catch (container::NoSuchElementException & exc)
1064                         {
1065                             throw RuntimeException(
1066                                 OUSTR("cannot get service type description: ") + exc.Message,
1067                                 Reference< XInterface >() );
1068                         }
1069                     }
1070                 }
1071                 catch (registry::InvalidValueException &)
1072                 {
1073                     // repair
1074                     xKey2->setStringValue( service_name );
1075                 }
1076             }
1077             else
1078             {
1079                 // insert singleton entry
1080                 xKey2 = xDest->getRootKey()->createKey( keyname );
1081                 xKey2->setStringValue( service_name );
1082             }
1083 
1084             Reference< registry::XRegistryKey > xRegisteredImplNames(
1085                 xKey2->openKey( OUSTR("REGISTERED_BY") ) );
1086             if (!xRegisteredImplNames.is() || !xRegisteredImplNames->isValid())
1087             {
1088                 // create
1089                 xRegisteredImplNames = xKey2->createKey( OUSTR("REGISTERED_BY") );
1090             }
1091 
1092             Sequence< OUString > implnames;
1093             try
1094             {
1095                 implnames = xRegisteredImplNames->getAsciiListValue();
1096             }
1097             catch (registry::InvalidValueException &)
1098             {
1099             }
1100             // check implname is already in
1101             sal_Int32 nPos_implnames = implnames.getLength();
1102             OUString const * pImplnames = implnames.getConstArray();
1103             while (nPos_implnames--)
1104             {
1105                 if (implname.equals( pImplnames[ nPos_implnames ] ))
1106                     break;
1107             }
1108             if (nPos_implnames < 0)
1109             {
1110                 // append and write back
1111                 implnames.realloc( implnames.getLength() +1 );
1112                 implnames[ implnames.getLength() -1 ] = implname;
1113                 xRegisteredImplNames->setAsciiListValue( implnames );
1114             }
1115         }
1116     }
1117 }
1118 
1119 
1120 //*************************************************************************
1121 //	static prepareRegistry
1122 //
1123 static void prepareRegistry(
1124     const Reference < XSimpleRegistry >& xDest,
1125     const Reference < XRegistryKey >& xSource,
1126     const OUString& implementationLoaderUrl,
1127     const OUString& locationUrl,
1128     Reference< XComponentContext > const & xContext )
1129     // throw ( InvalidRegistryException, CannotRegisterImplementationException, RuntimeException )
1130 {
1131     Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys();
1132 
1133     if (!subKeys.getLength())
1134     {
1135         throw InvalidRegistryException(
1136             OUString( RTL_CONSTASCII_USTRINGPARAM( "prepareRegistry(): source registry is empty" ) ),
1137             Reference< XInterface > () );
1138     }
1139 
1140     const StringPool & pool = spool();
1141 
1142     const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray();
1143     Reference < XRegistryKey > xImplKey;
1144 
1145     for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
1146     {
1147         xImplKey = pSubKeys[i];
1148 
1149         Reference < XRegistryKey >  xKey = xImplKey->openKey(
1150             pool.slash_UNO_slash_SERVICES );
1151 
1152         if (xKey.is())
1153         {
1154             // update entries in SERVICES section
1155             Sequence< Reference < XRegistryKey > > serviceKeys = xKey->openKeys();
1156             const Reference < XRegistryKey > * pServiceKeys = serviceKeys.getConstArray();
1157 
1158             OUString implName = OUString(xImplKey->getKeyName().getStr() + 1);
1159             sal_Int32 firstDot = implName.indexOf('/');
1160 
1161             if (firstDot >= 0)
1162                 implName = implName.copy(firstDot + 1);
1163 
1164             sal_Int32 offset = xKey->getKeyName().getLength() + 1;
1165 
1166             for (sal_Int32 j = 0; j < serviceKeys.getLength(); j++)
1167             {
1168                 OUString serviceName = pServiceKeys[j]->getKeyName().copy(offset);
1169 
1170                 createUniqueSubEntry(
1171                     xDest->getRootKey()->createKey(
1172                         pool.slash_SERVICES + serviceName ),
1173                     implName);
1174             }
1175 
1176             xKey = xImplKey->openKey( pool.slash_UNO );
1177             if (xKey.is())
1178             {
1179                 Sequence< Reference < XRegistryKey > > subKeys2 = xKey->openKeys();
1180 
1181                 if (subKeys2.getLength())
1182                 {
1183                     const Reference < XRegistryKey > * pSubKeys2 = subKeys2.getConstArray();
1184 
1185                     for (sal_Int32 j = 0; j < subKeys2.getLength(); j++)
1186                     {
1187                         if (pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SERVICES) &&
1188                             pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_REGISTRY_LINKS ) &&
1189                             pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SINGLETONS ))
1190                         {
1191                             prepareUserKeys(xDest, xKey, pSubKeys2[j], implName, sal_True);
1192                         }
1193                     }
1194                 }
1195             }
1196         }
1197 
1198         // update LOCATION entry
1199         xKey = xImplKey->createKey( pool.slash_UNO_slash_LOCATION );
1200 
1201         if (xKey.is())
1202         {
1203             xKey->setAsciiValue(locationUrl);
1204         }
1205 
1206         // update ACTIVATOR entry
1207         xKey = xImplKey->createKey( pool.slash_UNO_slash_ACTIVATOR );
1208 
1209         if (xKey.is())
1210         {
1211             xKey->setAsciiValue(implementationLoaderUrl);
1212         }
1213 
1214         xKey = xImplKey->openKey( pool.slash_UNO_slash_SERVICES );
1215 
1216         if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCIILIST))
1217         {
1218             // update link entries in REGISTRY_LINKS section
1219             Sequence<OUString> linkNames = xKey->getAsciiListValue();
1220 
1221             if (linkNames.getLength())
1222             {
1223                 const OUString* pLinkNames = linkNames.getConstArray();
1224 
1225                 for (sal_Int32 j = 0; j < linkNames.getLength(); j++)
1226                 {
1227                     prepareLink(xDest, xImplKey, pLinkNames[j]);
1228                 }
1229             }
1230         }
1231 
1232         insert_singletons( xDest, xImplKey, xContext );
1233     }
1234 }
1235 
1236 
1237 static void findImplementations(	const Reference < XRegistryKey > & xSource,
1238 									std::list <OUString>& implNames)
1239 {
1240 	sal_Bool isImplKey = sal_False;
1241 
1242 	try
1243 	{
1244 		Reference < XRegistryKey > xKey = xSource->openKey(
1245 			spool().slash_UNO_slash_SERVICES );
1246 
1247 		if (xKey.is() && (xKey->getKeyNames().getLength() > 0))
1248 		{
1249 			isImplKey = sal_True;
1250 
1251 			OUString implName = OUString(xSource->getKeyName().getStr() + 1).replace('/', '.').getStr();
1252 			sal_Int32 firstDot = implName.indexOf('.');
1253 
1254 			if (firstDot >= 0)
1255 				implName = implName.copy(firstDot + 1);
1256 
1257 			implNames.push_back(implName);
1258 		}
1259 	}
1260 	catch(InvalidRegistryException&)
1261 	{
1262 	}
1263 
1264 	if (isImplKey) return;
1265 
1266 	try
1267 	{
1268 		Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys();
1269 
1270 		if (subKeys.getLength() > 0)
1271 		{
1272 			const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray();
1273 
1274 			for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
1275 			{
1276 				findImplementations(pSubKeys[i], implNames);
1277 			}
1278 
1279 		}
1280 	}
1281 	catch(InvalidRegistryException&)
1282 	{
1283 	}
1284 }
1285 
1286 
1287 class ImplementationRegistration
1288 	: public WeakImplHelper3< XImplementationRegistration2, XServiceInfo, XInitialization >
1289 {
1290 public:
1291     ImplementationRegistration( const Reference < XComponentContext > & rSMgr );
1292     ~ImplementationRegistration();
1293 
1294 	// XServiceInfo
1295 	OUString 						SAL_CALL getImplementationName() throw(RuntimeException);
1296     sal_Bool 						SAL_CALL supportsService(const OUString& ServiceName) throw(RuntimeException);
1297     Sequence< OUString > 			SAL_CALL getSupportedServiceNames(void) throw(RuntimeException);
1298 
1299 	// XImplementationRegistration
1300     virtual void SAL_CALL registerImplementation(
1301 		const OUString& implementationLoader,
1302 		const OUString& location,
1303 		const Reference < XSimpleRegistry > & xReg)
1304 		throw(	CannotRegisterImplementationException, RuntimeException );
1305 
1306     virtual sal_Bool SAL_CALL revokeImplementation(
1307 		const OUString& location,
1308 		const Reference < XSimpleRegistry >& xReg)
1309 		throw( RuntimeException );
1310 
1311     virtual Sequence< OUString > SAL_CALL getImplementations(
1312 		const OUString& implementationLoader,
1313 		const OUString& location)
1314 		throw( RuntimeException );
1315     virtual Sequence< OUString > SAL_CALL checkInstantiation(
1316 		const OUString& implementationName)
1317 		throw( RuntimeException );
1318 
1319 	// XImplementationRegistration2
1320     virtual void SAL_CALL registerImplementationWithLocation(
1321 		const OUString& implementationLoader,
1322 		const OUString& location,
1323         const OUString& registeredLocation,
1324 		const Reference < XSimpleRegistry > & xReg)
1325 		throw(	CannotRegisterImplementationException, RuntimeException );
1326 
1327     // XInitialization
1328     virtual void SAL_CALL initialize(
1329 		const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments )
1330 		throw(	::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
1331 
1332 private: // helper methods
1333     void prepareRegister(
1334 		const OUString& implementationLoader,
1335 		const OUString& location,
1336         const OUString& registeredLocation,
1337 		const Reference < XSimpleRegistry > & xReg);
1338     // throw( CannotRegisterImplementationException, RuntimeException )
1339 
1340 	static void doRegister(	const Reference < XMultiComponentFactory >& xSMgr,
1341                             const Reference < XComponentContext > &xCtx,
1342                             const Reference < XImplementationLoader >& xAct,
1343                             const Reference < XSimpleRegistry >& xDest,
1344                             const OUString& implementationLoaderUrl,
1345                             const OUString& locationUrl,
1346                             const OUString& registeredLocationUrl);
1347         /* throw ( InvalidRegistryException,
1348                    MergeConflictException,
1349                    CannotRegisterImplementationException, RuntimeException ) */
1350 
1351     static void doRevoke( const Reference < XSimpleRegistry >& xDest,
1352                           const OUString& locationUrl );
1353         // throw( InvalidRegistryException, RuntimeException )
1354 	Reference< XSimpleRegistry > getRegistryFromServiceManager();
1355 
1356 	static Reference< XSimpleRegistry > createTemporarySimpleRegistry(
1357 		const Reference< XMultiComponentFactory > &rSMgr,
1358 		const Reference < XComponentContext > & rCtx );
1359 
1360 private: // members
1361 	Reference < XMultiComponentFactory >	m_xSMgr;
1362 	Reference < XComponentContext >         m_xCtx;
1363 };
1364 
1365 //*************************************************************************
1366 // ImplementationRegistration()
1367 //
1368 ImplementationRegistration::ImplementationRegistration( const Reference < XComponentContext > & xCtx )
1369 	: m_xSMgr( xCtx->getServiceManager() )
1370 	, m_xCtx( xCtx )
1371 {
1372 	g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
1373 }
1374 
1375 //*************************************************************************
1376 // ~ImplementationRegistration()
1377 //
1378 ImplementationRegistration::~ImplementationRegistration()
1379 {
1380 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
1381 }
1382 
1383 
1384 // XServiceInfo
1385 OUString ImplementationRegistration::getImplementationName() throw(RuntimeException)
1386 {
1387 	return stoc_bootstrap::impreg_getImplementationName();
1388 }
1389 
1390 // XServiceInfo
1391 sal_Bool ImplementationRegistration::supportsService(const OUString& ServiceName) throw(RuntimeException)
1392 {
1393 	Sequence< OUString > aSNL = getSupportedServiceNames();
1394 	const OUString * pArray = aSNL.getConstArray();
1395 	for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1396 		if( pArray[i] == ServiceName )
1397 			return sal_True;
1398 	return sal_False;
1399 }
1400 
1401 // XServiceInfo
1402 Sequence< OUString > ImplementationRegistration::getSupportedServiceNames(void) throw(RuntimeException)
1403 {
1404 	return stoc_bootstrap::impreg_getSupportedServiceNames();
1405 }
1406 
1407 Reference< XSimpleRegistry > ImplementationRegistration::getRegistryFromServiceManager()
1408 {
1409 	Reference < XPropertySet > xPropSet( m_xSMgr, UNO_QUERY );
1410 	Reference < XSimpleRegistry > xRegistry;
1411 
1412 	if( xPropSet.is() ) {
1413 
1414 		try {  // the implementation does not support XIntrospectionAccess !
1415 
1416 			Any aAny = xPropSet->getPropertyValue( spool().Registry );
1417 
1418 			if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )	{
1419 				aAny >>= xRegistry;
1420 			}
1421 	 	}
1422 	 	catch( UnknownPropertyException & ) {
1423 	 		// empty reference is error signal !
1424 		}
1425 	}
1426 
1427 	return xRegistry;
1428 }
1429 
1430 
1431 //************************************************************************
1432 // XInitialization
1433 //
1434 void ImplementationRegistration::initialize(
1435 	const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArgs )
1436 	throw(	::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1437 {
1438 
1439 	if( aArgs.getLength() != 4 ) {
1440         OUStringBuffer buf;
1441         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
1442             "ImplementationRegistration::initialize() expects 4 parameters, got "));
1443         buf.append( (sal_Int32) aArgs.getLength() );
1444 		throw IllegalArgumentException( buf.makeStringAndClear(),
1445                                         Reference<XInterface > (),
1446                                         0 );
1447 	}
1448 
1449 	Reference< XImplementationLoader > rLoader;
1450 	OUString loaderServiceName;
1451 	OUString locationUrl;
1452 	Reference< XSimpleRegistry > rReg;
1453 
1454 	// 1st argument : An instance of an implementation loader
1455 	if( aArgs.getConstArray()[0].getValueType().getTypeClass() == TypeClass_INTERFACE ) {
1456 		aArgs.getConstArray()[0] >>= rLoader;
1457 	}
1458 	if( !rLoader.is()) {
1459         OUStringBuffer buf;
1460         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
1461             "ImplementationRegistration::initialize() invalid first parameter,"
1462             "expected " ) );
1463         buf.append( getCppuType( &rLoader ).getTypeName() );
1464         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", got " ) );
1465         buf.append( aArgs.getConstArray()[0].getValueTypeName() );
1466 		throw IllegalArgumentException( buf.makeStringAndClear(),
1467                                         Reference< XInterface > (),
1468                                         0 );
1469 	}
1470 
1471 	// 2nd argument : The service name of the loader. This name is written into the registry
1472 	if( aArgs.getConstArray()[1].getValueType().getTypeClass() == TypeClass_STRING ) {
1473 		aArgs.getConstArray()[1] >>= loaderServiceName;
1474 	}
1475 	if( ! loaderServiceName.getLength() ) {
1476         OUStringBuffer buf;
1477         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
1478             "ImplementationRegistration::initialize() invalid second parameter,"
1479             "expected string, got " ) );
1480         buf.append( aArgs.getConstArray()[1].getValueTypeName() );
1481 		throw IllegalArgumentException( buf.makeStringAndClear(),
1482                                         Reference< XInterface > (),
1483                                         0 );
1484 	}
1485 
1486 	// 3rd argument : The file name of the dll, that contains the loader
1487 	if( aArgs.getConstArray()[2].getValueType().getTypeClass() == TypeClass_STRING ) {
1488 		aArgs.getConstArray()[2] >>= locationUrl;
1489 	}
1490 	if( ! locationUrl.getLength() ) {
1491         OUStringBuffer buf;
1492         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
1493             "ImplementationRegistration::initialize() invalid third parameter,"
1494             "expected string, got " ) );
1495         buf.append( aArgs.getConstArray()[2].getValueTypeName() );
1496 		throw IllegalArgumentException( buf.makeStringAndClear(),
1497                                         Reference< XInterface > (),
1498                                         0 );
1499 	}
1500 
1501 	// 4th argument : The registry, the service should be written to
1502 	if( aArgs.getConstArray()[3].getValueType().getTypeClass() == TypeClass_INTERFACE ) {
1503 		aArgs.getConstArray()[3] >>= rReg;
1504 	}
1505 
1506 	if( !rReg.is() ) {
1507 		rReg = getRegistryFromServiceManager();
1508 		if( !rReg.is() ) {
1509             OUStringBuffer buf;
1510             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
1511                 "ImplementationRegistration::initialize() invalid fourth parameter,"
1512                 "expected " ));
1513             buf.append( getCppuType( &rReg ).getTypeName() );
1514             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", got " ) );
1515             buf.append( aArgs.getConstArray()[3].getValueTypeName() );
1516             throw IllegalArgumentException( buf.makeStringAndClear(),
1517                                             Reference< XInterface > (),
1518                                             0 );
1519 		}
1520 	}
1521 
1522 	doRegister(m_xSMgr, m_xCtx, rLoader , rReg, loaderServiceName , locationUrl, locationUrl);
1523 }
1524 
1525 
1526 
1527 //*************************************************************************
1528 // virtual function registerImplementationWithLocation of XImplementationRegistration2
1529 //
1530 void ImplementationRegistration::registerImplementationWithLocation(
1531 	const OUString& implementationLoaderUrl,
1532 	const OUString& locationUrl,
1533     const OUString& registeredLocationUrl,
1534 	const Reference < XSimpleRegistry > & xReg)
1535 	throw( CannotRegisterImplementationException, RuntimeException )
1536 {
1537     prepareRegister(
1538         implementationLoaderUrl, locationUrl, registeredLocationUrl, xReg);
1539 }
1540 
1541 // helper function
1542 void ImplementationRegistration::prepareRegister(
1543 	const OUString& implementationLoaderUrl,
1544 	const OUString& locationUrl,
1545     const OUString& registeredLocationUrl,
1546 	const Reference < XSimpleRegistry > & xReg)
1547 	// throw( CannotRegisterImplementationException, RuntimeException )
1548 {
1549 	OUString implLoaderUrl(implementationLoaderUrl);
1550 	OUString activatorName;
1551 
1552 	if (implementationLoaderUrl.getLength() > 0)
1553 	{
1554 		OUString tmpActivator(implementationLoaderUrl);
1555         sal_Int32 nIndex = 0;
1556 		activatorName = tmpActivator.getToken(0, ':', nIndex );
1557 	} else
1558 	{
1559 		// check locationUrl to find out what kind of loader is needed
1560 		// set iimplLoaderUrl
1561 	}
1562 
1563 	if( m_xSMgr.is() ) {
1564         try
1565         {
1566             Reference < XImplementationLoader > xAct(
1567                 m_xSMgr->createInstanceWithContext(activatorName, m_xCtx) , UNO_QUERY );
1568             if (xAct.is())
1569             {
1570                 Reference < XSimpleRegistry > xRegistry;
1571 
1572                 if (xReg.is())
1573                 {
1574                     // registry supplied by user
1575                     xRegistry = xReg;
1576                 }
1577                 else
1578                 {
1579                     xRegistry = getRegistryFromServiceManager();
1580                 }
1581 
1582                 if ( xRegistry.is())
1583                 {
1584                     doRegister(m_xSMgr, m_xCtx, xAct, xRegistry, implLoaderUrl,
1585                                locationUrl, registeredLocationUrl);
1586                 }
1587             }
1588             else
1589             {
1590                 OUStringBuffer buf( 128 );
1591                 buf.appendAscii( "ImplementationRegistration::registerImplementation() - The service " );
1592                 buf.append( activatorName );
1593                 buf.appendAscii( " cannot be instantiated\n" );
1594                 throw CannotRegisterImplementationException(
1595                     buf.makeStringAndClear(), Reference< XInterface > () );
1596             }
1597         }
1598         catch( CannotRegisterImplementationException & )
1599         {
1600             throw;
1601         }
1602         catch( InvalidRegistryException & e )
1603         {
1604             OUStringBuffer buf;
1605             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
1606                 "ImplementationRegistration::registerImplementation() "
1607                 "InvalidRegistryException during registration (" ));
1608             buf.append( e.Message );
1609             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
1610             throw CannotRegisterImplementationException(
1611                 buf.makeStringAndClear(), Reference< XInterface > () );
1612         }
1613         catch( MergeConflictException & e )
1614         {
1615             OUStringBuffer buf;
1616             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
1617                 "ImplementationRegistration::registerImplementation() "
1618                 "MergeConflictException during registration (" ));
1619             buf.append( e.Message );
1620             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
1621             throw CannotRegisterImplementationException(
1622                 buf.makeStringAndClear(), Reference< XInterface > () );
1623         }
1624 	}
1625 	else
1626     {
1627         throw CannotRegisterImplementationException(
1628             OUString(RTL_CONSTASCII_USTRINGPARAM(
1629                 "ImplementationRegistration::registerImplementation() "
1630                 "no componentcontext available to instantiate loader")),
1631             Reference< XInterface > () );
1632     }
1633 }
1634 
1635 //*************************************************************************
1636 // virtual function registerImplementation of XImplementationRegistration
1637 //
1638 void ImplementationRegistration::registerImplementation(
1639 	const OUString& implementationLoaderUrl,
1640 	const OUString& locationUrl,
1641 	const Reference < XSimpleRegistry > & xReg)
1642 	throw( CannotRegisterImplementationException, RuntimeException )
1643 {
1644     prepareRegister(implementationLoaderUrl, locationUrl, locationUrl, xReg);
1645 }
1646 
1647 
1648 //*************************************************************************
1649 // virtual function revokeImplementation of XImplementationRegistration
1650 //
1651 sal_Bool ImplementationRegistration::revokeImplementation(const OUString& location,
1652 													  const Reference < XSimpleRegistry >& xReg)
1653 	throw ( RuntimeException )
1654 {
1655 	sal_Bool ret = sal_False;
1656 
1657 	Reference < XSimpleRegistry > xRegistry;
1658 
1659 	if (xReg.is()) {
1660 		xRegistry = xReg;
1661 	}
1662 	else {
1663 		Reference < XPropertySet > xPropSet = Reference< XPropertySet >::query( m_xSMgr );
1664 		if( xPropSet.is() ) {
1665 			try {
1666 				Any aAny = xPropSet->getPropertyValue( spool().Registry );
1667 
1668 				if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
1669 				{
1670 					aAny >>= xRegistry;
1671 				}
1672 			}
1673 			catch ( UnknownPropertyException & ) {
1674 			}
1675 		}
1676 	}
1677 
1678 	if (xRegistry.is())
1679 	{
1680         try
1681         {
1682             doRevoke(xRegistry, location);
1683             ret = sal_True;
1684         }
1685         catch( InvalidRegistryException & )
1686         {
1687             // no way to transport the error, as no exception is specified and a runtime
1688             // exception is not appropriate.
1689             OSL_ENSURE( 0 , "InvalidRegistryException during revokeImplementation" );
1690         }
1691 	}
1692 
1693 	return ret;
1694 }
1695 
1696 //*************************************************************************
1697 // virtual function getImplementations of XImplementationRegistration
1698 //
1699 Sequence< OUString > ImplementationRegistration::getImplementations(
1700 	const OUString & implementationLoaderUrl,
1701 	const OUString & locationUrl)
1702 	throw ( RuntimeException )
1703 {
1704 	OUString implLoaderUrl(implementationLoaderUrl);
1705 	OUString activatorName;
1706 
1707 	if (implementationLoaderUrl.getLength() > 0)
1708 	{
1709 		OUString tmpActivator(implementationLoaderUrl);
1710         sal_Int32 nIndex = 0;
1711 		activatorName = tmpActivator.getToken(0, ':', nIndex );
1712 	} else
1713 	{
1714 		// check locationUrl to find out what kind of loader is needed
1715 		// set implLoaderUrl
1716 	}
1717 
1718 	if( m_xSMgr.is() ) {
1719 
1720 		Reference < XImplementationLoader > xAct(
1721 			m_xSMgr->createInstanceWithContext( activatorName, m_xCtx ), UNO_QUERY );
1722 
1723 		if (xAct.is())
1724 		{
1725 
1726 			Reference < XSimpleRegistry > xReg =
1727 				createTemporarySimpleRegistry( m_xSMgr, m_xCtx);
1728 
1729 			if (xReg.is())
1730 			{
1731 				try
1732 				{
1733 					xReg->open(OUString() /* in mem */, sal_False, sal_True);
1734 					Reference < XRegistryKey > xImpl;
1735 
1736 					{ // only necessary	for deleting the temporary variable of rootkey
1737 						xImpl = xReg->getRootKey()->createKey( spool().slash_IMPLEMENTATIONS );
1738 					}
1739 					if (xAct->writeRegistryInfo(xImpl, implementationLoaderUrl, locationUrl))
1740 					{
1741 						std::list <OUString> implNames;
1742 
1743 						findImplementations(xImpl, implNames);
1744 
1745 						if (!implNames.empty())
1746 						{
1747 							std::list<OUString>::const_iterator iter = implNames.begin();
1748 
1749 							Sequence<OUString> seqImpl(implNames.size());
1750 							OUString *pImplNames = seqImpl.getArray();
1751 
1752 							sal_Int32 index = 0;
1753 							while (iter != implNames.end())
1754 							{
1755 								pImplNames[index] = *iter;
1756 								index++;
1757 								++iter;
1758 							}
1759 
1760 							xImpl->closeKey();
1761 							return seqImpl;
1762 						}
1763 					}
1764 
1765 					xImpl->closeKey();
1766 				}
1767 				catch(MergeConflictException&)
1768 				{
1769 				}
1770 				catch(InvalidRegistryException&)
1771 				{
1772 				}
1773 			}
1774 		}
1775 	}
1776 
1777 	return Sequence<OUString>();
1778 }
1779 
1780 //*************************************************************************
1781 // virtual function checkInstantiation of XImplementationRegistration
1782 //
1783 Sequence< OUString > ImplementationRegistration::checkInstantiation(const OUString&)
1784 	throw ( RuntimeException )
1785 {
1786 	OSL_ENSURE( sal_False, "ImplementationRegistration::checkInstantiation not implemented" );
1787 	return Sequence<OUString>();
1788 }
1789 
1790 //*************************************************************************
1791 // helper function doRegistration
1792 //
1793 
1794 void ImplementationRegistration::doRevoke(
1795 	const Reference < XSimpleRegistry >& xDest,
1796 	const OUString& locationUrl)
1797     // throw ( InvalidRegistryException, RuntimeException )
1798 {
1799     if( xDest.is() )
1800     {
1801         std::list<OUString> aNames;
1802 
1803         const StringPool &pool = spool();
1804         Reference < XRegistryKey > xRootKey( xDest->getRootKey() );
1805 
1806         Reference < XRegistryKey > xKey =
1807             xRootKey->openKey( pool.slash_IMPLEMENTATIONS );
1808         if (xKey.is() && xKey->isValid())
1809         {
1810             deleteAllImplementations(xDest, xKey, locationUrl, aNames);
1811         }
1812 
1813         xKey = xRootKey->openKey( pool.slash_SERVICES );
1814         if (xKey.is())
1815         {
1816             std::list<OUString>::const_iterator iter = aNames.begin();
1817 
1818             while (iter != aNames.end())
1819             {
1820                 deleteAllServiceEntries(xDest, xKey, *iter);
1821                 ++iter;
1822             }
1823         }
1824 
1825         xKey = xRootKey->openKey( OUSTR("/SINGLETONS") );
1826         if (xKey.is() && xKey->isValid())
1827         {
1828             delete_all_singleton_entries( xKey, aNames );
1829         }
1830 
1831         if (xRootKey.is())
1832             xRootKey->closeKey();
1833         if (xKey.is() && xKey->isValid() )
1834             xKey->closeKey();
1835     }
1836 }
1837 
1838 void ImplementationRegistration::doRegister(
1839 	const Reference< XMultiComponentFactory > & xSMgr,
1840 	const Reference< XComponentContext > &xCtx,
1841 	const Reference < XImplementationLoader > & xAct,
1842 	const Reference < XSimpleRegistry >& xDest,
1843 	const OUString& implementationLoaderUrl,
1844 	const OUString& locationUrl,
1845     const OUString& registeredLocationUrl)
1846     /* throw ( InvalidRegistryException,
1847                MergeConflictException,
1848                CannotRegisterImplementationException, RuntimeException ) */
1849 {
1850     Reference < XSimpleRegistry > 	xReg =
1851         createTemporarySimpleRegistry( xSMgr, xCtx );
1852     Reference < XRegistryKey > 		xSourceKey;
1853 
1854     if (xAct.is() && xReg.is() && xDest.is())
1855     {
1856         try
1857         {
1858             xReg->open(OUString() /* in mem */, sal_False, sal_True);
1859 
1860             { // only necessary	for deleting the temporary variable of rootkey
1861                 xSourceKey = xReg->getRootKey()->createKey( spool().slash_IMPLEMENTATIONS );
1862             }
1863 
1864             sal_Bool bSuccess =
1865                 xAct->writeRegistryInfo(xSourceKey, implementationLoaderUrl, locationUrl);
1866             if ( bSuccess )
1867             {
1868                 prepareRegistry(xDest, xSourceKey, implementationLoaderUrl, registeredLocationUrl, xCtx);
1869 
1870                 xSourceKey->closeKey();
1871 
1872                 xSourceKey = xReg->getRootKey();
1873                 Reference < XRegistryKey > xDestKey = xDest->getRootKey();
1874                 mergeKeys( xDestKey, xSourceKey );
1875                 xDestKey->closeKey();
1876                 xSourceKey->closeKey();
1877             }
1878             else
1879             {
1880                 throw CannotRegisterImplementationException(
1881                     OUString( RTL_CONSTASCII_USTRINGPARAM( "ImplementationRegistration::doRegistration() component registration signaled failure" ) ),
1882                     Reference< XInterface > () );
1883             }
1884 
1885             // Cleanup Source registry.
1886             if ( xSourceKey->isValid() )
1887                 xSourceKey->closeKey();
1888         }
1889         catch(CannotRegisterImplementationException&)
1890         {
1891             if ( xSourceKey->isValid() )
1892                 xSourceKey->closeKey();
1893             // and throw again
1894             throw;
1895         }
1896     }
1897 }
1898 
1899 
1900 
1901 Reference< XSimpleRegistry > ImplementationRegistration::createTemporarySimpleRegistry(
1902 	const Reference< XMultiComponentFactory > &rSMgr,
1903 	const Reference < XComponentContext > & xCtx)
1904 {
1905 
1906 	Reference < XSimpleRegistry > xReg(
1907 		rSMgr->createInstanceWithContext(
1908 			spool().com_sun_star_registry_SimpleRegistry,	xCtx ),
1909         UNO_QUERY);
1910 	OSL_ASSERT( xReg.is() );
1911 	return xReg;
1912 }
1913 }
1914 
1915 namespace stoc_bootstrap
1916 {
1917 //*************************************************************************
1918 Reference<XInterface> SAL_CALL ImplementationRegistration_CreateInstance(
1919     const Reference<XComponentContext> & xCtx ) // throw(Exception)
1920 {
1921 	return (XImplementationRegistration *)new stoc_impreg::ImplementationRegistration(xCtx);
1922 }
1923 
1924 }
1925 
1926