summaryrefslogtreecommitdiffstats
path: root/stoc/source/defaultregistry/defaultregistry.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stoc/source/defaultregistry/defaultregistry.cxx1196
1 files changed, 1196 insertions, 0 deletions
diff --git a/stoc/source/defaultregistry/defaultregistry.cxx b/stoc/source/defaultregistry/defaultregistry.cxx
new file mode 100644
index 000000000..92adf4642
--- /dev/null
+++ b/stoc/source/defaultregistry/defaultregistry.cxx
@@ -0,0 +1,1196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/mutex.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase4.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/registry/XSimpleRegistry.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace css::uno;
+using namespace css::registry;
+using namespace css::lang;
+using namespace css::container;
+using namespace cppu;
+using namespace osl;
+
+namespace {
+
+class NestedRegistryImpl : public WeakAggImplHelper4 < XSimpleRegistry, XInitialization, XServiceInfo, XEnumerationAccess >
+{
+public:
+ NestedRegistryImpl( );
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
+
+ // XSimpleRegistry
+ virtual OUString SAL_CALL getURL() override;
+ virtual void SAL_CALL open( const OUString& rURL, sal_Bool bReadOnly, sal_Bool bCreate ) override;
+ virtual sal_Bool SAL_CALL isValid( ) override;
+ virtual void SAL_CALL close( ) override;
+ virtual void SAL_CALL destroy( ) override;
+ virtual Reference< XRegistryKey > SAL_CALL getRootKey( ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( ) override;
+ virtual void SAL_CALL mergeKey( const OUString& aKeyName, const OUString& aUrl ) override;
+
+ // XEnumerationAccess
+ virtual Reference< XEnumeration > SAL_CALL createEnumeration( ) override;
+ virtual Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+ friend class NestedKeyImpl;
+protected:
+ Mutex m_mutex;
+ sal_uInt32 m_state;
+ Reference<XSimpleRegistry> m_localReg;
+ Reference<XSimpleRegistry> m_defaultReg;
+
+};
+
+
+// class NestedKeyImpl the implementation of interface XRegistryKey
+
+class NestedKeyImpl : public WeakImplHelper< XRegistryKey >
+{
+public:
+ NestedKeyImpl( NestedRegistryImpl* pDefaultRegistry,
+ Reference<XRegistryKey>& localKey,
+ Reference<XRegistryKey>& defaultKey);
+
+ NestedKeyImpl( const OUString& aKeyName,
+ NestedKeyImpl* pKey);
+
+ // XRegistryKey
+ virtual OUString SAL_CALL getKeyName() override;
+ virtual sal_Bool SAL_CALL isReadOnly( ) override;
+ virtual sal_Bool SAL_CALL isValid( ) override;
+ virtual RegistryKeyType SAL_CALL getKeyType( const OUString& rKeyName ) override;
+ virtual RegistryValueType SAL_CALL getValueType( ) override;
+ virtual sal_Int32 SAL_CALL getLongValue( ) override;
+ virtual void SAL_CALL setLongValue( sal_Int32 value ) override;
+ virtual Sequence< sal_Int32 > SAL_CALL getLongListValue( ) override;
+ virtual void SAL_CALL setLongListValue( const css::uno::Sequence< sal_Int32 >& seqValue ) override;
+ virtual OUString SAL_CALL getAsciiValue( ) override;
+ virtual void SAL_CALL setAsciiValue( const OUString& value ) override;
+ virtual Sequence< OUString > SAL_CALL getAsciiListValue( ) override;
+ virtual void SAL_CALL setAsciiListValue( const css::uno::Sequence< OUString >& seqValue ) override;
+ virtual OUString SAL_CALL getStringValue( ) override;
+ virtual void SAL_CALL setStringValue( const OUString& value ) override;
+ virtual Sequence< OUString > SAL_CALL getStringListValue( ) override;
+ virtual void SAL_CALL setStringListValue( const css::uno::Sequence< OUString >& seqValue ) override;
+ virtual Sequence< sal_Int8 > SAL_CALL getBinaryValue( ) override;
+ virtual void SAL_CALL setBinaryValue( const css::uno::Sequence< sal_Int8 >& value ) override;
+ virtual Reference< XRegistryKey > SAL_CALL openKey( const OUString& aKeyName ) override;
+ virtual Reference< XRegistryKey > SAL_CALL createKey( const OUString& aKeyName ) override;
+ virtual void SAL_CALL closeKey( ) override;
+ virtual void SAL_CALL deleteKey( const OUString& rKeyName ) override;
+ virtual Sequence< Reference< XRegistryKey > > SAL_CALL openKeys( ) override;
+ virtual Sequence< OUString > SAL_CALL getKeyNames( ) override;
+ virtual sal_Bool SAL_CALL createLink( const OUString& aLinkName, const OUString& aLinkTarget ) override;
+ virtual void SAL_CALL deleteLink( const OUString& rLinkName ) override;
+ virtual OUString SAL_CALL getLinkTarget( const OUString& rLinkName ) override;
+ virtual OUString SAL_CALL getResolvedName( const OUString& aKeyName ) override;
+
+protected:
+ void computeChanges();
+ OUString computeName(const OUString& name);
+
+ OUString m_name;
+ sal_uInt32 m_state;
+ rtl::Reference<NestedRegistryImpl> m_xRegistry;
+ Reference<XRegistryKey> m_localKey;
+ Reference<XRegistryKey> m_defaultKey;
+};
+
+
+NestedKeyImpl::NestedKeyImpl( NestedRegistryImpl* pDefaultRegistry,
+ Reference<XRegistryKey>& localKey,
+ Reference<XRegistryKey>& defaultKey )
+ : m_state(pDefaultRegistry->m_state), m_xRegistry(pDefaultRegistry), m_localKey(localKey), m_defaultKey(defaultKey)
+{
+ if (m_localKey.is())
+ {
+ m_name = m_localKey->getKeyName();
+ }
+ else if (m_defaultKey.is())
+ {
+ m_name = m_defaultKey->getKeyName();
+ }
+}
+
+
+NestedKeyImpl::NestedKeyImpl( const OUString& rKeyName,
+ NestedKeyImpl* pKey)
+ : m_xRegistry(pKey->m_xRegistry)
+{
+ if (pKey->m_localKey.is() && pKey->m_localKey->isValid())
+ {
+ m_localKey = pKey->m_localKey->openKey(rKeyName);
+ }
+ if (pKey->m_defaultKey.is() && pKey->m_defaultKey->isValid())
+ {
+ m_defaultKey = pKey->m_defaultKey->openKey(rKeyName);
+ }
+
+ if (m_localKey.is())
+ {
+ m_name = m_localKey->getKeyName();
+ }
+ else if (m_defaultKey.is())
+ {
+ m_name = m_defaultKey->getKeyName();
+ }
+
+ m_state = m_xRegistry->m_state;
+}
+
+void NestedKeyImpl::computeChanges()
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( m_state == m_xRegistry->m_state )
+ return;
+
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+
+ Reference<XRegistryKey> tmpKey = rootKey->openKey(m_name);
+
+ if ( tmpKey.is() )
+ {
+ m_localKey = rootKey->openKey(m_name);
+ }
+
+ m_state = m_xRegistry->m_state;
+}
+
+
+// NestedKey_Impl::computeName()
+
+OUString NestedKeyImpl::computeName(const OUString& name)
+{
+ OUString resLocalName, resDefaultName;
+
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ try
+ {
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ resLocalName = m_localKey->getResolvedName(name);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getResolvedName(name);
+ }
+
+ if ( !resLocalName.isEmpty() && m_xRegistry->m_defaultReg->isValid() )
+ {
+ Reference<XRegistryKey> localRoot(m_xRegistry->m_localReg->getRootKey());
+ Reference<XRegistryKey> defaultRoot(m_xRegistry->m_defaultReg->getRootKey());
+
+ resDefaultName = defaultRoot->getResolvedName(resLocalName);
+
+ sal_uInt32 count = 100;
+
+ while (resLocalName != resDefaultName && count > 0)
+ {
+ count--;
+
+ if (resLocalName.isEmpty() || resDefaultName.isEmpty())
+ throw InvalidRegistryException();
+
+ resLocalName = localRoot->getResolvedName(resDefaultName);
+ resDefaultName = defaultRoot->getResolvedName(resLocalName);
+ }
+ }
+ }
+ catch(InvalidRegistryException& )
+ {
+ }
+
+ return resLocalName;
+}
+
+
+OUString SAL_CALL NestedKeyImpl::getKeyName()
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ return m_name;
+}
+
+
+sal_Bool SAL_CALL NestedKeyImpl::isReadOnly( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( !m_localKey.is() || !m_localKey->isValid() )
+ throw InvalidRegistryException();
+
+ return m_localKey->isReadOnly();
+}
+
+
+sal_Bool SAL_CALL NestedKeyImpl::isValid( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ return ((m_localKey.is() && m_localKey->isValid()) ||
+ (m_defaultKey.is() && m_defaultKey->isValid()) );
+}
+
+
+RegistryKeyType SAL_CALL NestedKeyImpl::getKeyType( const OUString& rKeyName )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getKeyType(rKeyName);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getKeyType(rKeyName);
+ }
+
+ return RegistryKeyType_KEY;
+}
+
+
+RegistryValueType SAL_CALL NestedKeyImpl::getValueType( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getValueType();
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getValueType();
+ }
+
+ return RegistryValueType_NOT_DEFINED;
+}
+
+
+sal_Int32 SAL_CALL NestedKeyImpl::getLongValue( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getLongValue();
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getLongValue();
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+void SAL_CALL NestedKeyImpl::setLongValue( sal_Int32 value )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ m_localKey->setLongValue(value);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+ m_localKey->setLongValue(value);
+ m_state = m_xRegistry->m_state++;
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+Sequence< sal_Int32 > SAL_CALL NestedKeyImpl::getLongListValue( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getLongListValue();
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getLongListValue();
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+void SAL_CALL NestedKeyImpl::setLongListValue( const Sequence< sal_Int32 >& seqValue )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ m_localKey->setLongListValue(seqValue);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+ m_localKey->setLongListValue(seqValue);
+ m_state = m_xRegistry->m_state++;
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+OUString SAL_CALL NestedKeyImpl::getAsciiValue( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getAsciiValue();
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getAsciiValue();
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+void SAL_CALL NestedKeyImpl::setAsciiValue( const OUString& value )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ m_localKey->setAsciiValue(value);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+ m_localKey->setAsciiValue(value);
+ m_state = m_xRegistry->m_state++;
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+Sequence< OUString > SAL_CALL NestedKeyImpl::getAsciiListValue( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getAsciiListValue();
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getAsciiListValue();
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+void SAL_CALL NestedKeyImpl::setAsciiListValue( const Sequence< OUString >& seqValue )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ m_localKey->setAsciiListValue(seqValue);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+ m_localKey->setAsciiListValue(seqValue);
+ m_state = m_xRegistry->m_state++;
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+OUString SAL_CALL NestedKeyImpl::getStringValue( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getStringValue();
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getStringValue();
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+void SAL_CALL NestedKeyImpl::setStringValue( const OUString& value )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ m_localKey->setStringValue(value);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+ m_localKey->setStringValue(value);
+ m_state = m_xRegistry->m_state++;
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+Sequence< OUString > SAL_CALL NestedKeyImpl::getStringListValue( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getStringListValue();
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getStringListValue();
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+void SAL_CALL NestedKeyImpl::setStringListValue( const Sequence< OUString >& seqValue )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ m_localKey->setStringListValue(seqValue);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+ m_localKey->setStringListValue(seqValue);
+ m_state = m_xRegistry->m_state++;
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+Sequence< sal_Int8 > SAL_CALL NestedKeyImpl::getBinaryValue( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ return m_localKey->getBinaryValue();
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ return m_defaultKey->getBinaryValue();
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+void SAL_CALL NestedKeyImpl::setBinaryValue( const Sequence< sal_Int8 >& value )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ computeChanges();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ m_localKey->setBinaryValue(value);
+ }
+ else if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+ m_localKey->setBinaryValue(value);
+ m_state = m_xRegistry->m_state++;
+ }
+ else
+ {
+ throw InvalidRegistryException();
+ }
+}
+
+
+Reference< XRegistryKey > SAL_CALL NestedKeyImpl::openKey( const OUString& aKeyName )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( !m_localKey.is() && !m_defaultKey.is() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ OUString resolvedName = computeName(aKeyName);
+
+ if ( resolvedName.isEmpty() )
+ throw InvalidRegistryException();
+
+ Reference<XRegistryKey> localKey, defaultKey;
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ localKey = m_xRegistry->m_localReg->getRootKey()->openKey(resolvedName);
+ }
+ if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ defaultKey = m_xRegistry->m_defaultReg->getRootKey()->openKey(resolvedName);
+ }
+
+ if ( localKey.is() || defaultKey.is() )
+ {
+ return new NestedKeyImpl(m_xRegistry.get(), localKey, defaultKey);
+ }
+ else
+ {
+ return Reference<XRegistryKey>();
+ }
+}
+
+
+Reference< XRegistryKey > SAL_CALL NestedKeyImpl::createKey( const OUString& aKeyName )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( (!m_localKey.is() && !m_defaultKey.is()) ||
+ (m_localKey.is() && m_localKey->isReadOnly()) )
+ {
+ throw InvalidRegistryException();
+ }
+
+ OUString resolvedName = computeName(aKeyName);
+
+ if ( resolvedName.isEmpty() )
+ throw InvalidRegistryException();
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ Reference<XRegistryKey> localKey, defaultKey;
+
+ localKey = m_xRegistry->m_localReg->getRootKey()->createKey(resolvedName);
+ if ( localKey.is() )
+ {
+ if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ defaultKey = m_xRegistry->m_defaultReg->getRootKey()->openKey(resolvedName);
+ }
+
+ m_state = m_xRegistry->m_state++;
+
+ return new NestedKeyImpl(m_xRegistry.get(), localKey, defaultKey);
+ }
+ }
+ else
+ {
+ Reference<XRegistryKey> localKey, defaultKey;
+
+ if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+
+ localKey = m_xRegistry->m_localReg->getRootKey()->createKey(resolvedName);
+
+ if ( localKey.is() )
+ {
+ defaultKey = m_xRegistry->m_defaultReg->getRootKey()->openKey(resolvedName);
+
+ m_state = m_xRegistry->m_state++;
+
+ return new NestedKeyImpl(m_xRegistry.get(), localKey, defaultKey);
+ }
+ }
+ }
+
+ return Reference<XRegistryKey>();
+}
+
+
+void SAL_CALL NestedKeyImpl::closeKey( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ m_localKey->closeKey();
+ }
+ if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ m_defaultKey->closeKey();
+ }
+}
+
+
+void SAL_CALL NestedKeyImpl::deleteKey( const OUString& rKeyName )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( !m_localKey.is() || !m_localKey->isValid() ||
+ m_localKey->isReadOnly() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ OUString resolvedName = computeName(rKeyName);
+
+ if ( resolvedName.isEmpty() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ m_xRegistry->m_localReg->getRootKey()->deleteKey(resolvedName);
+}
+
+
+Sequence< Reference< XRegistryKey > > SAL_CALL NestedKeyImpl::openKeys( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( !m_localKey.is() && !m_defaultKey.is() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ Sequence<OUString> localSeq, defaultSeq;
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ localSeq = m_localKey->getKeyNames();
+ }
+ if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ defaultSeq = m_defaultKey->getKeyNames();
+ }
+
+ std::vector< Reference<XRegistryKey> > retVec;
+ retVec.reserve(localSeq.getLength() + defaultSeq.getLength());
+
+ auto lKeyNameToRegKey = [this](const OUString& rName) -> Reference<XRegistryKey> {
+ sal_Int32 lastIndex = rName.lastIndexOf('/');
+ OUString name = rName.copy(lastIndex);
+ return new NestedKeyImpl(name, this);
+ };
+
+ for (const auto& rKeyName : std::as_const(localSeq))
+ retVec.push_back(lKeyNameToRegKey(rKeyName));
+
+ for (const auto& rKeyName : std::as_const(defaultSeq))
+ {
+ if ( comphelper::findValue(localSeq, rKeyName) == -1 )
+ {
+ retVec.push_back(lKeyNameToRegKey(rKeyName));
+ }
+ }
+
+ return comphelper::containerToSequence(retVec);
+}
+
+
+Sequence< OUString > SAL_CALL NestedKeyImpl::getKeyNames( )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( !m_localKey.is() && !m_defaultKey.is() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ Sequence<OUString> localSeq, defaultSeq;
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ localSeq = m_localKey->getKeyNames();
+ }
+ if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ defaultSeq = m_defaultKey->getKeyNames();
+ }
+
+ return comphelper::combineSequences(localSeq, defaultSeq);
+}
+
+
+sal_Bool SAL_CALL NestedKeyImpl::createLink( const OUString& aLinkName, const OUString& aLinkTarget )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+
+ bool isCreated = false;
+ if ( !m_localKey.is() && !m_defaultKey.is() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ OUString linkName;
+ OUString resolvedName;
+ sal_Int32 lastIndex = aLinkName.lastIndexOf('/');
+
+ if ( lastIndex > 0 )
+ {
+ linkName = aLinkName.copy(0, lastIndex);
+
+ resolvedName = computeName(linkName);
+
+ if ( resolvedName.isEmpty() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ resolvedName += aLinkName.copy(lastIndex);
+ }
+ else
+ {
+ if ( lastIndex == 0 )
+ resolvedName = m_name + aLinkName;
+ else
+ resolvedName = m_name + "/" + aLinkName;
+ }
+
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ isCreated = m_xRegistry->m_localReg->getRootKey()->createLink(resolvedName, aLinkTarget);
+ }
+ else
+ {
+ if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ {
+ Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
+ m_localKey = rootKey->createKey(m_name);
+
+ isCreated = m_xRegistry->m_localReg->getRootKey()->createLink(resolvedName, aLinkTarget);
+ }
+ }
+
+ if ( isCreated )
+ m_state = m_xRegistry->m_state++;
+
+ return isCreated;
+}
+
+
+void SAL_CALL NestedKeyImpl::deleteLink( const OUString& rLinkName )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( !m_localKey.is() && !m_defaultKey.is() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ OUString linkName;
+ OUString resolvedName;
+ sal_Int32 lastIndex = rLinkName.lastIndexOf('/');
+
+ if ( lastIndex > 0 )
+ {
+ linkName = rLinkName.copy(0, lastIndex);
+
+ resolvedName = computeName(linkName);
+
+ if ( resolvedName.isEmpty() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ resolvedName += rLinkName.copy(lastIndex);
+ }
+ else
+ {
+ if ( lastIndex == 0 )
+ resolvedName = m_name + rLinkName;
+ else
+ resolvedName = m_name + "/" + rLinkName;
+ }
+
+ if ( !m_localKey.is() || !m_localKey->isValid() ||
+ m_localKey->isReadOnly() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ m_xRegistry->m_localReg->getRootKey()->deleteLink(resolvedName);
+}
+
+
+OUString SAL_CALL NestedKeyImpl::getLinkTarget( const OUString& rLinkName )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( !m_localKey.is() && !m_defaultKey.is() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ OUString linkName;
+ OUString resolvedName;
+ sal_Int32 lastIndex = rLinkName.lastIndexOf('/');
+
+ if ( lastIndex > 0 )
+ {
+ linkName = rLinkName.copy(0, lastIndex);
+
+ resolvedName = computeName(linkName);
+
+ if ( resolvedName.isEmpty() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ resolvedName += rLinkName.copy(lastIndex);
+ }
+ else
+ {
+ if ( lastIndex == 0 )
+ resolvedName = m_name + rLinkName;
+ else
+ resolvedName = m_name + "/" + rLinkName;
+ }
+
+ OUString linkTarget;
+ if ( m_localKey.is() && m_localKey->isValid() )
+ {
+ try
+ {
+ linkTarget = m_xRegistry->m_localReg->getRootKey()->getLinkTarget(resolvedName);
+ return linkTarget;
+ }
+ catch(InvalidRegistryException& )
+ {
+ }
+ }
+
+ if ( m_defaultKey.is() && m_defaultKey->isValid() )
+ linkTarget = m_xRegistry->m_defaultReg->getRootKey()->getLinkTarget(resolvedName);
+
+ return linkTarget;
+}
+
+
+OUString SAL_CALL NestedKeyImpl::getResolvedName( const OUString& aKeyName )
+{
+ Guard< Mutex > aGuard( m_xRegistry->m_mutex );
+ if ( !m_localKey.is() && !m_defaultKey.is() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ OUString resolvedName = computeName(aKeyName);
+
+ if ( resolvedName.isEmpty() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ return resolvedName;
+}
+
+
+// DefaultRegistry Implementation
+
+
+NestedRegistryImpl::NestedRegistryImpl( )
+ : m_state(0)
+{}
+
+class RegistryEnumueration : public WeakImplHelper< XEnumeration >
+{
+public:
+ RegistryEnumueration(
+ const Reference< XSimpleRegistry > &r1,
+ const Reference< XSimpleRegistry > &r2 )
+ : m_xReg1( r1 ) , m_xReg2( r2 )
+ {}
+public:
+ virtual sal_Bool SAL_CALL hasMoreElements( ) override;
+ virtual Any SAL_CALL nextElement( ) override;
+
+private:
+ Reference< XSimpleRegistry > m_xReg1;
+ Reference< XSimpleRegistry > m_xReg2;
+};
+
+sal_Bool RegistryEnumueration::hasMoreElements( )
+{
+ return m_xReg1.is() || m_xReg2.is();
+}
+
+Any RegistryEnumueration::nextElement( )
+{
+ Any a;
+ if( m_xReg1.is() )
+ {
+ a <<= m_xReg1;
+ m_xReg1.clear();
+ }
+ else if( m_xReg2.is() )
+ {
+ a <<= m_xReg2;
+ m_xReg2.clear();
+ }
+ else
+ {
+ throw NoSuchElementException( "NestedRegistry: no nextElement() !" );
+ }
+ return a;
+}
+
+
+Reference< XEnumeration > NestedRegistryImpl::createEnumeration( )
+{
+ MutexGuard guard( m_mutex );
+ return new RegistryEnumueration( m_localReg, m_defaultReg );
+}
+
+Type NestedRegistryImpl::getElementType( )
+{
+ return cppu::UnoType<decltype(m_localReg)>::get();
+}
+
+sal_Bool SAL_CALL NestedRegistryImpl::hasElements( )
+{
+ MutexGuard guard( m_mutex );
+ return m_localReg.is() || m_defaultReg.is();
+}
+
+
+OUString SAL_CALL NestedRegistryImpl::getImplementationName( )
+{
+ return "com.sun.star.comp.stoc.NestedRegistry";
+}
+
+sal_Bool SAL_CALL NestedRegistryImpl::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence<OUString> SAL_CALL NestedRegistryImpl::getSupportedServiceNames( )
+{
+ Sequence< OUString > seqNames { "com.sun.star.registry.NestedRegistry" };
+ return seqNames;
+}
+
+
+void SAL_CALL NestedRegistryImpl::initialize( const Sequence< Any >& aArguments )
+{
+ Guard< Mutex > aGuard( m_mutex );
+ if ( (aArguments.getLength() == 2) &&
+ (aArguments[0].getValueType().getTypeClass() == TypeClass_INTERFACE) &&
+ (aArguments[1].getValueType().getTypeClass() == TypeClass_INTERFACE) )
+ {
+ aArguments[0] >>= m_localReg;
+ aArguments[1] >>= m_defaultReg;
+ if ( m_localReg == m_defaultReg )
+ m_defaultReg.clear();
+ }
+}
+
+
+OUString SAL_CALL NestedRegistryImpl::getURL()
+{
+ Guard< Mutex > aGuard( m_mutex );
+ try
+ {
+ if ( m_localReg.is() && m_localReg->isValid() )
+ return m_localReg->getURL();
+ }
+ catch(InvalidRegistryException& )
+ {
+ }
+
+ return OUString();
+}
+
+
+void SAL_CALL NestedRegistryImpl::open( const OUString&, sal_Bool, sal_Bool )
+{
+ throw InvalidRegistryException(
+ "the 'open' method is not specified for a nested registry" );
+}
+
+
+sal_Bool SAL_CALL NestedRegistryImpl::isValid( )
+{
+ Guard< Mutex > aGuard( m_mutex );
+ try
+ {
+ if ( (m_localReg.is() && m_localReg->isValid()) ||
+ (m_defaultReg.is() && m_defaultReg->isValid()) )
+ return true;
+ }
+ catch(InvalidRegistryException& )
+ {
+ }
+
+ return false;
+}
+
+
+void SAL_CALL NestedRegistryImpl::close( )
+{
+ Guard< Mutex > aGuard( m_mutex );
+ if ( m_localReg.is() && m_localReg->isValid() )
+ {
+ m_localReg->close();
+ }
+ if ( m_defaultReg.is() && m_defaultReg->isValid() )
+ {
+ m_defaultReg->close();
+ }
+}
+
+
+void SAL_CALL NestedRegistryImpl::destroy( )
+{
+ throw InvalidRegistryException(
+ "the 'destroy' method is not specified for a nested registry" );
+}
+
+
+Reference< XRegistryKey > SAL_CALL NestedRegistryImpl::getRootKey( )
+{
+ Guard< Mutex > aGuard( m_mutex );
+ if ( !m_localReg.is() || !m_localReg->isValid() )
+ {
+ throw InvalidRegistryException();
+ }
+
+ Reference<XRegistryKey> localKey, defaultKey;
+
+ localKey = m_localReg->getRootKey();
+
+ if ( localKey.is() )
+ {
+ if ( m_defaultReg.is() && m_defaultReg->isValid() )
+ {
+ defaultKey = m_defaultReg->getRootKey();
+ }
+
+ return new NestedKeyImpl(this, localKey, defaultKey);
+ }
+
+ return Reference<XRegistryKey>();
+}
+
+
+sal_Bool SAL_CALL NestedRegistryImpl::isReadOnly( )
+{
+ Guard< Mutex > aGuard( m_mutex );
+ try
+ {
+ if ( m_localReg.is() && m_localReg->isValid() )
+ return m_localReg->isReadOnly();
+ }
+ catch(InvalidRegistryException& )
+ {
+ }
+
+ return false;
+}
+
+
+void SAL_CALL NestedRegistryImpl::mergeKey( const OUString& aKeyName, const OUString& aUrl )
+{
+ Guard< Mutex > aGuard( m_mutex );
+ if ( m_localReg.is() && m_localReg->isValid() )
+ {
+ m_localReg->mergeKey(aKeyName, aUrl);
+
+ m_state++;
+ }
+}
+
+} // namespace
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_stoc_NestedRegistry_get_implementation(
+ SAL_UNUSED_PARAMETER css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new NestedRegistryImpl);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */