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
;
60 constexpr OUStringLiteral slash_UNO_slash_REGISTRY_LINKS
61 = u
"/UNO/REGISTRY_LINKS";
62 constexpr OUStringLiteral slash_IMPLEMENTATIONS
63 = u
"/IMPLEMENTATIONS";
64 constexpr OUStringLiteral slash_UNO
66 constexpr OUStringLiteral slash_UNO_slash_SERVICES
68 constexpr OUStringLiteral slash_UNO_slash_SINGLETONS
70 constexpr OUStringLiteral slash_SERVICES
72 constexpr OUStringLiteral slash_UNO_slash_LOCATION
74 constexpr OUStringLiteral slash_UNO_slash_ACTIVATOR
76 constexpr OUStringLiteral colon_old
78 constexpr OUStringLiteral com_sun_star_registry_SimpleRegistry
79 = u
"com.sun.star.registry.SimpleRegistry";
80 constexpr OUStringLiteral Registry
83 // static deleteAllLinkReferences()
85 void deleteAllLinkReferences(const Reference
< XSimpleRegistry
>& xReg
,
86 const Reference
< XRegistryKey
>& xSource
)
87 // throw ( InvalidRegistryException, RuntimeException )
89 Reference
< XRegistryKey
> xKey
= xSource
->openKey(
90 slash_UNO_slash_REGISTRY_LINKS
);
92 if (!(xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCIILIST
)))
95 const Sequence
<OUString
> linkNames
= xKey
->getAsciiListValue();
97 if (!linkNames
.hasElements())
101 OUString aLinkParent
;
102 Reference
< XRegistryKey
> xLinkParent
;
103 const sal_Unicode
* pTmpName
= nullptr;
104 const sal_Unicode
* pShortName
= nullptr;
107 for (const OUString
& rLinkName
: linkNames
)
109 aLinkName
= rLinkName
;
111 pTmpName
= aLinkName
.getStr();
113 if (pTmpName
[0] != L
'/')
116 sal_Int32 nIndex
= rtl_ustr_indexOfChar( pTmpName
, '%' );
118 pShortName
= nullptr;
120 pShortName
= pTmpName
+nIndex
;
122 while (pShortName
&& pShortName
[1] == L
'%')
124 nIndex
= rtl_ustr_indexOfChar( pShortName
+2, '%' );
126 pShortName
= nullptr;
128 pShortName
+= nIndex
+2;
133 aLinkName
= aLinkName
.copy(0, pShortName
- pTmpName
);
136 xReg
->getRootKey()->deleteLink(aLinkName
);
138 sEnd
= aLinkName
.lastIndexOf( '/' );
140 aLinkParent
= aLinkName
.copy(0, sEnd
);
142 while(!aLinkParent
.isEmpty())
144 xLinkParent
= xReg
->getRootKey()->openKey(aLinkParent
);
146 if (xLinkParent
.is() && !xLinkParent
->getKeyNames().hasElements())
148 aLinkName
= aLinkParent
;
150 xReg
->getRootKey()->deleteKey(aLinkParent
);
152 sEnd
= aLinkName
.lastIndexOf( '/' );
154 aLinkParent
= aLinkName
.copy(0, sEnd
);
165 // static prepareLink
167 void prepareLink( const Reference
< XSimpleRegistry
> & xDest
,
168 const Reference
< XRegistryKey
> & xSource
,
169 const OUString
& link
)
170 // throw ( InvalidRegistryException, RuntimeException )
172 OUString linkRefName
= xSource
->getKeyName();
173 OUString
linkName(link
);
174 bool isRelativ
= false;
176 const sal_Unicode
* pTmpName
= link
.getStr();
177 const sal_Unicode
* pShortName
;
178 sal_Int32 nIndex
= rtl_ustr_indexOfChar( pTmpName
, '%' );
180 pShortName
= nullptr;
182 pShortName
= pTmpName
+nIndex
;
184 if (pTmpName
[0] != L
'/')
187 while (pShortName
&& pShortName
[1] == L
'%')
189 nIndex
= rtl_ustr_indexOfChar( pShortName
+2, '%' );
191 pShortName
= nullptr;
193 pShortName
+= nIndex
+2;
198 linkRefName
+= link
.subView(pShortName
- pTmpName
+ 1);
199 linkName
= link
.copy(0, pShortName
- pTmpName
);
203 xSource
->createLink(linkName
, linkRefName
);
205 xDest
->getRootKey()->createLink(linkName
, linkRefName
);
209 // static searchImplForLink
211 OUString
searchImplForLink(
212 const Reference
< XRegistryKey
> & xRootKey
,
213 std::u16string_view linkName
,
214 std::u16string_view implName
)
215 // throw ( InvalidRegistryException, RuntimeException )
217 Reference
< XRegistryKey
> xKey
= xRootKey
->openKey( slash_IMPLEMENTATIONS
);
220 const Sequence
< Reference
< XRegistryKey
> > subKeys( xKey
->openKeys() );
221 OUString
key_name( slash_UNO
+ linkName
);
223 for (const Reference
< XRegistryKey
>& xImplKey
: subKeys
)
227 if (xImplKey
->getKeyType( key_name
) == RegistryKeyType_LINK
)
229 OUString oldImplName
= xImplKey
->getKeyName().copy(strlen("/IMPLEMENTATIONS/"));
230 if (implName
!= oldImplName
)
236 catch(InvalidRegistryException
&)
246 // static searchLinkTargetForImpl
248 OUString
searchLinkTargetForImpl(const Reference
< XRegistryKey
>& xRootKey
,
249 std::u16string_view linkName
,
250 const OUString
& implName
)
252 Reference
< XRegistryKey
> xKey
= xRootKey
->openKey( slash_IMPLEMENTATIONS
);
256 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xKey
->openKeys();
258 OUString
qualifiedLinkName( slash_UNO
+ linkName
);
260 auto pSubKey
= std::find_if(subKeys
.begin(), subKeys
.end(),
261 [&implName
, &qualifiedLinkName
](const Reference
<XRegistryKey
>& rSubKey
) {
262 OUString tmpImplName
= rSubKey
->getKeyName().copy(strlen("/IMPLEMENTATIONS/"));
263 return tmpImplName
== implName
264 && rSubKey
->getKeyType( qualifiedLinkName
) == RegistryKeyType_LINK
;
266 if (pSubKey
!= subKeys
.end())
267 return (*pSubKey
)->getLinkTarget( qualifiedLinkName
);
274 // static createUniqueSubEntry
276 void createUniqueSubEntry(const Reference
< XRegistryKey
> & xSuperKey
,
277 const OUString
& value
)
278 // throw ( InvalidRegistryException, RuntimeException )
283 if (xSuperKey
->getValueType() == RegistryValueType_ASCIILIST
)
285 const Sequence
<OUString
> implEntries
= xSuperKey
->getAsciiListValue();
286 sal_Int32 length
= implEntries
.getLength();
288 bool bReady
= comphelper::findValue(implEntries
, value
) != -1;
292 Sequence
<OUString
> implEntriesNew(length
);
293 auto it
= implEntriesNew
.getArray();
296 std::copy_if(implEntries
.begin(), implEntries
.end(), std::next(it
),
297 [&value
](const OUString
& rEntry
) { return rEntry
!= value
; });
298 xSuperKey
->setAsciiListValue(implEntriesNew
);
301 Sequence
<OUString
> implEntriesNew(length
+1);
302 auto it
= implEntriesNew
.getArray();
305 std::copy(implEntries
.begin(), implEntries
.end(), std::next(it
));
306 xSuperKey
->setAsciiListValue(implEntriesNew
);
310 Sequence
<OUString
> implEntriesNew
{ value
};
312 xSuperKey
->setAsciiListValue(implEntriesNew
);
317 // static deleteSubEntry
319 bool deleteSubEntry(const Reference
< XRegistryKey
>& xSuperKey
, const OUString
& value
)
320 // throw ( InvalidRegistryException, RuntimeException )
322 if (xSuperKey
->getValueType() == RegistryValueType_ASCIILIST
)
324 const Sequence
<OUString
> implEntries
= xSuperKey
->getAsciiListValue();
325 sal_Int32 length
= implEntries
.getLength();
326 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), value
));
327 bool hasNoImplementations
= false;
329 if (equals
== length
)
331 hasNoImplementations
= true;
334 Sequence
<OUString
> implEntriesNew(length
- equals
);
336 std::copy_if(implEntries
.begin(), implEntries
.end(), implEntriesNew
.getArray(),
337 [&value
](const OUString
& rEntry
) { return rEntry
!= value
; });
338 xSuperKey
->setAsciiListValue(implEntriesNew
);
341 if (hasNoImplementations
)
350 // static prepareUserLink
352 void prepareUserLink(const Reference
< XSimpleRegistry
>& xDest
,
353 const OUString
& linkName
,
354 const OUString
& linkTarget
,
355 std::u16string_view implName
)
357 Reference
< XRegistryKey
> xRootKey
= xDest
->getRootKey();
359 if (xRootKey
->getKeyType(linkName
) == RegistryKeyType_LINK
)
361 OUString
oldImplName(searchImplForLink(xRootKey
, linkName
, implName
));
363 if (!oldImplName
.isEmpty())
365 createUniqueSubEntry(xDest
->getRootKey()->createKey(
366 linkName
+ colon_old
), oldImplName
);
370 if (xRootKey
->isValid())
371 xRootKey
->createLink(linkName
, linkTarget
);
375 // static deleteUserLink
377 void deletePathIfPossible(const Reference
< XRegistryKey
>& xRootKey
,
378 const OUString
& path
)
382 Sequence
<OUString
> keyNames(xRootKey
->openKey(path
)->getKeyNames());
384 if (!keyNames
.hasElements() &&
385 xRootKey
->openKey(path
)->getValueType() == RegistryValueType_NOT_DEFINED
)
387 xRootKey
->deleteKey(path
);
389 OUString newPath
= path
.copy(0, path
.lastIndexOf('/'));
391 if (newPath
.getLength() > 1)
392 deletePathIfPossible(xRootKey
, newPath
);
395 catch(InvalidRegistryException
&)
401 // static deleteUserLink
403 void deleteUserLink(const Reference
< XRegistryKey
>& xRootKey
,
404 const OUString
& linkName
,
405 std::u16string_view linkTarget
,
406 const OUString
& implName
)
407 // throw ( InvalidRegistryException, RuntimeException )
411 if (xRootKey
->getKeyType(linkName
) == RegistryKeyType_LINK
)
413 OUString tmpTarget
= xRootKey
->getLinkTarget(linkName
);
415 if (tmpTarget
== linkTarget
)
417 xRootKey
->deleteLink(linkName
);
421 Reference
< XRegistryKey
> xOldKey
= xRootKey
->openKey(
422 linkName
+ colon_old
);
425 if (xOldKey
->getValueType() == RegistryValueType_ASCIILIST
)
427 const Sequence
<OUString
> implEntries
= xOldKey
->getAsciiListValue();
428 sal_Int32 length
= implEntries
.getLength();
429 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), implName
));
430 bool hasNoImplementations
= false;
432 if (equals
== length
)
434 hasNoImplementations
= true;
439 if (length
> equals
+ 1)
441 Sequence
<OUString
> implEntriesNew(length
- equals
- 1);
442 auto pNewArray
= implEntriesNew
.getArray();
446 for (sal_Int32 i
= 0; i
< length
; i
++)
448 if (implEntries
[i
] != implName
)
452 oldImpl
= implEntries
[i
];
456 pNewArray
[j
++] = implEntries
[i
];
461 xOldKey
->setAsciiListValue(implEntriesNew
);
464 oldImpl
= implEntries
[0];
465 OUString
path(xOldKey
->getKeyName());
467 xRootKey
->deleteKey(path
);
470 OUString oldTarget
= searchLinkTargetForImpl(xRootKey
, linkName
, oldImpl
);
471 if (!oldTarget
.isEmpty())
473 xRootKey
->createLink(linkName
, oldTarget
);
477 if (hasNoImplementations
)
480 OUString
path(xOldKey
->getKeyName());
482 xRootKey
->deleteKey(path
);
492 OUString path
= linkName
.copy(0, linkName
.lastIndexOf('/'));
493 deletePathIfPossible(xRootKey
, path
);
498 // static prepareUserKeys
500 void prepareUserKeys(const Reference
< XSimpleRegistry
>& xDest
,
501 const Reference
< XRegistryKey
>& xUnoKey
,
502 const Reference
< XRegistryKey
>& xKey
,
503 const OUString
& implName
,
506 bool hasSubKeys
= false;
508 Sequence
<OUString
> keyNames
= xKey
->getKeyNames();
511 if (keyNames
.hasElements())
512 relativKey
= keyNames
.getConstArray()[0].copy(xKey
->getKeyName().getLength()+1);
514 if (keyNames
.getLength() == 1 &&
515 xKey
->getKeyType(relativKey
) == RegistryKeyType_LINK
)
519 OUString linkTarget
= xKey
->getLinkTarget(relativKey
);
521 OUString::Concat(xKey
->getKeyName().subView(xUnoKey
->getKeyName().getLength()))
526 prepareUserLink(xDest
, linkName
, linkTarget
, implName
);
529 deleteUserLink(xDest
->getRootKey(), linkName
, linkTarget
, implName
);
533 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xKey
->openKeys();
535 if (subKeys
.hasElements())
539 for (const Reference
< XRegistryKey
> & rSubKey
: subKeys
)
541 prepareUserKeys(xDest
, xUnoKey
, rSubKey
, implName
, bRegister
);
549 OUString
keyName(xKey
->getKeyName().copy(xUnoKey
->getKeyName().getLength()));
551 Reference
< XRegistryKey
> xRootKey
= xDest
->getRootKey();
554 createUniqueSubEntry(xRootKey
->createKey(keyName
), implName
);
558 Reference
< XRegistryKey
> rKey
= xRootKey
->openKey(keyName
);
561 deleteSubEntry(rKey
, implName
);
562 xRootKey
->deleteKey(keyName
);
565 OUString path
= keyName
.copy(0, keyName
.lastIndexOf('/'));
566 if( !path
.isEmpty() )
568 deletePathIfPossible(xRootKey
, path
);
574 // static deleteAllImplementations
576 void deleteAllImplementations( const Reference
< XSimpleRegistry
>& xReg
,
577 const Reference
< XRegistryKey
>& xSource
,
578 std::u16string_view locationUrl
,
579 std::vector
<OUString
> & implNames
)
580 // throw (InvalidRegistryException, RuntimeException)
582 Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
584 if (subKeys
.hasElements())
586 bool hasLocationUrl
= false;
588 for (const Reference
< XRegistryKey
> & xImplKey
: std::as_const(subKeys
))
590 Reference
< XRegistryKey
> xKey
= xImplKey
->openKey(
591 slash_UNO_slash_LOCATION
);
593 if (xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCII
))
595 if (xKey
->getAsciiValue() == locationUrl
)
597 hasLocationUrl
= true;
599 OUString
implName(xImplKey
->getKeyName().copy(1));
600 sal_Int32 firstDot
= implName
.indexOf('/');
603 implName
= implName
.copy(firstDot
+ 1);
605 implNames
.push_back(implName
);
607 deleteAllLinkReferences(xReg
, xImplKey
);
609 xKey
= xImplKey
->openKey( slash_UNO
);
612 const Sequence
< Reference
< XRegistryKey
> > subKeys2
= xKey
->openKeys();
614 for (const Reference
< XRegistryKey
> & rSubKey2
: subKeys2
)
616 if (rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_SERVICES
) &&
617 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_REGISTRY_LINKS
) &&
618 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_ACTIVATOR
) &&
619 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_SINGLETONS
) &&
620 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_LOCATION
) )
622 prepareUserKeys(xReg
, xKey
, rSubKey2
, implName
, false);
631 hasLocationUrl
= false;
632 OUString
path(xImplKey
->getKeyName());
633 xImplKey
->closeKey();
634 xReg
->getRootKey()->deleteKey(path
);
638 subKeys
= xSource
->openKeys();
639 if (!subKeys
.hasElements())
641 OUString
path(xSource
->getKeyName());
643 xReg
->getRootKey()->deleteKey(path
);
647 OUString
path(xSource
->getKeyName());
649 xReg
->getRootKey()->deleteKey(path
);
654 void delete_all_singleton_entries(
655 Reference
< registry::XRegistryKey
> const & xSingletons_section
,
656 ::std::vector
< OUString
> const & impl_names
)
657 // throw (InvalidRegistryException, RuntimeException)
659 Sequence
< Reference
< registry::XRegistryKey
> > singletons( xSingletons_section
->openKeys() );
660 Reference
< registry::XRegistryKey
> const * subkeys
= singletons
.getConstArray();
661 for ( sal_Int32 nPos
= singletons
.getLength(); nPos
--; )
663 Reference
< registry::XRegistryKey
> const & xSingleton
= subkeys
[ nPos
];
664 Reference
< registry::XRegistryKey
> xRegisteredImplNames(
665 xSingleton
->openKey( "REGISTERED_BY" ) );
666 if (xRegisteredImplNames
.is() && xRegisteredImplNames
->isValid())
668 Sequence
< OUString
> registered_implnames
;
671 registered_implnames
= xRegisteredImplNames
->getAsciiListValue();
673 catch (registry::InvalidValueException
&)
676 auto aNonConstRange
= asNonConstRange(registered_implnames
);
677 sal_Int32 nOrigRegLength
= registered_implnames
.getLength();
678 sal_Int32 nNewLength
= nOrigRegLength
;
679 for ( sal_Int32 n
= nOrigRegLength
; n
--; )
681 OUString
const & registered_implname
= registered_implnames
[ n
];
683 for (auto const& impl_name
: impl_names
)
685 if (impl_name
== registered_implname
)
687 aNonConstRange
[ n
] = registered_implnames
[ nNewLength
-1 ];
693 if (nNewLength
!= nOrigRegLength
)
697 // remove whole entry
698 xRegisteredImplNames
->closeKey();
699 xSingleton
->deleteKey( "REGISTERED_BY" );
700 // registry key cannot provide its relative name, only absolute :(
701 OUString
abs( xSingleton
->getKeyName() );
702 xSingletons_section
->deleteKey( abs
.copy( abs
.lastIndexOf( '/' ) +1 ) );
706 registered_implnames
.realloc( nNewLength
);
707 xRegisteredImplNames
->setAsciiListValue( registered_implnames
);
715 // static deleteAllServiceEntries
717 void deleteAllServiceEntries( const Reference
< XSimpleRegistry
>& xReg
,
718 const Reference
< XRegistryKey
>& xSource
,
719 const OUString
& implName
)
720 // throw ( InvalidRegistryException, RuntimeException )
722 Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
724 if (subKeys
.hasElements())
726 bool hasNoImplementations
= false;
728 for (const Reference
< XRegistryKey
> & xServiceKey
: std::as_const(subKeys
))
730 if (xServiceKey
->getValueType() == RegistryValueType_ASCIILIST
)
732 const Sequence
<OUString
> implEntries
= xServiceKey
->getAsciiListValue();
733 sal_Int32 length
= implEntries
.getLength();
734 sal_Int32 equals
= static_cast<sal_Int32
>(std::count(implEntries
.begin(), implEntries
.end(), implName
));
736 if (equals
== length
)
738 hasNoImplementations
= true;
743 Sequence
<OUString
> implEntriesNew(length
-equals
);
745 std::copy_if(implEntries
.begin(), implEntries
.end(), implEntriesNew
.getArray(),
746 [&implName
](const OUString
& rEntry
) { return rEntry
!= implName
; });
748 xServiceKey
->setAsciiListValue(implEntriesNew
);
753 if (hasNoImplementations
)
755 hasNoImplementations
= false;
756 OUString
path(xServiceKey
->getKeyName());
757 xServiceKey
->closeKey();
758 xReg
->getRootKey()->deleteKey(path
);
762 subKeys
= xSource
->openKeys();
763 if (!subKeys
.hasElements())
765 OUString
path(xSource
->getKeyName());
767 xReg
->getRootKey()->deleteKey(path
);
771 OUString
path(xSource
->getKeyName());
773 xReg
->getRootKey()->deleteKey(path
);
778 bool is_supported_service(
779 OUString
const & service_name
,
780 Reference
< reflection::XServiceTypeDescription
> const & xService_td
)
782 if (xService_td
->getName() == service_name
)
784 const Sequence
< Reference
< reflection::XServiceTypeDescription
> > seq(
785 xService_td
->getMandatoryServices() );
786 return std::any_of(seq
.begin(), seq
.end(), [&service_name
](const auto& rService
) {
787 return is_supported_service( service_name
, rService
); });
791 void insert_singletons(
792 Reference
< registry::XSimpleRegistry
> const & xDest
,
793 Reference
< registry::XRegistryKey
> const & xImplKey
,
794 Reference
< XComponentContext
> const & xContext
)
795 // throw( registry::InvalidRegistryException, registry::CannotRegisterImplementationException, RuntimeException )
798 Reference
< registry::XRegistryKey
> xKey( xImplKey
->openKey( "UNO/SINGLETONS" ) );
799 if (!(xKey
.is() && xKey
->isValid()))
802 OUString
implname( xImplKey
->getKeyName().copy( sizeof ("/IMPLEMENTATIONS/") -1 ) );
804 Sequence
< Reference
< registry::XRegistryKey
> > xSingletons_section( xKey
->openKeys() );
805 Reference
< registry::XRegistryKey
> const * p
= xSingletons_section
.getConstArray();
806 for ( sal_Int32 nPos
= xSingletons_section
.getLength(); nPos
--; )
808 Reference
< registry::XRegistryKey
> const & xSingleton
= p
[ nPos
];
809 OUString
singleton_name(
810 xSingleton
->getKeyName().copy(
811 implname
.getLength() + sizeof ("/IMPLEMENTATIONS//UNO/SINGLETONS/") -1 ) );
812 OUString
service_name( xSingleton
->getStringValue() );
814 OUString
keyname( "/SINGLETONS/" + singleton_name
);
815 Reference
< registry::XRegistryKey
> xKey2( xDest
->getRootKey()->openKey( keyname
) );
816 if (xKey2
.is() && xKey2
->isValid())
820 OUString
existing_name( xKey2
->getStringValue() );
821 if ( existing_name
!= service_name
)
823 Reference
< container::XHierarchicalNameAccess
> xTDMgr
;
825 "/singletons/com.sun.star.reflection.theTypeDescriptionManager";
826 xContext
->getValueByName( the_tdmgr
) >>= xTDMgr
;
829 throw RuntimeException( "cannot get singleton " + the_tdmgr
);
833 Reference
< reflection::XServiceTypeDescription
> xExistingService_td
;
834 xTDMgr
->getByHierarchicalName( existing_name
) >>= xExistingService_td
;
835 if (! xExistingService_td
.is())
837 throw RuntimeException( "cannot get service type description: " + existing_name
);
840 // everything's fine if existing service entry supports the one
842 if (! is_supported_service( service_name
, xExistingService_td
))
844 throw registry::CannotRegisterImplementationException(
845 "existing singleton service (" + singleton_name
+ "=" + existing_name
+ ") "
846 " does not support given one: " + service_name
);
849 catch (const container::NoSuchElementException
& exc
)
851 css::uno::Any anyEx
= cppu::getCaughtException();
852 throw css::lang::WrappedTargetRuntimeException(
853 "cannot get service type description: " + exc
.Message
,
858 catch (registry::InvalidValueException
&)
861 xKey2
->setStringValue( service_name
);
866 // insert singleton entry
867 xKey2
= xDest
->getRootKey()->createKey( keyname
);
868 xKey2
->setStringValue( service_name
);
871 Reference
< registry::XRegistryKey
> xRegisteredImplNames(
872 xKey2
->openKey( "REGISTERED_BY" ) );
873 if (!xRegisteredImplNames
.is() || !xRegisteredImplNames
->isValid())
876 xRegisteredImplNames
= xKey2
->createKey( "REGISTERED_BY" );
879 Sequence
< OUString
> implnames
;
882 implnames
= xRegisteredImplNames
->getAsciiListValue();
884 catch (registry::InvalidValueException
&)
887 // check implname is already in
888 if (comphelper::findValue(implnames
, implname
) == -1)
890 // append and write back
891 implnames
.realloc( implnames
.getLength() +1 );
892 implnames
.getArray()[ implnames
.getLength() -1 ] = implname
;
893 xRegisteredImplNames
->setAsciiListValue( implnames
);
899 // static prepareRegistry
901 void prepareRegistry(
902 const Reference
< XSimpleRegistry
>& xDest
,
903 const Reference
< XRegistryKey
>& xSource
,
904 const OUString
& implementationLoaderUrl
,
905 const OUString
& locationUrl
,
906 Reference
< XComponentContext
> const & xContext
)
907 // throw ( InvalidRegistryException, CannotRegisterImplementationException, RuntimeException )
909 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
911 if (!subKeys
.hasElements())
913 throw InvalidRegistryException(
914 "prepareRegistry(): source registry is empty" );
917 for (const Reference
< XRegistryKey
>& xImplKey
: subKeys
)
919 Reference
< XRegistryKey
> xKey
= xImplKey
->openKey(
920 slash_UNO_slash_SERVICES
);
924 // update entries in SERVICES section
925 const Sequence
< Reference
< XRegistryKey
> > serviceKeys
= xKey
->openKeys();
927 OUString implName
= xImplKey
->getKeyName().copy(1);
928 sal_Int32 firstDot
= implName
.indexOf('/');
931 implName
= implName
.copy(firstDot
+ 1);
933 sal_Int32 offset
= xKey
->getKeyName().getLength() + 1;
935 for (const Reference
< XRegistryKey
>& rServiceKey
: serviceKeys
)
937 OUString serviceName
= rServiceKey
->getKeyName().copy(offset
);
939 createUniqueSubEntry(
940 xDest
->getRootKey()->createKey(
941 slash_SERVICES
+ serviceName
),
945 xKey
= xImplKey
->openKey( slash_UNO
);
948 const Sequence
< Reference
< XRegistryKey
> > subKeys2
= xKey
->openKeys();
950 for (const Reference
< XRegistryKey
>& rSubKey2
: subKeys2
)
952 if (rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_SERVICES
) &&
953 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_REGISTRY_LINKS
) &&
954 rSubKey2
->getKeyName() != Concat2View(xImplKey
->getKeyName() + slash_UNO_slash_SINGLETONS
))
956 prepareUserKeys(xDest
, xKey
, rSubKey2
, implName
, true);
962 // update LOCATION entry
963 xKey
= xImplKey
->createKey( slash_UNO_slash_LOCATION
);
967 xKey
->setAsciiValue(locationUrl
);
970 // update ACTIVATOR entry
971 xKey
= xImplKey
->createKey( slash_UNO_slash_ACTIVATOR
);
975 xKey
->setAsciiValue(implementationLoaderUrl
);
978 xKey
= xImplKey
->openKey( slash_UNO_slash_SERVICES
);
980 if (xKey
.is() && (xKey
->getValueType() == RegistryValueType_ASCIILIST
))
982 // update link entries in REGISTRY_LINKS section
983 const Sequence
<OUString
> linkNames
= xKey
->getAsciiListValue();
985 for (const OUString
& rLinkName
: linkNames
)
987 prepareLink(xDest
, xImplKey
, rLinkName
);
991 insert_singletons( xDest
, xImplKey
, xContext
);
996 void findImplementations( const Reference
< XRegistryKey
> & xSource
,
997 std::vector
<OUString
>& implNames
)
999 bool isImplKey
= false;
1003 Reference
< XRegistryKey
> xKey
= xSource
->openKey(
1004 slash_UNO_slash_SERVICES
);
1006 if (xKey
.is() && xKey
->getKeyNames().hasElements())
1010 OUString implName
= xSource
->getKeyName().copy(1).replace('/', '.');
1011 sal_Int32 firstDot
= implName
.indexOf('.');
1014 implName
= implName
.copy(firstDot
+ 1);
1016 implNames
.push_back(implName
);
1019 catch(InvalidRegistryException
&)
1023 if (isImplKey
) return;
1027 const Sequence
< Reference
< XRegistryKey
> > subKeys
= xSource
->openKeys();
1029 for (const Reference
< XRegistryKey
>& rSubKey
: subKeys
)
1031 findImplementations(rSubKey
, implNames
);
1034 catch(InvalidRegistryException
&)
1040 class ImplementationRegistration
1041 : public WeakImplHelper
< XImplementationRegistration2
, XServiceInfo
, XInitialization
>
1044 explicit ImplementationRegistration( const Reference
< XComponentContext
> & rSMgr
);
1047 OUString SAL_CALL
getImplementationName() override
;
1048 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
1049 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
1051 // XImplementationRegistration
1052 virtual void SAL_CALL
registerImplementation(
1053 const OUString
& implementationLoader
,
1054 const OUString
& location
,
1055 const Reference
< XSimpleRegistry
> & xReg
) override
;
1057 virtual sal_Bool SAL_CALL
revokeImplementation(
1058 const OUString
& location
,
1059 const Reference
< XSimpleRegistry
>& xReg
) override
;
1061 virtual Sequence
< OUString
> SAL_CALL
getImplementations(
1062 const OUString
& implementationLoader
,
1063 const OUString
& location
) override
;
1064 virtual Sequence
< OUString
> SAL_CALL
checkInstantiation(
1065 const OUString
& implementationName
) override
;
1067 // XImplementationRegistration2
1068 virtual void SAL_CALL
registerImplementationWithLocation(
1069 const OUString
& implementationLoader
,
1070 const OUString
& location
,
1071 const OUString
& registeredLocation
,
1072 const Reference
< XSimpleRegistry
> & xReg
) override
;
1075 virtual void SAL_CALL
initialize(
1076 const css::uno::Sequence
< css::uno::Any
>& aArguments
) override
;
1078 private: // helper methods
1079 void prepareRegister(
1080 const OUString
& implementationLoader
,
1081 const OUString
& location
,
1082 const OUString
& registeredLocation
,
1083 const Reference
< XSimpleRegistry
> & xReg
);
1084 // throw( CannotRegisterImplementationException, RuntimeException )
1086 static void doRegister( const Reference
< XMultiComponentFactory
>& xSMgr
,
1087 const Reference
< XComponentContext
> &xCtx
,
1088 const Reference
< XImplementationLoader
>& xAct
,
1089 const Reference
< XSimpleRegistry
>& xDest
,
1090 const OUString
& implementationLoaderUrl
,
1091 const OUString
& locationUrl
,
1092 const OUString
& registeredLocationUrl
);
1093 /* throw ( InvalidRegistryException,
1094 MergeConflictException,
1095 CannotRegisterImplementationException, RuntimeException ) */
1097 static void doRevoke( const Reference
< XSimpleRegistry
>& xDest
,
1098 std::u16string_view locationUrl
);
1099 // throw( InvalidRegistryException, RuntimeException )
1100 Reference
< XSimpleRegistry
> getRegistryFromServiceManager() const;
1102 static Reference
< XSimpleRegistry
> createTemporarySimpleRegistry(
1103 const Reference
< XMultiComponentFactory
> &rSMgr
,
1104 const Reference
< XComponentContext
> & rCtx
);
1107 Reference
< XMultiComponentFactory
> m_xSMgr
;
1108 Reference
< XComponentContext
> m_xCtx
;
1112 // ImplementationRegistration()
1114 ImplementationRegistration::ImplementationRegistration( const Reference
< XComponentContext
> & xCtx
)
1115 : m_xSMgr( xCtx
->getServiceManager() )
1120 OUString
ImplementationRegistration::getImplementationName()
1122 return "com.sun.star.comp.stoc.ImplementationRegistration";
1126 sal_Bool
ImplementationRegistration::supportsService(const OUString
& ServiceName
)
1128 return cppu::supportsService(this, ServiceName
);
1132 Sequence
< OUString
> ImplementationRegistration::getSupportedServiceNames()
1134 return { "com.sun.star.registry.ImplementationRegistration" };
1137 Reference
< XSimpleRegistry
> ImplementationRegistration::getRegistryFromServiceManager() const
1139 Reference
< XPropertySet
> xPropSet( m_xSMgr
, UNO_QUERY
);
1140 Reference
< XSimpleRegistry
> xRegistry
;
1142 if( xPropSet
.is() ) {
1144 try { // the implementation does not support XIntrospectionAccess !
1146 Any aAny
= xPropSet
->getPropertyValue( Registry
);
1148 if( aAny
.getValueType().getTypeClass() == TypeClass_INTERFACE
) {
1152 catch( UnknownPropertyException
& ) {
1153 // empty reference is error signal !
1163 void ImplementationRegistration::initialize(
1164 const css::uno::Sequence
< css::uno::Any
>& aArgs
)
1167 if( aArgs
.getLength() != 4 ) {
1168 throw IllegalArgumentException(
1169 "ImplementationRegistration::initialize() expects 4 parameters, got " + OUString::number( aArgs
.getLength() ),
1170 Reference
<XInterface
> (), 0 );
1173 Reference
< XImplementationLoader
> rLoader
;
1174 OUString loaderServiceName
;
1175 OUString locationUrl
;
1176 Reference
< XSimpleRegistry
> rReg
;
1178 // 1st argument : An instance of an implementation loader
1179 if( aArgs
.getConstArray()[0].getValueType().getTypeClass() == TypeClass_INTERFACE
) {
1180 aArgs
.getConstArray()[0] >>= rLoader
;
1182 if( !rLoader
.is()) {
1183 throw IllegalArgumentException(
1184 "ImplementationRegistration::initialize() invalid first parameter,"
1185 "expected " + cppu::UnoType
<decltype(rLoader
)>::get().getTypeName() +
1186 ", got " + aArgs
.getConstArray()[0].getValueTypeName(),
1187 Reference
< XInterface
> (), 0 );
1190 // 2nd argument : The service name of the loader. This name is written into the registry
1191 if( aArgs
.getConstArray()[1].getValueType().getTypeClass() == TypeClass_STRING
) {
1192 aArgs
.getConstArray()[1] >>= loaderServiceName
;
1194 if( loaderServiceName
.isEmpty() ) {
1195 throw IllegalArgumentException(
1196 "ImplementationRegistration::initialize() invalid second parameter,"
1197 "expected string, got " + aArgs
.getConstArray()[1].getValueTypeName(),
1198 Reference
< XInterface
> (), 0 );
1201 // 3rd argument : The file name of the dll, that contains the loader
1202 if( aArgs
.getConstArray()[2].getValueType().getTypeClass() == TypeClass_STRING
) {
1203 aArgs
.getConstArray()[2] >>= locationUrl
;
1205 if( locationUrl
.isEmpty() ) {
1206 throw IllegalArgumentException(
1207 "ImplementationRegistration::initialize() invalid third parameter,"
1208 "expected string, got " + aArgs
.getConstArray()[2].getValueTypeName(),
1209 Reference
< XInterface
> (), 0 );
1212 // 4th argument : The registry, the service should be written to
1213 if( aArgs
.getConstArray()[3].getValueType().getTypeClass() == TypeClass_INTERFACE
) {
1214 aArgs
.getConstArray()[3] >>= rReg
;
1218 rReg
= getRegistryFromServiceManager();
1220 throw IllegalArgumentException(
1221 "ImplementationRegistration::initialize() invalid fourth parameter,"
1222 "expected " + cppu::UnoType
<decltype(rReg
)>::get().getTypeName() +
1223 ", got " + aArgs
.getConstArray()[3].getValueTypeName(),
1224 Reference
< XInterface
> (), 0 );
1228 doRegister(m_xSMgr
, m_xCtx
, rLoader
, rReg
, loaderServiceName
, locationUrl
, locationUrl
);
1232 // virtual function registerImplementationWithLocation of XImplementationRegistration2
1234 void ImplementationRegistration::registerImplementationWithLocation(
1235 const OUString
& implementationLoaderUrl
,
1236 const OUString
& locationUrl
,
1237 const OUString
& registeredLocationUrl
,
1238 const Reference
< XSimpleRegistry
> & xReg
)
1241 implementationLoaderUrl
, locationUrl
, registeredLocationUrl
, xReg
);
1245 void ImplementationRegistration::prepareRegister(
1246 const OUString
& implementationLoaderUrl
,
1247 const OUString
& locationUrl
,
1248 const OUString
& registeredLocationUrl
,
1249 const Reference
< XSimpleRegistry
> & xReg
)
1250 // throw( CannotRegisterImplementationException, RuntimeException )
1252 OUString activatorName
;
1254 if (!implementationLoaderUrl
.isEmpty())
1256 activatorName
= implementationLoaderUrl
.getToken(0, ':');
1259 // check locationUrl to find out what kind of loader is needed
1260 // set implLoaderUrl
1263 if( !m_xSMgr
.is() ) {
1264 throw CannotRegisterImplementationException(
1265 "ImplementationRegistration::registerImplementation() "
1266 "no componentcontext available to instantiate loader" );
1271 Reference
< XImplementationLoader
> xAct(
1272 m_xSMgr
->createInstanceWithContext(activatorName
, m_xCtx
) , UNO_QUERY
);
1275 throw CannotRegisterImplementationException(
1276 "ImplementationRegistration::registerImplementation() - The service "
1277 + activatorName
+ " cannot be instantiated" );
1280 Reference
< XSimpleRegistry
> xRegistry
;
1284 // registry supplied by user
1289 xRegistry
= getRegistryFromServiceManager();
1292 if ( xRegistry
.is())
1294 doRegister(m_xSMgr
, m_xCtx
, xAct
, xRegistry
, implementationLoaderUrl
,
1295 locationUrl
, registeredLocationUrl
);
1299 catch( CannotRegisterImplementationException
& )
1303 catch( const InvalidRegistryException
& e
)
1305 throw CannotRegisterImplementationException(
1306 "ImplementationRegistration::registerImplementation() "
1307 "InvalidRegistryException during registration (" + e
.Message
+ ")" );
1309 catch( const MergeConflictException
& e
)
1311 throw CannotRegisterImplementationException(
1312 "ImplementationRegistration::registerImplementation() "
1313 "MergeConflictException during registration (" + e
.Message
+ ")" );
1319 // virtual function registerImplementation of XImplementationRegistration
1321 void ImplementationRegistration::registerImplementation(
1322 const OUString
& implementationLoaderUrl
,
1323 const OUString
& locationUrl
,
1324 const Reference
< XSimpleRegistry
> & xReg
)
1326 prepareRegister(implementationLoaderUrl
, locationUrl
, locationUrl
, xReg
);
1330 // virtual function revokeImplementation of XImplementationRegistration
1332 sal_Bool
ImplementationRegistration::revokeImplementation(const OUString
& location
,
1333 const Reference
< XSimpleRegistry
>& xReg
)
1337 Reference
< XSimpleRegistry
> xRegistry
;
1343 Reference
< XPropertySet
> xPropSet( m_xSMgr
, UNO_QUERY
);
1344 if( xPropSet
.is() ) {
1346 Any aAny
= xPropSet
->getPropertyValue( Registry
);
1348 if( aAny
.getValueType().getTypeClass() == TypeClass_INTERFACE
)
1353 catch ( UnknownPropertyException
& ) {
1362 doRevoke(xRegistry
, location
);
1365 catch( InvalidRegistryException
& )
1367 // no way to transport the error, as no exception is specified and a runtime
1368 // exception is not appropriate.
1369 OSL_FAIL( "InvalidRegistryException during revokeImplementation" );
1377 // virtual function getImplementations of XImplementationRegistration
1379 Sequence
< OUString
> ImplementationRegistration::getImplementations(
1380 const OUString
& implementationLoaderUrl
,
1381 const OUString
& locationUrl
)
1383 OUString activatorName
;
1385 if (!implementationLoaderUrl
.isEmpty())
1387 activatorName
= implementationLoaderUrl
.getToken(0, ':');
1390 // check locationUrl to find out what kind of loader is needed
1391 // set implementationLoaderUrl
1394 if( m_xSMgr
.is() ) {
1396 Reference
< XImplementationLoader
> xAct(
1397 m_xSMgr
->createInstanceWithContext( activatorName
, m_xCtx
), UNO_QUERY
);
1402 Reference
< XSimpleRegistry
> xReg
=
1403 createTemporarySimpleRegistry( m_xSMgr
, m_xCtx
);
1409 xReg
->open(OUString() /* in mem */, false, true);
1410 Reference
< XRegistryKey
> xImpl
;
1412 { // only necessary for deleting the temporary variable of rootkey
1413 xImpl
= xReg
->getRootKey()->createKey( slash_IMPLEMENTATIONS
);
1415 if (xAct
->writeRegistryInfo(xImpl
, implementationLoaderUrl
, locationUrl
))
1417 std::vector
<OUString
> implNames
;
1419 findImplementations(xImpl
, implNames
);
1421 if (!implNames
.empty())
1423 Sequence
<OUString
> seqImpl(comphelper::containerToSequence(implNames
));
1431 catch(MergeConflictException
&)
1434 catch(InvalidRegistryException
&)
1441 return Sequence
<OUString
>();
1445 // virtual function checkInstantiation of XImplementationRegistration
1447 Sequence
< OUString
> ImplementationRegistration::checkInstantiation(const OUString
&)
1449 OSL_FAIL( "ImplementationRegistration::checkInstantiation not implemented" );
1450 return Sequence
<OUString
>();
1454 // helper function doRegistration
1457 void ImplementationRegistration::doRevoke(
1458 const Reference
< XSimpleRegistry
>& xDest
,
1459 std::u16string_view locationUrl
)
1460 // throw ( InvalidRegistryException, RuntimeException )
1465 std::vector
<OUString
> aNames
;
1467 Reference
< XRegistryKey
> xRootKey( xDest
->getRootKey() );
1469 Reference
< XRegistryKey
> xKey
=
1470 xRootKey
->openKey( slash_IMPLEMENTATIONS
);
1471 if (xKey
.is() && xKey
->isValid())
1473 deleteAllImplementations(xDest
, xKey
, locationUrl
, aNames
);
1476 xKey
= xRootKey
->openKey( slash_SERVICES
);
1479 for (auto const& name
: aNames
)
1481 deleteAllServiceEntries(xDest
, xKey
, name
);
1485 xKey
= xRootKey
->openKey( "/SINGLETONS" );
1486 if (xKey
.is() && xKey
->isValid())
1488 delete_all_singleton_entries( xKey
, aNames
);
1492 xRootKey
->closeKey();
1493 if (xKey
.is() && xKey
->isValid() )
1497 void ImplementationRegistration::doRegister(
1498 const Reference
< XMultiComponentFactory
> & xSMgr
,
1499 const Reference
< XComponentContext
> &xCtx
,
1500 const Reference
< XImplementationLoader
> & xAct
,
1501 const Reference
< XSimpleRegistry
>& xDest
,
1502 const OUString
& implementationLoaderUrl
,
1503 const OUString
& locationUrl
,
1504 const OUString
& registeredLocationUrl
)
1505 /* throw ( InvalidRegistryException,
1506 MergeConflictException,
1507 CannotRegisterImplementationException, RuntimeException ) */
1509 Reference
< XSimpleRegistry
> xReg
=
1510 createTemporarySimpleRegistry( xSMgr
, xCtx
);
1511 Reference
< XRegistryKey
> xSourceKey
;
1513 if (!(xAct
.is() && xReg
.is() && xDest
.is()))
1518 xReg
->open(OUString() /* in mem */, false, true);
1520 { // only necessary for deleting the temporary variable of rootkey
1521 xSourceKey
= xReg
->getRootKey()->createKey( slash_IMPLEMENTATIONS
);
1525 xAct
->writeRegistryInfo(xSourceKey
, implementationLoaderUrl
, locationUrl
);
1528 throw CannotRegisterImplementationException(
1529 "ImplementationRegistration::doRegistration() component registration signaled failure" );
1532 prepareRegistry(xDest
, xSourceKey
, implementationLoaderUrl
, registeredLocationUrl
, xCtx
);
1534 xSourceKey
->closeKey();
1536 xSourceKey
= xReg
->getRootKey();
1537 Reference
< XRegistryKey
> xDestKey
= xDest
->getRootKey();
1538 stoc_impreg::mergeKeys( xDestKey
, xSourceKey
);
1539 xDestKey
->closeKey();
1540 xSourceKey
->closeKey();
1543 // Cleanup Source registry.
1544 if ( xSourceKey
->isValid() )
1545 xSourceKey
->closeKey();
1547 catch(CannotRegisterImplementationException
&)
1549 if ( xSourceKey
->isValid() )
1550 xSourceKey
->closeKey();
1557 Reference
< XSimpleRegistry
> ImplementationRegistration::createTemporarySimpleRegistry(
1558 const Reference
< XMultiComponentFactory
> &rSMgr
,
1559 const Reference
< XComponentContext
> & xCtx
)
1562 Reference
< XSimpleRegistry
> xReg(
1563 rSMgr
->createInstanceWithContext(
1564 com_sun_star_registry_SimpleRegistry
, xCtx
),
1566 OSL_ASSERT( xReg
.is() );
1572 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1573 com_sun_star_comp_stoc_ImplementationRegistration_get_implementation(
1574 css::uno::XComponentContext
*context
,
1575 css::uno::Sequence
<css::uno::Any
> const &)
1577 return cppu::acquire(new ImplementationRegistration(context
));
1580 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */