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