1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <string_view>
24 #include <cppuhelper/exc_hlp.hxx>
25 #include <cppuhelper/weak.hxx>
26 #include <cppuhelper/implbase.hxx>
27 #include <cppuhelper/supportsservice.hxx>
28 #include <comphelper/sequence.hxx>
29 #include <rtl/ustring.hxx>
31 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/lang/XInitialization.hpp>
34 #include <com/sun/star/loader/XImplementationLoader.hpp>
35 #include <com/sun/star/registry/XImplementationRegistration2.hpp>
36 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
37 #include <com/sun/star/reflection/XServiceTypeDescription.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/uno/RuntimeException.hpp>
40 #include <com/sun/star/uno/XComponentContext.hpp>
42 #include "mergekeys.hxx"
49 using namespace com::sun::star
;
50 using namespace css::uno
;
51 using namespace css::loader
;
52 using namespace css::beans
;
53 using namespace css::lang
;
54 using namespace css::registry
;
59 constexpr OUString slash_UNO_slash_REGISTRY_LINKS
60 = u
"/UNO/REGISTRY_LINKS"_ustr
;
61 constexpr OUString slash_IMPLEMENTATIONS
62 = u
"/IMPLEMENTATIONS"_ustr
;
63 constexpr OUString slash_UNO
65 constexpr OUString slash_UNO_slash_SERVICES
66 = u
"/UNO/SERVICES"_ustr
;
67 constexpr OUString slash_UNO_slash_SINGLETONS
68 = u
"/UNO/SINGLETONS"_ustr
;
69 constexpr OUString slash_SERVICES
71 constexpr OUString slash_UNO_slash_LOCATION
72 = u
"/UNO/LOCATION"_ustr
;
73 constexpr OUString slash_UNO_slash_ACTIVATOR
74 = u
"/UNO/ACTIVATOR"_ustr
;
75 constexpr OUString colon_old
77 constexpr OUStringLiteral com_sun_star_registry_SimpleRegistry
78 = u
"com.sun.star.registry.SimpleRegistry";
79 constexpr OUString Registry
82 // static deleteAllLinkReferences()
84 void deleteAllLinkReferences(const Reference
< XSimpleRegistry
>& xReg
,
85 const Reference
< XRegistryKey
>& xSource
)
86 // throw ( InvalidRegistryException, RuntimeException )
88 Reference
< XRegistryKey
> xKey
= xSource
->openKey(
89 slash_UNO_slash_REGISTRY_LINKS
);
91 if (!(xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCIILIST
)))
94 const Sequence
<OUString
> linkNames
= xKey
->getAsciiListValue();
96 if (!linkNames
.hasElements())
100 OUString aLinkParent
;
101 Reference
< XRegistryKey
> xLinkParent
;
102 const sal_Unicode
* pTmpName
= nullptr;
103 const sal_Unicode
* pShortName
= nullptr;
106 for (const OUString
& rLinkName
: linkNames
)
108 aLinkName
= rLinkName
;
110 pTmpName
= aLinkName
.getStr();
112 if (pTmpName
[0] != L
'/')
115 sal_Int32 nIndex
= rtl_ustr_indexOfChar( pTmpName
, '%' );
117 pShortName
= nullptr;
119 pShortName
= pTmpName
+nIndex
;
121 while (pShortName
&& pShortName
[1] == L
'%')
123 nIndex
= rtl_ustr_indexOfChar( pShortName
+2, '%' );
125 pShortName
= nullptr;
127 pShortName
+= nIndex
+2;
132 aLinkName
= aLinkName
.copy(0, pShortName
- pTmpName
);
135 xReg
->getRootKey()->deleteLink(aLinkName
);
137 sEnd
= aLinkName
.lastIndexOf( '/' );
139 aLinkParent
= aLinkName
.copy(0, sEnd
);
141 while(!aLinkParent
.isEmpty())
143 xLinkParent
= xReg
->getRootKey()->openKey(aLinkParent
);
145 if (xLinkParent
.is() && !xLinkParent
->getKeyNames().hasElements())
147 aLinkName
= aLinkParent
;
149 xReg
->getRootKey()->deleteKey(aLinkParent
);
151 sEnd
= aLinkName
.lastIndexOf( '/' );
153 aLinkParent
= aLinkName
.copy(0, sEnd
);
164 // static prepareLink
166 void prepareLink( const Reference
< XSimpleRegistry
> & xDest
,
167 const Reference
< XRegistryKey
> & xSource
,
168 const OUString
& link
)
169 // throw ( InvalidRegistryException, RuntimeException )
171 OUString linkRefName
= xSource
->getKeyName();
172 OUString
linkName(link
);
173 bool isRelativ
= false;
175 const sal_Unicode
* pTmpName
= link
.getStr();
176 const sal_Unicode
* pShortName
;
177 sal_Int32 nIndex
= rtl_ustr_indexOfChar( pTmpName
, '%' );
179 pShortName
= nullptr;
181 pShortName
= pTmpName
+nIndex
;
183 if (pTmpName
[0] != L
'/')
186 while (pShortName
&& pShortName
[1] == L
'%')
188 nIndex
= rtl_ustr_indexOfChar( pShortName
+2, '%' );
190 pShortName
= nullptr;
192 pShortName
+= nIndex
+2;
197 linkRefName
+= link
.subView(pShortName
- pTmpName
+ 1);
198 linkName
= link
.copy(0, pShortName
- pTmpName
);
202 xSource
->createLink(linkName
, linkRefName
);
204 xDest
->getRootKey()->createLink(linkName
, linkRefName
);
208 // static searchImplForLink
210 OUString
searchImplForLink(
211 const Reference
< XRegistryKey
> & xRootKey
,
212 std::u16string_view linkName
,
213 std::u16string_view implName
)
214 // throw ( InvalidRegistryException, RuntimeException )
216 Reference
< XRegistryKey
> xKey
= xRootKey
->openKey( slash_IMPLEMENTATIONS
);
219 const Sequence
< Reference
< XRegistryKey
> > subKeys( xKey
->openKeys() );
220 OUString
key_name( slash_UNO
+ linkName
);
222 for (const Reference
< XRegistryKey
>& xImplKey
: subKeys
)
226 if (xImplKey
->getKeyType( key_name
) == RegistryKeyType_LINK
)
228 OUString oldImplName
= xImplKey
->getKeyName().copy(strlen("/IMPLEMENTATIONS/"));
229 if (implName
!= oldImplName
)
235 catch(InvalidRegistryException
&)
245 // static searchLinkTargetForImpl
247 OUString
searchLinkTargetForImpl(const Reference
< XRegistryKey
>& xRootKey
,
248 std::u16string_view linkName
,
249 const OUString
& implName
)
251 Reference
< XRegistryKey
> xKey
= xRootKey
->openKey( slash_IMPLEMENTATIONS
);
255 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xKey
->openKeys();
257 OUString
qualifiedLinkName( slash_UNO
+ linkName
);
259 auto pSubKey
= std::find_if(subKeys
.begin(), subKeys
.end(),
260 [&implName
, &qualifiedLinkName
](const Reference
<XRegistryKey
>& rSubKey
) {
261 OUString tmpImplName
= rSubKey
->getKeyName().copy(strlen("/IMPLEMENTATIONS/"));
262 return tmpImplName
== implName
263 && rSubKey
->getKeyType( qualifiedLinkName
) == RegistryKeyType_LINK
;
265 if (pSubKey
!= subKeys
.end())
266 return (*pSubKey
)->getLinkTarget( qualifiedLinkName
);
273 // static createUniqueSubEntry
275 void createUniqueSubEntry(const Reference
< XRegistryKey
> & xSuperKey
,
276 const OUString
& value
)
277 // throw ( InvalidRegistryException, RuntimeException )
282 if (xSuperKey
->getValueType() == RegistryValueType_ASCIILIST
)
284 const Sequence
<OUString
> implEntries
= xSuperKey
->getAsciiListValue();
285 sal_Int32 length
= implEntries
.getLength();
287 bool bReady
= comphelper::findValue(implEntries
, value
) != -1;
291 Sequence
<OUString
> implEntriesNew(length
);
292 auto it
= implEntriesNew
.getArray();
295 std::copy_if(implEntries
.begin(), implEntries
.end(), std::next(it
),
296 [&value
](const OUString
& rEntry
) { return rEntry
!= value
; });
297 xSuperKey
->setAsciiListValue(implEntriesNew
);
300 Sequence
<OUString
> implEntriesNew(length
+1);
301 auto it
= implEntriesNew
.getArray();
304 std::copy(implEntries
.begin(), implEntries
.end(), std::next(it
));
305 xSuperKey
->setAsciiListValue(implEntriesNew
);
309 Sequence
<OUString
> implEntriesNew
{ value
};
311 xSuperKey
->setAsciiListValue(implEntriesNew
);
316 // static deleteSubEntry
318 bool deleteSubEntry(const Reference
< XRegistryKey
>& xSuperKey
, const OUString
& value
)
319 // throw ( InvalidRegistryException, RuntimeException )
321 if (xSuperKey
->getValueType() == RegistryValueType_ASCIILIST
)
323 const Sequence
<OUString
> implEntries
= xSuperKey
->getAsciiListValue();
324 sal_Int32 length
= implEntries
.getLength();
325 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), value
));
326 bool hasNoImplementations
= false;
328 if (equals
== length
)
330 hasNoImplementations
= true;
333 Sequence
<OUString
> implEntriesNew(length
- equals
);
335 std::copy_if(implEntries
.begin(), implEntries
.end(), implEntriesNew
.getArray(),
336 [&value
](const OUString
& rEntry
) { return rEntry
!= value
; });
337 xSuperKey
->setAsciiListValue(implEntriesNew
);
340 if (hasNoImplementations
)
349 // static prepareUserLink
351 void prepareUserLink(const Reference
< XSimpleRegistry
>& xDest
,
352 const OUString
& linkName
,
353 const OUString
& linkTarget
,
354 std::u16string_view implName
)
356 Reference
< XRegistryKey
> xRootKey
= xDest
->getRootKey();
358 if (xRootKey
->getKeyType(linkName
) == RegistryKeyType_LINK
)
360 OUString
oldImplName(searchImplForLink(xRootKey
, linkName
, implName
));
362 if (!oldImplName
.isEmpty())
364 createUniqueSubEntry(xDest
->getRootKey()->createKey(
365 linkName
+ colon_old
), oldImplName
);
369 if (xRootKey
->isValid())
370 xRootKey
->createLink(linkName
, linkTarget
);
374 // static deleteUserLink
376 void deletePathIfPossible(const Reference
< XRegistryKey
>& xRootKey
,
377 const OUString
& path
)
381 Sequence
<OUString
> keyNames(xRootKey
->openKey(path
)->getKeyNames());
383 if (!keyNames
.hasElements() &&
384 xRootKey
->openKey(path
)->getValueType() == RegistryValueType_NOT_DEFINED
)
386 xRootKey
->deleteKey(path
);
388 OUString newPath
= path
.copy(0, path
.lastIndexOf('/'));
390 if (newPath
.getLength() > 1)
391 deletePathIfPossible(xRootKey
, newPath
);
394 catch(InvalidRegistryException
&)
400 // static deleteUserLink
402 void deleteUserLink(const Reference
< XRegistryKey
>& xRootKey
,
403 const OUString
& linkName
,
404 std::u16string_view linkTarget
,
405 const OUString
& implName
)
406 // throw ( InvalidRegistryException, RuntimeException )
410 if (xRootKey
->getKeyType(linkName
) == RegistryKeyType_LINK
)
412 OUString tmpTarget
= xRootKey
->getLinkTarget(linkName
);
414 if (tmpTarget
== linkTarget
)
416 xRootKey
->deleteLink(linkName
);
420 Reference
< XRegistryKey
> xOldKey
= xRootKey
->openKey(
421 linkName
+ colon_old
);
424 if (xOldKey
->getValueType() == RegistryValueType_ASCIILIST
)
426 const Sequence
<OUString
> implEntries
= xOldKey
->getAsciiListValue();
427 sal_Int32 length
= implEntries
.getLength();
428 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), implName
));
429 bool hasNoImplementations
= false;
431 if (equals
== length
)
433 hasNoImplementations
= true;
438 if (length
> equals
+ 1)
440 Sequence
<OUString
> implEntriesNew(length
- equals
- 1);
441 auto pNewArray
= implEntriesNew
.getArray();
445 for (sal_Int32 i
= 0; i
< length
; i
++)
447 if (implEntries
[i
] != implName
)
451 oldImpl
= implEntries
[i
];
455 pNewArray
[j
++] = implEntries
[i
];
460 xOldKey
->setAsciiListValue(implEntriesNew
);
463 oldImpl
= implEntries
[0];
464 OUString
path(xOldKey
->getKeyName());
466 xRootKey
->deleteKey(path
);
469 OUString oldTarget
= searchLinkTargetForImpl(xRootKey
, linkName
, oldImpl
);
470 if (!oldTarget
.isEmpty())
472 xRootKey
->createLink(linkName
, oldTarget
);
476 if (hasNoImplementations
)
479 OUString
path(xOldKey
->getKeyName());
481 xRootKey
->deleteKey(path
);
491 OUString path
= linkName
.copy(0, linkName
.lastIndexOf('/'));
492 deletePathIfPossible(xRootKey
, path
);
497 // static prepareUserKeys
499 void prepareUserKeys(const Reference
< XSimpleRegistry
>& xDest
,
500 const Reference
< XRegistryKey
>& xUnoKey
,
501 const Reference
< XRegistryKey
>& xKey
,
502 const OUString
& implName
,
505 bool hasSubKeys
= false;
507 Sequence
<OUString
> keyNames
= xKey
->getKeyNames();
510 if (keyNames
.hasElements())
511 relativKey
= keyNames
[0].copy(xKey
->getKeyName().getLength()+1);
513 if (keyNames
.getLength() == 1 &&
514 xKey
->getKeyType(relativKey
) == RegistryKeyType_LINK
)
518 OUString linkTarget
= xKey
->getLinkTarget(relativKey
);
520 OUString::Concat(xKey
->getKeyName().subView(xUnoKey
->getKeyName().getLength()))
525 prepareUserLink(xDest
, linkName
, linkTarget
, implName
);
528 deleteUserLink(xDest
->getRootKey(), linkName
, linkTarget
, implName
);
532 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xKey
->openKeys();
534 if (subKeys
.hasElements())
538 for (const Reference
< XRegistryKey
> & rSubKey
: subKeys
)
540 prepareUserKeys(xDest
, xUnoKey
, rSubKey
, implName
, bRegister
);
548 OUString
keyName(xKey
->getKeyName().copy(xUnoKey
->getKeyName().getLength()));
550 Reference
< XRegistryKey
> xRootKey
= xDest
->getRootKey();
553 createUniqueSubEntry(xRootKey
->createKey(keyName
), implName
);
557 Reference
< XRegistryKey
> rKey
= xRootKey
->openKey(keyName
);
560 deleteSubEntry(rKey
, implName
);
561 xRootKey
->deleteKey(keyName
);
564 OUString path
= keyName
.copy(0, keyName
.lastIndexOf('/'));
565 if( !path
.isEmpty() )
567 deletePathIfPossible(xRootKey
, path
);
573 // static deleteAllImplementations
575 void deleteAllImplementations( const Reference
< XSimpleRegistry
>& xReg
,
576 const Reference
< XRegistryKey
>& xSource
,
577 std::u16string_view locationUrl
,
578 std::vector
<OUString
> & implNames
)
579 // throw (InvalidRegistryException, RuntimeException)
581 Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
583 if (subKeys
.hasElements())
585 bool hasLocationUrl
= false;
587 for (const Reference
<XRegistryKey
>& xImplKey
: subKeys
)
589 Reference
< XRegistryKey
> xKey
= xImplKey
->openKey(
590 slash_UNO_slash_LOCATION
);
592 if (xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCII
))
594 if (xKey
->getAsciiValue() == locationUrl
)
596 hasLocationUrl
= true;
598 OUString
implName(xImplKey
->getKeyName().copy(1));
599 sal_Int32 firstDot
= implName
.indexOf('/');
602 implName
= implName
.copy(firstDot
+ 1);
604 implNames
.push_back(implName
);
606 deleteAllLinkReferences(xReg
, xImplKey
);
608 xKey
= xImplKey
->openKey( slash_UNO
);
611 const Sequence
< Reference
< XRegistryKey
> > subKeys2
= xKey
->openKeys();
613 for (const Reference
< XRegistryKey
> & rSubKey2
: subKeys2
)
615 if (rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_SERVICES
) &&
616 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_REGISTRY_LINKS
) &&
617 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_ACTIVATOR
) &&
618 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_SINGLETONS
) &&
619 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_LOCATION
) )
621 prepareUserKeys(xReg
, xKey
, rSubKey2
, implName
, false);
630 hasLocationUrl
= false;
631 OUString
path(xImplKey
->getKeyName());
632 xImplKey
->closeKey();
633 xReg
->getRootKey()->deleteKey(path
);
637 subKeys
= xSource
->openKeys();
638 if (!subKeys
.hasElements())
640 OUString
path(xSource
->getKeyName());
642 xReg
->getRootKey()->deleteKey(path
);
646 OUString
path(xSource
->getKeyName());
648 xReg
->getRootKey()->deleteKey(path
);
653 void delete_all_singleton_entries(
654 Reference
< registry::XRegistryKey
> const & xSingletons_section
,
655 ::std::vector
< OUString
> const & impl_names
)
656 // throw (InvalidRegistryException, RuntimeException)
658 Sequence
< Reference
< registry::XRegistryKey
> > singletons( xSingletons_section
->openKeys() );
659 for ( sal_Int32 nPos
= singletons
.getLength(); nPos
--; )
661 Reference
<registry::XRegistryKey
> const& xSingleton
= singletons
[nPos
];
662 Reference
< registry::XRegistryKey
> xRegisteredImplNames(
663 xSingleton
->openKey( u
"REGISTERED_BY"_ustr
) );
664 if (xRegisteredImplNames
.is() && xRegisteredImplNames
->isValid())
666 Sequence
< OUString
> registered_implnames
;
669 registered_implnames
= xRegisteredImplNames
->getAsciiListValue();
671 catch (registry::InvalidValueException
&)
674 auto aNonConstRange
= asNonConstRange(registered_implnames
);
675 sal_Int32 nOrigRegLength
= registered_implnames
.getLength();
676 sal_Int32 nNewLength
= nOrigRegLength
;
677 for ( sal_Int32 n
= nOrigRegLength
; n
--; )
679 OUString
const & registered_implname
= registered_implnames
[ n
];
681 for (auto const& impl_name
: impl_names
)
683 if (impl_name
== registered_implname
)
685 aNonConstRange
[ n
] = registered_implnames
[ nNewLength
-1 ];
691 if (nNewLength
!= nOrigRegLength
)
695 // remove whole entry
696 xRegisteredImplNames
->closeKey();
697 xSingleton
->deleteKey( u
"REGISTERED_BY"_ustr
);
698 // registry key cannot provide its relative name, only absolute :(
699 OUString
abs( xSingleton
->getKeyName() );
700 xSingletons_section
->deleteKey( abs
.copy( abs
.lastIndexOf( '/' ) +1 ) );
704 registered_implnames
.realloc( nNewLength
);
705 xRegisteredImplNames
->setAsciiListValue( registered_implnames
);
713 // static deleteAllServiceEntries
715 void deleteAllServiceEntries( const Reference
< XSimpleRegistry
>& xReg
,
716 const Reference
< XRegistryKey
>& xSource
,
717 const OUString
& implName
)
718 // throw ( InvalidRegistryException, RuntimeException )
720 Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
722 if (subKeys
.hasElements())
724 bool hasNoImplementations
= false;
726 for (const Reference
<XRegistryKey
>& xServiceKey
: subKeys
)
728 if (xServiceKey
->getValueType() == RegistryValueType_ASCIILIST
)
730 const Sequence
<OUString
> implEntries
= xServiceKey
->getAsciiListValue();
731 sal_Int32 length
= implEntries
.getLength();
732 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), implName
));
734 if (equals
== length
)
736 hasNoImplementations
= true;
741 Sequence
<OUString
> implEntriesNew(length
-equals
);
743 std::copy_if(implEntries
.begin(), implEntries
.end(), implEntriesNew
.getArray(),
744 [&implName
](const OUString
& rEntry
) { return rEntry
!= implName
; });
746 xServiceKey
->setAsciiListValue(implEntriesNew
);
751 if (hasNoImplementations
)
753 hasNoImplementations
= false;
754 OUString
path(xServiceKey
->getKeyName());
755 xServiceKey
->closeKey();
756 xReg
->getRootKey()->deleteKey(path
);
760 subKeys
= xSource
->openKeys();
761 if (!subKeys
.hasElements())
763 OUString
path(xSource
->getKeyName());
765 xReg
->getRootKey()->deleteKey(path
);
769 OUString
path(xSource
->getKeyName());
771 xReg
->getRootKey()->deleteKey(path
);
776 bool is_supported_service(
777 OUString
const & service_name
,
778 Reference
< reflection::XServiceTypeDescription
> const & xService_td
)
780 if (xService_td
->getName() == service_name
)
782 const Sequence
< Reference
< reflection::XServiceTypeDescription
> > seq(
783 xService_td
->getMandatoryServices() );
784 return std::any_of(seq
.begin(), seq
.end(), [&service_name
](const auto& rService
) {
785 return is_supported_service( service_name
, rService
); });
789 void insert_singletons(
790 Reference
< registry::XSimpleRegistry
> const & xDest
,
791 Reference
< registry::XRegistryKey
> const & xImplKey
,
792 Reference
< XComponentContext
> const & xContext
)
793 // throw( registry::InvalidRegistryException, registry::CannotRegisterImplementationException, RuntimeException )
796 Reference
< registry::XRegistryKey
> xKey( xImplKey
->openKey( u
"UNO/SINGLETONS"_ustr
) );
797 if (!(xKey
.is() && xKey
->isValid()))
800 OUString
implname( xImplKey
->getKeyName().copy( sizeof ("/IMPLEMENTATIONS/") -1 ) );
802 Sequence
< Reference
< registry::XRegistryKey
> > xSingletons_section( xKey
->openKeys() );
803 for ( sal_Int32 nPos
= xSingletons_section
.getLength(); nPos
--; )
805 Reference
<registry::XRegistryKey
> const& xSingleton
= xSingletons_section
[nPos
];
806 OUString
singleton_name(
807 xSingleton
->getKeyName().copy(
808 implname
.getLength() + sizeof ("/IMPLEMENTATIONS//UNO/SINGLETONS/") -1 ) );
809 OUString
service_name( xSingleton
->getStringValue() );
811 OUString
keyname( "/SINGLETONS/" + singleton_name
);
812 Reference
< registry::XRegistryKey
> xKey2( xDest
->getRootKey()->openKey( keyname
) );
813 if (xKey2
.is() && xKey2
->isValid())
817 OUString
existing_name( xKey2
->getStringValue() );
818 if ( existing_name
!= service_name
)
820 Reference
< container::XHierarchicalNameAccess
> xTDMgr
;
822 u
"/singletons/com.sun.star.reflection.theTypeDescriptionManager"_ustr
;
823 xContext
->getValueByName( the_tdmgr
) >>= xTDMgr
;
826 throw RuntimeException( "cannot get singleton " + the_tdmgr
);
830 Reference
< reflection::XServiceTypeDescription
> xExistingService_td
;
831 xTDMgr
->getByHierarchicalName( existing_name
) >>= xExistingService_td
;
832 if (! xExistingService_td
.is())
834 throw RuntimeException( "cannot get service type description: " + existing_name
);
837 // everything's fine if existing service entry supports the one
839 if (! is_supported_service( service_name
, xExistingService_td
))
841 throw registry::CannotRegisterImplementationException(
842 "existing singleton service (" + singleton_name
+ "=" + existing_name
+ ") "
843 " does not support given one: " + service_name
);
846 catch (const container::NoSuchElementException
& exc
)
848 css::uno::Any anyEx
= cppu::getCaughtException();
849 throw css::lang::WrappedTargetRuntimeException(
850 "cannot get service type description: " + exc
.Message
,
855 catch (registry::InvalidValueException
&)
858 xKey2
->setStringValue( service_name
);
863 // insert singleton entry
864 xKey2
= xDest
->getRootKey()->createKey( keyname
);
865 xKey2
->setStringValue( service_name
);
868 Reference
< registry::XRegistryKey
> xRegisteredImplNames(
869 xKey2
->openKey( u
"REGISTERED_BY"_ustr
) );
870 if (!xRegisteredImplNames
.is() || !xRegisteredImplNames
->isValid())
873 xRegisteredImplNames
= xKey2
->createKey( u
"REGISTERED_BY"_ustr
);
876 Sequence
< OUString
> implnames
;
879 implnames
= xRegisteredImplNames
->getAsciiListValue();
881 catch (registry::InvalidValueException
&)
884 // check implname is already in
885 if (comphelper::findValue(implnames
, implname
) == -1)
887 // append and write back
888 implnames
.realloc( implnames
.getLength() +1 );
889 implnames
.getArray()[ implnames
.getLength() -1 ] = implname
;
890 xRegisteredImplNames
->setAsciiListValue( implnames
);
896 // static prepareRegistry
898 void prepareRegistry(
899 const Reference
< XSimpleRegistry
>& xDest
,
900 const Reference
< XRegistryKey
>& xSource
,
901 const OUString
& implementationLoaderUrl
,
902 const OUString
& locationUrl
,
903 Reference
< XComponentContext
> const & xContext
)
904 // throw ( InvalidRegistryException, CannotRegisterImplementationException, RuntimeException )
906 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
908 if (!subKeys
.hasElements())
910 throw InvalidRegistryException(
911 u
"prepareRegistry(): source registry is empty"_ustr
);
914 for (const Reference
< XRegistryKey
>& xImplKey
: subKeys
)
916 Reference
< XRegistryKey
> xKey
= xImplKey
->openKey(
917 slash_UNO_slash_SERVICES
);
921 // update entries in SERVICES section
922 const Sequence
< Reference
< XRegistryKey
> > serviceKeys
= xKey
->openKeys();
924 OUString implName
= xImplKey
->getKeyName().copy(1);
925 sal_Int32 firstDot
= implName
.indexOf('/');
928 implName
= implName
.copy(firstDot
+ 1);
930 sal_Int32 offset
= xKey
->getKeyName().getLength() + 1;
932 for (const Reference
< XRegistryKey
>& rServiceKey
: serviceKeys
)
934 OUString serviceName
= rServiceKey
->getKeyName().copy(offset
);
936 createUniqueSubEntry(
937 xDest
->getRootKey()->createKey(
938 slash_SERVICES
+ serviceName
),
942 xKey
= xImplKey
->openKey( slash_UNO
);
945 const Sequence
< Reference
< XRegistryKey
> > subKeys2
= xKey
->openKeys();
947 for (const Reference
< XRegistryKey
>& rSubKey2
: subKeys2
)
949 if (rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_SERVICES
) &&
950 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_REGISTRY_LINKS
) &&
951 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_SINGLETONS
))
953 prepareUserKeys(xDest
, xKey
, rSubKey2
, implName
, true);
959 // update LOCATION entry
960 xKey
= xImplKey
->createKey( slash_UNO_slash_LOCATION
);
964 xKey
->setAsciiValue(locationUrl
);
967 // update ACTIVATOR entry
968 xKey
= xImplKey
->createKey( slash_UNO_slash_ACTIVATOR
);
972 xKey
->setAsciiValue(implementationLoaderUrl
);
975 xKey
= xImplKey
->openKey( slash_UNO_slash_SERVICES
);
977 if (xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCIILIST
))
979 // update link entries in REGISTRY_LINKS section
980 const Sequence
<OUString
> linkNames
= xKey
->getAsciiListValue();
982 for (const OUString
& rLinkName
: linkNames
)
984 prepareLink(xDest
, xImplKey
, rLinkName
);
988 insert_singletons( xDest
, xImplKey
, xContext
);
993 void findImplementations( const Reference
< XRegistryKey
> & xSource
,
994 std::vector
<OUString
>& implNames
)
996 bool isImplKey
= false;
1000 Reference
< XRegistryKey
> xKey
= xSource
->openKey(
1001 slash_UNO_slash_SERVICES
);
1003 if (xKey
.is() && xKey
->getKeyNames().hasElements())
1007 OUString implName
= xSource
->getKeyName().copy(1).replace('/', '.');
1008 sal_Int32 firstDot
= implName
.indexOf('.');
1011 implName
= implName
.copy(firstDot
+ 1);
1013 implNames
.push_back(implName
);
1016 catch(InvalidRegistryException
&)
1020 if (isImplKey
) return;
1024 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
1026 for (const Reference
< XRegistryKey
>& rSubKey
: subKeys
)
1028 findImplementations(rSubKey
, implNames
);
1031 catch(InvalidRegistryException
&)
1037 class ImplementationRegistration
1038 : public WeakImplHelper
< XImplementationRegistration2
, XServiceInfo
, XInitialization
>
1041 explicit ImplementationRegistration( const Reference
< XComponentContext
> & rSMgr
);
1044 OUString SAL_CALL
getImplementationName() override
;
1045 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
1046 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
1048 // XImplementationRegistration
1049 virtual void SAL_CALL
registerImplementation(
1050 const OUString
& implementationLoader
,
1051 const OUString
& location
,
1052 const Reference
< XSimpleRegistry
> & xReg
) override
;
1054 virtual sal_Bool SAL_CALL
revokeImplementation(
1055 const OUString
& location
,
1056 const Reference
< XSimpleRegistry
>& xReg
) override
;
1058 virtual Sequence
< OUString
> SAL_CALL
getImplementations(
1059 const OUString
& implementationLoader
,
1060 const OUString
& location
) override
;
1061 virtual Sequence
< OUString
> SAL_CALL
checkInstantiation(
1062 const OUString
& implementationName
) override
;
1064 // XImplementationRegistration2
1065 virtual void SAL_CALL
registerImplementationWithLocation(
1066 const OUString
& implementationLoader
,
1067 const OUString
& location
,
1068 const OUString
& registeredLocation
,
1069 const Reference
< XSimpleRegistry
> & xReg
) override
;
1072 virtual void SAL_CALL
initialize(
1073 const css::uno::Sequence
< css::uno::Any
>& aArguments
) override
;
1075 private: // helper methods
1076 void prepareRegister(
1077 const OUString
& implementationLoader
,
1078 const OUString
& location
,
1079 const OUString
& registeredLocation
,
1080 const Reference
< XSimpleRegistry
> & xReg
);
1081 // throw( CannotRegisterImplementationException, RuntimeException )
1083 static void doRegister( const Reference
< XMultiComponentFactory
>& xSMgr
,
1084 const Reference
< XComponentContext
> &xCtx
,
1085 const Reference
< XImplementationLoader
>& xAct
,
1086 const Reference
< XSimpleRegistry
>& xDest
,
1087 const OUString
& implementationLoaderUrl
,
1088 const OUString
& locationUrl
,
1089 const OUString
& registeredLocationUrl
);
1090 /* throw ( InvalidRegistryException,
1091 MergeConflictException,
1092 CannotRegisterImplementationException, RuntimeException ) */
1094 static void doRevoke( const Reference
< XSimpleRegistry
>& xDest
,
1095 std::u16string_view locationUrl
);
1096 // throw( InvalidRegistryException, RuntimeException )
1097 Reference
< XSimpleRegistry
> getRegistryFromServiceManager() const;
1099 static Reference
< XSimpleRegistry
> createTemporarySimpleRegistry(
1100 const Reference
< XMultiComponentFactory
> &rSMgr
,
1101 const Reference
< XComponentContext
> & rCtx
);
1104 Reference
< XMultiComponentFactory
> m_xSMgr
;
1105 Reference
< XComponentContext
> m_xCtx
;
1109 // ImplementationRegistration()
1111 ImplementationRegistration::ImplementationRegistration( const Reference
< XComponentContext
> & xCtx
)
1112 : m_xSMgr( xCtx
->getServiceManager() )
1117 OUString
ImplementationRegistration::getImplementationName()
1119 return u
"com.sun.star.comp.stoc.ImplementationRegistration"_ustr
;
1123 sal_Bool
ImplementationRegistration::supportsService(const OUString
& ServiceName
)
1125 return cppu::supportsService(this, ServiceName
);
1129 Sequence
< OUString
> ImplementationRegistration::getSupportedServiceNames()
1131 return { u
"com.sun.star.registry.ImplementationRegistration"_ustr
};
1134 Reference
< XSimpleRegistry
> ImplementationRegistration::getRegistryFromServiceManager() const
1136 Reference
< XPropertySet
> xPropSet( m_xSMgr
, UNO_QUERY
);
1137 Reference
< XSimpleRegistry
> xRegistry
;
1139 if( xPropSet
.is() ) {
1141 try { // the implementation does not support XIntrospectionAccess !
1143 Any aAny
= xPropSet
->getPropertyValue( Registry
);
1145 if( aAny
.getValueTypeClass() == TypeClass_INTERFACE
) {
1149 catch( UnknownPropertyException
& ) {
1150 // empty reference is error signal !
1160 void ImplementationRegistration::initialize(
1161 const css::uno::Sequence
< css::uno::Any
>& aArgs
)
1164 if( aArgs
.getLength() != 4 ) {
1165 throw IllegalArgumentException(
1166 "ImplementationRegistration::initialize() expects 4 parameters, got " + OUString::number( aArgs
.getLength() ),
1167 Reference
<XInterface
> (), 0 );
1170 Reference
< XImplementationLoader
> rLoader
;
1171 OUString loaderServiceName
;
1172 OUString locationUrl
;
1173 Reference
< XSimpleRegistry
> rReg
;
1175 // 1st argument : An instance of an implementation loader
1176 if( aArgs
[0].getValueTypeClass() == TypeClass_INTERFACE
) {
1177 aArgs
[0] >>= rLoader
;
1179 if( !rLoader
.is()) {
1180 throw IllegalArgumentException(
1181 "ImplementationRegistration::initialize() invalid first parameter,"
1182 "expected " + cppu::UnoType
<decltype(rLoader
)>::get().getTypeName() +
1183 ", got " + aArgs
[0].getValueTypeName(),
1184 Reference
< XInterface
> (), 0 );
1187 // 2nd argument : The service name of the loader. This name is written into the registry
1188 if( aArgs
[1].getValueTypeClass() == TypeClass_STRING
) {
1189 aArgs
[1] >>= loaderServiceName
;
1191 if( loaderServiceName
.isEmpty() ) {
1192 throw IllegalArgumentException(
1193 "ImplementationRegistration::initialize() invalid second parameter,"
1194 "expected string, got " + aArgs
[1].getValueTypeName(),
1195 Reference
< XInterface
> (), 0 );
1198 // 3rd argument : The file name of the dll, that contains the loader
1199 if( aArgs
[2].getValueTypeClass() == TypeClass_STRING
) {
1200 aArgs
[2] >>= locationUrl
;
1202 if( locationUrl
.isEmpty() ) {
1203 throw IllegalArgumentException(
1204 "ImplementationRegistration::initialize() invalid third parameter,"
1205 "expected string, got " + aArgs
[2].getValueTypeName(),
1206 Reference
< XInterface
> (), 0 );
1209 // 4th argument : The registry, the service should be written to
1210 if( aArgs
[3].getValueTypeClass() == TypeClass_INTERFACE
) {
1215 rReg
= getRegistryFromServiceManager();
1217 throw IllegalArgumentException(
1218 "ImplementationRegistration::initialize() invalid fourth parameter,"
1219 "expected " + cppu::UnoType
<decltype(rReg
)>::get().getTypeName() +
1220 ", got " + aArgs
[3].getValueTypeName(),
1221 Reference
< XInterface
> (), 0 );
1225 doRegister(m_xSMgr
, m_xCtx
, rLoader
, rReg
, loaderServiceName
, locationUrl
, locationUrl
);
1229 // virtual function registerImplementationWithLocation of XImplementationRegistration2
1231 void ImplementationRegistration::registerImplementationWithLocation(
1232 const OUString
& implementationLoaderUrl
,
1233 const OUString
& locationUrl
,
1234 const OUString
& registeredLocationUrl
,
1235 const Reference
< XSimpleRegistry
> & xReg
)
1238 implementationLoaderUrl
, locationUrl
, registeredLocationUrl
, xReg
);
1242 void ImplementationRegistration::prepareRegister(
1243 const OUString
& implementationLoaderUrl
,
1244 const OUString
& locationUrl
,
1245 const OUString
& registeredLocationUrl
,
1246 const Reference
< XSimpleRegistry
> & xReg
)
1247 // throw( CannotRegisterImplementationException, RuntimeException )
1249 OUString activatorName
;
1251 if (!implementationLoaderUrl
.isEmpty())
1253 activatorName
= implementationLoaderUrl
.getToken(0, ':');
1256 // check locationUrl to find out what kind of loader is needed
1257 // set implLoaderUrl
1260 if( !m_xSMgr
.is() ) {
1261 throw CannotRegisterImplementationException(
1262 u
"ImplementationRegistration::registerImplementation() "
1263 "no componentcontext available to instantiate loader"_ustr
);
1268 Reference
< XImplementationLoader
> xAct(
1269 m_xSMgr
->createInstanceWithContext(activatorName
, m_xCtx
) , UNO_QUERY
);
1272 throw CannotRegisterImplementationException(
1273 "ImplementationRegistration::registerImplementation() - The service "
1274 + activatorName
+ " cannot be instantiated" );
1277 Reference
< XSimpleRegistry
> xRegistry
;
1281 // registry supplied by user
1286 xRegistry
= getRegistryFromServiceManager();
1289 if ( xRegistry
.is())
1291 doRegister(m_xSMgr
, m_xCtx
, xAct
, xRegistry
, implementationLoaderUrl
,
1292 locationUrl
, registeredLocationUrl
);
1296 catch( CannotRegisterImplementationException
& )
1300 catch( const InvalidRegistryException
& e
)
1302 throw CannotRegisterImplementationException(
1303 "ImplementationRegistration::registerImplementation() "
1304 "InvalidRegistryException during registration (" + e
.Message
+ ")" );
1306 catch( const MergeConflictException
& e
)
1308 throw CannotRegisterImplementationException(
1309 "ImplementationRegistration::registerImplementation() "
1310 "MergeConflictException during registration (" + e
.Message
+ ")" );
1316 // virtual function registerImplementation of XImplementationRegistration
1318 void ImplementationRegistration::registerImplementation(
1319 const OUString
& implementationLoaderUrl
,
1320 const OUString
& locationUrl
,
1321 const Reference
< XSimpleRegistry
> & xReg
)
1323 prepareRegister(implementationLoaderUrl
, locationUrl
, locationUrl
, xReg
);
1327 // virtual function revokeImplementation of XImplementationRegistration
1329 sal_Bool
ImplementationRegistration::revokeImplementation(const OUString
& location
,
1330 const Reference
< XSimpleRegistry
>& xReg
)
1334 Reference
< XSimpleRegistry
> xRegistry
;
1340 Reference
< XPropertySet
> xPropSet( m_xSMgr
, UNO_QUERY
);
1341 if( xPropSet
.is() ) {
1343 Any aAny
= xPropSet
->getPropertyValue( Registry
);
1345 if( aAny
.getValueTypeClass() == TypeClass_INTERFACE
)
1350 catch ( UnknownPropertyException
& ) {
1359 doRevoke(xRegistry
, location
);
1362 catch( InvalidRegistryException
& )
1364 // no way to transport the error, as no exception is specified and a runtime
1365 // exception is not appropriate.
1366 OSL_FAIL( "InvalidRegistryException during revokeImplementation" );
1374 // virtual function getImplementations of XImplementationRegistration
1376 Sequence
< OUString
> ImplementationRegistration::getImplementations(
1377 const OUString
& implementationLoaderUrl
,
1378 const OUString
& locationUrl
)
1380 OUString activatorName
;
1382 if (!implementationLoaderUrl
.isEmpty())
1384 activatorName
= implementationLoaderUrl
.getToken(0, ':');
1387 // check locationUrl to find out what kind of loader is needed
1388 // set implementationLoaderUrl
1391 if( m_xSMgr
.is() ) {
1393 Reference
< XImplementationLoader
> xAct(
1394 m_xSMgr
->createInstanceWithContext( activatorName
, m_xCtx
), UNO_QUERY
);
1399 Reference
< XSimpleRegistry
> xReg
=
1400 createTemporarySimpleRegistry( m_xSMgr
, m_xCtx
);
1406 xReg
->open(OUString() /* in mem */, false, true);
1407 Reference
< XRegistryKey
> xImpl
;
1409 { // only necessary for deleting the temporary variable of rootkey
1410 xImpl
= xReg
->getRootKey()->createKey( slash_IMPLEMENTATIONS
);
1412 if (xAct
->writeRegistryInfo(xImpl
, implementationLoaderUrl
, locationUrl
))
1414 std::vector
<OUString
> implNames
;
1416 findImplementations(xImpl
, implNames
);
1418 if (!implNames
.empty())
1420 Sequence
<OUString
> seqImpl(comphelper::containerToSequence(implNames
));
1428 catch(MergeConflictException
&)
1431 catch(InvalidRegistryException
&)
1438 return Sequence
<OUString
>();
1442 // virtual function checkInstantiation of XImplementationRegistration
1444 Sequence
< OUString
> ImplementationRegistration::checkInstantiation(const OUString
&)
1446 OSL_FAIL( "ImplementationRegistration::checkInstantiation not implemented" );
1447 return Sequence
<OUString
>();
1451 // helper function doRegistration
1454 void ImplementationRegistration::doRevoke(
1455 const Reference
< XSimpleRegistry
>& xDest
,
1456 std::u16string_view locationUrl
)
1457 // throw ( InvalidRegistryException, RuntimeException )
1462 std::vector
<OUString
> aNames
;
1464 Reference
< XRegistryKey
> xRootKey( xDest
->getRootKey() );
1466 Reference
< XRegistryKey
> xKey
=
1467 xRootKey
->openKey( slash_IMPLEMENTATIONS
);
1468 if (xKey
.is() && xKey
->isValid())
1470 deleteAllImplementations(xDest
, xKey
, locationUrl
, aNames
);
1473 xKey
= xRootKey
->openKey( slash_SERVICES
);
1476 for (auto const& name
: aNames
)
1478 deleteAllServiceEntries(xDest
, xKey
, name
);
1482 xKey
= xRootKey
->openKey( u
"/SINGLETONS"_ustr
);
1483 if (xKey
.is() && xKey
->isValid())
1485 delete_all_singleton_entries( xKey
, aNames
);
1489 xRootKey
->closeKey();
1490 if (xKey
.is() && xKey
->isValid() )
1494 void ImplementationRegistration::doRegister(
1495 const Reference
< XMultiComponentFactory
> & xSMgr
,
1496 const Reference
< XComponentContext
> &xCtx
,
1497 const Reference
< XImplementationLoader
> & xAct
,
1498 const Reference
< XSimpleRegistry
>& xDest
,
1499 const OUString
& implementationLoaderUrl
,
1500 const OUString
& locationUrl
,
1501 const OUString
& registeredLocationUrl
)
1502 /* throw ( InvalidRegistryException,
1503 MergeConflictException,
1504 CannotRegisterImplementationException, RuntimeException ) */
1506 Reference
< XSimpleRegistry
> xReg
=
1507 createTemporarySimpleRegistry( xSMgr
, xCtx
);
1508 Reference
< XRegistryKey
> xSourceKey
;
1510 if (!(xAct
.is() && xReg
.is() && xDest
.is()))
1515 xReg
->open(OUString() /* in mem */, false, true);
1517 { // only necessary for deleting the temporary variable of rootkey
1518 xSourceKey
= xReg
->getRootKey()->createKey( slash_IMPLEMENTATIONS
);
1522 xAct
->writeRegistryInfo(xSourceKey
, implementationLoaderUrl
, locationUrl
);
1525 throw CannotRegisterImplementationException(
1526 u
"ImplementationRegistration::doRegistration() component registration signaled failure"_ustr
);
1529 prepareRegistry(xDest
, xSourceKey
, implementationLoaderUrl
, registeredLocationUrl
, xCtx
);
1531 xSourceKey
->closeKey();
1533 xSourceKey
= xReg
->getRootKey();
1534 Reference
< XRegistryKey
> xDestKey
= xDest
->getRootKey();
1535 stoc_impreg::mergeKeys( xDestKey
, xSourceKey
);
1536 xDestKey
->closeKey();
1537 xSourceKey
->closeKey();
1540 // Cleanup Source registry.
1541 if ( xSourceKey
->isValid() )
1542 xSourceKey
->closeKey();
1544 catch(CannotRegisterImplementationException
&)
1546 if ( xSourceKey
->isValid() )
1547 xSourceKey
->closeKey();
1554 Reference
< XSimpleRegistry
> ImplementationRegistration::createTemporarySimpleRegistry(
1555 const Reference
< XMultiComponentFactory
> &rSMgr
,
1556 const Reference
< XComponentContext
> & xCtx
)
1559 Reference
< XSimpleRegistry
> xReg(
1560 rSMgr
->createInstanceWithContext(
1561 com_sun_star_registry_SimpleRegistry
, xCtx
),
1563 OSL_ASSERT( xReg
.is() );
1569 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1570 com_sun_star_comp_stoc_ImplementationRegistration_get_implementation(
1571 css::uno::XComponentContext
*context
,
1572 css::uno::Sequence
<css::uno::Any
> const &)
1574 return cppu::acquire(new ImplementationRegistration(context
));
1577 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */