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 com::sun::star::uno;
59 : using namespace com::sun::star::loader;
60 : using namespace com::sun::star::beans;
61 : using namespace com::sun::star::lang;
62 : using namespace com::sun::star::registry;
63 : using namespace cppu;
64 : using namespace osl;
65 :
66 : namespace {
67 :
68 0 : 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 0 : 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 0 : , Registry( "Registry" )
93 0 : {}
94 : };
95 :
96 0 : const StringPool &spool()
97 : {
98 : static StringPool *pPool = 0;
99 0 : if( ! pPool )
100 : {
101 0 : MutexGuard guard( Mutex::getGlobalMutex() );
102 0 : if( ! pPool )
103 : {
104 0 : static StringPool pool;
105 0 : pPool = &pool;
106 0 : }
107 : }
108 0 : return *pPool;
109 : }
110 :
111 :
112 : // static deleteAllLinkReferences()
113 :
114 0 : static void deleteAllLinkReferences(const Reference < XSimpleRegistry >& xReg,
115 : const Reference < XRegistryKey >& xSource)
116 : // throw ( InvalidRegistryException, RuntimeException )
117 : {
118 0 : Reference < XRegistryKey > xKey = xSource->openKey(
119 0 : spool().slash_UNO_slash_REGISTRY_LINKS );
120 :
121 0 : 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 0 : }
192 0 : }
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 : sal_Bool isRelativ = sal_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 = sal_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 0 : static void createUniqueSubEntry(const Reference < XRegistryKey > & xSuperKey,
326 : const OUString& value)
327 : // throw ( InvalidRegistryException, RuntimeException )
328 : {
329 0 : if (xSuperKey.is())
330 : {
331 : // try
332 : // {
333 0 : if (xSuperKey->getValueType() == RegistryValueType_ASCIILIST)
334 : {
335 0 : sal_Int32 length = 0;
336 0 : sal_Bool bReady = sal_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 0 : Sequence<OUString> implEntriesNew(1);
371 :
372 0 : implEntriesNew.getArray()[0] = value;
373 :
374 0 : xSuperKey->setAsciiListValue(implEntriesNew);
375 : }
376 : // }
377 : // catch(InvalidRegistryException&)
378 : // {
379 : // }
380 : }
381 0 : }
382 :
383 :
384 : // static deleteSubEntry
385 :
386 0 : static sal_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 : sal_Bool hasNoImplementations = sal_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 = sal_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 sal_True;
423 0 : }
424 : }
425 0 : return sal_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 : sal_Bool bClean = sal_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 : sal_Bool hasNoImplementations = sal_False;
509 :
510 0 : if (xOldKey->getValueType() == RegistryValueType_ASCIILIST)
511 : {
512 0 : Sequence<OUString> implEntries = xOldKey->getAsciiListValue();
513 0 : sal_Int32 length = implEntries.getLength();
514 0 : sal_Int32 equals = 0;
515 :
516 0 : for (sal_Int32 i = 0; i < length; i++)
517 : {
518 0 : if (implEntries.getConstArray()[i] == implName)
519 0 : equals++;
520 : }
521 :
522 0 : if (equals == length)
523 : {
524 0 : hasNoImplementations = sal_True;
525 : } else
526 : {
527 0 : OUString oldImpl;
528 :
529 0 : if (length > equals + 1)
530 : {
531 0 : Sequence<OUString> implEntriesNew(length - equals - 1);
532 :
533 0 : sal_Int32 j = 0;
534 0 : sal_Bool first = sal_True;
535 0 : for (sal_Int32 i = 0; i < length; i++)
536 : {
537 0 : if (implEntries.getConstArray()[i] != implName)
538 : {
539 0 : if (first)
540 : {
541 0 : oldImpl = implEntries.getConstArray()[i];
542 0 : first = sal_False;
543 : } else
544 : {
545 0 : implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i];
546 : }
547 : }
548 : }
549 :
550 0 : xOldKey->setAsciiListValue(implEntriesNew);
551 : } else
552 : {
553 0 : oldImpl = implEntries.getConstArray()[0];
554 0 : OUString path(xOldKey->getKeyName());
555 0 : xOldKey->closeKey();
556 0 : xRootKey->deleteKey(path);
557 : }
558 :
559 0 : OUString oldTarget = searchLinkTargetForImpl(xRootKey, linkName, oldImpl);
560 0 : if (!oldTarget.isEmpty())
561 : {
562 0 : xRootKey->createLink(linkName, oldTarget);
563 0 : }
564 : }
565 :
566 0 : if (hasNoImplementations)
567 : {
568 0 : bClean = sal_True;
569 0 : hasNoImplementations = sal_False;
570 0 : OUString path(xOldKey->getKeyName());
571 0 : xOldKey->closeKey();
572 0 : xRootKey->deleteKey(path);
573 0 : }
574 : }
575 : } else
576 : {
577 0 : bClean = sal_True;
578 : }
579 :
580 0 : if (bClean)
581 : {
582 0 : OUString tmpName(linkName);
583 0 : OUString path = tmpName.copy(0, tmpName.lastIndexOf('/'));
584 0 : deletePathIfPossible(xRootKey, path);
585 0 : }
586 0 : }
587 :
588 :
589 : // static prepareUserKeys
590 :
591 0 : static void prepareUserKeys(const Reference < XSimpleRegistry >& xDest,
592 : const Reference < XRegistryKey >& xUnoKey,
593 : const Reference < XRegistryKey >& xKey,
594 : const OUString& implName,
595 : sal_Bool bRegister)
596 : {
597 0 : sal_Bool hasSubKeys = sal_False;
598 :
599 0 : Sequence<OUString> keyNames = xKey->getKeyNames();
600 :
601 0 : OUString relativKey;
602 0 : if (keyNames.getLength())
603 0 : relativKey = keyNames.getConstArray()[0].copy(xKey->getKeyName().getLength()+1);
604 :
605 0 : if (keyNames.getLength() == 1 &&
606 0 : xKey->getKeyType(relativKey) == RegistryKeyType_LINK)
607 : {
608 0 : hasSubKeys = sal_True;
609 :
610 0 : OUString linkTarget = xKey->getLinkTarget(relativKey);
611 0 : OUString linkName(xKey->getKeyName().copy(xUnoKey->getKeyName().getLength()));
612 :
613 0 : linkName = linkName + "/" + relativKey;
614 :
615 0 : if (bRegister)
616 : {
617 0 : prepareUserLink(xDest, linkName, linkTarget, implName);
618 : } else
619 : {
620 0 : deleteUserLink(xDest->getRootKey(), linkName, linkTarget, implName);
621 0 : }
622 : } else
623 : {
624 0 : Sequence< Reference < XRegistryKey> > subKeys = xKey->openKeys();
625 :
626 0 : if (subKeys.getLength())
627 : {
628 0 : hasSubKeys = sal_True;
629 0 : const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray();
630 :
631 0 : for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
632 : {
633 0 : prepareUserKeys(xDest, xUnoKey, pSubKeys[i], implName, bRegister);
634 : }
635 0 : }
636 : }
637 :
638 0 : if (! hasSubKeys)
639 : {
640 0 : OUString keyName(xKey->getKeyName().copy(xUnoKey->getKeyName().getLength()));
641 :
642 0 : Reference < XRegistryKey > xRootKey = xDest->getRootKey();
643 0 : if (bRegister)
644 : {
645 0 : createUniqueSubEntry(xRootKey->createKey(keyName), implName);
646 : }
647 : else
648 : {
649 0 : Reference< XRegistryKey > rKey = xRootKey->openKey(keyName);
650 0 : if( rKey.is() )
651 : {
652 0 : deleteSubEntry(rKey, implName);
653 0 : xRootKey->deleteKey(keyName);
654 : }
655 :
656 0 : OUString path = keyName.copy(0, keyName.lastIndexOf('/'));
657 0 : if( !path.isEmpty() )
658 : {
659 0 : deletePathIfPossible(xRootKey, path);
660 0 : }
661 0 : }
662 0 : }
663 0 : }
664 :
665 :
666 : // static deleteAllImplementations
667 :
668 0 : static void deleteAllImplementations( const Reference < XSimpleRegistry >& xReg,
669 : const Reference < XRegistryKey >& xSource,
670 : const OUString& locationUrl,
671 : std::list<OUString> & implNames)
672 : // throw (InvalidRegistryException, RuntimeException)
673 : {
674 0 : Sequence < Reference < XRegistryKey > > subKeys = xSource->openKeys();
675 :
676 0 : if (subKeys.getLength() > 0)
677 : {
678 0 : const Reference < XRegistryKey> * pSubKeys = subKeys.getConstArray();
679 0 : Reference < XRegistryKey > xImplKey;
680 0 : sal_Bool hasLocationUrl = sal_False;
681 :
682 0 : const StringPool &pool = spool();
683 0 : for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
684 : {
685 0 : xImplKey = pSubKeys[i];
686 0 : Reference < XRegistryKey > xKey = xImplKey->openKey(
687 0 : pool.slash_UNO_slash_LOCATION );
688 :
689 0 : if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCII))
690 : {
691 0 : if (xKey->getAsciiValue() == locationUrl)
692 : {
693 0 : hasLocationUrl = sal_True;
694 :
695 0 : OUString implName(xImplKey->getKeyName().getStr() + 1);
696 0 : sal_Int32 firstDot = implName.indexOf('/');
697 :
698 0 : if (firstDot >= 0)
699 0 : implName = implName.copy(firstDot + 1);
700 :
701 0 : implNames.push_back(implName);
702 :
703 0 : deleteAllLinkReferences(xReg, xImplKey);
704 :
705 0 : xKey = xImplKey->openKey( pool.slash_UNO );
706 0 : if (xKey.is())
707 : {
708 0 : Sequence< Reference < XRegistryKey > > subKeys2 = xKey->openKeys();
709 :
710 0 : if (subKeys2.getLength())
711 : {
712 0 : const Reference < XRegistryKey > * pSubKeys2 = subKeys2.getConstArray();
713 :
714 0 : for (sal_Int32 j = 0; j < subKeys2.getLength(); j++)
715 : {
716 0 : if (pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SERVICES ) &&
717 0 : pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_REGISTRY_LINKS ) &&
718 0 : pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_ACTIVATOR ) &&
719 0 : pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SINGLETONS ) &&
720 0 : pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_LOCATION) )
721 : {
722 0 : prepareUserKeys(xReg, xKey, pSubKeys2[j], implName, sal_False);
723 : }
724 : }
725 0 : }
726 0 : }
727 : }
728 : }
729 :
730 0 : if (hasLocationUrl)
731 : {
732 0 : hasLocationUrl = sal_False;
733 0 : OUString path(xImplKey->getKeyName());
734 0 : xImplKey->closeKey();
735 0 : xReg->getRootKey()->deleteKey(path);
736 : }
737 0 : }
738 :
739 0 : subKeys = xSource->openKeys();
740 0 : if (subKeys.getLength() == 0)
741 : {
742 0 : OUString path(xSource->getKeyName());
743 0 : xSource->closeKey();
744 0 : xReg->getRootKey()->deleteKey(path);
745 0 : }
746 : } else
747 : {
748 0 : OUString path(xSource->getKeyName());
749 0 : xSource->closeKey();
750 0 : xReg->getRootKey()->deleteKey(path);
751 0 : }
752 0 : }
753 :
754 :
755 0 : static void delete_all_singleton_entries(
756 : Reference < registry::XRegistryKey > const & xSingletons_section,
757 : ::std::list< OUString > const & impl_names )
758 : // throw (InvalidRegistryException, RuntimeException)
759 : {
760 0 : Sequence< Reference< registry::XRegistryKey > > singletons( xSingletons_section->openKeys() );
761 0 : Reference< registry::XRegistryKey > const * subkeys = singletons.getConstArray();
762 0 : for ( sal_Int32 nPos = singletons.getLength(); nPos--; )
763 : {
764 0 : Reference< registry::XRegistryKey > const & xSingleton = subkeys[ nPos ];
765 : Reference< registry::XRegistryKey > xRegisteredImplNames(
766 0 : xSingleton->openKey( "REGISTERED_BY" ) );
767 0 : if (xRegisteredImplNames.is() && xRegisteredImplNames->isValid())
768 : {
769 0 : Sequence< OUString > registered_implnames;
770 : try
771 : {
772 0 : registered_implnames = xRegisteredImplNames->getAsciiListValue();
773 : }
774 0 : catch (registry::InvalidValueException &)
775 : {
776 : }
777 0 : OUString const * p = registered_implnames.getConstArray();
778 0 : sal_Int32 nOrigRegLength = registered_implnames.getLength();
779 0 : sal_Int32 nNewLength = nOrigRegLength;
780 0 : for ( sal_Int32 n = nOrigRegLength; n--; )
781 : {
782 0 : OUString const & registered_implname = p[ n ];
783 :
784 0 : ::std::list< OUString >::const_iterator iPos( impl_names.begin() );
785 0 : ::std::list< OUString >::const_iterator const iEnd( impl_names.end() );
786 0 : for ( ; iPos != iEnd; ++iPos )
787 : {
788 0 : if (iPos->equals( registered_implname ))
789 : {
790 0 : registered_implnames[ n ] = p[ nNewLength -1 ];
791 0 : --nNewLength;
792 : }
793 : }
794 : }
795 :
796 0 : if (nNewLength != nOrigRegLength)
797 : {
798 0 : if (0 == nNewLength)
799 : {
800 : // remove whole entry
801 0 : xRegisteredImplNames->closeKey();
802 0 : xSingleton->deleteKey( "REGISTERED_BY" );
803 : // registry key cannot provide its relative name, only absolute :(
804 0 : OUString abs( xSingleton->getKeyName() );
805 0 : xSingletons_section->deleteKey( abs.copy( abs.lastIndexOf( '/' ) +1 ) );
806 : }
807 : else
808 : {
809 0 : registered_implnames.realloc( nNewLength );
810 0 : xRegisteredImplNames->setAsciiListValue( registered_implnames );
811 : }
812 0 : }
813 : }
814 0 : }
815 0 : }
816 :
817 :
818 : // static deleteAllServiceEntries
819 :
820 0 : static void deleteAllServiceEntries( const Reference < XSimpleRegistry >& xReg,
821 : const Reference < XRegistryKey >& xSource,
822 : const OUString& implName)
823 : // throw ( InvalidRegistryException, RuntimeException )
824 : {
825 0 : Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys();
826 :
827 0 : if (subKeys.getLength() > 0)
828 : {
829 0 : const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray();
830 0 : Reference < XRegistryKey > xServiceKey;
831 0 : sal_Bool hasNoImplementations = sal_False;
832 :
833 0 : for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
834 : {
835 0 : xServiceKey = pSubKeys[i];
836 :
837 0 : if (xServiceKey->getValueType() == RegistryValueType_ASCIILIST)
838 : {
839 0 : Sequence<OUString> implEntries = xServiceKey->getAsciiListValue();
840 0 : sal_Int32 length = implEntries.getLength();
841 0 : sal_Int32 equals = 0;
842 :
843 0 : for (sal_Int32 j = 0; j < length; j++)
844 : {
845 0 : if (implEntries.getConstArray()[j] == implName)
846 0 : equals++;
847 : }
848 :
849 0 : if (equals == length)
850 : {
851 0 : hasNoImplementations = sal_True;
852 : } else
853 : {
854 0 : if (equals > 0)
855 : {
856 0 : Sequence<OUString> implEntriesNew(length-equals);
857 :
858 0 : sal_Int32 j = 0;
859 0 : for (sal_Int32 k = 0; k < length; k++)
860 : {
861 0 : if (implEntries.getConstArray()[k] != implName)
862 : {
863 0 : implEntriesNew.getArray()[j++] = implEntries.getConstArray()[k];
864 : }
865 : }
866 :
867 0 : xServiceKey->setAsciiListValue(implEntriesNew);
868 : }
869 0 : }
870 : }
871 :
872 0 : if (hasNoImplementations)
873 : {
874 0 : hasNoImplementations = sal_False;
875 0 : OUString path(xServiceKey->getKeyName());
876 0 : xServiceKey->closeKey();
877 0 : xReg->getRootKey()->deleteKey(path);
878 : }
879 : }
880 :
881 0 : subKeys = xSource->openKeys();
882 0 : if (subKeys.getLength() == 0)
883 : {
884 0 : OUString path(xSource->getKeyName());
885 0 : xSource->closeKey();
886 0 : xReg->getRootKey()->deleteKey(path);
887 0 : }
888 : } else
889 : {
890 0 : OUString path(xSource->getKeyName());
891 0 : xSource->closeKey();
892 0 : xReg->getRootKey()->deleteKey(path);
893 0 : }
894 0 : }
895 :
896 :
897 0 : static bool is_supported_service(
898 : OUString const & service_name,
899 : Reference< reflection::XServiceTypeDescription > const & xService_td )
900 : {
901 0 : if (xService_td->getName().equals( service_name ))
902 0 : return true;
903 : Sequence< Reference< reflection::XServiceTypeDescription > > seq(
904 0 : xService_td->getMandatoryServices() );
905 0 : Reference< reflection::XServiceTypeDescription > const * p = seq.getConstArray();
906 0 : for ( sal_Int32 nPos = seq.getLength(); nPos--; )
907 : {
908 0 : if (is_supported_service( service_name, p[ nPos ] ))
909 0 : return true;
910 : }
911 0 : return false;
912 : }
913 :
914 :
915 0 : static void insert_singletons(
916 : Reference< registry::XSimpleRegistry > const & xDest,
917 : Reference< registry::XRegistryKey > const & xImplKey,
918 : Reference< XComponentContext > const & xContext )
919 : // throw( registry::InvalidRegistryException, registry::CannotRegisterImplementationException, RuntimeException )
920 : {
921 : // singletons
922 0 : Reference< registry::XRegistryKey > xKey( xImplKey->openKey( "UNO/SINGLETONS" ) );
923 0 : if (xKey.is() && xKey->isValid())
924 : {
925 0 : OUString implname( xImplKey->getKeyName().copy( sizeof ("/IMPLEMENTATIONS/") -1 ) );
926 : // singleton entries
927 0 : Sequence< Reference< registry::XRegistryKey > > xSingletons_section( xKey->openKeys() );
928 0 : Reference< registry::XRegistryKey > const * p = xSingletons_section.getConstArray();
929 0 : for ( sal_Int32 nPos = xSingletons_section.getLength(); nPos--; )
930 : {
931 0 : Reference< registry::XRegistryKey > const & xSingleton = p[ nPos ];
932 : OUString singleton_name(
933 0 : xSingleton->getKeyName().copy(
934 0 : implname.getLength() + sizeof ("/IMPLEMENTATIONS//UNO/SINGLETONS/") -1 ) );
935 0 : OUString service_name( xSingleton->getStringValue() );
936 :
937 0 : OUString keyname( "/SINGLETONS/" + singleton_name );
938 0 : Reference< registry::XRegistryKey > xKey2( xDest->getRootKey()->openKey( keyname ) );
939 0 : if (xKey2.is() && xKey2->isValid())
940 : {
941 : try
942 : {
943 0 : OUString existing_name( xKey2->getStringValue() );
944 0 : if (! existing_name.equals( service_name ))
945 : {
946 0 : Reference< container::XHierarchicalNameAccess > xTDMgr;
947 : OUString the_tdmgr =
948 0 : "/singletons/com.sun.star.reflection.theTypeDescriptionManager";
949 0 : xContext->getValueByName( the_tdmgr ) >>= xTDMgr;
950 0 : if (! xTDMgr.is())
951 : {
952 : throw RuntimeException(
953 0 : "cannot get singleton " + the_tdmgr,
954 0 : Reference< XInterface >() );
955 : }
956 : try
957 : {
958 0 : Reference< reflection::XServiceTypeDescription > xExistingService_td;
959 0 : xTDMgr->getByHierarchicalName( existing_name ) >>= xExistingService_td;
960 0 : if (! xExistingService_td.is())
961 : {
962 : throw RuntimeException(
963 0 : "cannot get service type description: " + existing_name,
964 0 : Reference< XInterface >() );
965 : }
966 :
967 : // everything's fine if existing service entry supports the one
968 : // to be registered
969 0 : if (! is_supported_service( service_name, xExistingService_td ))
970 : {
971 0 : OUStringBuffer buf( 64 );
972 0 : buf.append( "existing singleton service (" );
973 0 : buf.append( singleton_name );
974 0 : buf.append( '=' );
975 0 : buf.append( existing_name );
976 0 : buf.append( ") does not support given one: " );
977 0 : buf.append( service_name );
978 : throw registry::CannotRegisterImplementationException(
979 0 : buf.makeStringAndClear(), Reference< XInterface >() );
980 0 : }
981 : }
982 0 : catch (const container::NoSuchElementException & exc)
983 : {
984 : throw RuntimeException(
985 0 : "cannot get service type description: " + exc.Message,
986 0 : Reference< XInterface >() );
987 0 : }
988 0 : }
989 : }
990 0 : catch (registry::InvalidValueException &)
991 : {
992 : // repair
993 0 : xKey2->setStringValue( service_name );
994 : }
995 : }
996 : else
997 : {
998 : // insert singleton entry
999 0 : xKey2 = xDest->getRootKey()->createKey( keyname );
1000 0 : xKey2->setStringValue( service_name );
1001 : }
1002 :
1003 : Reference< registry::XRegistryKey > xRegisteredImplNames(
1004 0 : xKey2->openKey( "REGISTERED_BY" ) );
1005 0 : if (!xRegisteredImplNames.is() || !xRegisteredImplNames->isValid())
1006 : {
1007 : // create
1008 0 : xRegisteredImplNames = xKey2->createKey( "REGISTERED_BY" );
1009 : }
1010 :
1011 0 : Sequence< OUString > implnames;
1012 : try
1013 : {
1014 0 : implnames = xRegisteredImplNames->getAsciiListValue();
1015 : }
1016 0 : catch (registry::InvalidValueException &)
1017 : {
1018 : }
1019 : // check implname is already in
1020 0 : sal_Int32 nPos_implnames = implnames.getLength();
1021 0 : OUString const * pImplnames = implnames.getConstArray();
1022 0 : while (nPos_implnames--)
1023 : {
1024 0 : if (implname.equals( pImplnames[ nPos_implnames ] ))
1025 0 : break;
1026 : }
1027 0 : if (nPos_implnames < 0)
1028 : {
1029 : // append and write back
1030 0 : implnames.realloc( implnames.getLength() +1 );
1031 0 : implnames[ implnames.getLength() -1 ] = implname;
1032 0 : xRegisteredImplNames->setAsciiListValue( implnames );
1033 : }
1034 0 : }
1035 0 : }
1036 0 : }
1037 :
1038 :
1039 :
1040 : // static prepareRegistry
1041 :
1042 0 : static void prepareRegistry(
1043 : const Reference < XSimpleRegistry >& xDest,
1044 : const Reference < XRegistryKey >& xSource,
1045 : const OUString& implementationLoaderUrl,
1046 : const OUString& locationUrl,
1047 : Reference< XComponentContext > const & xContext )
1048 : // throw ( InvalidRegistryException, CannotRegisterImplementationException, RuntimeException )
1049 : {
1050 0 : Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys();
1051 :
1052 0 : if (!subKeys.getLength())
1053 : {
1054 : throw InvalidRegistryException(
1055 : OUString( "prepareRegistry(): source registry is empty" ),
1056 0 : Reference< XInterface > () );
1057 : }
1058 :
1059 0 : const StringPool & pool = spool();
1060 :
1061 0 : const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray();
1062 0 : Reference < XRegistryKey > xImplKey;
1063 :
1064 0 : for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
1065 : {
1066 0 : xImplKey = pSubKeys[i];
1067 :
1068 0 : Reference < XRegistryKey > xKey = xImplKey->openKey(
1069 0 : pool.slash_UNO_slash_SERVICES );
1070 :
1071 0 : if (xKey.is())
1072 : {
1073 : // update entries in SERVICES section
1074 0 : Sequence< Reference < XRegistryKey > > serviceKeys = xKey->openKeys();
1075 0 : const Reference < XRegistryKey > * pServiceKeys = serviceKeys.getConstArray();
1076 :
1077 0 : OUString implName = OUString(xImplKey->getKeyName().getStr() + 1);
1078 0 : sal_Int32 firstDot = implName.indexOf('/');
1079 :
1080 0 : if (firstDot >= 0)
1081 0 : implName = implName.copy(firstDot + 1);
1082 :
1083 0 : sal_Int32 offset = xKey->getKeyName().getLength() + 1;
1084 :
1085 0 : for (sal_Int32 j = 0; j < serviceKeys.getLength(); j++)
1086 : {
1087 0 : OUString serviceName = pServiceKeys[j]->getKeyName().copy(offset);
1088 :
1089 : createUniqueSubEntry(
1090 0 : xDest->getRootKey()->createKey(
1091 0 : pool.slash_SERVICES + serviceName ),
1092 0 : implName);
1093 0 : }
1094 :
1095 0 : xKey = xImplKey->openKey( pool.slash_UNO );
1096 0 : if (xKey.is())
1097 : {
1098 0 : Sequence< Reference < XRegistryKey > > subKeys2 = xKey->openKeys();
1099 :
1100 0 : if (subKeys2.getLength())
1101 : {
1102 0 : const Reference < XRegistryKey > * pSubKeys2 = subKeys2.getConstArray();
1103 :
1104 0 : for (sal_Int32 j = 0; j < subKeys2.getLength(); j++)
1105 : {
1106 0 : if (pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SERVICES) &&
1107 0 : pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_REGISTRY_LINKS ) &&
1108 0 : pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SINGLETONS ))
1109 : {
1110 0 : prepareUserKeys(xDest, xKey, pSubKeys2[j], implName, sal_True);
1111 : }
1112 : }
1113 0 : }
1114 0 : }
1115 : }
1116 :
1117 : // update LOCATION entry
1118 0 : xKey = xImplKey->createKey( pool.slash_UNO_slash_LOCATION );
1119 :
1120 0 : if (xKey.is())
1121 : {
1122 0 : xKey->setAsciiValue(locationUrl);
1123 : }
1124 :
1125 : // update ACTIVATOR entry
1126 0 : xKey = xImplKey->createKey( pool.slash_UNO_slash_ACTIVATOR );
1127 :
1128 0 : if (xKey.is())
1129 : {
1130 0 : xKey->setAsciiValue(implementationLoaderUrl);
1131 : }
1132 :
1133 0 : xKey = xImplKey->openKey( pool.slash_UNO_slash_SERVICES );
1134 :
1135 0 : if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCIILIST))
1136 : {
1137 : // update link entries in REGISTRY_LINKS section
1138 0 : Sequence<OUString> linkNames = xKey->getAsciiListValue();
1139 :
1140 0 : if (linkNames.getLength())
1141 : {
1142 0 : const OUString* pLinkNames = linkNames.getConstArray();
1143 :
1144 0 : for (sal_Int32 j = 0; j < linkNames.getLength(); j++)
1145 : {
1146 0 : prepareLink(xDest, xImplKey, pLinkNames[j]);
1147 : }
1148 0 : }
1149 : }
1150 :
1151 0 : insert_singletons( xDest, xImplKey, xContext );
1152 0 : }
1153 0 : }
1154 :
1155 :
1156 0 : static void findImplementations( const Reference < XRegistryKey > & xSource,
1157 : std::list <OUString>& implNames)
1158 : {
1159 0 : sal_Bool isImplKey = sal_False;
1160 :
1161 : try
1162 : {
1163 0 : Reference < XRegistryKey > xKey = xSource->openKey(
1164 0 : spool().slash_UNO_slash_SERVICES );
1165 :
1166 0 : if (xKey.is() && (xKey->getKeyNames().getLength() > 0))
1167 : {
1168 0 : isImplKey = sal_True;
1169 :
1170 0 : OUString implName = OUString(xSource->getKeyName().getStr() + 1).replace('/', '.').getStr();
1171 0 : sal_Int32 firstDot = implName.indexOf('.');
1172 :
1173 0 : if (firstDot >= 0)
1174 0 : implName = implName.copy(firstDot + 1);
1175 :
1176 0 : implNames.push_back(implName);
1177 0 : }
1178 : }
1179 0 : catch(InvalidRegistryException&)
1180 : {
1181 : }
1182 :
1183 0 : if (isImplKey) return;
1184 :
1185 : try
1186 : {
1187 0 : Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys();
1188 :
1189 0 : if (subKeys.getLength() > 0)
1190 : {
1191 0 : const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray();
1192 :
1193 0 : for (sal_Int32 i = 0; i < subKeys.getLength(); i++)
1194 : {
1195 0 : findImplementations(pSubKeys[i], implNames);
1196 : }
1197 :
1198 0 : }
1199 : }
1200 0 : catch(InvalidRegistryException&)
1201 : {
1202 : }
1203 : }
1204 :
1205 :
1206 : class ImplementationRegistration
1207 : : public WeakImplHelper3< XImplementationRegistration2, XServiceInfo, XInitialization >
1208 : {
1209 : public:
1210 : ImplementationRegistration( const Reference < XComponentContext > & rSMgr );
1211 : virtual ~ImplementationRegistration();
1212 :
1213 : // XServiceInfo
1214 : OUString SAL_CALL getImplementationName() throw(RuntimeException, std::exception) SAL_OVERRIDE;
1215 : sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(RuntimeException, std::exception) SAL_OVERRIDE;
1216 : Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(RuntimeException, std::exception) SAL_OVERRIDE;
1217 :
1218 : // XImplementationRegistration
1219 : virtual void SAL_CALL registerImplementation(
1220 : const OUString& implementationLoader,
1221 : const OUString& location,
1222 : const Reference < XSimpleRegistry > & xReg)
1223 : throw( CannotRegisterImplementationException, RuntimeException, std::exception ) SAL_OVERRIDE;
1224 :
1225 : virtual sal_Bool SAL_CALL revokeImplementation(
1226 : const OUString& location,
1227 : const Reference < XSimpleRegistry >& xReg)
1228 : throw( RuntimeException, std::exception ) SAL_OVERRIDE;
1229 :
1230 : virtual Sequence< OUString > SAL_CALL getImplementations(
1231 : const OUString& implementationLoader,
1232 : const OUString& location)
1233 : throw( RuntimeException, std::exception ) SAL_OVERRIDE;
1234 : virtual Sequence< OUString > SAL_CALL checkInstantiation(
1235 : const OUString& implementationName)
1236 : throw( RuntimeException, std::exception ) SAL_OVERRIDE;
1237 :
1238 : // XImplementationRegistration2
1239 : virtual void SAL_CALL registerImplementationWithLocation(
1240 : const OUString& implementationLoader,
1241 : const OUString& location,
1242 : const OUString& registeredLocation,
1243 : const Reference < XSimpleRegistry > & xReg)
1244 : throw( CannotRegisterImplementationException, RuntimeException, std::exception ) SAL_OVERRIDE;
1245 :
1246 : // XInitialization
1247 : virtual void SAL_CALL initialize(
1248 : const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments )
1249 : throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
1250 :
1251 : private: // helper methods
1252 : void prepareRegister(
1253 : const OUString& implementationLoader,
1254 : const OUString& location,
1255 : const OUString& registeredLocation,
1256 : const Reference < XSimpleRegistry > & xReg);
1257 : // throw( CannotRegisterImplementationException, RuntimeException )
1258 :
1259 : static void doRegister( const Reference < XMultiComponentFactory >& xSMgr,
1260 : const Reference < XComponentContext > &xCtx,
1261 : const Reference < XImplementationLoader >& xAct,
1262 : const Reference < XSimpleRegistry >& xDest,
1263 : const OUString& implementationLoaderUrl,
1264 : const OUString& locationUrl,
1265 : const OUString& registeredLocationUrl);
1266 : /* throw ( InvalidRegistryException,
1267 : MergeConflictException,
1268 : CannotRegisterImplementationException, RuntimeException ) */
1269 :
1270 : static void doRevoke( const Reference < XSimpleRegistry >& xDest,
1271 : const OUString& locationUrl );
1272 : // throw( InvalidRegistryException, RuntimeException )
1273 : Reference< XSimpleRegistry > getRegistryFromServiceManager();
1274 :
1275 : static Reference< XSimpleRegistry > createTemporarySimpleRegistry(
1276 : const Reference< XMultiComponentFactory > &rSMgr,
1277 : const Reference < XComponentContext > & rCtx );
1278 :
1279 : private: // members
1280 : Reference < XMultiComponentFactory > m_xSMgr;
1281 : Reference < XComponentContext > m_xCtx;
1282 : };
1283 :
1284 :
1285 : // ImplementationRegistration()
1286 :
1287 0 : ImplementationRegistration::ImplementationRegistration( const Reference < XComponentContext > & xCtx )
1288 0 : : m_xSMgr( xCtx->getServiceManager() )
1289 0 : , m_xCtx( xCtx )
1290 0 : {}
1291 :
1292 :
1293 : // ~ImplementationRegistration()
1294 :
1295 0 : ImplementationRegistration::~ImplementationRegistration() {}
1296 :
1297 : // XServiceInfo
1298 0 : OUString ImplementationRegistration::getImplementationName() throw(RuntimeException, std::exception)
1299 : {
1300 0 : return OUString("com.sun.star.comp.stoc.ImplementationRegistration");
1301 : }
1302 :
1303 : // XServiceInfo
1304 0 : sal_Bool ImplementationRegistration::supportsService(const OUString& ServiceName) throw(RuntimeException, std::exception)
1305 : {
1306 0 : return cppu::supportsService(this, ServiceName);
1307 : }
1308 :
1309 : // XServiceInfo
1310 0 : Sequence< OUString > ImplementationRegistration::getSupportedServiceNames(void) throw(RuntimeException, std::exception)
1311 : {
1312 0 : Sequence< OUString > seqNames(1);
1313 0 : seqNames[0] = "com.sun.star.registry.ImplementationRegistration";
1314 0 : return seqNames;
1315 : }
1316 :
1317 0 : Reference< XSimpleRegistry > ImplementationRegistration::getRegistryFromServiceManager()
1318 : {
1319 0 : Reference < XPropertySet > xPropSet( m_xSMgr, UNO_QUERY );
1320 0 : Reference < XSimpleRegistry > xRegistry;
1321 :
1322 0 : if( xPropSet.is() ) {
1323 :
1324 : try { // the implementation does not support XIntrospectionAccess !
1325 :
1326 0 : Any aAny = xPropSet->getPropertyValue( spool().Registry );
1327 :
1328 0 : if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE ) {
1329 0 : aAny >>= xRegistry;
1330 0 : }
1331 : }
1332 0 : catch( UnknownPropertyException & ) {
1333 : // empty reference is error signal !
1334 : }
1335 : }
1336 :
1337 0 : return xRegistry;
1338 : }
1339 :
1340 :
1341 :
1342 : // XInitialization
1343 :
1344 0 : void ImplementationRegistration::initialize(
1345 : const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArgs )
1346 : throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
1347 : {
1348 :
1349 0 : if( aArgs.getLength() != 4 ) {
1350 0 : OUStringBuffer buf;
1351 0 : buf.append( "ImplementationRegistration::initialize() expects 4 parameters, got " );
1352 0 : buf.append( (sal_Int32) aArgs.getLength() );
1353 : throw IllegalArgumentException( buf.makeStringAndClear(),
1354 : Reference<XInterface > (),
1355 0 : 0 );
1356 : }
1357 :
1358 0 : Reference< XImplementationLoader > rLoader;
1359 0 : OUString loaderServiceName;
1360 0 : OUString locationUrl;
1361 0 : Reference< XSimpleRegistry > rReg;
1362 :
1363 : // 1st argument : An instance of an implementation loader
1364 0 : if( aArgs.getConstArray()[0].getValueType().getTypeClass() == TypeClass_INTERFACE ) {
1365 0 : aArgs.getConstArray()[0] >>= rLoader;
1366 : }
1367 0 : if( !rLoader.is()) {
1368 0 : OUStringBuffer buf;
1369 : buf.append( "ImplementationRegistration::initialize() invalid first parameter,"
1370 0 : "expected " );
1371 0 : buf.append( getCppuType( &rLoader ).getTypeName() );
1372 0 : buf.append( ", got " );
1373 0 : buf.append( aArgs.getConstArray()[0].getValueTypeName() );
1374 : throw IllegalArgumentException( buf.makeStringAndClear(),
1375 : Reference< XInterface > (),
1376 0 : 0 );
1377 : }
1378 :
1379 : // 2nd argument : The service name of the loader. This name is written into the registry
1380 0 : if( aArgs.getConstArray()[1].getValueType().getTypeClass() == TypeClass_STRING ) {
1381 0 : aArgs.getConstArray()[1] >>= loaderServiceName;
1382 : }
1383 0 : if( loaderServiceName.isEmpty() ) {
1384 0 : OUStringBuffer buf;
1385 : buf.append( "ImplementationRegistration::initialize() invalid second parameter,"
1386 0 : "expected string, got " );
1387 0 : buf.append( aArgs.getConstArray()[1].getValueTypeName() );
1388 : throw IllegalArgumentException( buf.makeStringAndClear(),
1389 : Reference< XInterface > (),
1390 0 : 0 );
1391 : }
1392 :
1393 : // 3rd argument : The file name of the dll, that contains the loader
1394 0 : if( aArgs.getConstArray()[2].getValueType().getTypeClass() == TypeClass_STRING ) {
1395 0 : aArgs.getConstArray()[2] >>= locationUrl;
1396 : }
1397 0 : if( locationUrl.isEmpty() ) {
1398 0 : OUStringBuffer buf;
1399 : buf.append( "ImplementationRegistration::initialize() invalid third parameter,"
1400 0 : "expected string, got " );
1401 0 : buf.append( aArgs.getConstArray()[2].getValueTypeName() );
1402 : throw IllegalArgumentException( buf.makeStringAndClear(),
1403 : Reference< XInterface > (),
1404 0 : 0 );
1405 : }
1406 :
1407 : // 4th argument : The registry, the service should be written to
1408 0 : if( aArgs.getConstArray()[3].getValueType().getTypeClass() == TypeClass_INTERFACE ) {
1409 0 : aArgs.getConstArray()[3] >>= rReg;
1410 : }
1411 :
1412 0 : if( !rReg.is() ) {
1413 0 : rReg = getRegistryFromServiceManager();
1414 0 : if( !rReg.is() ) {
1415 0 : OUStringBuffer buf;
1416 : buf.append( "ImplementationRegistration::initialize() invalid fourth parameter,"
1417 0 : "expected " );
1418 0 : buf.append( getCppuType( &rReg ).getTypeName() );
1419 0 : buf.append( ", got " );
1420 0 : buf.append( aArgs.getConstArray()[3].getValueTypeName() );
1421 : throw IllegalArgumentException( buf.makeStringAndClear(),
1422 : Reference< XInterface > (),
1423 0 : 0 );
1424 : }
1425 : }
1426 :
1427 0 : doRegister(m_xSMgr, m_xCtx, rLoader , rReg, loaderServiceName , locationUrl, locationUrl);
1428 0 : }
1429 :
1430 :
1431 :
1432 :
1433 : // virtual function registerImplementationWithLocation of XImplementationRegistration2
1434 :
1435 0 : void ImplementationRegistration::registerImplementationWithLocation(
1436 : const OUString& implementationLoaderUrl,
1437 : const OUString& locationUrl,
1438 : const OUString& registeredLocationUrl,
1439 : const Reference < XSimpleRegistry > & xReg)
1440 : throw( CannotRegisterImplementationException, RuntimeException, std::exception )
1441 : {
1442 : prepareRegister(
1443 0 : implementationLoaderUrl, locationUrl, registeredLocationUrl, xReg);
1444 0 : }
1445 :
1446 : // helper function
1447 0 : void ImplementationRegistration::prepareRegister(
1448 : const OUString& implementationLoaderUrl,
1449 : const OUString& locationUrl,
1450 : const OUString& registeredLocationUrl,
1451 : const Reference < XSimpleRegistry > & xReg)
1452 : // throw( CannotRegisterImplementationException, RuntimeException )
1453 : {
1454 0 : OUString implLoaderUrl(implementationLoaderUrl);
1455 0 : OUString activatorName;
1456 :
1457 0 : if (!implementationLoaderUrl.isEmpty())
1458 : {
1459 0 : OUString tmpActivator(implementationLoaderUrl);
1460 0 : sal_Int32 nIndex = 0;
1461 0 : activatorName = tmpActivator.getToken(0, ':', nIndex );
1462 : } else
1463 : {
1464 : // check locationUrl to find out what kind of loader is needed
1465 : // set iimplLoaderUrl
1466 : }
1467 :
1468 0 : if( m_xSMgr.is() ) {
1469 : try
1470 : {
1471 : Reference < XImplementationLoader > xAct(
1472 0 : m_xSMgr->createInstanceWithContext(activatorName, m_xCtx) , UNO_QUERY );
1473 0 : if (xAct.is())
1474 : {
1475 0 : Reference < XSimpleRegistry > xRegistry;
1476 :
1477 0 : if (xReg.is())
1478 : {
1479 : // registry supplied by user
1480 0 : xRegistry = xReg;
1481 : }
1482 : else
1483 : {
1484 0 : xRegistry = getRegistryFromServiceManager();
1485 : }
1486 :
1487 0 : if ( xRegistry.is())
1488 : {
1489 : doRegister(m_xSMgr, m_xCtx, xAct, xRegistry, implLoaderUrl,
1490 0 : locationUrl, registeredLocationUrl);
1491 0 : }
1492 : }
1493 : else
1494 : {
1495 0 : OUStringBuffer buf( 128 );
1496 0 : buf.appendAscii( "ImplementationRegistration::registerImplementation() - The service " );
1497 0 : buf.append( activatorName );
1498 0 : buf.appendAscii( " cannot be instantiated\n" );
1499 : throw CannotRegisterImplementationException(
1500 0 : buf.makeStringAndClear(), Reference< XInterface > () );
1501 0 : }
1502 : }
1503 0 : catch( CannotRegisterImplementationException & )
1504 : {
1505 0 : throw;
1506 : }
1507 0 : catch( const InvalidRegistryException & e )
1508 : {
1509 0 : OUStringBuffer buf;
1510 : buf.append( "ImplementationRegistration::registerImplementation() "
1511 0 : "InvalidRegistryException during registration (" );
1512 0 : buf.append( e.Message );
1513 0 : buf.append( ")" );
1514 : throw CannotRegisterImplementationException(
1515 0 : buf.makeStringAndClear(), Reference< XInterface > () );
1516 : }
1517 0 : catch( const MergeConflictException & e )
1518 : {
1519 0 : OUStringBuffer buf;
1520 : buf.append( "ImplementationRegistration::registerImplementation() "
1521 0 : "MergeConflictException during registration (" );
1522 0 : buf.append( e.Message );
1523 0 : buf.append( ")" );
1524 : throw CannotRegisterImplementationException(
1525 0 : buf.makeStringAndClear(), Reference< XInterface > () );
1526 : }
1527 : }
1528 : else
1529 : {
1530 : throw CannotRegisterImplementationException(
1531 : OUString(
1532 : "ImplementationRegistration::registerImplementation() "
1533 : "no componentcontext available to instantiate loader"),
1534 0 : Reference< XInterface > () );
1535 0 : }
1536 0 : }
1537 :
1538 :
1539 : // virtual function registerImplementation of XImplementationRegistration
1540 :
1541 0 : void ImplementationRegistration::registerImplementation(
1542 : const OUString& implementationLoaderUrl,
1543 : const OUString& locationUrl,
1544 : const Reference < XSimpleRegistry > & xReg)
1545 : throw( CannotRegisterImplementationException, RuntimeException, std::exception )
1546 : {
1547 0 : prepareRegister(implementationLoaderUrl, locationUrl, locationUrl, xReg);
1548 0 : }
1549 :
1550 :
1551 :
1552 : // virtual function revokeImplementation of XImplementationRegistration
1553 :
1554 0 : sal_Bool ImplementationRegistration::revokeImplementation(const OUString& location,
1555 : const Reference < XSimpleRegistry >& xReg)
1556 : throw ( RuntimeException, std::exception )
1557 : {
1558 0 : sal_Bool ret = sal_False;
1559 :
1560 0 : Reference < XSimpleRegistry > xRegistry;
1561 :
1562 0 : if (xReg.is()) {
1563 0 : xRegistry = xReg;
1564 : }
1565 : else {
1566 0 : Reference < XPropertySet > xPropSet = Reference< XPropertySet >::query( m_xSMgr );
1567 0 : if( xPropSet.is() ) {
1568 : try {
1569 0 : Any aAny = xPropSet->getPropertyValue( spool().Registry );
1570 :
1571 0 : if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
1572 : {
1573 0 : aAny >>= xRegistry;
1574 0 : }
1575 : }
1576 0 : catch ( UnknownPropertyException & ) {
1577 : }
1578 0 : }
1579 : }
1580 :
1581 0 : if (xRegistry.is())
1582 : {
1583 : try
1584 : {
1585 0 : doRevoke(xRegistry, location);
1586 0 : ret = sal_True;
1587 : }
1588 0 : catch( InvalidRegistryException & )
1589 : {
1590 : // no way to transport the error, as no exception is specified and a runtime
1591 : // exception is not appropriate.
1592 : OSL_FAIL( "InvalidRegistryException during revokeImplementation" );
1593 : }
1594 : }
1595 :
1596 0 : return ret;
1597 : }
1598 :
1599 :
1600 : // virtual function getImplementations of XImplementationRegistration
1601 :
1602 0 : Sequence< OUString > ImplementationRegistration::getImplementations(
1603 : const OUString & implementationLoaderUrl,
1604 : const OUString & locationUrl)
1605 : throw ( RuntimeException, std::exception )
1606 : {
1607 0 : OUString activatorName;
1608 :
1609 0 : if (!implementationLoaderUrl.isEmpty())
1610 : {
1611 0 : OUString tmpActivator(implementationLoaderUrl);
1612 0 : sal_Int32 nIndex = 0;
1613 0 : activatorName = tmpActivator.getToken(0, ':', nIndex );
1614 : } else
1615 : {
1616 : // check locationUrl to find out what kind of loader is needed
1617 : // set implementationLoaderUrl
1618 : }
1619 :
1620 0 : if( m_xSMgr.is() ) {
1621 :
1622 : Reference < XImplementationLoader > xAct(
1623 0 : m_xSMgr->createInstanceWithContext( activatorName, m_xCtx ), UNO_QUERY );
1624 :
1625 0 : if (xAct.is())
1626 : {
1627 :
1628 : Reference < XSimpleRegistry > xReg =
1629 0 : createTemporarySimpleRegistry( m_xSMgr, m_xCtx);
1630 :
1631 0 : if (xReg.is())
1632 : {
1633 : try
1634 : {
1635 0 : xReg->open(OUString() /* in mem */, sal_False, sal_True);
1636 0 : Reference < XRegistryKey > xImpl;
1637 :
1638 : { // only necessary for deleting the temporary variable of rootkey
1639 0 : xImpl = xReg->getRootKey()->createKey( spool().slash_IMPLEMENTATIONS );
1640 : }
1641 0 : if (xAct->writeRegistryInfo(xImpl, implementationLoaderUrl, locationUrl))
1642 : {
1643 0 : std::list <OUString> implNames;
1644 :
1645 0 : findImplementations(xImpl, implNames);
1646 :
1647 0 : if (!implNames.empty())
1648 : {
1649 0 : std::list<OUString>::const_iterator iter = implNames.begin();
1650 :
1651 0 : Sequence<OUString> seqImpl(implNames.size());
1652 0 : OUString *pImplNames = seqImpl.getArray();
1653 :
1654 0 : sal_Int32 index = 0;
1655 0 : while (iter != implNames.end())
1656 : {
1657 0 : pImplNames[index] = *iter;
1658 0 : index++;
1659 0 : ++iter;
1660 : }
1661 :
1662 0 : xImpl->closeKey();
1663 0 : return seqImpl;
1664 0 : }
1665 : }
1666 :
1667 0 : xImpl->closeKey();
1668 : }
1669 0 : catch(MergeConflictException&)
1670 : {
1671 : }
1672 0 : catch(InvalidRegistryException&)
1673 : {
1674 : }
1675 0 : }
1676 0 : }
1677 : }
1678 :
1679 0 : return Sequence<OUString>();
1680 : }
1681 :
1682 :
1683 : // virtual function checkInstantiation of XImplementationRegistration
1684 :
1685 0 : Sequence< OUString > ImplementationRegistration::checkInstantiation(const OUString&)
1686 : throw ( RuntimeException, std::exception )
1687 : {
1688 : OSL_FAIL( "ImplementationRegistration::checkInstantiation not implemented" );
1689 0 : return Sequence<OUString>();
1690 : }
1691 :
1692 :
1693 : // helper function doRegistration
1694 :
1695 :
1696 0 : void ImplementationRegistration::doRevoke(
1697 : const Reference < XSimpleRegistry >& xDest,
1698 : const OUString& locationUrl)
1699 : // throw ( InvalidRegistryException, RuntimeException )
1700 : {
1701 0 : if( xDest.is() )
1702 : {
1703 0 : std::list<OUString> aNames;
1704 :
1705 0 : const StringPool &pool = spool();
1706 0 : Reference < XRegistryKey > xRootKey( xDest->getRootKey() );
1707 :
1708 : Reference < XRegistryKey > xKey =
1709 0 : xRootKey->openKey( pool.slash_IMPLEMENTATIONS );
1710 0 : if (xKey.is() && xKey->isValid())
1711 : {
1712 0 : deleteAllImplementations(xDest, xKey, locationUrl, aNames);
1713 : }
1714 :
1715 0 : xKey = xRootKey->openKey( pool.slash_SERVICES );
1716 0 : if (xKey.is())
1717 : {
1718 0 : std::list<OUString>::const_iterator iter = aNames.begin();
1719 :
1720 0 : while (iter != aNames.end())
1721 : {
1722 0 : deleteAllServiceEntries(xDest, xKey, *iter);
1723 0 : ++iter;
1724 : }
1725 : }
1726 :
1727 0 : xKey = xRootKey->openKey( "/SINGLETONS" );
1728 0 : if (xKey.is() && xKey->isValid())
1729 : {
1730 0 : delete_all_singleton_entries( xKey, aNames );
1731 : }
1732 :
1733 0 : if (xRootKey.is())
1734 0 : xRootKey->closeKey();
1735 0 : if (xKey.is() && xKey->isValid() )
1736 0 : xKey->closeKey();
1737 : }
1738 0 : }
1739 :
1740 0 : void ImplementationRegistration::doRegister(
1741 : const Reference< XMultiComponentFactory > & xSMgr,
1742 : const Reference< XComponentContext > &xCtx,
1743 : const Reference < XImplementationLoader > & xAct,
1744 : const Reference < XSimpleRegistry >& xDest,
1745 : const OUString& implementationLoaderUrl,
1746 : const OUString& locationUrl,
1747 : const OUString& registeredLocationUrl)
1748 : /* throw ( InvalidRegistryException,
1749 : MergeConflictException,
1750 : CannotRegisterImplementationException, RuntimeException ) */
1751 : {
1752 : Reference < XSimpleRegistry > xReg =
1753 0 : createTemporarySimpleRegistry( xSMgr, xCtx );
1754 0 : Reference < XRegistryKey > xSourceKey;
1755 :
1756 0 : if (xAct.is() && xReg.is() && xDest.is())
1757 : {
1758 : try
1759 : {
1760 0 : xReg->open(OUString() /* in mem */, sal_False, sal_True);
1761 :
1762 : { // only necessary for deleting the temporary variable of rootkey
1763 0 : xSourceKey = xReg->getRootKey()->createKey( spool().slash_IMPLEMENTATIONS );
1764 : }
1765 :
1766 : sal_Bool bSuccess =
1767 0 : xAct->writeRegistryInfo(xSourceKey, implementationLoaderUrl, locationUrl);
1768 0 : if ( bSuccess )
1769 : {
1770 0 : prepareRegistry(xDest, xSourceKey, implementationLoaderUrl, registeredLocationUrl, xCtx);
1771 :
1772 0 : xSourceKey->closeKey();
1773 :
1774 0 : xSourceKey = xReg->getRootKey();
1775 0 : Reference < XRegistryKey > xDestKey = xDest->getRootKey();
1776 0 : stoc_impreg::mergeKeys( xDestKey, xSourceKey );
1777 0 : xDestKey->closeKey();
1778 0 : xSourceKey->closeKey();
1779 : }
1780 : else
1781 : {
1782 : throw CannotRegisterImplementationException(
1783 : OUString( "ImplementationRegistration::doRegistration() component registration signaled failure" ),
1784 0 : Reference< XInterface > () );
1785 : }
1786 :
1787 : // Cleanup Source registry.
1788 0 : if ( xSourceKey->isValid() )
1789 0 : xSourceKey->closeKey();
1790 : }
1791 0 : catch(CannotRegisterImplementationException&)
1792 : {
1793 0 : if ( xSourceKey->isValid() )
1794 0 : xSourceKey->closeKey();
1795 : // and throw again
1796 0 : throw;
1797 : }
1798 0 : }
1799 0 : }
1800 :
1801 :
1802 :
1803 0 : Reference< XSimpleRegistry > ImplementationRegistration::createTemporarySimpleRegistry(
1804 : const Reference< XMultiComponentFactory > &rSMgr,
1805 : const Reference < XComponentContext > & xCtx)
1806 : {
1807 :
1808 : Reference < XSimpleRegistry > xReg(
1809 0 : rSMgr->createInstanceWithContext(
1810 0 : spool().com_sun_star_registry_SimpleRegistry, xCtx ),
1811 0 : UNO_QUERY);
1812 : OSL_ASSERT( xReg.is() );
1813 0 : return xReg;
1814 : }
1815 :
1816 : }
1817 :
1818 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1819 0 : com_sun_star_comp_stoc_ImplementationRegistration_get_implementation(
1820 : css::uno::XComponentContext *context,
1821 : css::uno::Sequence<css::uno::Any> const &)
1822 : {
1823 0 : return cppu::acquire(new ImplementationRegistration(context));
1824 : }
1825 :
1826 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|