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