diff options
Diffstat (limited to 'stoc/source/implementationregistration/implreg.cxx')
-rw-r--r-- | stoc/source/implementationregistration/implreg.cxx | 1930 |
1 files changed, 1930 insertions, 0 deletions
diff --git a/stoc/source/implementationregistration/implreg.cxx b/stoc/source/implementationregistration/implreg.cxx new file mode 100644 index 000000000000..df63bfbfaee1 --- /dev/null +++ b/stoc/source/implementationregistration/implreg.cxx @@ -0,0 +1,1930 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <stdlib.h> +#include <string.h> +#include <list> + +#include <unistd.h> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/servicefactory.hxx> +#ifndef _CPPUHELPER_IMPLBASE3_HXX +#include <cppuhelper/implbase3.hxx> +#endif +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ +#include <cppuhelper/implementationentry.hxx> +#endif + +#include <uno/mapping.hxx> +#include <osl/thread.h> + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <osl/process.h> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/loader/XImplementationLoader.hpp> +#include <com/sun/star/registry/XImplementationRegistration2.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/reflection/XServiceTypeDescription.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" + +#include "mergekeys.hxx" + +#if defined(SAL_W32) || defined(SAL_OS2) +#include <io.h> +#endif + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::loader; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; +using namespace cppu; +using namespace rtl; +using namespace osl; + + +#define IMPLNAME "com.sun.star.comp.stoc.ImplementationRegistration" +#define SERVICENAME "com.sun.star.registry.ImplementationRegistration" +namespace stoc_impreg +{ +struct StringPool +{ + OUString sImplementationName; + OUString sServiceName; + OUString TMP; + OUString TEMP; + OUString slash_UNO_slash_REGISTRY_LINKS; + OUString slash_IMPLEMENTATIONS; + OUString slash_UNO; + OUString slash_UNO_slash_SERVICES; + OUString slash_UNO_slash_SINGLETONS; + OUString slash_SERVICES; + OUString slash_UNO_slash_LOCATION; + OUString slash_UNO_slash_ACTIVATOR; + OUString colon_old; + OUString com_sun_star_registry_SimpleRegistry; + OUString Registry; + StringPool() + : sImplementationName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ) + , sServiceName( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME ) ) + , TMP( RTL_CONSTASCII_USTRINGPARAM( "TMP" ) ) + , TEMP( RTL_CONSTASCII_USTRINGPARAM( "TEMP" ) ) + , slash_UNO_slash_REGISTRY_LINKS( RTL_CONSTASCII_USTRINGPARAM("/UNO/REGISTRY_LINKS")) + , slash_IMPLEMENTATIONS( RTL_CONSTASCII_USTRINGPARAM( "/IMPLEMENTATIONS" ) ) + , slash_UNO( RTL_CONSTASCII_USTRINGPARAM("/UNO")) + , slash_UNO_slash_SERVICES( RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")) + , slash_UNO_slash_SINGLETONS( RTL_CONSTASCII_USTRINGPARAM("/UNO/SINGLETONS")) + , slash_SERVICES( RTL_CONSTASCII_USTRINGPARAM("/SERVICES/") ) + , slash_UNO_slash_LOCATION( RTL_CONSTASCII_USTRINGPARAM("/UNO/LOCATION") ) + , slash_UNO_slash_ACTIVATOR( RTL_CONSTASCII_USTRINGPARAM("/UNO/ACTIVATOR") ) + , colon_old( RTL_CONSTASCII_USTRINGPARAM(":old")) + , com_sun_star_registry_SimpleRegistry(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.SimpleRegistry") ) + , Registry( RTL_CONSTASCII_USTRINGPARAM("Registry") ) + {} +private: + StringPool( const StringPool & ); +}; + +const StringPool &spool() +{ + static StringPool *pPool = 0; + if( ! pPool ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pPool ) + { + static StringPool pool; + pPool = &pool; + } + } + return *pPool; +} +} + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_bootstrap +{ +Sequence< OUString > impreg_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = stoc_impreg::spool().sServiceName; + pNames = &seqNames; + } + } + return *pNames; +} + +OUString impreg_getImplementationName() +{ + return stoc_impreg::spool().sImplementationName; +} +} + +namespace stoc_impreg +{ +//************************************************************************* +// static deleteAllLinkReferences() +// +static void deleteAllLinkReferences(const Reference < XSimpleRegistry >& xReg, + const Reference < XRegistryKey >& xSource) + // throw ( InvalidRegistryException, RuntimeException ) +{ + Reference < XRegistryKey > xKey = xSource->openKey( + spool().slash_UNO_slash_REGISTRY_LINKS ); + + if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCIILIST)) + { + Sequence<OUString> linkNames = xKey->getAsciiListValue(); + + if (linkNames.getLength()) + { + const OUString* pLinkNames = linkNames.getConstArray(); + + OUString aLinkName; + OUString aLinkParent; + Reference < XRegistryKey > xLinkParent; + const sal_Unicode* pTmpName = NULL; + const sal_Unicode* pShortName = NULL; + sal_Int32 sEnd = 0; + + for (sal_Int32 i = 0; i < linkNames.getLength(); i++) + { + aLinkName = pLinkNames[i]; + + pTmpName = aLinkName.getStr(); + + if (pTmpName[0] != L'/') + continue; + + sal_Int32 nIndex = rtl_ustr_indexOfChar( pTmpName, '%' ); + if ( nIndex == -1 ) + pShortName = 0; + else + pShortName = pTmpName+nIndex; + + while (pShortName && pShortName[1] == L'%') + { + nIndex = rtl_ustr_indexOfChar( pShortName+2, '%' ); + if ( nIndex == -1 ) + pShortName = 0; + else + pShortName += nIndex+2; + } + + if (pShortName) + { + aLinkName = aLinkName.copy(0, pShortName - pTmpName); + } + + xReg->getRootKey()->deleteLink(aLinkName); + + sEnd = rtl_ustr_lastIndexOfChar( aLinkName.getStr(), '/' ); + + aLinkParent = aLinkName.copy(0, sEnd); + + while(aLinkParent.getLength()) + { + xLinkParent = xReg->getRootKey()->openKey(aLinkParent); + + if (xLinkParent.is() && (xLinkParent->getKeyNames().getLength() == 0)) + { + aLinkName = aLinkParent; + + xReg->getRootKey()->deleteKey(aLinkParent); + + sEnd = rtl_ustr_lastIndexOfChar( aLinkName.getStr(), '/' ); + + aLinkParent = aLinkName.copy(0, sEnd); + } else + { + break; + } + } + } + } + } +} + +//************************************************************************* +// static prepareLink +// +static void prepareLink( const Reference < XSimpleRegistry > & xDest, + const Reference < XRegistryKey > & xSource, + const OUString& link) + // throw ( InvalidRegistryException, RuntimeException ) +{ + OUString linkRefName = xSource->getKeyName(); + OUString linkName(link); + sal_Bool isRelativ = sal_False; + + const sal_Unicode* pTmpName = link.getStr(); + const sal_Unicode* pShortName; + sal_Int32 nIndex = rtl_ustr_indexOfChar( pTmpName, '%' ); + if ( nIndex == -1 ) + pShortName = 0; + else + pShortName = pTmpName+nIndex; + + if (pTmpName[0] != L'/') + isRelativ = sal_True; + + while (pShortName && pShortName[1] == L'%') + { + nIndex = rtl_ustr_indexOfChar( pShortName+2, '%' ); + if ( nIndex == -1 ) + pShortName = 0; + else + pShortName += nIndex+2; + } + + if (pShortName) + { + linkRefName = linkRefName + link.copy(pShortName - pTmpName + 1); + linkName = link.copy(0, pShortName - pTmpName); + } + + if (isRelativ) + xSource->createLink(linkName, linkRefName); + else + xDest->getRootKey()->createLink(linkName, linkRefName); +} + +//************************************************************************* +// static searchImplForLink +// +static OUString searchImplForLink( + const Reference < XRegistryKey > & xRootKey, + const OUString& linkName, + const OUString& implName ) + // throw ( InvalidRegistryException, RuntimeException ) +{ + const StringPool & pool = spool(); + Reference < XRegistryKey > xKey = xRootKey->openKey( pool.slash_IMPLEMENTATIONS ); + if (xKey.is()) + { + Sequence< Reference < XRegistryKey > > subKeys( xKey->openKeys() ); + const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray(); + OUString key_name( pool.slash_UNO + linkName ); + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + try + { + Reference < XRegistryKey > xImplKey( pSubKeys[i] ); + if (xImplKey->getKeyType( key_name ) == RegistryKeyType_LINK) + { + OUString oldImplName = xImplKey->getKeyName().copy(strlen("/IMPLEMENTATIONS/")); + if (implName != oldImplName) + { + return oldImplName; + } + } + } + catch(InvalidRegistryException&) + { + } + } + } + + return OUString(); +} + +//************************************************************************* +// static searchLinkTargetForImpl +// +static OUString searchLinkTargetForImpl(const Reference < XRegistryKey >& xRootKey, + const OUString& linkName, + const OUString& implName) + // throw ( InvalidRegistryException, RuntimeException ) +{ + OUString ret; + +// try +// { + const StringPool & pool = spool(); + Reference < XRegistryKey > xKey = xRootKey->openKey( pool.slash_IMPLEMENTATIONS ); + + if (xKey.is()) + { + Sequence< Reference < XRegistryKey > > subKeys = xKey->openKeys(); + + const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray(); + Reference < XRegistryKey > xImplKey; + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + xImplKey = pSubKeys[i]; + + OUString tmpImplName = xImplKey->getKeyName().copy(strlen("/IMPLEMENTATIONS/")); + OUString qualifiedLinkName( pool.slash_UNO ); + qualifiedLinkName += linkName; + if (tmpImplName == implName && + xImplKey->getKeyType( qualifiedLinkName ) == RegistryKeyType_LINK) + { + return xImplKey->getLinkTarget( qualifiedLinkName ); + } + } + } +// } +// catch(InvalidRegistryException&) +// { +// } + + return ret; +} + +//************************************************************************* +// static createUniqueSubEntry +// +static void createUniqueSubEntry(const Reference < XRegistryKey > & xSuperKey, + const OUString& value) + // throw ( InvalidRegistryException, RuntimeException ) +{ + if (xSuperKey.is()) + { +// try +// { + if (xSuperKey->getValueType() == RegistryValueType_ASCIILIST) + { + sal_Int32 length = 0; + sal_Bool bReady = sal_False; + + Sequence<OUString> implEntries = xSuperKey->getAsciiListValue(); + length = implEntries.getLength(); + + for (sal_Int32 i = 0; !bReady && (i < length); i++) + { + bReady = (implEntries.getConstArray()[i] == value); + } + + if (bReady) + { + Sequence<OUString> implEntriesNew(length); + implEntriesNew.getArray()[0] = value; + + for (sal_Int32 i=0, j=1; i < length; i++) + { + if (implEntries.getConstArray()[i] != value) + implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i]; + } + xSuperKey->setAsciiListValue(implEntriesNew); + } else + { + Sequence<OUString> implEntriesNew(length+1); + implEntriesNew.getArray()[0] = value; + + for (sal_Int32 i = 0; i < length; i++) + { + implEntriesNew.getArray()[i+1] = implEntries.getConstArray()[i]; + } + xSuperKey->setAsciiListValue(implEntriesNew); + } + } else + { + Sequence<OUString> implEntriesNew(1); + + implEntriesNew.getArray()[0] = value; + + xSuperKey->setAsciiListValue(implEntriesNew); + } +// } +// catch(InvalidRegistryException&) +// { +// } + } +} + +//************************************************************************* +// static deleteSubEntry +// +static sal_Bool deleteSubEntry(const Reference < XRegistryKey >& xSuperKey, const OUString& value) + // throw ( InvalidRegistryException, RuntimeException ) +{ + if (xSuperKey->getValueType() == RegistryValueType_ASCIILIST) + { + Sequence<OUString> implEntries = xSuperKey->getAsciiListValue(); + sal_Int32 length = implEntries.getLength(); + sal_Int32 equals = 0; + sal_Bool hasNoImplementations = sal_False; + + for (sal_Int32 i = 0; i < length; i++) + { + if (implEntries.getConstArray()[i] == value) + equals++; + } + + if (equals == length) + { + hasNoImplementations = sal_True; + } else + { + Sequence<OUString> implEntriesNew(length - equals); + + sal_Int32 j = 0; + for (sal_Int32 i = 0; i < length; i++) + { + if (implEntries.getConstArray()[i] != value) + { + implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i]; + } + } + xSuperKey->setAsciiListValue(implEntriesNew); + } + + if (hasNoImplementations) + { + return sal_True; + } + } + return sal_False; +} + +//************************************************************************* +// static prepareUserLink +// +static void prepareUserLink(const Reference < XSimpleRegistry >& xDest, + const OUString& linkName, + const OUString& linkTarget, + const OUString& implName) + // throw ( InvalidRegistryException, RuntimeException ) +{ + sal_Bool ret = sal_False; + + Reference < XRegistryKey > xRootKey; + +// try +// { + xRootKey = xDest->getRootKey(); + + if (xRootKey->getKeyType(linkName) == RegistryKeyType_LINK) + { + OUString oldImplName(searchImplForLink(xRootKey, linkName, implName)); + + if (oldImplName.getLength()) + { + createUniqueSubEntry(xDest->getRootKey()->createKey( + linkName + spool().colon_old ), oldImplName); + } + } +// } +// catch (InvalidRegistryException&) +// { +// } + +// try +// { + if (xRootKey->isValid()) + { + ret = xRootKey->createLink(linkName, linkTarget); + } +// } +// catch(InvalidRegistryException&) +// { +// } + +// return ret; +} + +//************************************************************************* +// static deleteUserLink +// +static void deletePathIfPossible(const Reference < XRegistryKey >& xRootKey, + const OUString& path) +{ + try + { + Sequence<OUString> keyNames(xRootKey->openKey(path)->getKeyNames()); + + if (keyNames.getLength() == 0 && + xRootKey->openKey(path)->getValueType() == RegistryValueType_NOT_DEFINED) + { + xRootKey->deleteKey(path); + + OUString tmpPath(path); + OUString newPath = tmpPath.copy(0, tmpPath.lastIndexOf('/')); + + if (newPath.getLength() > 1) + deletePathIfPossible(xRootKey, newPath); + } + } + catch(InvalidRegistryException&) + { + } +} + + +//************************************************************************* +// static deleteUserLink +// +static void deleteUserLink(const Reference < XRegistryKey >& xRootKey, + const OUString& linkName, + const OUString& linkTarget, + const OUString& implName) + // throw ( InvalidRegistryException, RuntimeException ) +{ + sal_Bool bClean = sal_False; + + if (xRootKey->getKeyType(linkName) == RegistryKeyType_LINK) + { + OUString tmpTarget = xRootKey->getLinkTarget(linkName); + + if (tmpTarget == linkTarget) + { + xRootKey->deleteLink(linkName); + } + } + + Reference < XRegistryKey > xOldKey = xRootKey->openKey( + linkName + spool().colon_old ); + if (xOldKey.is()) + { + sal_Bool hasNoImplementations = sal_False; + + if (xOldKey->getValueType() == RegistryValueType_ASCIILIST) + { + Sequence<OUString> implEntries = xOldKey->getAsciiListValue(); + sal_Int32 length = implEntries.getLength(); + sal_Int32 equals = 0; + + for (sal_Int32 i = 0; i < length; i++) + { + if (implEntries.getConstArray()[i] == implName) + equals++; + } + + if (equals == length) + { + hasNoImplementations = sal_True; + } else + { + OUString oldImpl; + + if (length > equals + 1) + { + Sequence<OUString> implEntriesNew(length - equals - 1); + + sal_Int32 j = 0; + sal_Bool first = sal_True; + for (sal_Int32 i = 0; i < length; i++) + { + if (implEntries.getConstArray()[i] != implName) + { + if (first) + { + oldImpl = implEntries.getConstArray()[i]; + first = sal_False; + } else + { + implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i]; + } + } + } + + xOldKey->setAsciiListValue(implEntriesNew); + } else + { + oldImpl = implEntries.getConstArray()[0]; + + xOldKey->closeKey(); + xRootKey->deleteKey(xOldKey->getKeyName()); + } + + OUString oldTarget = searchLinkTargetForImpl(xRootKey, linkName, oldImpl); + if (oldTarget.getLength()) + { + xRootKey->createLink(linkName, oldTarget); + } + } + + if (hasNoImplementations) + { + bClean = sal_True; + hasNoImplementations = sal_False; + xOldKey->closeKey(); + xRootKey->deleteKey(xOldKey->getKeyName()); + } + } + } else + { + bClean = sal_True; + } + + if (bClean) + { + OUString tmpName(linkName); + OUString path = tmpName.copy(0, tmpName.lastIndexOf('/')); + deletePathIfPossible(xRootKey, path); + } +} + +//************************************************************************* +// static prepareUserKeys +// +static void prepareUserKeys(const Reference < XSimpleRegistry >& xDest, + const Reference < XRegistryKey >& xUnoKey, + const Reference < XRegistryKey >& xKey, + const OUString& implName, + sal_Bool bRegister) + // throw ( InvalidRegistryException, RuntimeException ) +{ + sal_Bool hasSubKeys = sal_False; + + Sequence<OUString> keyNames = xKey->getKeyNames(); + + OUString relativKey; + if (keyNames.getLength()) + relativKey = keyNames.getConstArray()[0].copy(xKey->getKeyName().getLength()+1); + + if (keyNames.getLength() == 1 && + xKey->getKeyType(relativKey) == RegistryKeyType_LINK) + { + hasSubKeys = sal_True; + + OUString linkTarget = xKey->getLinkTarget(relativKey); + OUString linkName(xKey->getKeyName().copy(xUnoKey->getKeyName().getLength())); + + linkName = linkName + OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + relativKey; + + if (bRegister) + { + prepareUserLink(xDest, linkName, linkTarget, implName); + } else + { + deleteUserLink(xDest->getRootKey(), linkName, linkTarget, implName); + } + } else + { + Sequence< Reference < XRegistryKey> > subKeys = xKey->openKeys(); + + if (subKeys.getLength()) + { + hasSubKeys = sal_True; + const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray(); + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + prepareUserKeys(xDest, xUnoKey, pSubKeys[i], implName, bRegister); + } + } + } + + if (! hasSubKeys) + { + OUString keyName(xKey->getKeyName().copy(xUnoKey->getKeyName().getLength())); + + Reference < XRegistryKey > xRootKey = xDest->getRootKey(); + if (bRegister) + { + createUniqueSubEntry(xRootKey->createKey(keyName), implName); + } + else + { + Reference< XRegistryKey > rKey = xRootKey->openKey(keyName); + if( rKey.is() ) + { + deleteSubEntry(rKey, implName); + xRootKey->deleteKey(keyName); + } + + OUString path = keyName.copy(0, keyName.lastIndexOf('/')); + if( path.getLength() ) + { + deletePathIfPossible(xRootKey, path); + } + } + } + return; +} + +//************************************************************************* +// static deleteAllImplementations +// +static void deleteAllImplementations( const Reference < XSimpleRegistry >& xReg, + const Reference < XRegistryKey >& xSource, + const OUString& locationUrl, + std::list<OUString> & implNames) + // throw (InvalidRegistryException, RuntimeException) +{ + Sequence < Reference < XRegistryKey > > subKeys = xSource->openKeys(); + + if (subKeys.getLength() > 0) + { + const Reference < XRegistryKey> * pSubKeys = subKeys.getConstArray(); + Reference < XRegistryKey > xImplKey; + sal_Bool hasLocationUrl = sal_False; + + const StringPool &pool = spool(); + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + xImplKey = pSubKeys[i]; + Reference < XRegistryKey > xKey = xImplKey->openKey( + pool.slash_UNO_slash_LOCATION ); + + if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCII)) + { + if (xKey->getAsciiValue() == locationUrl) + { + hasLocationUrl = sal_True; + + OUString implName(xImplKey->getKeyName().getStr() + 1); + sal_Int32 firstDot = implName.indexOf('/'); + + if (firstDot >= 0) + implName = implName.copy(firstDot + 1); + + implNames.push_back(implName); + + deleteAllLinkReferences(xReg, xImplKey); + + xKey = xImplKey->openKey( pool.slash_UNO ); + if (xKey.is()) + { + Sequence< Reference < XRegistryKey > > subKeys2 = xKey->openKeys(); + + if (subKeys2.getLength()) + { + const Reference < XRegistryKey > * pSubKeys2 = subKeys2.getConstArray(); + + for (sal_Int32 j = 0; j < subKeys2.getLength(); j++) + { + if (pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SERVICES ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_REGISTRY_LINKS ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_ACTIVATOR ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SINGLETONS ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_LOCATION) ) + { + prepareUserKeys(xReg, xKey, pSubKeys2[j], implName, sal_False); + } + } + } + } + } + } + + if (hasLocationUrl) + { + hasLocationUrl = sal_False; + xImplKey->closeKey(); + xReg->getRootKey()->deleteKey(xImplKey->getKeyName()); + } + } + + subKeys = xSource->openKeys(); + if (subKeys.getLength() == 0) + { + xSource->closeKey(); + xReg->getRootKey()->deleteKey(xSource->getKeyName()); + } + } else + { + xSource->closeKey(); + xReg->getRootKey()->deleteKey(xSource->getKeyName()); + } +} + +//================================================================================================== +static void delete_all_singleton_entries( + Reference < registry::XRegistryKey > const & xSingletons_section, + ::std::list< OUString > const & impl_names ) + // throw (InvalidRegistryException, RuntimeException) +{ + Sequence< Reference< registry::XRegistryKey > > singletons( xSingletons_section->openKeys() ); + Reference< registry::XRegistryKey > const * subkeys = singletons.getConstArray(); + for ( sal_Int32 nPos = singletons.getLength(); nPos--; ) + { + Reference< registry::XRegistryKey > const & xSingleton = subkeys[ nPos ]; + Reference< registry::XRegistryKey > xRegisteredImplNames( + xSingleton->openKey( OUSTR("REGISTERED_BY") ) ); + if (xRegisteredImplNames.is() && xRegisteredImplNames->isValid()) + { + Sequence< OUString > registered_implnames; + try + { + registered_implnames = xRegisteredImplNames->getAsciiListValue(); + } + catch (registry::InvalidValueException &) + { + } + OUString const * p = registered_implnames.getConstArray(); + sal_Int32 nOrigRegLength = registered_implnames.getLength(); + sal_Int32 nNewLength = nOrigRegLength; + for ( sal_Int32 n = nOrigRegLength; n--; ) + { + OUString const & registered_implname = p[ n ]; + + ::std::list< OUString >::const_iterator iPos( impl_names.begin() ); + ::std::list< OUString >::const_iterator const iEnd( impl_names.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + if (iPos->equals( registered_implname )) + { + registered_implnames[ n ] = p[ nNewLength -1 ]; + --nNewLength; + } + } + } + + if (nNewLength != nOrigRegLength) + { + if (0 == nNewLength) + { + // remove whole entry + xRegisteredImplNames->closeKey(); + xSingleton->deleteKey( OUSTR("REGISTERED_BY") ); + // registry key cannot provide its relative name, only absolute :( + OUString abs( xSingleton->getKeyName() ); + xSingletons_section->deleteKey( abs.copy( abs.lastIndexOf( '/' ) +1 ) ); + } + else + { + registered_implnames.realloc( nNewLength ); + xRegisteredImplNames->setAsciiListValue( registered_implnames ); + } + } + } + } +} + +//************************************************************************* +// static deleteAllServiceEntries +// +static void deleteAllServiceEntries( const Reference < XSimpleRegistry >& xReg, + const Reference < XRegistryKey >& xSource, + const OUString& implName) + // throw ( InvalidRegistryException, RuntimeException ) +{ + Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys(); + + if (subKeys.getLength() > 0) + { + const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray(); + Reference < XRegistryKey > xServiceKey; + sal_Bool hasNoImplementations = sal_False; + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + xServiceKey = pSubKeys[i]; + + if (xServiceKey->getValueType() == RegistryValueType_ASCIILIST) + { + Sequence<OUString> implEntries = xServiceKey->getAsciiListValue(); + sal_Int32 length = implEntries.getLength(); + sal_Int32 equals = 0; + + for (sal_Int32 j = 0; j < length; j++) + { + if (implEntries.getConstArray()[j] == implName) + equals++; + } + + if (equals == length) + { + hasNoImplementations = sal_True; + } else + { + if (equals > 0) + { + Sequence<OUString> implEntriesNew(length-equals); + + sal_Int32 j = 0; + for (sal_Int32 k = 0; k < length; k++) + { + if (implEntries.getConstArray()[k] != implName) + { + implEntriesNew.getArray()[j++] = implEntries.getConstArray()[k]; + } + } + + xServiceKey->setAsciiListValue(implEntriesNew); + } + } + } + + if (hasNoImplementations) + { + hasNoImplementations = sal_False; + xServiceKey->closeKey(); + xReg->getRootKey()->deleteKey(xServiceKey->getKeyName()); + } + } + + subKeys = xSource->openKeys(); + if (subKeys.getLength() == 0) + { + xSource->closeKey(); + xReg->getRootKey()->deleteKey(xSource->getKeyName()); + } + } else + { + xSource->closeKey(); + xReg->getRootKey()->deleteKey(xSource->getKeyName()); + } +} + +//-------------------------------------------------------------------------------------------------- +static bool is_supported_service( + OUString const & service_name, + Reference< reflection::XServiceTypeDescription > const & xService_td ) +{ + if (xService_td->getName().equals( service_name )) + return true; + Sequence< Reference< reflection::XServiceTypeDescription > > seq( + xService_td->getMandatoryServices() ); + Reference< reflection::XServiceTypeDescription > const * p = seq.getConstArray(); + for ( sal_Int32 nPos = seq.getLength(); nPos--; ) + { + if (is_supported_service( service_name, p[ nPos ] )) + return true; + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +static void insert_singletons( + Reference< registry::XSimpleRegistry > const & xDest, + Reference< registry::XRegistryKey > const & xImplKey, + Reference< XComponentContext > const & xContext ) + // throw( registry::InvalidRegistryException, registry::CannotRegisterImplementationException, RuntimeException ) +{ + // singletons + Reference< registry::XRegistryKey > xKey( xImplKey->openKey( OUSTR("UNO/SINGLETONS") ) ); + if (xKey.is() && xKey->isValid()) + { + OUString implname( xImplKey->getKeyName().copy( sizeof ("/IMPLEMENTATIONS/") -1 ) ); + // singleton entries + Sequence< Reference< registry::XRegistryKey > > xSingletons_section( xKey->openKeys() ); + Reference< registry::XRegistryKey > const * p = xSingletons_section.getConstArray(); + for ( sal_Int32 nPos = xSingletons_section.getLength(); nPos--; ) + { + Reference< registry::XRegistryKey > const & xSingleton = p[ nPos ]; + OUString singleton_name( + xSingleton->getKeyName().copy( + implname.getLength() + sizeof ("/IMPLEMENTATIONS//UNO/SINGLETONS/") -1 ) ); + OUString service_name( xSingleton->getStringValue() ); + + OUString keyname( OUSTR("/SINGLETONS/") + singleton_name ); + Reference< registry::XRegistryKey > xKey2( xDest->getRootKey()->openKey( keyname ) ); + if (xKey2.is() && xKey2->isValid()) + { + try + { + OUString existing_name( xKey2->getStringValue() ); + if (! existing_name.equals( service_name )) + { + Reference< container::XHierarchicalNameAccess > xTDMgr; + OUString the_tdmgr = + OUSTR("/singletons/com.sun.star.reflection.theTypeDescriptionManager"); + xContext->getValueByName( the_tdmgr ) >>= xTDMgr; + if (! xTDMgr.is()) + { + throw RuntimeException( + OUSTR("cannot get singleton ") + the_tdmgr, + Reference< XInterface >() ); + } + try + { + Reference< reflection::XServiceTypeDescription > xExistingService_td; + xTDMgr->getByHierarchicalName( existing_name ) >>= xExistingService_td; + if (! xExistingService_td.is()) + { + throw RuntimeException( + OUSTR("cannot get service type description: ") + existing_name, + Reference< XInterface >() ); + } + + // everything's fine if existing service entry supports the one + // to be registered + if (! is_supported_service( service_name, xExistingService_td )) + { + OUStringBuffer buf( 64 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("existing singleton service (") ); + buf.append( singleton_name ); + buf.append( (sal_Unicode)'=' ); + buf.append( existing_name ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM(") does not support given one: ") ); + buf.append( service_name ); + throw registry::CannotRegisterImplementationException( + buf.makeStringAndClear(), Reference< XInterface >() ); + } + } + catch (container::NoSuchElementException & exc) + { + throw RuntimeException( + OUSTR("cannot get service type description: ") + exc.Message, + Reference< XInterface >() ); + } + } + } + catch (registry::InvalidValueException &) + { + // repair + xKey2->setStringValue( service_name ); + } + } + else + { + // insert singleton entry + xKey2 = xDest->getRootKey()->createKey( keyname ); + xKey2->setStringValue( service_name ); + } + + Reference< registry::XRegistryKey > xRegisteredImplNames( + xKey2->openKey( OUSTR("REGISTERED_BY") ) ); + if (!xRegisteredImplNames.is() || !xRegisteredImplNames->isValid()) + { + // create + xRegisteredImplNames = xKey2->createKey( OUSTR("REGISTERED_BY") ); + } + + Sequence< OUString > implnames; + try + { + implnames = xRegisteredImplNames->getAsciiListValue(); + } + catch (registry::InvalidValueException &) + { + } + // check implname is already in + sal_Int32 nPos_implnames = implnames.getLength(); + OUString const * pImplnames = implnames.getConstArray(); + while (nPos_implnames--) + { + if (implname.equals( pImplnames[ nPos_implnames ] )) + break; + } + if (nPos_implnames < 0) + { + // append and write back + implnames.realloc( implnames.getLength() +1 ); + implnames[ implnames.getLength() -1 ] = implname; + xRegisteredImplNames->setAsciiListValue( implnames ); + } + } + } +} + + +//************************************************************************* +// static prepareRegistry +// +static void prepareRegistry( + const Reference < XSimpleRegistry >& xDest, + const Reference < XRegistryKey >& xSource, + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + Reference< XComponentContext > const & xContext ) + // throw ( InvalidRegistryException, CannotRegisterImplementationException, RuntimeException ) +{ + Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys(); + + if (!subKeys.getLength()) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "prepareRegistry(): source registry is empty" ) ), + Reference< XInterface > () ); + } + + const StringPool & pool = spool(); + + const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray(); + Reference < XRegistryKey > xImplKey; + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + xImplKey = pSubKeys[i]; + + Reference < XRegistryKey > xKey = xImplKey->openKey( + pool.slash_UNO_slash_SERVICES ); + + if (xKey.is()) + { + // update entries in SERVICES section + Sequence< Reference < XRegistryKey > > serviceKeys = xKey->openKeys(); + OUString implName; + + if (serviceKeys.getLength()) + { + const Reference < XRegistryKey > * pServiceKeys = serviceKeys.getConstArray(); + + implName = OUString(xImplKey->getKeyName().getStr() + 1); + sal_Int32 firstDot = implName.indexOf('/'); + + if (firstDot >= 0) + implName = implName.copy(firstDot + 1); + + sal_Int32 offset = xKey->getKeyName().getLength() + 1; + + for (sal_Int32 j = 0; j < serviceKeys.getLength(); j++) + { + OUString serviceName = pServiceKeys[j]->getKeyName().copy(offset); + + createUniqueSubEntry( + xDest->getRootKey()->createKey( + pool.slash_SERVICES + serviceName ), + implName); + } + + } + else + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "prepareRegistry(): no service names given by component" ) ), + Reference< XInterface > () ); + } + + xKey = xImplKey->openKey( pool.slash_UNO ); + if (xKey.is()) + { + Sequence< Reference < XRegistryKey > > subKeys2 = xKey->openKeys(); + + if (subKeys2.getLength()) + { + const Reference < XRegistryKey > * pSubKeys2 = subKeys2.getConstArray(); + + for (sal_Int32 j = 0; j < subKeys2.getLength(); j++) + { + if (pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SERVICES) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_REGISTRY_LINKS ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SINGLETONS )) + { + prepareUserKeys(xDest, xKey, pSubKeys2[j], implName, sal_True); + } + } + } + } + + // update LOCATION entry + xKey = xImplKey->createKey( pool.slash_UNO_slash_LOCATION ); + + if (xKey.is()) + { + xKey->setAsciiValue(locationUrl); + } + + // update ACTIVATOR entry + xKey = xImplKey->createKey( pool.slash_UNO_slash_ACTIVATOR ); + + if (xKey.is()) + { + xKey->setAsciiValue(implementationLoaderUrl); + } + + xKey = xImplKey->openKey( pool.slash_UNO_slash_SERVICES ); + + if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCIILIST)) + { + // update link entries in REGISTRY_LINKS section + Sequence<OUString> linkNames = xKey->getAsciiListValue(); + + if (linkNames.getLength()) + { + const OUString* pLinkNames = linkNames.getConstArray(); + + for (sal_Int32 j = 0; j < linkNames.getLength(); j++) + { + prepareLink(xDest, xImplKey, pLinkNames[j]); + } + } + } + } + + insert_singletons( xDest, xImplKey, xContext ); + } +} + + +static void findImplementations( const Reference < XRegistryKey > & xSource, + std::list <OUString>& implNames) +{ + sal_Bool isImplKey = sal_False; + + try + { + Reference < XRegistryKey > xKey = xSource->openKey( + spool().slash_UNO_slash_SERVICES ); + + if (xKey.is() && (xKey->getKeyNames().getLength() > 0)) + { + isImplKey = sal_True; + + OUString implName = OUString(xSource->getKeyName().getStr() + 1).replace('/', '.').getStr(); + sal_Int32 firstDot = implName.indexOf('.'); + + if (firstDot >= 0) + implName = implName.copy(firstDot + 1); + + implNames.push_back(implName); + } + } + catch(InvalidRegistryException&) + { + } + + if (isImplKey) return; + + try + { + Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys(); + + if (subKeys.getLength() > 0) + { + const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray(); + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + findImplementations(pSubKeys[i], implNames); + } + + } + } + catch(InvalidRegistryException&) + { + } +} + + +class ImplementationRegistration + : public WeakImplHelper3< XImplementationRegistration2, XServiceInfo, XInitialization > +{ +public: + ImplementationRegistration( const Reference < XComponentContext > & rSMgr ); + ~ImplementationRegistration(); + + // XServiceInfo + OUString SAL_CALL getImplementationName() throw(RuntimeException); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(RuntimeException); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(RuntimeException); + + // XImplementationRegistration + virtual void SAL_CALL registerImplementation( + const OUString& implementationLoader, + const OUString& location, + const Reference < XSimpleRegistry > & xReg) + throw( CannotRegisterImplementationException, RuntimeException ); + + virtual sal_Bool SAL_CALL revokeImplementation( + const OUString& location, + const Reference < XSimpleRegistry >& xReg) + throw( RuntimeException ); + + virtual Sequence< OUString > SAL_CALL getImplementations( + const OUString& implementationLoader, + const OUString& location) + throw( RuntimeException ); + virtual Sequence< OUString > SAL_CALL checkInstantiation( + const OUString& implementationName) + throw( RuntimeException ); + + // XImplementationRegistration2 + virtual void SAL_CALL registerImplementationWithLocation( + const OUString& implementationLoader, + const OUString& location, + const OUString& registeredLocation, + const Reference < XSimpleRegistry > & xReg) + throw( CannotRegisterImplementationException, RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + +private: // helper methods + void prepareRegister( + const OUString& implementationLoader, + const OUString& location, + const OUString& registeredLocation, + const Reference < XSimpleRegistry > & xReg); + // throw( CannotRegisterImplementationException, RuntimeException ) + + static void doRegister( const Reference < XMultiComponentFactory >& xSMgr, + const Reference < XComponentContext > &xCtx, + const Reference < XImplementationLoader >& xAct, + const Reference < XSimpleRegistry >& xDest, + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const OUString& registeredLocationUrl); + /* throw ( InvalidRegistryException, + MergeConflictException, + CannotRegisterImplementationException, RuntimeException ) */ + + static void doRevoke( const Reference < XSimpleRegistry >& xDest, + const OUString& locationUrl ); + // throw( InvalidRegistryException, RuntimeException ) + Reference< XSimpleRegistry > getRegistryFromServiceManager(); + + static Reference< XSimpleRegistry > createTemporarySimpleRegistry( + const Reference< XMultiComponentFactory > &rSMgr, + const Reference < XComponentContext > & rCtx ); + +private: // members + Reference < XMultiComponentFactory > m_xSMgr; + Reference < XComponentContext > m_xCtx; +}; + +//************************************************************************* +// ImplementationRegistration() +// +ImplementationRegistration::ImplementationRegistration( const Reference < XComponentContext > & xCtx ) + : m_xSMgr( xCtx->getServiceManager() ) + , m_xCtx( xCtx ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +//************************************************************************* +// ~ImplementationRegistration() +// +ImplementationRegistration::~ImplementationRegistration() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + + +// XServiceInfo +OUString ImplementationRegistration::getImplementationName() throw(RuntimeException) +{ + return stoc_bootstrap::impreg_getImplementationName(); +} + +// XServiceInfo +sal_Bool ImplementationRegistration::supportsService(const OUString& ServiceName) throw(RuntimeException) +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +// XServiceInfo +Sequence< OUString > ImplementationRegistration::getSupportedServiceNames(void) throw(RuntimeException) +{ + return stoc_bootstrap::impreg_getSupportedServiceNames(); +} + +Reference< XSimpleRegistry > ImplementationRegistration::getRegistryFromServiceManager() +{ + Reference < XPropertySet > xPropSet( m_xSMgr, UNO_QUERY ); + Reference < XSimpleRegistry > xRegistry; + + if( xPropSet.is() ) { + + try { // the implementation does not support XIntrospectionAccess ! + + Any aAny = xPropSet->getPropertyValue( spool().Registry ); + + if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE ) { + aAny >>= xRegistry; + } + } + catch( UnknownPropertyException & ) { + // empty reference is error signal ! + } + } + + return xRegistry; +} + + +//************************************************************************ +// XInitialization +// +void ImplementationRegistration::initialize( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArgs ) + throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + + if( aArgs.getLength() != 4 ) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() expects 4 parameters, got ")); + buf.append( (sal_Int32) aArgs.getLength() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference<XInterface > (), + 0 ); + } + + Reference< XImplementationLoader > rLoader; + OUString loaderServiceName; + OUString locationUrl; + Reference< XSimpleRegistry > rReg; + + // 1st argument : An instance of an implementation loader + if( aArgs.getConstArray()[0].getValueType().getTypeClass() == TypeClass_INTERFACE ) { + aArgs.getConstArray()[0] >>= rLoader; + } + if( !rLoader.is()) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() invalid first parameter," + "expected " ) ); + buf.append( getCppuType( &rLoader ).getTypeName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", got " ) ); + buf.append( aArgs.getConstArray()[0].getValueTypeName() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference< XInterface > (), + 0 ); + } + + // 2nd argument : The service name of the loader. This name is written into the registry + if( aArgs.getConstArray()[1].getValueType().getTypeClass() == TypeClass_STRING ) { + aArgs.getConstArray()[1] >>= loaderServiceName; + } + if( ! loaderServiceName.getLength() ) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() invalid second parameter," + "expected string, got " ) ); + buf.append( aArgs.getConstArray()[1].getValueTypeName() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference< XInterface > (), + 0 ); + } + + // 3rd argument : The file name of the dll, that contains the loader + if( aArgs.getConstArray()[2].getValueType().getTypeClass() == TypeClass_STRING ) { + aArgs.getConstArray()[2] >>= locationUrl; + } + if( ! locationUrl.getLength() ) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() invalid third parameter," + "expected string, got " ) ); + buf.append( aArgs.getConstArray()[2].getValueTypeName() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference< XInterface > (), + 0 ); + } + + // 4th argument : The registry, the service should be written to + if( aArgs.getConstArray()[3].getValueType().getTypeClass() == TypeClass_INTERFACE ) { + aArgs.getConstArray()[3] >>= rReg; + } + + if( !rReg.is() ) { + rReg = getRegistryFromServiceManager(); + if( !rReg.is() ) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() invalid fourth parameter," + "expected " )); + buf.append( getCppuType( &rReg ).getTypeName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", got " ) ); + buf.append( aArgs.getConstArray()[3].getValueTypeName() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference< XInterface > (), + 0 ); + } + } + + doRegister(m_xSMgr, m_xCtx, rLoader , rReg, loaderServiceName , locationUrl, locationUrl); +} + + + +//************************************************************************* +// virtual function registerImplementationWithLocation of XImplementationRegistration2 +// +void ImplementationRegistration::registerImplementationWithLocation( + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const OUString& registeredLocationUrl, + const Reference < XSimpleRegistry > & xReg) + throw( CannotRegisterImplementationException, RuntimeException ) +{ + prepareRegister( + implementationLoaderUrl, locationUrl, registeredLocationUrl, xReg); +} + +// helper function +void ImplementationRegistration::prepareRegister( + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const OUString& registeredLocationUrl, + const Reference < XSimpleRegistry > & xReg) + // throw( CannotRegisterImplementationException, RuntimeException ) +{ + OUString implLoaderUrl(implementationLoaderUrl); + OUString activatorName; + + if (implementationLoaderUrl.getLength() > 0) + { + OUString tmpActivator(implementationLoaderUrl); + sal_Int32 nIndex = 0; + activatorName = tmpActivator.getToken(0, ':', nIndex ); + } else + { + // check locationUrl to find out what kind of loader is needed + // set iimplLoaderUrl + } + + if( m_xSMgr.is() ) { + try + { + Reference < XImplementationLoader > xAct( + m_xSMgr->createInstanceWithContext(activatorName, m_xCtx) , UNO_QUERY ); + if (xAct.is()) + { + Reference < XSimpleRegistry > xRegistry; + + if (xReg.is()) + { + // registry supplied by user + xRegistry = xReg; + } + else + { + xRegistry = getRegistryFromServiceManager(); + } + + if ( xRegistry.is()) + { + doRegister(m_xSMgr, m_xCtx, xAct, xRegistry, implLoaderUrl, + locationUrl, registeredLocationUrl); + } + } + else + { + OUStringBuffer buf( 128 ); + buf.appendAscii( "ImplementationRegistration::registerImplementation() - The service " ); + buf.append( activatorName ); + buf.appendAscii( " cannot be instantiated\n" ); + throw CannotRegisterImplementationException( + buf.makeStringAndClear(), Reference< XInterface > () ); + } + } + catch( CannotRegisterImplementationException & ) + { + throw; + } + catch( InvalidRegistryException & e ) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::registerImplementation() " + "InvalidRegistryException during registration (" )); + buf.append( e.Message ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) ); + throw CannotRegisterImplementationException( + buf.makeStringAndClear(), Reference< XInterface > () ); + } + catch( MergeConflictException & e ) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::registerImplementation() " + "MergeConflictException during registration (" )); + buf.append( e.Message ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) ); + throw CannotRegisterImplementationException( + buf.makeStringAndClear(), Reference< XInterface > () ); + } + } + else + { + throw CannotRegisterImplementationException( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "ImplementationRegistration::registerImplementation() " + "no componentcontext available to instantiate loader")), + Reference< XInterface > () ); + } +} + +//************************************************************************* +// virtual function registerImplementation of XImplementationRegistration +// +void ImplementationRegistration::registerImplementation( + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const Reference < XSimpleRegistry > & xReg) + throw( CannotRegisterImplementationException, RuntimeException ) +{ + prepareRegister(implementationLoaderUrl, locationUrl, locationUrl, xReg); +} + + +//************************************************************************* +// virtual function revokeImplementation of XImplementationRegistration +// +sal_Bool ImplementationRegistration::revokeImplementation(const OUString& location, + const Reference < XSimpleRegistry >& xReg) + throw ( RuntimeException ) +{ + sal_Bool ret = sal_False; + + Reference < XSimpleRegistry > xRegistry; + + if (xReg.is()) { + xRegistry = xReg; + } + else { + Reference < XPropertySet > xPropSet = Reference< XPropertySet >::query( m_xSMgr ); + if( xPropSet.is() ) { + try { + Any aAny = xPropSet->getPropertyValue( spool().Registry ); + + if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE ) + { + aAny >>= xRegistry; + } + } + catch ( UnknownPropertyException & ) { + } + } + } + + if (xRegistry.is()) + { + try + { + doRevoke(xRegistry, location); + ret = sal_True; + } + catch( InvalidRegistryException & ) + { + // no way to transport the error, as no exception is specified and a runtime + // exception is not appropriate. + OSL_ENSURE( 0 , "InvalidRegistryException during revokeImplementation" ); + } + } + + return ret; +} + +//************************************************************************* +// virtual function getImplementations of XImplementationRegistration +// +Sequence< OUString > ImplementationRegistration::getImplementations( + const OUString & implementationLoaderUrl, + const OUString & locationUrl) + throw ( RuntimeException ) +{ + OUString implLoaderUrl(implementationLoaderUrl); + OUString activatorName; + + if (implementationLoaderUrl.getLength() > 0) + { + OUString tmpActivator(implementationLoaderUrl); + sal_Int32 nIndex = 0; + activatorName = tmpActivator.getToken(0, ':', nIndex ); + } else + { + // check locationUrl to find out what kind of loader is needed + // set implLoaderUrl + } + + if( m_xSMgr.is() ) { + + Reference < XImplementationLoader > xAct( + m_xSMgr->createInstanceWithContext( activatorName, m_xCtx ), UNO_QUERY ); + + if (xAct.is()) + { + + Reference < XSimpleRegistry > xReg = + createTemporarySimpleRegistry( m_xSMgr, m_xCtx); + + if (xReg.is()) + { + try + { + xReg->open(OUString() /* in mem */, sal_False, sal_True); + Reference < XRegistryKey > xImpl; + + { // only necessary for deleting the temporary variable of rootkey + xImpl = xReg->getRootKey()->createKey( spool().slash_IMPLEMENTATIONS ); + } + if (xAct->writeRegistryInfo(xImpl, implementationLoaderUrl, locationUrl)) + { + std::list <OUString> implNames; + + findImplementations(xImpl, implNames); + + if (!implNames.empty()) + { + std::list<OUString>::const_iterator iter = implNames.begin(); + + Sequence<OUString> seqImpl(implNames.size()); + OUString *pImplNames = seqImpl.getArray(); + + sal_Int32 index = 0; + while (iter != implNames.end()) + { + pImplNames[index] = *iter; + index++; + ++iter; + } + + xImpl->closeKey(); + return seqImpl; + } + } + + xImpl->closeKey(); + } + catch(MergeConflictException&) + { + } + catch(InvalidRegistryException&) + { + } + } + } + } + + return Sequence<OUString>(); +} + +//************************************************************************* +// virtual function checkInstantiation of XImplementationRegistration +// +Sequence< OUString > ImplementationRegistration::checkInstantiation(const OUString&) + throw ( RuntimeException ) +{ + OSL_ENSURE( sal_False, "ImplementationRegistration::checkInstantiation not implemented" ); + return Sequence<OUString>(); +} + +//************************************************************************* +// helper function doRegistration +// + +void ImplementationRegistration::doRevoke( + const Reference < XSimpleRegistry >& xDest, + const OUString& locationUrl) + // throw ( InvalidRegistryException, RuntimeException ) +{ + if( xDest.is() ) + { + std::list<OUString> aNames; + + const StringPool &pool = spool(); + Reference < XRegistryKey > xRootKey( xDest->getRootKey() ); + + Reference < XRegistryKey > xKey = + xRootKey->openKey( pool.slash_IMPLEMENTATIONS ); + if (xKey.is() && xKey->isValid()) + { + deleteAllImplementations(xDest, xKey, locationUrl, aNames); + } + + xKey = xRootKey->openKey( pool.slash_SERVICES ); + if (xKey.is()) + { + std::list<OUString>::const_iterator iter = aNames.begin(); + + while (iter != aNames.end()) + { + deleteAllServiceEntries(xDest, xKey, *iter); + ++iter; + } + } + + xKey = xRootKey->openKey( OUSTR("/SINGLETONS") ); + if (xKey.is() && xKey->isValid()) + { + delete_all_singleton_entries( xKey, aNames ); + } + + if (xRootKey.is()) + xRootKey->closeKey(); + if (xKey.is() && xKey->isValid() ) + xKey->closeKey(); + } +} + +void ImplementationRegistration::doRegister( + const Reference< XMultiComponentFactory > & xSMgr, + const Reference< XComponentContext > &xCtx, + const Reference < XImplementationLoader > & xAct, + const Reference < XSimpleRegistry >& xDest, + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const OUString& registeredLocationUrl) + /* throw ( InvalidRegistryException, + MergeConflictException, + CannotRegisterImplementationException, RuntimeException ) */ +{ + Reference < XSimpleRegistry > xReg = + createTemporarySimpleRegistry( xSMgr, xCtx ); + Reference < XRegistryKey > xSourceKey; + + if (xAct.is() && xReg.is() && xDest.is()) + { + try + { + xReg->open(OUString() /* in mem */, sal_False, sal_True); + + { // only necessary for deleting the temporary variable of rootkey + xSourceKey = xReg->getRootKey()->createKey( spool().slash_IMPLEMENTATIONS ); + } + + sal_Bool bSuccess = + xAct->writeRegistryInfo(xSourceKey, implementationLoaderUrl, locationUrl); + if ( bSuccess ) + { + prepareRegistry(xDest, xSourceKey, implementationLoaderUrl, registeredLocationUrl, xCtx); + + xSourceKey->closeKey(); + + xSourceKey = xReg->getRootKey(); + Reference < XRegistryKey > xDestKey = xDest->getRootKey(); + mergeKeys( xDestKey, xSourceKey ); + xDestKey->closeKey(); + xSourceKey->closeKey(); + } + else + { + throw CannotRegisterImplementationException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ImplementationRegistration::doRegistration() component registration signaled failure" ) ), + Reference< XInterface > () ); + } + + // Cleanup Source registry. + if ( xSourceKey->isValid() ) + xSourceKey->closeKey(); + } + catch(CannotRegisterImplementationException&) + { + if ( xSourceKey->isValid() ) + xSourceKey->closeKey(); + // and throw again + throw; + } + } +} + + + +Reference< XSimpleRegistry > ImplementationRegistration::createTemporarySimpleRegistry( + const Reference< XMultiComponentFactory > &rSMgr, + const Reference < XComponentContext > & xCtx) +{ + + Reference < XSimpleRegistry > xReg( + rSMgr->createInstanceWithContext( + spool().com_sun_star_registry_SimpleRegistry, xCtx ), + UNO_QUERY); + OSL_ASSERT( xReg.is() ); + return xReg; +} +} + +namespace stoc_bootstrap +{ +//************************************************************************* +Reference<XInterface> SAL_CALL ImplementationRegistration_CreateInstance( + const Reference<XComponentContext> & xCtx ) // throw(Exception) +{ + return (XImplementationRegistration *)new stoc_impreg::ImplementationRegistration(xCtx); +} + +} + |