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>
30 #include <tools/diagnose_ex.h>
32 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/lang/XInitialization.hpp>
35 #include <com/sun/star/loader/XImplementationLoader.hpp>
36 #include <com/sun/star/registry/XImplementationRegistration2.hpp>
37 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
38 #include <com/sun/star/reflection/XServiceTypeDescription.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/uno/RuntimeException.hpp>
41 #include <com/sun/star/uno/XComponentContext.hpp>
43 #include "mergekeys.hxx"
50 using namespace com::sun::star
;
51 using namespace css::uno
;
52 using namespace css::loader
;
53 using namespace css::beans
;
54 using namespace css::lang
;
55 using namespace css::registry
;
61 constexpr OUStringLiteral slash_UNO_slash_REGISTRY_LINKS
62 = u
"/UNO/REGISTRY_LINKS";
63 constexpr OUStringLiteral slash_IMPLEMENTATIONS
64 = u
"/IMPLEMENTATIONS";
65 constexpr OUStringLiteral slash_UNO
67 constexpr OUStringLiteral slash_UNO_slash_SERVICES
69 constexpr OUStringLiteral slash_UNO_slash_SINGLETONS
71 constexpr OUStringLiteral slash_SERVICES
73 constexpr OUStringLiteral slash_UNO_slash_LOCATION
75 constexpr OUStringLiteral slash_UNO_slash_ACTIVATOR
77 constexpr OUStringLiteral colon_old
79 constexpr OUStringLiteral com_sun_star_registry_SimpleRegistry
80 = u
"com.sun.star.registry.SimpleRegistry";
81 constexpr OUStringLiteral Registry
84 // static deleteAllLinkReferences()
86 void deleteAllLinkReferences(const Reference
< XSimpleRegistry
>& xReg
,
87 const Reference
< XRegistryKey
>& xSource
)
88 // throw ( InvalidRegistryException, RuntimeException )
90 Reference
< XRegistryKey
> xKey
= xSource
->openKey(
91 slash_UNO_slash_REGISTRY_LINKS
);
93 if (!(xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCIILIST
)))
96 const Sequence
<OUString
> linkNames
= xKey
->getAsciiListValue();
98 if (!linkNames
.hasElements())
102 OUString aLinkParent
;
103 Reference
< XRegistryKey
> xLinkParent
;
104 const sal_Unicode
* pTmpName
= nullptr;
105 const sal_Unicode
* pShortName
= nullptr;
108 for (const OUString
& rLinkName
: linkNames
)
110 aLinkName
= rLinkName
;
112 pTmpName
= aLinkName
.getStr();
114 if (pTmpName
[0] != L
'/')
117 sal_Int32 nIndex
= rtl_ustr_indexOfChar( pTmpName
, '%' );
119 pShortName
= nullptr;
121 pShortName
= pTmpName
+nIndex
;
123 while (pShortName
&& pShortName
[1] == L
'%')
125 nIndex
= rtl_ustr_indexOfChar( pShortName
+2, '%' );
127 pShortName
= nullptr;
129 pShortName
+= nIndex
+2;
134 aLinkName
= aLinkName
.copy(0, pShortName
- pTmpName
);
137 xReg
->getRootKey()->deleteLink(aLinkName
);
139 sEnd
= aLinkName
.lastIndexOf( '/' );
141 aLinkParent
= aLinkName
.copy(0, sEnd
);
143 while(!aLinkParent
.isEmpty())
145 xLinkParent
= xReg
->getRootKey()->openKey(aLinkParent
);
147 if (xLinkParent
.is() && !xLinkParent
->getKeyNames().hasElements())
149 aLinkName
= aLinkParent
;
151 xReg
->getRootKey()->deleteKey(aLinkParent
);
153 sEnd
= aLinkName
.lastIndexOf( '/' );
155 aLinkParent
= aLinkName
.copy(0, sEnd
);
166 // static prepareLink
168 void prepareLink( const Reference
< XSimpleRegistry
> & xDest
,
169 const Reference
< XRegistryKey
> & xSource
,
170 const OUString
& link
)
171 // throw ( InvalidRegistryException, RuntimeException )
173 OUString linkRefName
= xSource
->getKeyName();
174 OUString
linkName(link
);
175 bool isRelativ
= false;
177 const sal_Unicode
* pTmpName
= link
.getStr();
178 const sal_Unicode
* pShortName
;
179 sal_Int32 nIndex
= rtl_ustr_indexOfChar( pTmpName
, '%' );
181 pShortName
= nullptr;
183 pShortName
= pTmpName
+nIndex
;
185 if (pTmpName
[0] != L
'/')
188 while (pShortName
&& pShortName
[1] == L
'%')
190 nIndex
= rtl_ustr_indexOfChar( pShortName
+2, '%' );
192 pShortName
= nullptr;
194 pShortName
+= nIndex
+2;
199 linkRefName
+= link
.subView(pShortName
- pTmpName
+ 1);
200 linkName
= link
.copy(0, pShortName
- pTmpName
);
204 xSource
->createLink(linkName
, linkRefName
);
206 xDest
->getRootKey()->createLink(linkName
, linkRefName
);
210 // static searchImplForLink
212 OUString
searchImplForLink(
213 const Reference
< XRegistryKey
> & xRootKey
,
214 std::u16string_view linkName
,
215 std::u16string_view implName
)
216 // throw ( InvalidRegistryException, RuntimeException )
218 Reference
< XRegistryKey
> xKey
= xRootKey
->openKey( slash_IMPLEMENTATIONS
);
221 const Sequence
< Reference
< XRegistryKey
> > subKeys( xKey
->openKeys() );
222 OUString
key_name( slash_UNO
+ linkName
);
224 for (const Reference
< XRegistryKey
>& xImplKey
: subKeys
)
228 if (xImplKey
->getKeyType( key_name
) == RegistryKeyType_LINK
)
230 OUString oldImplName
= xImplKey
->getKeyName().copy(strlen("/IMPLEMENTATIONS/"));
231 if (implName
!= oldImplName
)
237 catch(InvalidRegistryException
&)
247 // static searchLinkTargetForImpl
249 OUString
searchLinkTargetForImpl(const Reference
< XRegistryKey
>& xRootKey
,
250 std::u16string_view linkName
,
251 const OUString
& implName
)
253 Reference
< XRegistryKey
> xKey
= xRootKey
->openKey( slash_IMPLEMENTATIONS
);
257 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xKey
->openKeys();
259 OUString
qualifiedLinkName( slash_UNO
+ linkName
);
261 auto pSubKey
= std::find_if(subKeys
.begin(), subKeys
.end(),
262 [&implName
, &qualifiedLinkName
](const Reference
<XRegistryKey
>& rSubKey
) {
263 OUString tmpImplName
= rSubKey
->getKeyName().copy(strlen("/IMPLEMENTATIONS/"));
264 return tmpImplName
== implName
265 && rSubKey
->getKeyType( qualifiedLinkName
) == RegistryKeyType_LINK
;
267 if (pSubKey
!= subKeys
.end())
268 return (*pSubKey
)->getLinkTarget( qualifiedLinkName
);
275 // static createUniqueSubEntry
277 void createUniqueSubEntry(const Reference
< XRegistryKey
> & xSuperKey
,
278 const OUString
& value
)
279 // throw ( InvalidRegistryException, RuntimeException )
284 if (xSuperKey
->getValueType() == RegistryValueType_ASCIILIST
)
286 const Sequence
<OUString
> implEntries
= xSuperKey
->getAsciiListValue();
287 sal_Int32 length
= implEntries
.getLength();
289 bool bReady
= comphelper::findValue(implEntries
, value
) != -1;
293 Sequence
<OUString
> implEntriesNew(length
);
294 auto it
= implEntriesNew
.getArray();
297 std::copy_if(implEntries
.begin(), implEntries
.end(), std::next(it
),
298 [&value
](const OUString
& rEntry
) { return rEntry
!= value
; });
299 xSuperKey
->setAsciiListValue(implEntriesNew
);
302 Sequence
<OUString
> implEntriesNew(length
+1);
303 auto it
= implEntriesNew
.getArray();
306 std::copy(implEntries
.begin(), implEntries
.end(), std::next(it
));
307 xSuperKey
->setAsciiListValue(implEntriesNew
);
311 Sequence
<OUString
> implEntriesNew
{ value
};
313 xSuperKey
->setAsciiListValue(implEntriesNew
);
318 // static deleteSubEntry
320 bool deleteSubEntry(const Reference
< XRegistryKey
>& xSuperKey
, const OUString
& value
)
321 // throw ( InvalidRegistryException, RuntimeException )
323 if (xSuperKey
->getValueType() == RegistryValueType_ASCIILIST
)
325 const Sequence
<OUString
> implEntries
= xSuperKey
->getAsciiListValue();
326 sal_Int32 length
= implEntries
.getLength();
327 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), value
));
328 bool hasNoImplementations
= false;
330 if (equals
== length
)
332 hasNoImplementations
= true;
335 Sequence
<OUString
> implEntriesNew(length
- equals
);
337 std::copy_if(implEntries
.begin(), implEntries
.end(), implEntriesNew
.getArray(),
338 [&value
](const OUString
& rEntry
) { return rEntry
!= value
; });
339 xSuperKey
->setAsciiListValue(implEntriesNew
);
342 if (hasNoImplementations
)
351 // static prepareUserLink
353 void prepareUserLink(const Reference
< XSimpleRegistry
>& xDest
,
354 const OUString
& linkName
,
355 const OUString
& linkTarget
,
356 std::u16string_view implName
)
358 Reference
< XRegistryKey
> xRootKey
= xDest
->getRootKey();
360 if (xRootKey
->getKeyType(linkName
) == RegistryKeyType_LINK
)
362 OUString
oldImplName(searchImplForLink(xRootKey
, linkName
, implName
));
364 if (!oldImplName
.isEmpty())
366 createUniqueSubEntry(xDest
->getRootKey()->createKey(
367 linkName
+ colon_old
), oldImplName
);
371 if (xRootKey
->isValid())
372 xRootKey
->createLink(linkName
, linkTarget
);
376 // static deleteUserLink
378 void deletePathIfPossible(const Reference
< XRegistryKey
>& xRootKey
,
379 const OUString
& path
)
383 Sequence
<OUString
> keyNames(xRootKey
->openKey(path
)->getKeyNames());
385 if (!keyNames
.hasElements() &&
386 xRootKey
->openKey(path
)->getValueType() == RegistryValueType_NOT_DEFINED
)
388 xRootKey
->deleteKey(path
);
390 OUString newPath
= path
.copy(0, path
.lastIndexOf('/'));
392 if (newPath
.getLength() > 1)
393 deletePathIfPossible(xRootKey
, newPath
);
396 catch(InvalidRegistryException
&)
402 // static deleteUserLink
404 void deleteUserLink(const Reference
< XRegistryKey
>& xRootKey
,
405 const OUString
& linkName
,
406 std::u16string_view linkTarget
,
407 const OUString
& implName
)
408 // throw ( InvalidRegistryException, RuntimeException )
412 if (xRootKey
->getKeyType(linkName
) == RegistryKeyType_LINK
)
414 OUString tmpTarget
= xRootKey
->getLinkTarget(linkName
);
416 if (tmpTarget
== linkTarget
)
418 xRootKey
->deleteLink(linkName
);
422 Reference
< XRegistryKey
> xOldKey
= xRootKey
->openKey(
423 linkName
+ colon_old
);
426 if (xOldKey
->getValueType() == RegistryValueType_ASCIILIST
)
428 const Sequence
<OUString
> implEntries
= xOldKey
->getAsciiListValue();
429 sal_Int32 length
= implEntries
.getLength();
430 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), implName
));
431 bool hasNoImplementations
= false;
433 if (equals
== length
)
435 hasNoImplementations
= true;
440 if (length
> equals
+ 1)
442 Sequence
<OUString
> implEntriesNew(length
- equals
- 1);
443 auto pNewArray
= implEntriesNew
.getArray();
447 for (sal_Int32 i
= 0; i
< length
; i
++)
449 if (implEntries
[i
] != implName
)
453 oldImpl
= implEntries
[i
];
457 pNewArray
[j
++] = implEntries
[i
];
462 xOldKey
->setAsciiListValue(implEntriesNew
);
465 oldImpl
= implEntries
[0];
466 OUString
path(xOldKey
->getKeyName());
468 xRootKey
->deleteKey(path
);
471 OUString oldTarget
= searchLinkTargetForImpl(xRootKey
, linkName
, oldImpl
);
472 if (!oldTarget
.isEmpty())
474 xRootKey
->createLink(linkName
, oldTarget
);
478 if (hasNoImplementations
)
481 OUString
path(xOldKey
->getKeyName());
483 xRootKey
->deleteKey(path
);
493 OUString path
= linkName
.copy(0, linkName
.lastIndexOf('/'));
494 deletePathIfPossible(xRootKey
, path
);
499 // static prepareUserKeys
501 void prepareUserKeys(const Reference
< XSimpleRegistry
>& xDest
,
502 const Reference
< XRegistryKey
>& xUnoKey
,
503 const Reference
< XRegistryKey
>& xKey
,
504 const OUString
& implName
,
507 bool hasSubKeys
= false;
509 Sequence
<OUString
> keyNames
= xKey
->getKeyNames();
512 if (keyNames
.hasElements())
513 relativKey
= keyNames
.getConstArray()[0].copy(xKey
->getKeyName().getLength()+1);
515 if (keyNames
.getLength() == 1 &&
516 xKey
->getKeyType(relativKey
) == RegistryKeyType_LINK
)
520 OUString linkTarget
= xKey
->getLinkTarget(relativKey
);
521 OUString
linkName(xKey
->getKeyName().copy(xUnoKey
->getKeyName().getLength()));
523 linkName
+= "/" + relativKey
;
527 prepareUserLink(xDest
, linkName
, linkTarget
, implName
);
530 deleteUserLink(xDest
->getRootKey(), linkName
, linkTarget
, implName
);
534 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xKey
->openKeys();
536 if (subKeys
.hasElements())
540 for (const Reference
< XRegistryKey
> & rSubKey
: subKeys
)
542 prepareUserKeys(xDest
, xUnoKey
, rSubKey
, implName
, bRegister
);
550 OUString
keyName(xKey
->getKeyName().copy(xUnoKey
->getKeyName().getLength()));
552 Reference
< XRegistryKey
> xRootKey
= xDest
->getRootKey();
555 createUniqueSubEntry(xRootKey
->createKey(keyName
), implName
);
559 Reference
< XRegistryKey
> rKey
= xRootKey
->openKey(keyName
);
562 deleteSubEntry(rKey
, implName
);
563 xRootKey
->deleteKey(keyName
);
566 OUString path
= keyName
.copy(0, keyName
.lastIndexOf('/'));
567 if( !path
.isEmpty() )
569 deletePathIfPossible(xRootKey
, path
);
575 // static deleteAllImplementations
577 void deleteAllImplementations( const Reference
< XSimpleRegistry
>& xReg
,
578 const Reference
< XRegistryKey
>& xSource
,
579 std::u16string_view locationUrl
,
580 std::vector
<OUString
> & implNames
)
581 // throw (InvalidRegistryException, RuntimeException)
583 Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
585 if (subKeys
.hasElements())
587 bool hasLocationUrl
= false;
589 for (const Reference
< XRegistryKey
> & xImplKey
: std::as_const(subKeys
))
591 Reference
< XRegistryKey
> xKey
= xImplKey
->openKey(
592 slash_UNO_slash_LOCATION
);
594 if (xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCII
))
596 if (xKey
->getAsciiValue() == locationUrl
)
598 hasLocationUrl
= true;
600 OUString
implName(xImplKey
->getKeyName().copy(1));
601 sal_Int32 firstDot
= implName
.indexOf('/');
604 implName
= implName
.copy(firstDot
+ 1);
606 implNames
.push_back(implName
);
608 deleteAllLinkReferences(xReg
, xImplKey
);
610 xKey
= xImplKey
->openKey( slash_UNO
);
613 const Sequence
< Reference
< XRegistryKey
> > subKeys2
= xKey
->openKeys();
615 for (const Reference
< XRegistryKey
> & rSubKey2
: subKeys2
)
617 if (rSubKey2
->getKeyName() != OUStringConcatenation(xImplKey
->getKeyName() + slash_UNO_slash_SERVICES
) &&
618 rSubKey2
->getKeyName() != OUStringConcatenation(xImplKey
->getKeyName() + slash_UNO_slash_REGISTRY_LINKS
) &&
619 rSubKey2
->getKeyName() != OUStringConcatenation(xImplKey
->getKeyName() + slash_UNO_slash_ACTIVATOR
) &&
620 rSubKey2
->getKeyName() != OUStringConcatenation(xImplKey
->getKeyName() + slash_UNO_slash_SINGLETONS
) &&
621 rSubKey2
->getKeyName() != OUStringConcatenation(xImplKey
->getKeyName() + slash_UNO_slash_LOCATION
) )
623 prepareUserKeys(xReg
, xKey
, rSubKey2
, implName
, false);
632 hasLocationUrl
= false;
633 OUString
path(xImplKey
->getKeyName());
634 xImplKey
->closeKey();
635 xReg
->getRootKey()->deleteKey(path
);
639 subKeys
= xSource
->openKeys();
640 if (!subKeys
.hasElements())
642 OUString
path(xSource
->getKeyName());
644 xReg
->getRootKey()->deleteKey(path
);
648 OUString
path(xSource
->getKeyName());
650 xReg
->getRootKey()->deleteKey(path
);
655 void delete_all_singleton_entries(
656 Reference
< registry::XRegistryKey
> const & xSingletons_section
,
657 ::std::vector
< OUString
> const & impl_names
)
658 // throw (InvalidRegistryException, RuntimeException)
660 Sequence
< Reference
< registry::XRegistryKey
> > singletons( xSingletons_section
->openKeys() );
661 Reference
< registry::XRegistryKey
> const * subkeys
= singletons
.getConstArray();
662 for ( sal_Int32 nPos
= singletons
.getLength(); nPos
--; )
664 Reference
< registry::XRegistryKey
> const & xSingleton
= subkeys
[ nPos
];
665 Reference
< registry::XRegistryKey
> xRegisteredImplNames(
666 xSingleton
->openKey( "REGISTERED_BY" ) );
667 if (xRegisteredImplNames
.is() && xRegisteredImplNames
->isValid())
669 Sequence
< OUString
> registered_implnames
;
672 registered_implnames
= xRegisteredImplNames
->getAsciiListValue();
674 catch (registry::InvalidValueException
&)
677 OUString
const * p
= registered_implnames
.getConstArray();
678 sal_Int32 nOrigRegLength
= registered_implnames
.getLength();
679 sal_Int32 nNewLength
= nOrigRegLength
;
680 for ( sal_Int32 n
= nOrigRegLength
; n
--; )
682 OUString
const & registered_implname
= p
[ n
];
684 for (auto const& impl_name
: impl_names
)
686 if (impl_name
== registered_implname
)
688 registered_implnames
[ n
] = p
[ nNewLength
-1 ];
694 if (nNewLength
!= nOrigRegLength
)
698 // remove whole entry
699 xRegisteredImplNames
->closeKey();
700 xSingleton
->deleteKey( "REGISTERED_BY" );
701 // registry key cannot provide its relative name, only absolute :(
702 OUString
abs( xSingleton
->getKeyName() );
703 xSingletons_section
->deleteKey( abs
.copy( abs
.lastIndexOf( '/' ) +1 ) );
707 registered_implnames
.realloc( nNewLength
);
708 xRegisteredImplNames
->setAsciiListValue( registered_implnames
);
716 // static deleteAllServiceEntries
718 void deleteAllServiceEntries( const Reference
< XSimpleRegistry
>& xReg
,
719 const Reference
< XRegistryKey
>& xSource
,
720 const OUString
& implName
)
721 // throw ( InvalidRegistryException, RuntimeException )
723 Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
725 if (subKeys
.hasElements())
727 bool hasNoImplementations
= false;
729 for (const Reference
< XRegistryKey
> & xServiceKey
: std::as_const(subKeys
))
731 if (xServiceKey
->getValueType() == RegistryValueType_ASCIILIST
)
733 const Sequence
<OUString
> implEntries
= xServiceKey
->getAsciiListValue();
734 sal_Int32 length
= implEntries
.getLength();
735 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), implName
));
737 if (equals
== length
)
739 hasNoImplementations
= true;
744 Sequence
<OUString
> implEntriesNew(length
-equals
);
746 std::copy_if(implEntries
.begin(), implEntries
.end(), implEntriesNew
.getArray(),
747 [&implName
](const OUString
& rEntry
) { return rEntry
!= implName
; });
749 xServiceKey
->setAsciiListValue(implEntriesNew
);
754 if (hasNoImplementations
)
756 hasNoImplementations
= false;
757 OUString
path(xServiceKey
->getKeyName());
758 xServiceKey
->closeKey();
759 xReg
->getRootKey()->deleteKey(path
);
763 subKeys
= xSource
->openKeys();
764 if (!subKeys
.hasElements())
766 OUString
path(xSource
->getKeyName());
768 xReg
->getRootKey()->deleteKey(path
);
772 OUString
path(xSource
->getKeyName());
774 xReg
->getRootKey()->deleteKey(path
);
779 bool is_supported_service(
780 OUString
const & service_name
,
781 Reference
< reflection::XServiceTypeDescription
> const & xService_td
)
783 if (xService_td
->getName() == service_name
)
785 const Sequence
< Reference
< reflection::XServiceTypeDescription
> > seq(
786 xService_td
->getMandatoryServices() );
787 return std::any_of(seq
.begin(), seq
.end(), [&service_name
](const auto& rService
) {
788 return is_supported_service( service_name
, rService
); });
792 void insert_singletons(
793 Reference
< registry::XSimpleRegistry
> const & xDest
,
794 Reference
< registry::XRegistryKey
> const & xImplKey
,
795 Reference
< XComponentContext
> const & xContext
)
796 // throw( registry::InvalidRegistryException, registry::CannotRegisterImplementationException, RuntimeException )
799 Reference
< registry::XRegistryKey
> xKey( xImplKey
->openKey( "UNO/SINGLETONS" ) );
800 if (!(xKey
.is() && xKey
->isValid()))
803 OUString
implname( xImplKey
->getKeyName().copy( sizeof ("/IMPLEMENTATIONS/") -1 ) );
805 Sequence
< Reference
< registry::XRegistryKey
> > xSingletons_section( xKey
->openKeys() );
806 Reference
< registry::XRegistryKey
> const * p
= xSingletons_section
.getConstArray();
807 for ( sal_Int32 nPos
= xSingletons_section
.getLength(); nPos
--; )
809 Reference
< registry::XRegistryKey
> const & xSingleton
= p
[ nPos
];
810 OUString
singleton_name(
811 xSingleton
->getKeyName().copy(
812 implname
.getLength() + sizeof ("/IMPLEMENTATIONS//UNO/SINGLETONS/") -1 ) );
813 OUString
service_name( xSingleton
->getStringValue() );
815 OUString
keyname( "/SINGLETONS/" + singleton_name
);
816 Reference
< registry::XRegistryKey
> xKey2( xDest
->getRootKey()->openKey( keyname
) );
817 if (xKey2
.is() && xKey2
->isValid())
821 OUString
existing_name( xKey2
->getStringValue() );
822 if ( existing_name
!= service_name
)
824 Reference
< container::XHierarchicalNameAccess
> xTDMgr
;
826 "/singletons/com.sun.star.reflection.theTypeDescriptionManager";
827 xContext
->getValueByName( the_tdmgr
) >>= xTDMgr
;
830 throw RuntimeException( "cannot get singleton " + the_tdmgr
);
834 Reference
< reflection::XServiceTypeDescription
> xExistingService_td
;
835 xTDMgr
->getByHierarchicalName( existing_name
) >>= xExistingService_td
;
836 if (! xExistingService_td
.is())
838 throw RuntimeException( "cannot get service type description: " + existing_name
);
841 // everything's fine if existing service entry supports the one
843 if (! is_supported_service( service_name
, xExistingService_td
))
845 throw registry::CannotRegisterImplementationException(
846 "existing singleton service (" + singleton_name
+ "=" + existing_name
+ ") "
847 " does not support given one: " + service_name
);
850 catch (const container::NoSuchElementException
& exc
)
852 css::uno::Any anyEx
= cppu::getCaughtException();
853 throw css::lang::WrappedTargetRuntimeException(
854 "cannot get service type description: " + exc
.Message
,
859 catch (registry::InvalidValueException
&)
862 xKey2
->setStringValue( service_name
);
867 // insert singleton entry
868 xKey2
= xDest
->getRootKey()->createKey( keyname
);
869 xKey2
->setStringValue( service_name
);
872 Reference
< registry::XRegistryKey
> xRegisteredImplNames(
873 xKey2
->openKey( "REGISTERED_BY" ) );
874 if (!xRegisteredImplNames
.is() || !xRegisteredImplNames
->isValid())
877 xRegisteredImplNames
= xKey2
->createKey( "REGISTERED_BY" );
880 Sequence
< OUString
> implnames
;
883 implnames
= xRegisteredImplNames
->getAsciiListValue();
885 catch (registry::InvalidValueException
&)
888 // check implname is already in
889 if (comphelper::findValue(implnames
, implname
) == -1)
891 // append and write back
892 implnames
.realloc( implnames
.getLength() +1 );
893 implnames
[ implnames
.getLength() -1 ] = implname
;
894 xRegisteredImplNames
->setAsciiListValue( implnames
);
900 // static prepareRegistry
902 void prepareRegistry(
903 const Reference
< XSimpleRegistry
>& xDest
,
904 const Reference
< XRegistryKey
>& xSource
,
905 const OUString
& implementationLoaderUrl
,
906 const OUString
& locationUrl
,
907 Reference
< XComponentContext
> const & xContext
)
908 // throw ( InvalidRegistryException, CannotRegisterImplementationException, RuntimeException )
910 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
912 if (!subKeys
.hasElements())
914 throw InvalidRegistryException(
915 "prepareRegistry(): source registry is empty" );
918 for (const Reference
< XRegistryKey
>& xImplKey
: subKeys
)
920 Reference
< XRegistryKey
> xKey
= xImplKey
->openKey(
921 slash_UNO_slash_SERVICES
);
925 // update entries in SERVICES section
926 const Sequence
< Reference
< XRegistryKey
> > serviceKeys
= xKey
->openKeys();
928 OUString implName
= xImplKey
->getKeyName().copy(1);
929 sal_Int32 firstDot
= implName
.indexOf('/');
932 implName
= implName
.copy(firstDot
+ 1);
934 sal_Int32 offset
= xKey
->getKeyName().getLength() + 1;
936 for (const Reference
< XRegistryKey
>& rServiceKey
: serviceKeys
)
938 OUString serviceName
= rServiceKey
->getKeyName().copy(offset
);
940 createUniqueSubEntry(
941 xDest
->getRootKey()->createKey(
942 slash_SERVICES
+ serviceName
),
946 xKey
= xImplKey
->openKey( slash_UNO
);
949 const Sequence
< Reference
< XRegistryKey
> > subKeys2
= xKey
->openKeys();
951 for (const Reference
< XRegistryKey
>& rSubKey2
: subKeys2
)
953 if (rSubKey2
->getKeyName() != OUStringConcatenation(xImplKey
->getKeyName() + slash_UNO_slash_SERVICES
) &&
954 rSubKey2
->getKeyName() != OUStringConcatenation(xImplKey
->getKeyName() + slash_UNO_slash_REGISTRY_LINKS
) &&
955 rSubKey2
->getKeyName() != OUStringConcatenation(xImplKey
->getKeyName() + slash_UNO_slash_SINGLETONS
))
957 prepareUserKeys(xDest
, xKey
, rSubKey2
, implName
, true);
963 // update LOCATION entry
964 xKey
= xImplKey
->createKey( slash_UNO_slash_LOCATION
);
968 xKey
->setAsciiValue(locationUrl
);
971 // update ACTIVATOR entry
972 xKey
= xImplKey
->createKey( slash_UNO_slash_ACTIVATOR
);
976 xKey
->setAsciiValue(implementationLoaderUrl
);
979 xKey
= xImplKey
->openKey( slash_UNO_slash_SERVICES
);
981 if (xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCIILIST
))
983 // update link entries in REGISTRY_LINKS section
984 const Sequence
<OUString
> linkNames
= xKey
->getAsciiListValue();
986 for (const OUString
& rLinkName
: linkNames
)
988 prepareLink(xDest
, xImplKey
, rLinkName
);
992 insert_singletons( xDest
, xImplKey
, xContext
);
997 void findImplementations( const Reference
< XRegistryKey
> & xSource
,
998 std::vector
<OUString
>& implNames
)
1000 bool isImplKey
= false;
1004 Reference
< XRegistryKey
> xKey
= xSource
->openKey(
1005 slash_UNO_slash_SERVICES
);
1007 if (xKey
.is() && xKey
->getKeyNames().hasElements())
1011 OUString implName
= xSource
->getKeyName().copy(1).replace('/', '.');
1012 sal_Int32 firstDot
= implName
.indexOf('.');
1015 implName
= implName
.copy(firstDot
+ 1);
1017 implNames
.push_back(implName
);
1020 catch(InvalidRegistryException
&)
1024 if (isImplKey
) return;
1028 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
1030 for (const Reference
< XRegistryKey
>& rSubKey
: subKeys
)
1032 findImplementations(rSubKey
, implNames
);
1035 catch(InvalidRegistryException
&)
1041 class ImplementationRegistration
1042 : public WeakImplHelper
< XImplementationRegistration2
, XServiceInfo
, XInitialization
>
1045 explicit ImplementationRegistration( const Reference
< XComponentContext
> & rSMgr
);
1048 OUString SAL_CALL
getImplementationName() override
;
1049 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
1050 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
1052 // XImplementationRegistration
1053 virtual void SAL_CALL
registerImplementation(
1054 const OUString
& implementationLoader
,
1055 const OUString
& location
,
1056 const Reference
< XSimpleRegistry
> & xReg
) override
;
1058 virtual sal_Bool SAL_CALL
revokeImplementation(
1059 const OUString
& location
,
1060 const Reference
< XSimpleRegistry
>& xReg
) override
;
1062 virtual Sequence
< OUString
> SAL_CALL
getImplementations(
1063 const OUString
& implementationLoader
,
1064 const OUString
& location
) override
;
1065 virtual Sequence
< OUString
> SAL_CALL
checkInstantiation(
1066 const OUString
& implementationName
) override
;
1068 // XImplementationRegistration2
1069 virtual void SAL_CALL
registerImplementationWithLocation(
1070 const OUString
& implementationLoader
,
1071 const OUString
& location
,
1072 const OUString
& registeredLocation
,
1073 const Reference
< XSimpleRegistry
> & xReg
) override
;
1076 virtual void SAL_CALL
initialize(
1077 const css::uno::Sequence
< css::uno::Any
>& aArguments
) override
;
1079 private: // helper methods
1080 void prepareRegister(
1081 const OUString
& implementationLoader
,
1082 const OUString
& location
,
1083 const OUString
& registeredLocation
,
1084 const Reference
< XSimpleRegistry
> & xReg
);
1085 // throw( CannotRegisterImplementationException, RuntimeException )
1087 static void doRegister( const Reference
< XMultiComponentFactory
>& xSMgr
,
1088 const Reference
< XComponentContext
> &xCtx
,
1089 const Reference
< XImplementationLoader
>& xAct
,
1090 const Reference
< XSimpleRegistry
>& xDest
,
1091 const OUString
& implementationLoaderUrl
,
1092 const OUString
& locationUrl
,
1093 const OUString
& registeredLocationUrl
);
1094 /* throw ( InvalidRegistryException,
1095 MergeConflictException,
1096 CannotRegisterImplementationException, RuntimeException ) */
1098 static void doRevoke( const Reference
< XSimpleRegistry
>& xDest
,
1099 std::u16string_view locationUrl
);
1100 // throw( InvalidRegistryException, RuntimeException )
1101 Reference
< XSimpleRegistry
> getRegistryFromServiceManager() const;
1103 static Reference
< XSimpleRegistry
> createTemporarySimpleRegistry(
1104 const Reference
< XMultiComponentFactory
> &rSMgr
,
1105 const Reference
< XComponentContext
> & rCtx
);
1108 Reference
< XMultiComponentFactory
> m_xSMgr
;
1109 Reference
< XComponentContext
> m_xCtx
;
1113 // ImplementationRegistration()
1115 ImplementationRegistration::ImplementationRegistration( const Reference
< XComponentContext
> & xCtx
)
1116 : m_xSMgr( xCtx
->getServiceManager() )
1121 OUString
ImplementationRegistration::getImplementationName()
1123 return "com.sun.star.comp.stoc.ImplementationRegistration";
1127 sal_Bool
ImplementationRegistration::supportsService(const OUString
& ServiceName
)
1129 return cppu::supportsService(this, ServiceName
);
1133 Sequence
< OUString
> ImplementationRegistration::getSupportedServiceNames()
1135 return { "com.sun.star.registry.ImplementationRegistration" };
1138 Reference
< XSimpleRegistry
> ImplementationRegistration::getRegistryFromServiceManager() const
1140 Reference
< XPropertySet
> xPropSet( m_xSMgr
, UNO_QUERY
);
1141 Reference
< XSimpleRegistry
> xRegistry
;
1143 if( xPropSet
.is() ) {
1145 try { // the implementation does not support XIntrospectionAccess !
1147 Any aAny
= xPropSet
->getPropertyValue( Registry
);
1149 if( aAny
.getValueType().getTypeClass() == TypeClass_INTERFACE
) {
1153 catch( UnknownPropertyException
& ) {
1154 // empty reference is error signal !
1164 void ImplementationRegistration::initialize(
1165 const css::uno::Sequence
< css::uno::Any
>& aArgs
)
1168 if( aArgs
.getLength() != 4 ) {
1169 throw IllegalArgumentException(
1170 "ImplementationRegistration::initialize() expects 4 parameters, got " + OUString::number( aArgs
.getLength() ),
1171 Reference
<XInterface
> (), 0 );
1174 Reference
< XImplementationLoader
> rLoader
;
1175 OUString loaderServiceName
;
1176 OUString locationUrl
;
1177 Reference
< XSimpleRegistry
> rReg
;
1179 // 1st argument : An instance of an implementation loader
1180 if( aArgs
.getConstArray()[0].getValueType().getTypeClass() == TypeClass_INTERFACE
) {
1181 aArgs
.getConstArray()[0] >>= rLoader
;
1183 if( !rLoader
.is()) {
1184 throw IllegalArgumentException(
1185 "ImplementationRegistration::initialize() invalid first parameter,"
1186 "expected " + cppu::UnoType
<decltype(rLoader
)>::get().getTypeName() +
1187 ", got " + aArgs
.getConstArray()[0].getValueTypeName(),
1188 Reference
< XInterface
> (), 0 );
1191 // 2nd argument : The service name of the loader. This name is written into the registry
1192 if( aArgs
.getConstArray()[1].getValueType().getTypeClass() == TypeClass_STRING
) {
1193 aArgs
.getConstArray()[1] >>= loaderServiceName
;
1195 if( loaderServiceName
.isEmpty() ) {
1196 throw IllegalArgumentException(
1197 "ImplementationRegistration::initialize() invalid second parameter,"
1198 "expected string, got " + aArgs
.getConstArray()[1].getValueTypeName(),
1199 Reference
< XInterface
> (), 0 );
1202 // 3rd argument : The file name of the dll, that contains the loader
1203 if( aArgs
.getConstArray()[2].getValueType().getTypeClass() == TypeClass_STRING
) {
1204 aArgs
.getConstArray()[2] >>= locationUrl
;
1206 if( locationUrl
.isEmpty() ) {
1207 throw IllegalArgumentException(
1208 "ImplementationRegistration::initialize() invalid third parameter,"
1209 "expected string, got " + aArgs
.getConstArray()[2].getValueTypeName(),
1210 Reference
< XInterface
> (), 0 );
1213 // 4th argument : The registry, the service should be written to
1214 if( aArgs
.getConstArray()[3].getValueType().getTypeClass() == TypeClass_INTERFACE
) {
1215 aArgs
.getConstArray()[3] >>= rReg
;
1219 rReg
= getRegistryFromServiceManager();
1221 throw IllegalArgumentException(
1222 "ImplementationRegistration::initialize() invalid fourth parameter,"
1223 "expected " + cppu::UnoType
<decltype(rReg
)>::get().getTypeName() +
1224 ", got " + aArgs
.getConstArray()[3].getValueTypeName(),
1225 Reference
< XInterface
> (), 0 );
1229 doRegister(m_xSMgr
, m_xCtx
, rLoader
, rReg
, loaderServiceName
, locationUrl
, locationUrl
);
1233 // virtual function registerImplementationWithLocation of XImplementationRegistration2
1235 void ImplementationRegistration::registerImplementationWithLocation(
1236 const OUString
& implementationLoaderUrl
,
1237 const OUString
& locationUrl
,
1238 const OUString
& registeredLocationUrl
,
1239 const Reference
< XSimpleRegistry
> & xReg
)
1242 implementationLoaderUrl
, locationUrl
, registeredLocationUrl
, xReg
);
1246 void ImplementationRegistration::prepareRegister(
1247 const OUString
& implementationLoaderUrl
,
1248 const OUString
& locationUrl
,
1249 const OUString
& registeredLocationUrl
,
1250 const Reference
< XSimpleRegistry
> & xReg
)
1251 // throw( CannotRegisterImplementationException, RuntimeException )
1253 OUString activatorName
;
1255 if (!implementationLoaderUrl
.isEmpty())
1257 activatorName
= implementationLoaderUrl
.getToken(0, ':');
1260 // check locationUrl to find out what kind of loader is needed
1261 // set implLoaderUrl
1264 if( !m_xSMgr
.is() ) {
1265 throw CannotRegisterImplementationException(
1266 "ImplementationRegistration::registerImplementation() "
1267 "no componentcontext available to instantiate loader" );
1272 Reference
< XImplementationLoader
> xAct(
1273 m_xSMgr
->createInstanceWithContext(activatorName
, m_xCtx
) , UNO_QUERY
);
1276 throw CannotRegisterImplementationException(
1277 "ImplementationRegistration::registerImplementation() - The service "
1278 + activatorName
+ " cannot be instantiated" );
1281 Reference
< XSimpleRegistry
> xRegistry
;
1285 // registry supplied by user
1290 xRegistry
= getRegistryFromServiceManager();
1293 if ( xRegistry
.is())
1295 doRegister(m_xSMgr
, m_xCtx
, xAct
, xRegistry
, implementationLoaderUrl
,
1296 locationUrl
, registeredLocationUrl
);
1300 catch( CannotRegisterImplementationException
& )
1304 catch( const InvalidRegistryException
& e
)
1306 throw CannotRegisterImplementationException(
1307 "ImplementationRegistration::registerImplementation() "
1308 "InvalidRegistryException during registration (" + e
.Message
+ ")" );
1310 catch( const MergeConflictException
& e
)
1312 throw CannotRegisterImplementationException(
1313 "ImplementationRegistration::registerImplementation() "
1314 "MergeConflictException during registration (" + e
.Message
+ ")" );
1320 // virtual function registerImplementation of XImplementationRegistration
1322 void ImplementationRegistration::registerImplementation(
1323 const OUString
& implementationLoaderUrl
,
1324 const OUString
& locationUrl
,
1325 const Reference
< XSimpleRegistry
> & xReg
)
1327 prepareRegister(implementationLoaderUrl
, locationUrl
, locationUrl
, xReg
);
1331 // virtual function revokeImplementation of XImplementationRegistration
1333 sal_Bool
ImplementationRegistration::revokeImplementation(const OUString
& location
,
1334 const Reference
< XSimpleRegistry
>& xReg
)
1338 Reference
< XSimpleRegistry
> xRegistry
;
1344 Reference
< XPropertySet
> xPropSet( m_xSMgr
, UNO_QUERY
);
1345 if( xPropSet
.is() ) {
1347 Any aAny
= xPropSet
->getPropertyValue( Registry
);
1349 if( aAny
.getValueType().getTypeClass() == TypeClass_INTERFACE
)
1354 catch ( UnknownPropertyException
& ) {
1363 doRevoke(xRegistry
, location
);
1366 catch( InvalidRegistryException
& )
1368 // no way to transport the error, as no exception is specified and a runtime
1369 // exception is not appropriate.
1370 TOOLS_WARN_EXCEPTION( "stoc", "InvalidRegistryException during revokeImplementation" );
1378 // virtual function getImplementations of XImplementationRegistration
1380 Sequence
< OUString
> ImplementationRegistration::getImplementations(
1381 const OUString
& implementationLoaderUrl
,
1382 const OUString
& locationUrl
)
1384 OUString activatorName
;
1386 if (!implementationLoaderUrl
.isEmpty())
1388 activatorName
= implementationLoaderUrl
.getToken(0, ':');
1391 // check locationUrl to find out what kind of loader is needed
1392 // set implementationLoaderUrl
1395 if( m_xSMgr
.is() ) {
1397 Reference
< XImplementationLoader
> xAct(
1398 m_xSMgr
->createInstanceWithContext( activatorName
, m_xCtx
), UNO_QUERY
);
1403 Reference
< XSimpleRegistry
> xReg
=
1404 createTemporarySimpleRegistry( m_xSMgr
, m_xCtx
);
1410 xReg
->open(OUString() /* in mem */, false, true);
1411 Reference
< XRegistryKey
> xImpl
;
1413 { // only necessary for deleting the temporary variable of rootkey
1414 xImpl
= xReg
->getRootKey()->createKey( slash_IMPLEMENTATIONS
);
1416 if (xAct
->writeRegistryInfo(xImpl
, implementationLoaderUrl
, locationUrl
))
1418 std::vector
<OUString
> implNames
;
1420 findImplementations(xImpl
, implNames
);
1422 if (!implNames
.empty())
1424 Sequence
<OUString
> seqImpl(comphelper::containerToSequence(implNames
));
1432 catch(MergeConflictException
&)
1435 catch(InvalidRegistryException
&)
1442 return Sequence
<OUString
>();
1446 // virtual function checkInstantiation of XImplementationRegistration
1448 Sequence
< OUString
> ImplementationRegistration::checkInstantiation(const OUString
&)
1450 OSL_FAIL( "ImplementationRegistration::checkInstantiation not implemented" );
1451 return Sequence
<OUString
>();
1455 // helper function doRegistration
1458 void ImplementationRegistration::doRevoke(
1459 const Reference
< XSimpleRegistry
>& xDest
,
1460 std::u16string_view locationUrl
)
1461 // throw ( InvalidRegistryException, RuntimeException )
1466 std::vector
<OUString
> aNames
;
1468 Reference
< XRegistryKey
> xRootKey( xDest
->getRootKey() );
1470 Reference
< XRegistryKey
> xKey
=
1471 xRootKey
->openKey( slash_IMPLEMENTATIONS
);
1472 if (xKey
.is() && xKey
->isValid())
1474 deleteAllImplementations(xDest
, xKey
, locationUrl
, aNames
);
1477 xKey
= xRootKey
->openKey( slash_SERVICES
);
1480 for (auto const& name
: aNames
)
1482 deleteAllServiceEntries(xDest
, xKey
, name
);
1486 xKey
= xRootKey
->openKey( "/SINGLETONS" );
1487 if (xKey
.is() && xKey
->isValid())
1489 delete_all_singleton_entries( xKey
, aNames
);
1493 xRootKey
->closeKey();
1494 if (xKey
.is() && xKey
->isValid() )
1498 void ImplementationRegistration::doRegister(
1499 const Reference
< XMultiComponentFactory
> & xSMgr
,
1500 const Reference
< XComponentContext
> &xCtx
,
1501 const Reference
< XImplementationLoader
> & xAct
,
1502 const Reference
< XSimpleRegistry
>& xDest
,
1503 const OUString
& implementationLoaderUrl
,
1504 const OUString
& locationUrl
,
1505 const OUString
& registeredLocationUrl
)
1506 /* throw ( InvalidRegistryException,
1507 MergeConflictException,
1508 CannotRegisterImplementationException, RuntimeException ) */
1510 Reference
< XSimpleRegistry
> xReg
=
1511 createTemporarySimpleRegistry( xSMgr
, xCtx
);
1512 Reference
< XRegistryKey
> xSourceKey
;
1514 if (!(xAct
.is() && xReg
.is() && xDest
.is()))
1519 xReg
->open(OUString() /* in mem */, false, true);
1521 { // only necessary for deleting the temporary variable of rootkey
1522 xSourceKey
= xReg
->getRootKey()->createKey( slash_IMPLEMENTATIONS
);
1526 xAct
->writeRegistryInfo(xSourceKey
, implementationLoaderUrl
, locationUrl
);
1529 throw CannotRegisterImplementationException(
1530 "ImplementationRegistration::doRegistration() component registration signaled failure" );
1533 prepareRegistry(xDest
, xSourceKey
, implementationLoaderUrl
, registeredLocationUrl
, xCtx
);
1535 xSourceKey
->closeKey();
1537 xSourceKey
= xReg
->getRootKey();
1538 Reference
< XRegistryKey
> xDestKey
= xDest
->getRootKey();
1539 stoc_impreg::mergeKeys( xDestKey
, xSourceKey
);
1540 xDestKey
->closeKey();
1541 xSourceKey
->closeKey();
1544 // Cleanup Source registry.
1545 if ( xSourceKey
->isValid() )
1546 xSourceKey
->closeKey();
1548 catch(CannotRegisterImplementationException
&)
1550 if ( xSourceKey
->isValid() )
1551 xSourceKey
->closeKey();
1558 Reference
< XSimpleRegistry
> ImplementationRegistration::createTemporarySimpleRegistry(
1559 const Reference
< XMultiComponentFactory
> &rSMgr
,
1560 const Reference
< XComponentContext
> & xCtx
)
1563 Reference
< XSimpleRegistry
> xReg(
1564 rSMgr
->createInstanceWithContext(
1565 com_sun_star_registry_SimpleRegistry
, xCtx
),
1567 OSL_ASSERT( xReg
.is() );
1573 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1574 com_sun_star_comp_stoc_ImplementationRegistration_get_implementation(
1575 css::uno::XComponentContext
*context
,
1576 css::uno::Sequence
<css::uno::Any
> const &)
1578 return cppu::acquire(new ImplementationRegistration(context
));
1581 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */