summaryrefslogtreecommitdiff
path: root/configmgr/source/registry
diff options
context:
space:
mode:
authorJörg Barfurth <jb@openoffice.org>2001-02-23 09:39:30 +0000
committerJörg Barfurth <jb@openoffice.org>2001-02-23 09:39:30 +0000
commit33fa38cac36eeb0c3690cc052f0eeb33876c265f (patch)
tree878ce35bb9f2eff0ce9cb6508e476b948f2386d7 /configmgr/source/registry
parentdfadbaefb86c035e9841edbfcf93d93592d05fe9 (diff)
#79256# Improved handling of NULL values. Overall modernization of this adapter implementation
Diffstat (limited to 'configmgr/source/registry')
-rw-r--r--configmgr/source/registry/cfgregistrykey.cxx1229
-rw-r--r--configmgr/source/registry/cfgregistrykey.hxx104
-rw-r--r--configmgr/source/registry/configregistry.cxx162
-rw-r--r--configmgr/source/registry/configregistry.hxx15
4 files changed, 1112 insertions, 398 deletions
diff --git a/configmgr/source/registry/cfgregistrykey.cxx b/configmgr/source/registry/cfgregistrykey.cxx
index d32de6963e..4242b0c09d 100644
--- a/configmgr/source/registry/cfgregistrykey.cxx
+++ b/configmgr/source/registry/cfgregistrykey.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: cfgregistrykey.cxx,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: fs $ $Date: 2000-11-16 08:12:14 $
+ * last change: $Author: jb $ $Date: 2001-02-23 10:39:30 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -76,15 +76,33 @@
#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
+#ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
+#include <com/sun/star/container/XNamed.hpp>
+#endif
+#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
+#include <com/sun/star/container/XChild.hpp>
+#endif
+#ifndef _COM_SUN_STAR_CONTAINER_XHIERARCHICALNAME_HPP_
+#include <com/sun/star/container/XHierarchicalName.hpp>
+#endif
#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif
+#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTY_HPP_
#include <com/sun/star/beans/Property.hpp>
#endif
+#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#endif
+#ifndef _COM_SUN_STAR_BEANS_XPROPERTY_HPP_
+#include <com/sun/star/beans/XProperty.hpp>
+#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
@@ -93,6 +111,8 @@
#include <typelib/typedescription.hxx>
#endif
+#include <limits>
+
#define THISREF() static_cast< ::cppu::OWeakObject* >(this)
#define UNISTRING(c) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(c) )
@@ -108,173 +128,498 @@ using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::container;
using namespace ::osl;
using namespace ::cppu;
+using ::rtl::OUString;
//--------------------------------------------------------------------------
namespace {
inline
- Type getBinaryDataType() {
+ Type getBinaryDataType()
+ {
Sequence<sal_Int8> const * const p= 0;
return ::getCppuType(p);
}
+ inline
+ bool isAscii(sal_Unicode ch)
+ {
+ return 0 <= ch && ch < 128;
+ }
+ inline
+ bool isAscii(sal_Unicode const * ps, sal_Int32 nLen )
+ {
+ for (int i= 0; i< nLen; ++i)
+ if ( !isAscii( ps[i] ) )
+ return false;
+ return true;
+ }
+ inline
+ bool isAscii(OUString const& str)
+ {
+ return isAscii(str.getStr(),str.getLength());
+ }
+ inline
+ bool isAscii(Sequence< OUString > const& strList)
+ {
+ for (int i= 0; i< strList.getLength(); ++i)
+ if ( !isAscii( strList[i] ) )
+ return false;
+ return true;
+ }
}
//==========================================================================
//= OConfigurationRegistryKey
//==========================================================================
+static
+OUString getNodeName(const Reference< XNameAccess >& _xNode)
+{
+ Reference< XNamed > xName( _xNode, UNO_QUERY );
+ if (xName.is())
+ return xName->getName();
+
+ // fallback
+ Reference< XHierarchicalName > xPath( _xNode, UNO_QUERY );
+ if (xPath.is())
+ return xPath->getHierarchicalName();
+
+ OSL_ENSURE( !_xNode.is(), "Cannot get name of node");
+ return OUString();
+}
//--------------------------------------------------------------------------
+
OConfigurationRegistryKey::OConfigurationRegistryKey
- (const Reference< XNameAccess >& _rxContainerNode
+ (const Reference< XNameAccess >& _rxRootNode
,sal_Bool _bWriteable
,SubtreeRoot
)
- :m_xNodeAccess(_rxContainerNode)
+ :m_aMutex()
,m_bReadOnly(!_bWriteable)
- ,m_xNodeDeepAccess(_rxContainerNode, UNO_QUERY)
+ ,m_xNode(_rxRootNode)
+ ,m_xParentNode()
+ ,m_sLocalName() // this will be treated as root - maybe use hierarchical name (ß)
{
- OSL_ENSURE(m_xNodeAccess.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid config node param !");
+ OSL_ENSURE(m_xNode.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid config node param !");
+}
+
+//--------------------------------------------------------------------------
+OConfigurationRegistryKey::OConfigurationRegistryKey
+ (const Reference< XNameAccess >& _rxNode
+ ,sal_Bool _bWriteable
+ )
+ :m_aMutex()
+ ,m_bReadOnly(!_bWriteable)
+ ,m_xNode(_rxNode)
+ ,m_xParentNode()
+ ,m_sLocalName( getNodeName(_rxNode) ) // this will be treated as root
+{
+ OSL_ENSURE(m_xNode.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid config node param !");
}
//--------------------------------------------------------------------------
OConfigurationRegistryKey::OConfigurationRegistryKey(
- const Reference< XNameAccess >& _rxContainerNode,
+ const Reference< XNameAccess >& _rxParentNode,
const ::rtl::OUString& _rLocalName,
sal_Bool _bWriteable)
- :m_xNodeAccess(_rxContainerNode)
+ :m_aMutex()
,m_bReadOnly(!_bWriteable)
- ,m_xNodeDeepAccess(_rxContainerNode, UNO_QUERY)
+ ,m_xNode()
+ ,m_xParentNode(_rxParentNode)
,m_sLocalName(_rLocalName)
{
- OSL_ENSURE(m_xNodeAccess.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid config node param !");
+ OSL_ENSURE(m_xParentNode.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid parent node param !");
OSL_ENSURE(m_sLocalName.getLength(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid relative name !");
+ OSL_ENSURE(m_xParentNode->hasByName( m_sLocalName ), "OConfigurationRegistryKey::OConfigurationRegistryKey : key not found in parent node !" ); //
}
//--------------------------------------------------------------------------
OConfigurationRegistryKey::OConfigurationRegistryKey(
Any _rCurrentValue,
const Reference< XNameAccess >& _rxParentNode,
- const ::rtl::OUString& _rRelativeName,
+ const ::rtl::OUString& _rLocalName,
sal_Bool _bWriteable)
- :m_aLeafElement(_rCurrentValue)
- ,m_xLeafParent(_rxParentNode)
- ,m_sLocalName(_rRelativeName)
+ :m_aMutex()
,m_bReadOnly(!_bWriteable)
+ ,m_xNode()
+ ,m_xParentNode(_rxParentNode)
+ ,m_sLocalName(_rLocalName)
{
- OSL_ENSURE(_rxParentNode.is() && _rCurrentValue.hasValue(),
- "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid value and/or parent !");
- OSL_ENSURE(m_bReadOnly || Reference< XNameReplace >(_rxParentNode, UNO_QUERY).is(),
- "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid parent (no value write access) !");
+ OSL_ENSURE(m_xParentNode.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid parent node param !");
OSL_ENSURE(m_sLocalName.getLength(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid relative name !");
+ OSL_ENSURE(m_xParentNode->hasByName( m_sLocalName ), "OConfigurationRegistryKey::OConfigurationRegistryKey : key not found in parent node !" ); //
+ OSL_ENSURE(m_xParentNode->getByName( m_sLocalName ) == _rCurrentValue, "OConfigurationRegistryKey::OConfigurationRegistryKey : wrong value parameter !" ); //
+
+ _rCurrentValue >>= m_xNode; // we don't care if that fails
+}
+//--------------------------------------------------------------------------
+
+Reference<XPropertySetInfo> OConfigurationRegistryKey::implGetParentPropertyInfo() throw(RuntimeException)
+{
+ if (!m_xParentNode.is())
+ {
+ Reference< XChild > xChild(m_xNode, UNO_QUERY);
+ if (xChild.is())
+ m_xParentNode = m_xParentNode.query(xChild->getParent());
+ }
+
+ Reference< XPropertySetInfo > xParentInfo; // the result
+
+ Reference< XPropertySet > xParentProperties(m_xParentNode, UNO_QUERY);
+ if (xParentProperties.is())
+ {
+ xParentInfo = xParentProperties->getPropertySetInfo();
+ if (xParentInfo.is() && !xParentInfo->hasPropertyByName(m_sLocalName))
+ {
+ OSL_ENSURE(false, "OConfigurationRegistryKey: This key is unknown in the parent node's PropertySetInfo !");
+ xParentInfo.clear(); // this key is unknow, so don't return the info
+ }
+ }
+
+ return xParentInfo;
+}
+//--------------------------------------------------------------------------
+
+static
+sal_Bool isNodeReadOnly(Reference< XInterface > const& _xNode) throw(RuntimeException)
+{
+ OSL_ASSERT( _xNode.is() );
+
+ Reference< XProperty > xProperty(_xNode, UNO_QUERY);
+ if (xProperty.is())
+ {
+ Property aProperty = xProperty->getAsProperty();
+
+ return (aProperty.Attributes & PropertyAttribute::READONLY) != 0;
+ }
+
+ Reference< XServiceInfo > xServiceInfo( _xNode, UNO_QUERY );
+ if (xServiceInfo.is())
+ {
+ // does it announce update capability ?
+ if (xServiceInfo->supportsService(UNISTRING("com.sun.star.configuration.ConfigurationUpdateAccess")))
+ return false;
+
+ // else does it announce the expected service at all ?
+ else if (xServiceInfo->supportsService(UNISTRING("com.sun.star.configuration.ConfigurationAccess")))
+ return true;
+ }
+
+ // no XProperty, no (meaningful) ServiceInfo - what can we do
+ return false;
+}
+
+//--------------------------------------------------------------------------
+
+sal_Bool OConfigurationRegistryKey::implIsReadOnly() throw (RuntimeException)
+{
+ sal_Bool bResult = m_bReadOnly;;
+
+ // do checks only if this was requested to be writable
+ if (m_bReadOnly)
+ {
+ // nothing to check
+ }
+
+ // try to ask the node itself
+ else if (m_xNode.is())
+ {
+ bResult = m_bReadOnly = isNodeReadOnly( m_xNode );
+ }
+
+ // else use the parent
+ else if (m_xParentNode.is())
+ {
+ Reference< XPropertySetInfo > xParentInfo = implGetParentPropertyInfo();
+
+ if (xParentInfo.is())
+ {
+ Property aProperty = xParentInfo->getPropertyByName(m_sLocalName);
+
+ bResult = m_bReadOnly = ((aProperty.Attributes & PropertyAttribute::READONLY) != 0);
+ }
+ else
+ {
+ // no property info about this key ? - check if the parent itself is writable
+
+ // NOTE: do not set m_bReadOnly here, as we haven't really found out about this object
+ bResult = isNodeReadOnly( m_xParentNode );
+ }
+ }
+ else
+ {
+ // no data at all
+ OSL_ENSURE(false, "implIsReadOnly called for invalid object");
+ bResult = true; // no object is certainly not writable ;-)
+ }
+
+ return bResult;
+}
+//--------------------------------------------------------------------------
+
+sal_Bool OConfigurationRegistryKey::implEnsureNode() throw (InvalidRegistryException,RuntimeException)
+{
+ if (!m_xNode.is())
+ {
+ OSL_ENSURE( m_xParentNode.is(), "implEnsureNode called for invalid registry key");
+ if (m_xParentNode.is())
+ {
+ try
+ {
+ Any aNode = m_xParentNode->getByName( m_sLocalName );
+
+ if ( !(aNode >>= m_xNode) )
+ OSL_ENSURE( ! (aNode.hasValue() && aNode.getValueTypeClass() == TypeClass_INTERFACE),
+ "OConfigurationRegistryKey: Node object does not implement expected interface");
+ }
+ catch (NoSuchElementException& e)
+ {
+ m_xParentNode.clear();
+
+ OUString sMessage = UNISTRING("Invalid OConfigurationRegistryKey. The node \"");
+ sMessage += m_sLocalName;
+ sMessage += UNISTRING("\" was not found in the parent. Parent error message: \n");
+ sMessage += e.Message;
+
+ throw InvalidRegistryException(sMessage, THISREF());
+ }
+ }
+ }
+ return m_xNode.is();
}
+//--------------------------------------------------------------------------
+
+Type OConfigurationRegistryKey::implGetUnoType() throw (RuntimeException)
+{
+ Type aType;
+ if (m_xNode.is())
+ {
+ aType = getCppuType(&m_xNode); // Its just an interface type
+ }
+ else if (m_xParentNode.is())
+ {
+ Reference< XPropertySetInfo > xParentInfo = implGetParentPropertyInfo();
+ if (xParentInfo.is())
+ {
+ aType = xParentInfo->getPropertyByName( m_sLocalName ).Type;
+ }
+ else
+ {
+ aType = m_xParentNode->getElementType();
+ }
+ }
+ else
+ {
+ OSL_ASSERT( aType.getTypeClass() == TypeClass_VOID );
+ OSL_ENSURE( false, "implGetUnoType called for invalid registry key");
+ }
+ return aType;
+}
//--------------------------------------------------------------------------
-void OConfigurationRegistryKey::checkValid(KEY_ACCESS_TYPE _eIntentedAccess) throw (InvalidRegistryException)
+
+sal_Bool OConfigurationRegistryKey::implEnsureValue() throw (RuntimeException)
{
- if (!isValid())
+ if (m_xNode.is())
+ return false;
+
+ OSL_ENSURE( m_xParentNode.is(), "implEnsureValue called for invalid registry key");
+ if (!m_xParentNode.is())
+ return false;
+
+ switch (implGetUnoType().getTypeClass())
+ {
+ case TypeClass_INTERFACE:
+ return false;
+
+ case TypeClass_BYTE:
+ case TypeClass_UNSIGNED_SHORT:
+ case TypeClass_UNSIGNED_LONG:
+ case TypeClass_UNSIGNED_HYPER:
+ case TypeClass_FLOAT:
+ OSL_ENSURE(false, "Unexpected (UNSIGNED INTERGRAL or FLOAT) type found for configuration node");
+
+ case TypeClass_STRING:
+ case TypeClass_BOOLEAN:
+ case TypeClass_SHORT:
+ case TypeClass_LONG:
+ case TypeClass_HYPER:
+ case TypeClass_DOUBLE:
+ case TypeClass_SEQUENCE:
+ return true;
+
+ case TypeClass_ANY:
+ return true;
+
+ case TypeClass_VOID:
+ OSL_ENSURE(false, "OConfigurationRegistryKey: Key does not exist or has VOID type");
+ return false;
+
+ default:
+ OSL_ENSURE(false, "OConfigurationRegistryKey: Key has unexpected UNO type (class)");
+ return false;
+ }
+}
+//--------------------------------------------------------------------------
+
+sal_Bool OConfigurationRegistryKey::implIsValid() throw ()
+{
+ return m_xNode.is() || (m_xParentNode.is() && m_xParentNode->hasByName( m_sLocalName ) );
+}
+//--------------------------------------------------------------------------
+
+void OConfigurationRegistryKey::checkValid(KEY_ACCESS_TYPE _eIntentedAccess) throw (InvalidRegistryException,RuntimeException)
+{
+ if (!implIsValid())
throw InvalidRegistryException(UNISTRING("The registry is not bound to a configuration node anymore."), THISREF());
// "anymore", because at the moment the ctor was called it probably was bound ....
+
switch (_eIntentedAccess)
{
case KAT_VALUE_WRITE:
- if (m_bReadOnly)
+ if (implIsReadOnly())
throw InvalidRegistryException(UNISTRING("This configuration node is not writeable."), THISREF());
+
// !!! NO !!! BREAK !!!
case KAT_VALUE:
- if (!m_aLeafElement.hasValue())
- throw InvalidRegistryException(UNISTRING("This configuration node does not have a value, it is a container."), THISREF());
- if (!m_xLeafParent.is())
- throw InvalidRegistryException(UNISTRING("This configuration nodes parent is invalid."), THISREF());
+ if (m_xNode.is())
+ throw InvalidRegistryException(UNISTRING("This configuration node is not a value, but an internal container."), THISREF());
+
+ if (!m_xParentNode.is())
+ throw InvalidRegistryException(UNISTRING("This configuration node is invalid. It has no parent."), THISREF());
+
+ if (!implEnsureValue())
+ throw InvalidRegistryException(UNISTRING("This configuration does not have a legal value type."), THISREF());
break;
+
case KAT_CHILD:
- if (!m_xNodeAccess.is())
+ if (!implEnsureNode())
throw InvalidRegistryException(UNISTRING("This configuration node does not have children, it is a value node."), THISREF());
break;
+
+ case KAT_META:
+ break;
}
}
//--------------------------------------------------------------------------
-Any OConfigurationRegistryKey::getEmptyLeafDefault(const ::rtl::OUString& _rParentName, const ::rtl::OUString& _rElementLocalName)
+Any OConfigurationRegistryKey::implCreateDefaultElement(Type const& _aValueType) throw (RuntimeException)
{
Any aReturn;
- Any aParent = getDescendant(_rParentName);
- Reference< XInterface > xParent;
- ::cppu::extractInterface(xParent, aParent);
- OSL_ENSURE(xParent.is(), "OConfigurationRegistryKey::getEmptyLeafDefault: suspicious behaviour of the ConfigurationAccess!");
- // if not exception was thrown at all (no above when askeing for the original element, and not in the
- // recursive call to the elements parent), there should be an interface for the parent node ('cause
- // it must exist)
- Reference< XPropertySet > xParentProperties(xParent, UNO_QUERY);
- if (!xParentProperties.is())
- {
- // no fallback anymore
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getEmtyLeafDefault: no fallback anymore to handle the NULL value!");
- // this assertion is just to point the clients to the fatal error ....
- ::rtl::OUString sMessage(UNISTRING("There is an element named "));
- sMessage += _rParentName;
- sMessage += UNISTRING("/");
- sMessage += _rElementLocalName;
- sMessage += UNISTRING(", but it can't be wrapped as registry key. It's current value is NULL, and the parent node is unable to provide type informations.");
- throw InvalidRegistryException(sMessage, THISREF());
- }
-
- Type aElementType = ::getCppuType(static_cast< ::rtl::OUString* >(NULL));
- // assume a string as fallback
- try
- {
- Reference< XPropertySetInfo > xElementInfo = xParentProperties->getPropertySetInfo();
- Property aElementDescription = xElementInfo->getPropertyByName(_rElementLocalName);
- aElementType = aElementDescription.Type;
- }
- catch(Exception&)
+ switch (_aValueType.getTypeClass())
{
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getEmptyLeafDefault: could not retrieve the element type!");
- }
+ case TypeClass_STRING:
+ aReturn <<= OUString();
+ break;
+
+ // we don't distinguish between the different integer types or boolean
+ // (the RegistryKeyType is not granular enough),
+ // but we can't handle them all the same way here
+ case TypeClass_BYTE:
+ case TypeClass_UNSIGNED_SHORT:
+ case TypeClass_SHORT:
+ aReturn <<= (sal_Int16)0;
+ break;
+
+ case TypeClass_UNSIGNED_LONG:
+ case TypeClass_LONG:
+ aReturn <<= (sal_Int32)0;
+ break;
+
+ case TypeClass_BOOLEAN:
+ aReturn <<= sal_Bool(false);
+ break;
+
+ // we cannot really handle 64-bit ints in the registry (but here we can)
+ case TypeClass_UNSIGNED_HYPER:
+ case TypeClass_HYPER:
+ OSL_ENSURE(false, "Warning: cannot handle 64-bit values correctly in registry");
+ aReturn <<= (sal_Int64)0;
+ break;
+
+ // we cannot really handle doubles in the registry (but here we can)
+ case TypeClass_FLOAT:
+ case TypeClass_DOUBLE:
+ OSL_ENSURE(false, "Warning: cannot handle DOUBLE correctly in registry");
+ aReturn <<= (double)0;
+ break;
+
+ // we really want to leave an Any as NULL - hopefully this is acceptable to the set
+ case TypeClass_ANY:
+ break;
+
+ case TypeClass_SEQUENCE:
+ if (_aValueType == getBinaryDataType())
+ aReturn <<= Sequence< sal_Int8 >();
- switch (aElementType.getTypeClass())
- {
- case TypeClass_STRING:
- aReturn <<= ::rtl::OUString();
- break;
- case TypeClass_SHORT:
- case TypeClass_UNSIGNED_SHORT:
- case TypeClass_BYTE:
- case TypeClass_LONG:
- case TypeClass_UNSIGNED_LONG:
- case TypeClass_BOOLEAN:
- aReturn <<= (sal_Int32)0;
- // we don't distinguish between the different integer types (the RegistryKeyType is not
- // granular enough), so we can handle them all the same way here
- break;
- case TypeClass_SEQUENCE:
- if (m_aLeafElement.getValueType() == getBinaryDataType())
- aReturn <<= Sequence< sal_Int8 >();
- else
+ else
+ {
+ Type aElementType = getSequenceElementType(_aValueType);
+ switch (aElementType.getTypeClass())
{
- Type aElementType = getSequenceElementType(m_aLeafElement.getValueType());
- switch (aElementType.getTypeClass())
+ case TypeClass_STRING:
+ aReturn <<= Sequence< OUString >();
+ break;
+
+ case TypeClass_BYTE:
+ case TypeClass_UNSIGNED_SHORT:
+ case TypeClass_SHORT:
+ aReturn <<= Sequence< sal_Int16 >();
+ break;
+
+ case TypeClass_UNSIGNED_LONG:
+ case TypeClass_LONG:
+ aReturn <<= Sequence< sal_Int32 >();
+ break;
+
+ case TypeClass_BOOLEAN:
+ aReturn <<= Sequence< sal_Bool >();
+ break;
+
+ case TypeClass_UNSIGNED_HYPER:
+ case TypeClass_HYPER:
+ aReturn <<= Sequence< sal_Int64 >();
+ break;
+
+ case TypeClass_FLOAT:
+ case TypeClass_DOUBLE:
+ aReturn <<= Sequence< double >();
+ break;
+
+ case TypeClass_SEQUENCE:
+ OSL_ENSURE(false, "Warning: cannot handle Sequence< BINARY > correctly in registry");
+ if (aElementType == getBinaryDataType())
{
- case TypeClass_SHORT:
- case TypeClass_UNSIGNED_SHORT:
- case TypeClass_BYTE:
- case TypeClass_LONG:
- case TypeClass_UNSIGNED_LONG:
- case TypeClass_BOOLEAN:
- aReturn <<= Sequence< sal_Int32 >();
- break;
- case TypeClass_STRING:
- aReturn <<= Sequence< ::rtl::OUString >();
- break;
+ OSL_ENSURE(false, "Warning: cannot handle Sequence< BINARY > correctly in registry");
+ aReturn <<= Sequence< Sequence< sal_Int8 > >();
+ break;
}
+
+ // else FALL THRU to default
+ default:
+ OSL_ENSURE(false, "Unexpected sequence element type for configuration node - returning NULL");
+ // throw here ??
+ break;
}
- break;
+ }
+ break;
+
+ case TypeClass_INTERFACE:
+ OSL_ENSURE(false, "Invalid call to OConfigurationRegistryKey::implCreateDefaultElement. Inner nodes must be created by a factory");
+ break;
+
+ default:
+ OSL_ENSURE(false, "Unexpected value type for configuration node - returning NULL");
+ // throw here ??
+ break;
}
+ OSL_ENSURE( aReturn.getValueType() == _aValueType || (_aValueType.getTypeClass() == TypeClass_ANY && !aReturn.hasValue()),
+ "Warning: Unexpected data type found in Registry - returning similar value or NULL");
return aReturn;
}
//--------------------------------------------------------------------------
-Any OConfigurationRegistryKey::getDescendant(const ::rtl::OUString& _rDescendantName) throw(InvalidRegistryException)
+Any OConfigurationRegistryKey::implGetDescendant(const OUString& _rDescendantName) throw(InvalidRegistryException, RuntimeException)
{
Any aElementReturn;
@@ -282,88 +627,127 @@ Any OConfigurationRegistryKey::getDescendant(const ::rtl::OUString& _rDescendant
{
if (-1 != _rDescendantName.indexOf('/'))
{
- if (m_xNodeDeepAccess.is())
- aElementReturn = m_xNodeDeepAccess->getByHierarchicalName(_rDescendantName);
+ Reference< XHierarchicalNameAccess > xDeepAccess( m_xNode, UNO_QUERY );
+ if (xDeepAccess.is())
+ aElementReturn = xDeepAccess->getByHierarchicalName(_rDescendantName);
else
throw InvalidRegistryException(UNISTRING("Nested element access not supported by this node."), THISREF());
}
else
{
- if (m_xNodeAccess.is())
- aElementReturn = m_xNodeAccess->getByName(_rDescendantName);
+ if (m_xNode.is())
+ aElementReturn = m_xNode->getByName(_rDescendantName);
+
else
{
+ // implEnsureNode should have been called before this method
OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getDescendant : invalid call !");
- // this method should not be called if the object does not represent a container node ...
+
+ // this method should not be called if the object does not represent a container node ...
throw InvalidRegistryException(UNISTRING("invalid object."), THISREF());
}
}
}
catch(NoSuchElementException&)
{ // not allowed to leave the method, wrap it
- ::rtl::OUString sMessage(UNISTRING("There is no element named "));
+ OUString sMessage(UNISTRING("There is no element named "));
sMessage += _rDescendantName;
sMessage += UNISTRING(".");
throw InvalidRegistryException(sMessage, THISREF());
}
- catch(WrappedTargetException&)
+ catch(WrappedTargetException& wte)
{ // allowed to be thrown by XNameAccess::getByName, but not allowed to leave this method
- ::rtl::OUString sMessage(UNISTRING("The configuration node could not provide an element for "));
+ OUString sMessage(UNISTRING("The configuration node could not provide an element for "));
sMessage += _rDescendantName;
- sMessage += UNISTRING(".");
+ sMessage += UNISTRING(". Original Error: ");
+ sMessage += wte.Message;
throw InvalidRegistryException(sMessage, THISREF());
}
- if (!aElementReturn.hasValue())
- { // the path may have refered to a leaf which is currently NULL. As the registry API we're implementing here
- // (as a wrapper for the real configuration API) does not allow NULL values, we need a fallback.
-
- sal_Int32 nSeparatorPos = _rDescendantName.indexOf('/');
- if (-1 != nSeparatorPos)
- {
-
- aElementReturn = getEmptyLeafDefault(_rDescendantName.copy(0, nSeparatorPos), _rDescendantName.copy(nSeparatorPos + 1));
- if (!aElementReturn.hasValue())
- {
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getDescendant: unsupported type!");
- ::rtl::OUString sMessage(UNISTRING("There is an element named "));
- sMessage += _rDescendantName;
- sMessage += UNISTRING(", but it can't be wrapped as registry key. There is not equivalent registry type to map the node value to.");
- throw InvalidRegistryException(sMessage, THISREF());
- }
- }
- }
-
return aElementReturn;
}
//--------------------------------------------------------------------------
-void OConfigurationRegistryKey::writeValueNode(const Any& _rValue) throw(InvalidRegistryException, RuntimeException)
+void OConfigurationRegistryKey::implSetValue(const Any& _rValue) throw(InvalidRegistryException, RuntimeException)
{
- MutexGuard aGuard(m_aMutex);
checkValid(KAT_VALUE_WRITE);
- Reference< XNameReplace > xParentValueAccess(m_xLeafParent, UNO_QUERY);
- if (!xParentValueAccess.is())
- throw InvalidRegistryException(UNISTRING("The parent configuration node does not allow write access to it's children."), THISREF());
-
- try
- {
- xParentValueAccess->replaceByName(m_sLocalName, _rValue);
- }
- catch(IllegalArgumentException&)
- {
- throw InvalidRegistryException(UNISTRING("Unable to replace the old value. The configuration node threw an IllegalArgumentException."), THISREF());
- }
- catch(NoSuchElementException&)
+ // one possible interface
+ Reference< XNameReplace > xParentValueAccess(m_xParentNode, UNO_QUERY);
+ if (xParentValueAccess.is())
{
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::writeValueNode : a NoSuchElementException should be impossible !");
- throw InvalidRegistryException(UNISTRING("Unable to replace the old value. The configuration node threw an NoSuchElementException."), THISREF());
+ try
+ {
+ xParentValueAccess->replaceByName(m_sLocalName, _rValue);
+ }
+ catch(IllegalArgumentException& iae)
+ {
+ OUString sMessage = UNISTRING("Unable to replace the old value. The configuration node threw an ");
+ sMessage += UNISTRING("IllegalArgumentException: ");
+ sMessage += iae.Message;
+ throw InvalidRegistryException(sMessage, THISREF());
+ }
+ catch(NoSuchElementException& nse)
+ {
+ OSL_ENSURE(false, "OConfigurationRegistryKey::writeValueNode : a NoSuchElementException should be impossible !");
+
+ OUString sMessage = UNISTRING("Unable to replace the old value. The configuration node threw an ");
+ sMessage += UNISTRING("NoSuchElementException: ");
+ sMessage += nse.Message;
+ throw InvalidRegistryException(sMessage, THISREF());
+ }
+ catch(WrappedTargetException& wte)
+ {
+ OUString sMessage = UNISTRING("Unable to replace the old value. The configuration node threw an ");
+ sMessage += UNISTRING("WrappedTargetException: ");
+ sMessage += wte.Message;
+ throw InvalidRegistryException(sMessage, THISREF());
+ }
+ return;
}
- catch(WrappedTargetException&)
+
+ // not found - try other interface
+ Reference< XPropertySet > xParentPropertySet(m_xParentNode, UNO_QUERY);
+ if (xParentPropertySet.is())
{
- throw InvalidRegistryException(UNISTRING("Unable to replace the old value. The configuration node threw an WrappedTargetException."), THISREF());
+ try
+ {
+ xParentPropertySet->setPropertyValue(m_sLocalName, _rValue);
+ }
+ catch(IllegalArgumentException& iae)
+ {
+ OUString sMessage = UNISTRING("Unable to set a new value. The configuration node threw an ");
+ sMessage += UNISTRING("IllegalArgumentException: ");
+ sMessage += iae.Message;
+ throw InvalidRegistryException(sMessage, THISREF());
+ }
+ catch(UnknownPropertyException& upe)
+ {
+ OSL_ENSURE(false, "OConfigurationRegistryKey::writeValueNode : a UnknownPropertyException should be impossible !");
+
+ OUString sMessage = UNISTRING("Unable to set a new value. The configuration node threw an ");
+ sMessage += UNISTRING("UnknownPropertyException: ");
+ sMessage += upe.Message;
+ throw InvalidRegistryException(sMessage, THISREF());
+ }
+ catch(PropertyVetoException& pve)
+ {
+ OUString sMessage = UNISTRING("Unable to set a new value. The configuration node threw an ");
+ sMessage += UNISTRING("PropertyVetoException: ");
+ sMessage += pve.Message;
+ throw InvalidRegistryException(sMessage, THISREF());
+ }
+ catch(WrappedTargetException& wte)
+ {
+ OUString sMessage = UNISTRING("Unable to set a new value. The configuration node threw an ");
+ sMessage += UNISTRING("WrappedTargetException: ");
+ sMessage += wte.Message;
+ throw InvalidRegistryException(sMessage, THISREF());
+ }
+ return;
}
+
+ throw InvalidRegistryException(UNISTRING("No interface found on parent node for writing to configuration value node."), THISREF());
}
//--------------------------------------------------------------------------
@@ -385,94 +769,240 @@ sal_Bool SAL_CALL OConfigurationRegistryKey::isValid( ) throw(RuntimeException)
{
MutexGuard aGuard(m_aMutex);
// TODO : perhaps if the registry we're a part of is closed ....
- return m_xNodeAccess.is() || m_aLeafElement.hasValue();
+ return implIsValid();
}
//--------------------------------------------------------------------------
RegistryKeyType SAL_CALL OConfigurationRegistryKey::getKeyType( const ::rtl::OUString& _rKeyName ) throw(InvalidRegistryException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkValid(KAT_CHILD);
// no further checks are made (for performance reasons) ...
+ // Maybe we should check only KAT_META for consistency ?
+ checkValid(KAT_CHILD);
+
return RegistryKeyType_KEY;
}
//--------------------------------------------------------------------------
-typedef typelib_TypeDescriptionReference ElementTypeDesc;
-
RegistryValueType SAL_CALL OConfigurationRegistryKey::getValueType( ) throw(InvalidRegistryException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkValid(KAT_VALUE);
+ checkValid(KAT_META);
- switch (m_aLeafElement.getValueType().getTypeClass())
- {
- case TypeClass_STRING:
- return RegistryValueType_STRING;
- case TypeClass_SHORT:
- case TypeClass_UNSIGNED_SHORT:
- case TypeClass_BYTE:
- case TypeClass_LONG:
- case TypeClass_UNSIGNED_LONG:
- case TypeClass_BOOLEAN:
- return RegistryValueType_LONG;
- case TypeClass_SEQUENCE:
- if (m_aLeafElement.getValueType() == getBinaryDataType())
- return RegistryValueType_BINARY;
- else
+ const Type aUnoType = implGetUnoType();
+
+ switch (aUnoType.getTypeClass())
+ {
+ case TypeClass_INTERFACE: // this is really a case of 'no value type'
+ return RegistryValueType_NOT_DEFINED;
+
+ case TypeClass_ANY: // this is really a case of 'all value types allowed'
+ return RegistryValueType_NOT_DEFINED;
+
+ case TypeClass_STRING:
+ return RegistryValueType_STRING;
+
+ case TypeClass_BYTE:
+ case TypeClass_UNSIGNED_SHORT:
+ case TypeClass_UNSIGNED_LONG:
+ OSL_ENSURE(false, "Unexpected UNSIGNED type found for configuration node");
+ // FALL THRU
+
+ case TypeClass_BOOLEAN:
+ case TypeClass_SHORT:
+ case TypeClass_LONG:
+ return RegistryValueType_LONG;
+
+ case TypeClass_FLOAT:
+ case TypeClass_DOUBLE:
+ OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support floating point numbers !");
+ return RegistryValueType_LONG;
+
+ case TypeClass_UNSIGNED_HYPER:
+ case TypeClass_HYPER:
+ OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support 64-bit integer numbers !");
+ return RegistryValueType_LONG;
+
+ case TypeClass_SEQUENCE:
+ if ( aUnoType.equals( getBinaryDataType() ) )
+ return RegistryValueType_BINARY;
+
+ else
+ {
+ Type aElementType = getSequenceElementType(aUnoType);
+
+ switch (aElementType.getTypeClass())
{
- Type aElementType = getSequenceElementType(m_aLeafElement.getValueType());
- switch (aElementType.getTypeClass())
- {
- case TypeClass_SHORT:
- case TypeClass_UNSIGNED_SHORT:
- case TypeClass_BYTE:
- case TypeClass_LONG:
- case TypeClass_UNSIGNED_LONG:
- case TypeClass_BOOLEAN:
- return RegistryValueType_LONGLIST;
- case TypeClass_STRING:
- return RegistryValueType_STRINGLIST;
- case TypeClass_DOUBLE:
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support lists of floating point numbers !");
- default:
- if (aElementType.equals(getBinaryDataType()))
- OSL_ENSURE(sal_False,"OConfigurationRegistryKey::getValueType : Registry cannot support LIST of BINARY");
- else
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : unknown sequence element type !");
- return RegistryValueType_NOT_DEFINED;
- }
+ case TypeClass_STRING:
+ return RegistryValueType_STRINGLIST;
+
+ case TypeClass_BYTE:
+ OSL_ASSERT(false); // this is caught by the 'binary' case
+
+ case TypeClass_UNSIGNED_SHORT:
+ case TypeClass_UNSIGNED_LONG:
+ OSL_ENSURE(false, "Unexpected UNSIGNED-List type found for configuration node");
+ // FALL THRU
+
+ case TypeClass_BOOLEAN:
+ case TypeClass_SHORT:
+ case TypeClass_LONG:
+ return RegistryValueType_LONGLIST;
+
+ case TypeClass_FLOAT:
+ case TypeClass_DOUBLE:
+ OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support floating point number lists !");
+ return RegistryValueType_LONGLIST;
+
+ case TypeClass_UNSIGNED_HYPER:
+ case TypeClass_HYPER:
+ OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support 64-bit integer number lists !");
+ return RegistryValueType_LONGLIST;
+
+ case TypeClass_ANY:
+ OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : Unexpected: Any as sequence element type !");
+ return RegistryValueType_NOT_DEFINED;
+
+ default:
+ if (aElementType.equals(getBinaryDataType()))
+ OSL_ENSURE(sal_False,"OConfigurationRegistryKey::getValueType : Registry cannot support LIST of BINARY");
+ else
+ OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : unknown sequence element type !");
+
+ return RegistryValueType_NOT_DEFINED;
}
- case TypeClass_DOUBLE:
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support floating point numbers !");
- return RegistryValueType_NOT_DEFINED;
- default:
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : unknown entry type !");
- return RegistryValueType_NOT_DEFINED;
+ }
+
+ default:
+ OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : unknown entry type !");
+ return RegistryValueType_NOT_DEFINED;
}
}
//--------------------------------------------------------------------------
+
+Any OConfigurationRegistryKey::implGetValue() throw(InvalidRegistryException, RuntimeException)
+{
+ checkValid(KAT_VALUE);
+
+ return m_xParentNode->getByName( m_sLocalName );
+}
+
+//--------------------------------------------------------------------------
sal_Int32 SAL_CALL OConfigurationRegistryKey::getLongValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkValid(KAT_VALUE);
-#define EXTRACT(tcname, type) \
- case TypeClass_##tcname : { type nNativeValue; m_aLeafElement >>= nNativeValue; nLongValue = nNativeValue; }
+ Any aValue = implGetValue();
sal_Int32 nLongValue(0);
- switch (m_aLeafElement.getValueTypeClass())
+ switch (aValue.getValueTypeClass())
{
- case TypeClass_SHORT : { sal_Int16 nNativeValue; m_aLeafElement >>= nNativeValue; nLongValue = nNativeValue; } break;
- case TypeClass_UNSIGNED_SHORT : { sal_uInt16 nNativeValue; m_aLeafElement >>= nNativeValue; nLongValue = nNativeValue; } break;
- case TypeClass_BYTE : { sal_Int8 nNativeValue; m_aLeafElement >>= nNativeValue; nLongValue = nNativeValue; } break;
- case TypeClass_LONG : { sal_Int32 nNativeValue; m_aLeafElement >>= nNativeValue; nLongValue = nNativeValue; } break;
- case TypeClass_UNSIGNED_LONG : { sal_uInt32 nNativeValue; m_aLeafElement >>= nNativeValue; nLongValue = nNativeValue; } break;
- case TypeClass_BOOLEAN : { sal_Bool nNativeValue; m_aLeafElement >>= nNativeValue; nLongValue = nNativeValue; } break;
- default:
- throw InvalidValueException(UNISTRING("This node does not contain a long (or a compatible) value."), THISREF());
+ // integral types that are small enough are straightforward
+ case TypeClass_BYTE : { sal_Int8 nNativeValue; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
+ case TypeClass_BOOLEAN : { sal_Bool nNativeValue; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
+ case TypeClass_SHORT : { sal_Int16 nNativeValue; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
+ case TypeClass_UNSIGNED_SHORT : { sal_uInt16 nNativeValue; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
+ case TypeClass_LONG : { sal_Int32 nNativeValue; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
+
+ // this is lossless, but not value-preserving - use cast to avoid warnings
+ case TypeClass_UNSIGNED_LONG:
+ {
+ sal_uInt32 nNativeValue;
+ aValue >>= nNativeValue;
+ nLongValue = sal_Int32(nNativeValue);
+ }
+ break;
+
+ // the following are larger than Long - check for loss and throw if applicable
+ case TypeClass_HYPER:
+ {
+ sal_Int64 nNativeValue;
+ aValue >>= nNativeValue;
+ nLongValue = sal_Int32(nNativeValue);
+
+ // check for data loss
+ if (sal_Int64(nLongValue) != nNativeValue)
+ throw InvalidValueException(UNISTRING("Unsigned Hyper value too large for long; Value cannot be retrieved using registry."), THISREF());
+ }
+ break;
+
+ case TypeClass_UNSIGNED_HYPER:
+ {
+ sal_uInt64 nNativeValue;
+ aValue >>= nNativeValue;
+ nLongValue = sal_Int32(nNativeValue);
+
+ // check for data loss
+ if (sal_uInt64(sal_uInt32(nLongValue)) != nNativeValue)
+ throw InvalidValueException(UNISTRING("Unsigned Hyper value too large for long; Value cannot be retrieved using registry."), THISREF());
+ }
+ break;
+
+ // for floating point types we need a limit for loss checking
+ case TypeClass_FLOAT:
+ OSL_ENSURE(false, "Unexpected type FLOAT in configuration node");
+ {
+ // treat as double
+ float fNativeValue;
+ if (aValue >>= fNativeValue)
+ aValue <<= double(fNativeValue);
+ }
+ // fall thru
+
+ case TypeClass_DOUBLE:
+ {
+ double fNativeValue;
+ aValue >>= fNativeValue;
+
+ // find a reasonable allowed imprecision
+ const double fEps = (2.*fNativeValue + 5.) * std::numeric_limits<double>::epsilon();
+
+ // should be rounding here
+ nLongValue = sal_Int32(fNativeValue);
+
+ // check for data loss
+ bool bRecheck = false;
+
+ double diff = fNativeValue-double(nLongValue);
+ if ( diff > fEps)
+ {
+ // substitute for rounding here
+ if (diff > .5)
+ {
+ ++nLongValue;
+ diff = fNativeValue-double(nLongValue);
+ }
+ bRecheck = true;
+ }
+ else if ( diff < -fEps)
+ {
+ // substitute for rounding here
+ if (diff < -.5)
+ {
+ --nLongValue;
+ diff = fNativeValue-double(nLongValue);
+ }
+ bRecheck = true;
+ }
+
+ if (bRecheck)
+ {
+ if (diff > fEps || diff < -fEps)
+ throw InvalidValueException(UNISTRING("Double value cannot fit in Long; Value cannot be retrieved using registry."), THISREF());
+ }
+ }
+ break;
+
+ case TypeClass_VOID:
+ // allow NULL values, if we maybe advertise this node as long
+ if (this->getValueType() == RegistryValueType_LONG)
+ break;
+ // else FALL THRU to exception
+
+ default:
+ throw InvalidValueException(UNISTRING("This node does not contain a long (or a compatible) value."), THISREF());
}
return nLongValue;
}
@@ -480,54 +1010,72 @@ sal_Int32 SAL_CALL OConfigurationRegistryKey::getLongValue( ) throw(InvalidRegi
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistryKey::setLongValue( sal_Int32 _nValue ) throw(InvalidRegistryException, RuntimeException)
{
- writeValueNode(makeAny(_nValue));
+ MutexGuard aGuard(m_aMutex);
+
+ implSetValue(makeAny(_nValue));
}
//--------------------------------------------------------------------------
Sequence< sal_Int32 > SAL_CALL OConfigurationRegistryKey::getLongListValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkValid(KAT_VALUE);
+
+ Any aValue = implGetValue();
Sequence< sal_Int32 > aReturn;
- if (m_aLeafElement >>= aReturn)
- return aReturn;
+ if (!(aValue >>= aReturn))
+ {
+ // TODO : maybe it's a sequence of sal_Int8 or anything like that which we're able to convert ....
- // TODO : maybe it's a sequence of sal_Int8 or anything like that which we're able to convert ....
+ throw InvalidValueException(UNISTRING("This configuration node does not contain a list of longs !"), THISREF());
+ }
- throw InvalidValueException(UNISTRING("This configuration node does not contain a list of longs !"), THISREF());
+ return aReturn;
}
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistryKey::setLongListValue( const Sequence< sal_Int32 >& _seqValue ) throw(InvalidRegistryException, RuntimeException)
{
- writeValueNode(makeAny(_seqValue));
+ MutexGuard aGuard(m_aMutex);
+
+ implSetValue(makeAny(_seqValue));
}
//--------------------------------------------------------------------------
-::rtl::OUString SAL_CALL OConfigurationRegistryKey::getAsciiValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
+OUString SAL_CALL OConfigurationRegistryKey::getAsciiValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
{
- ::rtl::OUString sReturn = getStringValue();
- // TODO : check if it's really ascii ...
+ OUString sReturn = getStringValue();
+
+ if (!isAscii(sReturn))
+ throw InvalidValueException(UNISTRING("This configuration node value (a string) is not pure ASCII !"), THISREF());
+
return sReturn;
}
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistryKey::setAsciiValue( const ::rtl::OUString& _rValue ) throw(InvalidRegistryException, RuntimeException)
{
+ OSL_ENSURE( isAscii(_rValue), "The string passesd to OConfigurationRegistryKey::setAsciiValue is not pure ASCII");
+
setStringValue(_rValue);
}
//--------------------------------------------------------------------------
-Sequence< ::rtl::OUString > SAL_CALL OConfigurationRegistryKey::getAsciiListValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
+Sequence< OUString > SAL_CALL OConfigurationRegistryKey::getAsciiListValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
{
- return getStringListValue();
- // TODO : it's not really an "ascii list" .... perhaps we should throw an exception here ...
+ Sequence<OUString> aReturn = getStringListValue();
+
+ if (!isAscii(aReturn))
+ throw InvalidValueException(UNISTRING("This configuration node value (a string list) is not pure ASCII !"), THISREF());
+
+ return aReturn;
}
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistryKey::setAsciiListValue( const Sequence< ::rtl::OUString >& _seqValue ) throw(InvalidRegistryException, RuntimeException)
{
+ OSL_ENSURE( isAscii(_seqValue), "The string passesd to OConfigurationRegistryKey::setAsciiValue is not pure ASCII");
+
setStringListValue(_seqValue);
}
@@ -535,47 +1083,55 @@ void SAL_CALL OConfigurationRegistryKey::setAsciiListValue( const Sequence< ::rt
::rtl::OUString SAL_CALL OConfigurationRegistryKey::getStringValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkValid(KAT_VALUE);
- ::rtl::OUString sReturn;
- if (!(m_aLeafElement >>= sReturn))
+ Any aValue = implGetValue();
+
+ OUString sReturn;
+ if (!(aValue >>= sReturn))
throw InvalidValueException(UNISTRING("This node does not contain a string value."), THISREF());
+
return sReturn;
}
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistryKey::setStringValue( const ::rtl::OUString& _rValue ) throw(InvalidRegistryException, RuntimeException)
{
- writeValueNode(makeAny(_rValue));
+ MutexGuard aGuard(m_aMutex);
+
+ implSetValue(makeAny(_rValue));
}
//--------------------------------------------------------------------------
Sequence< ::rtl::OUString > SAL_CALL OConfigurationRegistryKey::getStringListValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkValid(KAT_VALUE);
- Sequence< ::rtl::OUString > aReturn;
- if (m_aLeafElement >>= aReturn)
- return aReturn;
+ Any aValue = implGetValue();
- throw InvalidValueException(UNISTRING("This configuration node does not contain a list of strings !"), THISREF());
+ Sequence< OUString > aReturn;
+ if (!(aValue >>= aReturn))
+ throw InvalidValueException(UNISTRING("This configuration node does not contain a list of strings !"), THISREF());
+
+ return aReturn;
}
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistryKey::setStringListValue( const Sequence< ::rtl::OUString >& _seqValue ) throw(InvalidRegistryException, RuntimeException)
{
- writeValueNode(makeAny(_seqValue));
+ MutexGuard aGuard(m_aMutex);
+
+ implSetValue(makeAny(_seqValue));
}
//--------------------------------------------------------------------------
Sequence< sal_Int8 > SAL_CALL OConfigurationRegistryKey::getBinaryValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkValid(KAT_VALUE);
+
+ Any aValue = implGetValue();
Sequence< sal_Int8 > aReturn;
- if (m_aLeafElement >>= aReturn)
+ if (!(aValue >>= aReturn))
return aReturn;
throw InvalidValueException(UNISTRING("This configuration node does not contain a list of strings !"), THISREF());
@@ -584,40 +1140,26 @@ Sequence< sal_Int8 > SAL_CALL OConfigurationRegistryKey::getBinaryValue( ) thro
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistryKey::setBinaryValue( const Sequence< sal_Int8 >& _rValue ) throw(InvalidRegistryException, RuntimeException)
{
- writeValueNode(makeAny(_rValue));
+ MutexGuard aGuard(m_aMutex);
+
+ implSetValue(makeAny(_rValue));
}
//--------------------------------------------------------------------------
Reference< XRegistryKey > OConfigurationRegistryKey::implGetKey( const ::rtl::OUString& _rKeyName )
- throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException)
+ throw(InvalidRegistryException, RuntimeException)
{
- ::rtl::OUString sDescRelativeName(_rKeyName);
- // will be the name of the new key relative to it's parent
- sal_Bool bDeepAccess = sal_False;
- sal_Int32 nSeparatorPos = _rKeyName.lastIndexOf('/');
- if ((nSeparatorPos >= 0) && (nSeparatorPos == (_rKeyName.getLength() - 1)))
- // recognize a trailing slashs
- nSeparatorPos = _rKeyName.lastIndexOf('/', nSeparatorPos - 1);
- if (nSeparatorPos >= 1)
- {
- sDescRelativeName = _rKeyName.copy(nSeparatorPos + 1);
- bDeepAccess = sal_True;
- }
-
- Any aDescendant = getDescendant(_rKeyName);
+ Any aDescendant = implGetDescendant(_rKeyName);
if (aDescendant.getValueType().getTypeClass() == TypeClass_INTERFACE)
{
- Reference< XNameAccess > xContainerNode;
- ::cppu::extractInterface(xContainerNode, aDescendant);
- if (!xContainerNode.is())
- throw InvalidRegistryException(UNISTRING("invalid descendant node."), THISREF());
- return new OConfigurationRegistryKey(xContainerNode, sDescRelativeName, !m_bReadOnly);
+ Reference< XNameAccess > xNode;
+ ::cppu::extractInterface(xNode, aDescendant);
+ if (!xNode.is())
+ throw InvalidRegistryException(UNISTRING("invalid descendant node. No XNameAccess found."), THISREF());
+ return new OConfigurationRegistryKey(xNode, !m_bReadOnly);
}
else
{
- Reference< XNameAccess > xDescParent(m_xNodeAccess); // the parent config node of the descandent
-
- OSL_ENSURE(aDescendant.hasValue(), "OConfigurationRegistryKey::openKey : invalid return from getDescendant.");
#ifdef DEBUG
switch (aDescendant.getValueType().getTypeClass())
{
@@ -630,18 +1172,48 @@ Reference< XRegistryKey > OConfigurationRegistryKey::implGetKey( const ::rtl::OU
case TypeClass_BOOLEAN:
case TypeClass_SEQUENCE:
break;
+ case TypeClass_VOID: // NULL value found
+ break;
default:
- OSL_ENSURE(sal_False, "OConfigurationRegistryKey::openKey : unknown or invalid descendant value type !");
+ OSL_ENSURE(sal_False, "OConfigurationRegistryKey::openKey : unknown, invalid or unhandled descendant value type !");
}
#endif
- if (bDeepAccess)
+
+ Reference< XNameAccess > xDescParent(m_xNode); // the parent config node of the descandent
+
+ OUString sDescRelativeName(_rKeyName);
+ sal_Int32 nSeparatorPos = _rKeyName.lastIndexOf('/');
+
+ if ( (nSeparatorPos > 0) && (nSeparatorPos == (_rKeyName.getLength() - 1)) )
+ {
+ // recognize a trailing slash
+ sDescRelativeName = sDescRelativeName.copy(0, nSeparatorPos);
+ OSL_ASSERT(sDescRelativeName.getLength() == nSeparatorPos);
+
+ nSeparatorPos = sDescRelativeName.lastIndexOf('/');
+ OSL_ASSERT(sDescRelativeName.getLength() > nSeparatorPos);
+ }
+
+ if (nSeparatorPos >= 1)
{
- Any aDescParent = getDescendant(_rKeyName.copy(0, nSeparatorPos));
+ Any aDescParent = implGetDescendant(_rKeyName.copy(0, nSeparatorPos));
::cppu::extractInterface(xDescParent, aDescParent);
if (!xDescParent.is())
throw InvalidRegistryException(UNISTRING("The internal registry structure seems to be corrupt."), THISREF());
+
+ // will be the name of the new key relative to it's parent
+ sDescRelativeName = sDescRelativeName.copy(nSeparatorPos + 1);
+ }
+ else if (nSeparatorPos == 0)
+ {
+ OSL_ENSURE(false, "Component root path specified for value ?");
+ throw InvalidRegistryException(UNISTRING("Component root path found for value. The internal registry structure seems to be corrupt."), THISREF());
+
}
+ OSL_ENSURE(xDescParent.is(), "No Parent Node found for value ?");
+ OSL_ENSURE(xDescParent->hasByName(sDescRelativeName), "Parent Node does not contain found value ?");
+
return new OConfigurationRegistryKey(aDescendant, xDescParent, sDescRelativeName, !m_bReadOnly);
}
}
@@ -656,7 +1228,7 @@ Reference< XRegistryKey > SAL_CALL OConfigurationRegistryKey::openKey( const ::r
}
//--------------------------------------------------------------------------
-void OConfigurationRegistryKey::checkRelativeKeyName(::rtl::OUString& _rKeyName) throw(InvalidRegistryException, RuntimeException)
+void OConfigurationRegistryKey::checkRelativeKeyName(OUString& _rKeyName) throw(InvalidRegistryException, RuntimeException)
{
// no empty names allowed
if (!_rKeyName.getLength())
@@ -684,14 +1256,24 @@ Reference< XRegistryKey > SAL_CALL OConfigurationRegistryKey::createKey( const :
if (m_bReadOnly)
throw InvalidRegistryException(UNISTRING("The key is read only."), THISREF());
- ::rtl::OUString sKeyName(_rKeyName);
+ OSL_ENSURE(m_xNode.is(), "OConfigurationRegistryKey::createKey : somebody changed the checkValid(KAT_CHILD) behaviour !");
+
+ OUString sKeyName(_rKeyName);
checkRelativeKeyName(sKeyName);
sal_Int32 nSeparatorPos = sKeyName.lastIndexOf('/');
if (-1 != nSeparatorPos)
{
- // deep access. delegate it to a registry key which is one level above the to-be-created one
- ::rtl::OUString sSetNodeName = sKeyName.copy(0, nSeparatorPos);
+ // check if we have the key already
+ Reference< XHierarchicalNameAccess > xDeepAccess(m_xNode, UNO_QUERY);
+ if (xDeepAccess.is() && xDeepAccess->hasByHierarchicalName(sKeyName))
+ {
+ // already there - just open it
+ return implGetKey(sKeyName);
+ }
+
+ // deep access, but not found. delegate it to a registry key which is one level above the to-be-created one
+ OUString sSetNodeName = sKeyName.copy(0, nSeparatorPos);
sKeyName = sKeyName.copy(nSeparatorPos + 1);
Reference< XRegistryKey > xSetNode = implGetKey(sSetNodeName);
@@ -704,58 +1286,86 @@ Reference< XRegistryKey > SAL_CALL OConfigurationRegistryKey::createKey( const :
}
// The requested new key is one level below ourself. Can't delegate the creation.
- Reference< XNameContainer > xContainer(m_xNodeAccess, UNO_QUERY);
- Reference< XSingleServiceFactory > xChildFactory(xContainer, UNO_QUERY);
- if (!xChildFactory.is())
- throw InvalidRegistryException(UNISTRING("The configuration node represented by this key is not a container node, you can't insert keys."), THISREF());
+ if (m_xNode->hasByName(sKeyName) )
+ {
+ // already there - just open it
+ return implGetKey(sKeyName);
+ }
- // In the configuration API, the creation of a new child is two-stage process : first you create a child which
- // is "floating", i.e. does not belong to the configuration tree, yet. After filling it with values, you insert
- // it into the container node which was used for the creation.
- // We can't map this behaviour with the registry API, so we have to combine both steps
+ Reference< XNameContainer > xContainer(m_xNode, UNO_QUERY);
+ if (!xContainer.is())
+ throw InvalidRegistryException(UNISTRING("The configuration node represented by this key is not a set node, you can't insert keys."), THISREF());
- // create a new floating child for the container node
- Reference< XInterface > xFloatingChild;
- try
+ Any aValueToInsert;
+
+ Reference< XSingleServiceFactory > xChildFactory(xContainer, UNO_QUERY);
+ if (xChildFactory.is())
{
- xFloatingChild = xChildFactory->createInstance();
- }
- catch (RuntimeException&)
- { // allowed to leave this method
- throw;
+ // In the configuration API, the creation of a new child is two-stage process : first you create a child which
+ // is "floating", i.e. does not belong to the configuration tree, yet. After filling it with values, you insert
+ // it into the container node which was used for the creation.
+ // We can't map this behaviour with the registry API, so we have to combine both steps
+
+ // create a new floating child for the container node
+ try
+ {
+ Reference< XInterface > xFloatingChild = xChildFactory->createInstance();
+ OSL_ENSURE( xFloatingChild.is(), "The newly created element is NULL !");
+
+ Reference< XNameAccess > xInsertedChild(xFloatingChild, UNO_QUERY);
+ OSL_ENSURE( xInsertedChild.is(), "The newly created element does not provide the required interface");
+
+ if (!xInsertedChild.is())
+ throw InvalidRegistryException(UNISTRING("An internal error occured. The objects provided by the configuration API are invalid."), THISREF());
+
+ aValueToInsert <<= xInsertedChild; // xFloatingChild;
+ }
+ catch (RuntimeException&)
+ { // allowed to leave this method
+ throw;
+ }
+ catch (Exception& e)
+ { // not allowed to leave this method
+ throw InvalidRegistryException(UNISTRING("Unable to create a new child for the configuration node. Original error message as provided by the configuration API : ") += e.Message,
+ THISREF());
+ }
+ OSL_ENSURE(aValueToInsert.hasValue(), "New Child node did not get into the Any ?");
}
- catch (Exception& e)
- { // not allowed to leave this method
- throw InvalidRegistryException(UNISTRING("Unable to create a new child for the configuration node. Original error message as provided by the configuration API : ") += e.Message,
- THISREF());
+ else
+ {
+ // If the elements of the set are simple values, we need to create a matching value
+ Type aElementType = xContainer->getElementType();
+ aValueToInsert = implCreateDefaultElement(aElementType);
+
+ OSL_ENSURE(aValueToInsert.hasValue() || aElementType.getTypeClass() == TypeClass_ANY, "Internal error: NULL value created for new value element ?");
}
// and immediately insert it into the container
try
{
- xContainer->insertByName(sKeyName, makeAny(xFloatingChild));
+ xContainer->insertByName(sKeyName, aValueToInsert);
}
catch (IllegalArgumentException& e)
{
- throw InvalidRegistryException(UNISTRING("illegal argument : ") += e.Message, THISREF());
+ throw InvalidRegistryException(UNISTRING("illegal argument to InsertByName: ") += e.Message, THISREF());
}
catch (ElementExistException& e)
{
- if (e.Message.getLength())
- throw InvalidRegistryException(e.Message, THISREF());
- else
- throw InvalidRegistryException((UNISTRING("There already is an element named ") += sKeyName) += UNISTRING("."), THISREF());
+ OSL_ENSURE(false, "There was an element of the same name inserted just now");
+
+ // try to return that one
+ try { return implGetKey(sKeyName); }
+ catch (Exception&) { OSL_ENSURE(false, "But the other element cannot be retrieved"); }
+
+
+ throw InvalidRegistryException(UNISTRING("Inserting raised a NoSuchElementException for an unavailable element ! Original error message : ") += e.Message, THISREF());
}
catch (WrappedTargetException& e)
{
- throw InvalidRegistryException(UNISTRING("Caught an WrappedTargetException. Original error message : ") += e.Message, THISREF());
+ throw InvalidRegistryException(UNISTRING("Inserting raised a WrappedTargetException. Original error message : ") += e.Message, THISREF());
}
- Reference< XNameAccess > xInsertedChild(xFloatingChild, UNO_QUERY);
- if (!xInsertedChild.is())
- throw InvalidRegistryException(UNISTRING("An internal error occured. The objects provided by the configuration API are invalid."), THISREF());
-
- return new OConfigurationRegistryKey(xInsertedChild, sKeyName, !m_bReadOnly);
+ return new OConfigurationRegistryKey(aValueToInsert, m_xNode, sKeyName, !m_bReadOnly);
}
//--------------------------------------------------------------------------
@@ -763,15 +1373,15 @@ void SAL_CALL OConfigurationRegistryKey::closeKey( ) throw(InvalidRegistryExcep
{
MutexGuard aGuard(m_aMutex);
- m_xNodeAccess = NULL;
- m_xNodeDeepAccess = NULL;
- m_aLeafElement.clear();
- m_xLeafParent = NULL;
- m_sLocalName = ::rtl::OUString();
+ checkValid(KAT_META);
+
+ m_xNode.clear();
+ m_xParentNode.clear();
+// m_sLocalName = OUString(); - local name is const ...
}
//--------------------------------------------------------------------------
-void SAL_CALL OConfigurationRegistryKey::deleteKey( const ::rtl::OUString& _rKeyName ) throw(InvalidRegistryException, RuntimeException)
+void SAL_CALL OConfigurationRegistryKey::deleteKey( const OUString& _rKeyName ) throw(InvalidRegistryException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
@@ -779,7 +1389,7 @@ void SAL_CALL OConfigurationRegistryKey::deleteKey( const ::rtl::OUString& _rKey
if (m_bReadOnly)
throw InvalidRegistryException(UNISTRING("The key is read only."), THISREF());
- ::rtl::OUString sKeyName(_rKeyName);
+ OUString sKeyName(_rKeyName);
checkRelativeKeyName(sKeyName);
sal_Int32 nSeparatorPos = sKeyName.lastIndexOf('/');
@@ -800,11 +1410,11 @@ void SAL_CALL OConfigurationRegistryKey::deleteKey( const ::rtl::OUString& _rKey
}
// The requested new key is one level below ourself. Can't delegate the creation.
- Reference< XNameContainer > xContainer(m_xNodeAccess, UNO_QUERY);
+ Reference< XNameContainer > xContainer(m_xNode, UNO_QUERY);
if (!xContainer.is())
- throw InvalidRegistryException(UNISTRING("The configuration node represented by this key is not a container node, you can't remove keys."), THISREF());
+ throw InvalidRegistryException(UNISTRING("The configuration node represented by this key is not a set node, you can't remove keys."), THISREF());
- // and immediately insert it into the container
+ // and immediately remove it from the container
try
{
xContainer->removeByName(sKeyName);
@@ -814,11 +1424,11 @@ void SAL_CALL OConfigurationRegistryKey::deleteKey( const ::rtl::OUString& _rKey
if (e.Message.getLength())
throw InvalidRegistryException(e.Message, THISREF());
else
- throw InvalidRegistryException((UNISTRING("There is no element named ") += sKeyName) += UNISTRING("."), THISREF());
+ throw InvalidRegistryException((UNISTRING("There is no element named ") += sKeyName) += UNISTRING(" to remove."), THISREF());
}
catch (WrappedTargetException& e)
{
- throw InvalidRegistryException(UNISTRING("Caught an WrappedTargetException. Original error message : ") += e.Message, THISREF());
+ throw InvalidRegistryException(UNISTRING("Removing a node caused a WrappedTargetException. Original error message : ") += e.Message, THISREF());
}
}
@@ -828,12 +1438,14 @@ Sequence< Reference< XRegistryKey > > SAL_CALL OConfigurationRegistryKey::openKe
MutexGuard aGuard(m_aMutex);
checkValid(KAT_CHILD);
- Sequence< ::rtl::OUString > aNames(m_xNodeAccess->getElementNames());
- const ::rtl::OUString* pNames = aNames.getConstArray();
- Sequence< Reference< XRegistryKey > > aReturn(aNames.getLength());
- Reference< XRegistryKey >* pReturn = aReturn.getArray();
- for (sal_Int32 i=0; i<aNames.getLength(); ++i, ++pNames, ++pReturn)
- *pReturn = implGetKey(*pNames);
+ Sequence< ::rtl::OUString > aNames(m_xNode->getElementNames());
+
+ sal_Int32 const nCount = aNames.getLength();
+
+ Sequence< Reference< XRegistryKey > > aReturn(nCount);
+
+ for (sal_Int32 i=0; i<nCount; ++i)
+ aReturn[i] = implGetKey(aNames[i]);
return aReturn;
}
@@ -843,7 +1455,7 @@ Sequence< ::rtl::OUString > SAL_CALL OConfigurationRegistryKey::getKeyNames( )
{
MutexGuard aGuard(m_aMutex);
checkValid(KAT_CHILD);
- return m_xNodeAccess->getElementNames();
+ return m_xNode->getElementNames();
}
//--------------------------------------------------------------------------
@@ -873,7 +1485,6 @@ void SAL_CALL OConfigurationRegistryKey::deleteLink( const ::rtl::OUString& rLin
MutexGuard aGuard(m_aMutex);
throw InvalidRegistryException(UNISTRING("This registry, which is base on a configuration tree, does not support links."), THISREF());
}
-
//--------------------------------------------------------------------------
//..........................................................................
} // namespace configmgr
diff --git a/configmgr/source/registry/cfgregistrykey.hxx b/configmgr/source/registry/cfgregistrykey.hxx
index c4c4815728..306ceffb21 100644
--- a/configmgr/source/registry/cfgregistrykey.hxx
+++ b/configmgr/source/registry/cfgregistrykey.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: cfgregistrykey.hxx,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: fs $ $Date: 2000-11-16 08:12:14 $
+ * last change: $Author: jb $ $Date: 2001-02-23 10:39:30 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -75,6 +75,9 @@
#ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP_
#include <com/sun/star/registry/XRegistryKey.hpp>
#endif
+#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/Mutex.hxx>
@@ -100,26 +103,20 @@ class OConfigurationRegistryKey
sal_Bool m_bReadOnly; /// is the key readonly ?
::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >
- m_xNodeAccess; /// the config node object, if it describes a container
- ::com::sun::star::uno::Reference< ::com::sun::star::container::XHierarchicalNameAccess >
- m_xNodeDeepAccess; /// for accessing elements which are grandchildren
+ m_xNode; /// the config node object, if it is a container
- ::com::sun::star::uno::Any
- m_aLeafElement; /// if the key represents a leaf, this is the value
::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >
- m_xLeafParent; /// if the key represents a leaf, this is it's parent. used for write access
+ m_xParentNode; /// if the key is not the root, this is it's parent.
- ::rtl::OUString m_sLocalName; /** the name of the element relative to the parent, which would be
- m_xLeafParent in case the key represents a value node
+ const ::rtl::OUString m_sLocalName; /** the name of the element relative to the parent, which is
+ m_xParentNode if that is present
*/
- // TODO : the current concept does not recognize any changes in the config tree, i.e. the values stored
- // in a configuration key wrapper are not changed if the value in the corresponding config node changes.
+ // TODO : the current concept does not recognize when config keys are disposed (e.g. when the registry is closed)
+ //
// Possible solutions:
- // 1. on each value (or even on each sub key) access, the node is read from the configuration hierarchy, again.
- // sounds very expensive.
- // 2. each registry key is a listener on the node it represents.
- // sounds expensive, too.
+ // 1. each registry key is a listener on the component containing its node
+ // may be is expensive ?.
//
// At the moment we ignore this restriction, but perhaps we can't do that forever ....
@@ -127,23 +124,31 @@ public:
/// when used as ctor parameter, this indicates that the key wraps a config tree subtree root
struct SubtreeRoot { };
- /** builds an registry key which wraps the root of a configuration node
+ /** builds an registry key which wraps the root of a configuration registry
*/
OConfigurationRegistryKey(
- const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxContainerNode
+ const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxRootNode
,sal_Bool _bWriteable
,SubtreeRoot
);
- /** builds an registry key for a configuration container node
- @param _rxContainerNode the container the key should represent
- @param _rLocalName the name of the node local to it's parent. Must be empty only if
- the key represents the root node of a navigatable sub tree.
+ /** builds an registry key for a configuration node
+ @param _rxContainerNode the node the key should represent
@param _bWriteable should the key be writeable ?
*/
OConfigurationRegistryKey(
- const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxContainerNode
- ,const ::rtl::OUString& _rLocalName
+ const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxNode
+ ,sal_Bool _bWriteable
+ );
+
+ /** builds an registry key for a configuration child node.
+ @param _rxParentNode the parent of the node. Used for update access and for obtaining the initial value.
+ @param _rRelativeName te relative name within the parent
+ @param _bWriteable should the key be writeable ?
+ */
+ OConfigurationRegistryKey(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxParentNode
+ ,const ::rtl::OUString& _rRelativeName
,sal_Bool _bWriteable
);
@@ -202,11 +207,30 @@ protected:
KAT_CHILD /// access to one of the (grand-)children of the node
};
+ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
+ implGetParentPropertyInfo()
+ throw(::com::sun::star::uno::RuntimeException);
+
+ sal_Bool implIsReadOnly()
+ throw(::com::sun::star::uno::RuntimeException);
+
+ sal_Bool implEnsureNode()
+ throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
+
+ ::com::sun::star::uno::Type implGetUnoType()
+ throw(::com::sun::star::uno::RuntimeException);
+
+ sal_Bool implEnsureValue()
+ throw(::com::sun::star::uno::RuntimeException);
+
+ sal_Bool implIsValid() throw ();
+
/** check if the registry key is valid
@param _eIntentedAccess type of access which the caller wants to perform on the object
@throws <type scope="com.sun.star.registry">InvalidRegistryException</type> if the key is invalid
*/
- void checkValid(KEY_ACCESS_TYPE _eIntentedAccess) throw (::com::sun::star::registry::InvalidRegistryException);
+ void checkValid(KEY_ACCESS_TYPE _eIntentedAccess)
+ throw (::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
/** return an child element.
@param _rDescendantName the name of the descendant to open. May have a depth of more than 1, if
@@ -218,14 +242,20 @@ protected:
the element refered by _rName does not exist, the configuration node threw an exception, or
the name has a depth of more than one and the config node does not support this.
*/
- ::com::sun::star::uno::Any getDescendant(const ::rtl::OUString& _rDescendantName) throw(::com::sun::star::registry::InvalidRegistryException);
+ ::com::sun::star::uno::Any
+ implGetDescendant(const ::rtl::OUString& _rDescendantName)
+ throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
/** write the given value into the configuration node the object represents.
@throws <type scope="com.sun.star.registry">InvalidRegistryException</type> if the key is invalid,
not opened for write access or the configurations parent is not able to provide a value access
@throws <type scope="com.sun.star.uno">RuntimeException</type> if a fatal runtime error occurs
*/
- void writeValueNode(const ::com::sun::star::uno::Any& _rValue) throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
+ void implSetValue(const ::com::sun::star::uno::Any& _rValue)
+ throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
+
+ ::com::sun::star::uno::Any implGetValue()
+ throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
/** open the sub key (depth 1 or more) determined by the given name
@param _rKeyName the name of the descendant node
@@ -234,7 +264,9 @@ protected:
the element refered by _rName does not exist, the configuration node threw an exception, or
the name has a depth of more than one and the config node does not support this.
*/
- ::com::sun::star::uno::Reference< ::com::sun::star::registry::XRegistryKey > OConfigurationRegistryKey::implGetKey( const ::rtl::OUString& _rKeyName ) throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
+ ::com::sun::star::uno::Reference< ::com::sun::star::registry::XRegistryKey >
+ implGetKey( const ::rtl::OUString& _rKeyName )
+ throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
/** check the given (relative) key name syntactically.
@@ -247,21 +279,25 @@ protected:
@throws InvalidRegistryException
if the name is empty or consists of slashes only
*/
- void checkRelativeKeyName(::rtl::OUString& _rKeyName) throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
+ void checkRelativeKeyName(::rtl::OUString& _rKeyName)
+ throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
- /** get a default value for a leaf which is originally NULL
+ /** get a default value for a value of a given type
- <p>The configuration leaf nodes are allowed to be NULL, but we no no chance to wrap this here (the registry
+ <p>Some configuration value nodes are allowed to be NULL, but we no no chance to wrap this here (the registry
interface does not allow NULL values). So in case we encounter such a NULL leaf, we create a default value for
it, dependent on the type of the leaf (which can be retrieved from it's parent).</p>
+ @param _rType the type of the element to create
@return
an <type scope="com::sun::star::uno">Any</type> representing a default for the node value type. If the
- return value is still VOID, the node has an unsupported type (e.g. double)
+ return value is still VOID, the node has a nullable type (e.g. any)
@throws com::sun::star::registry::InvalidRegistryException
- if the parent node specified by <arg>_rParentName</arg> did not provide type information for the node
+ if the type given could not be supported
*/
- ::com::sun::star::uno::Any getEmptyLeafDefault(const ::rtl::OUString& _rParentName, const ::rtl::OUString& _rElementLocalName);
+ ::com::sun::star::uno::Any
+ implCreateDefaultElement(::com::sun::star::uno::Type const& _rType)
+ throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
};
diff --git a/configmgr/source/registry/configregistry.cxx b/configmgr/source/registry/configregistry.cxx
index d6feab1fd7..c7b99c9a2d 100644
--- a/configmgr/source/registry/configregistry.cxx
+++ b/configmgr/source/registry/configregistry.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: configregistry.cxx,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: fs $ $Date: 2000-10-25 06:50:58 $
+ * last change: $Author: jb $ $Date: 2001-02-23 10:39:30 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -79,12 +79,18 @@
#ifndef _COM_SUN_STAR_LANG_SERVICENOTREGISTEREDEXCEPTION_HPP_
#include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
#endif
+#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
+#include <com/sun/star/lang/DisposedException.hpp>
+#endif
+#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
+#include <com/sun/star/beans/PropertyValue.hpp>
+#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#define THISREF() static_cast< ::cppu::OWeakObject* >(this)
-#define UNISTRING(c) ::rtl::OUString::createFromAscii(c)
+#define UNISTRING(c) makeUniString(c)
//..........................................................................
namespace configmgr
@@ -98,10 +104,20 @@ using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::container;
using namespace ::osl;
using namespace ::cppu;
+using ::rtl::OUString;
+
+namespace beans = ::com::sun::star::beans;
//==========================================================================
//= OConfigurationRegistry
//==========================================================================
+ inline
+ static
+ OUString makeUniString(char const* c)
+ {
+ return OUString::createFromAscii(c);
+ }
+
static const AsciiServiceName aConfigRegistryServices[] =
{
@@ -129,21 +145,23 @@ using namespace ::cppu;
OConfigurationRegistry::OConfigurationRegistry(const Reference< XMultiServiceFactory >& _rORB) throw(Exception, RuntimeException)
:ServiceComponentImpl(&s_aServiceInfo)
,m_xORB(_rORB)
- ,m_aFlushListeners(m_aMutex)
{
// create the configuration provider used for accessing the configuration
OSL_ENSHURE(m_xORB.is(), "OConfigurationRegistry::OConfigurationRegistry : invalid service factory !");
if (m_xORB.is())
+ {
m_xConfigurationProvider =
- Reference< XMultiServiceFactory > (
- m_xORB->createInstance(UNISTRING("com.sun.star.configuration.ConfigurationProvider")),
- UNO_QUERY
+ m_xConfigurationProvider.query(
+ m_xORB->createInstance(UNISTRING("com.sun.star.configuration.ConfigurationProvider"))
);
+ }
if (!m_xConfigurationProvider.is())
+ {
// it's heavily needed ...
throw ServiceNotRegisteredException(UNISTRING("Failed to instantiate the mandatory service com.sun.star.configuration.ConfigurationProvider."),
THISREF());
+ }
}
//--------------------------------------------------------------------------
@@ -185,9 +203,11 @@ Sequence< sal_Int8 > SAL_CALL OConfigurationRegistry::getImplementationId( ) th
}
//--------------------------------------------------------------------------
-void OConfigurationRegistry::checkOpen() throw(InvalidRegistryException, RuntimeException)
+
+// Not guarded !
+void OConfigurationRegistry::implCheckOpen() throw(InvalidRegistryException, RuntimeException)
{
- if (!isOpen())
+ if (!implIsOpen())
throw InvalidRegistryException(UNISTRING("The registry is not bound to a configuration node."), THISREF());
}
@@ -195,25 +215,37 @@ void OConfigurationRegistry::checkOpen() throw(InvalidRegistryException, Runtime
void SAL_CALL OConfigurationRegistry::open( const ::rtl::OUString& _rURL, sal_Bool _bReadOnly, sal_Bool _bCreate ) throw(InvalidRegistryException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- if (isOpen())
+
+ if (implIsOpen())
close();
::rtl::OUString sNodePath = getNodePathFromURL(_rURL);
if (!m_xConfigurationProvider.is())
- throw RuntimeException(UNISTRING("invalid object. configuration provider is already disposed."), THISREF());
+ throw DisposedException(UNISTRING("invalid object. configuration provider is already disposed."), THISREF());
Reference< XInterface > xNodeAccess;
try
{
- // the one and only parameter for creating the config access : the node path
+ char const * const sAccessType = _bReadOnly ?
+ "com.sun.star.configuration.ConfigurationAccess" :
+ "com.sun.star.configuration.ConfigurationUpdateAccess";
+
+ // prepare parameters for creating the config access : the node path
+ beans::PropertyValue aArgValue;
+ aArgValue.Handle = -1;
+
+ // currently theres is one parameter: the node path
Sequence< Any > aArguments(1);
- aArguments[0] <<= sNodePath;
- if (_bReadOnly)
- xNodeAccess = m_xConfigurationProvider->createInstanceWithArguments(UNISTRING("com.sun.star.configuration.ConfigurationAccess"), aArguments);
- else
- xNodeAccess = m_xConfigurationProvider->createInstanceWithArguments(UNISTRING("com.sun.star.configuration.ConfigurationUpdateAccess"), aArguments);
+ // Argumenbt: NodePath
+ aArgValue.Name = UNISTRING("nodepath");
+ aArgValue.Value <<= sNodePath;
+
+ aArguments[0] <<= aArgValue;
+
+
+ xNodeAccess = m_xConfigurationProvider->createInstanceWithArguments(UNISTRING(sAccessType), aArguments);
}
catch (RuntimeException&)
{ // allowed to leave this method
@@ -229,7 +261,7 @@ void SAL_CALL OConfigurationRegistry::open( const ::rtl::OUString& _rURL, sal_Bo
Reference< XNameAccess > xReadRoot(xNodeAccess, UNO_QUERY);
if (!_bReadOnly)
- m_xUpdateRoot = m_xUpdateRoot.query(xNodeAccess);
+ m_xUpdateRoot = m_xUpdateRoot.query(xReadRoot);
if (!xReadRoot.is() || (!_bReadOnly && !m_xUpdateRoot.is()))
throw InvalidRegistryException(UNISTRING("The object supplied the by configuration provider is invalid."), THISREF());
@@ -242,31 +274,59 @@ void SAL_CALL OConfigurationRegistry::open( const ::rtl::OUString& _rURL, sal_Bo
sal_Bool SAL_CALL OConfigurationRegistry::isValid( ) throw(RuntimeException)
{
MutexGuard aGuard(m_aMutex);
+ return implIsOpen();
+}
+
+//--------------------------------------------------------------------------
+sal_Bool OConfigurationRegistry::implIsOpen( ) throw(RuntimeException)
+{
return m_xRootKey.is();
}
//--------------------------------------------------------------------------
-void SAL_CALL OConfigurationRegistry::close( ) throw(InvalidRegistryException, RuntimeException)
+void SAL_CALL OConfigurationRegistry::close( ) throw(InvalidRegistryException, RuntimeException)
{
- MutexGuard aGuard(m_aMutex);
+ ClearableMutexGuard aGuard(m_aMutex);
- if (m_xRootKey.is())
- m_xRootKey->closeKey();
+ Reference< XRegistryKey > xRootKey(m_xRootKey);
m_xRootKey = NULL;
Reference< XComponent > xRootComponent(m_xSubtreeRoot, UNO_QUERY);
- if (xRootComponent.is())
- xRootComponent->dispose();
m_xSubtreeRoot = NULL;
m_xUpdateRoot = NULL;
m_sLocation = ::rtl::OUString();
+
+ aGuard.clear();
+
+ if (xRootKey.is())
+ xRootKey->closeKey();
+
+ if (xRootComponent.is())
+ xRootComponent->dispose();
+}
+
+//--------------------------------------------------------------------------
+void SAL_CALL OConfigurationRegistry::disposing()
+{
+ close();
+
+ {
+ MutexGuard aGuard(m_aMutex);
+
+ m_xConfigurationProvider.clear();
+ m_xORB.clear();
+ }
+
+ ServiceComponentImpl::disposing();
}
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistry::destroy( ) throw(InvalidRegistryException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
+ implCheckOpen();
+
throw InvalidRegistryException(UNISTRING("This registry is a wrapper for a configuration access. It can not be destroyed."), THISREF());
}
@@ -274,7 +334,7 @@ void SAL_CALL OConfigurationRegistry::destroy( ) throw(InvalidRegistryException
Reference< XRegistryKey > SAL_CALL OConfigurationRegistry::getRootKey( ) throw(InvalidRegistryException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkOpen();
+ implCheckOpen();
return m_xRootKey;
}
@@ -283,7 +343,7 @@ Reference< XRegistryKey > SAL_CALL OConfigurationRegistry::getRootKey( ) throw(
sal_Bool SAL_CALL OConfigurationRegistry::isReadOnly( ) throw(InvalidRegistryException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
- checkOpen();
+ implCheckOpen();
return !m_xUpdateRoot.is();
// if we don't have the update root, we're readonly
@@ -293,6 +353,8 @@ sal_Bool SAL_CALL OConfigurationRegistry::isReadOnly( ) throw(InvalidRegistryEx
void SAL_CALL OConfigurationRegistry::mergeKey( const ::rtl::OUString& aKeyName, const ::rtl::OUString& aUrl ) throw(InvalidRegistryException, MergeConflictException, RuntimeException)
{
MutexGuard aGuard(m_aMutex);
+ implCheckOpen();
+
// not supported. but we can't throw an NoSupportException here ...
throw InvalidRegistryException(UNISTRING("You can't merge into this registry. It's just a wrapper for a configuration node, which has a fixed structure which can not be modified"), THISREF());
}
@@ -302,39 +364,49 @@ void SAL_CALL OConfigurationRegistry::flush( ) throw(RuntimeException)
{
{
MutexGuard aGuard(m_aMutex);
-
- try
+ if (m_xUpdateRoot.is())
{
- m_xUpdateRoot->commitChanges();
- }
- catch (WrappedTargetException& e)
- { // not allowed to leave this method
- // TODO : the specification of XFlushable has to be changed !!!!!
- OSL_ENSHURE(sal_False, "OConfigurationRegistry::flush : caught an exception, could not flush the data !");
- return;
-// ::rtl::OUString sMessage;
-// sMessage = UNISTRING("The changes made could not be committed. Orginal exception message : ");
-// sMessage += e.Message;
-// throw RuntimeException(sMessage, THISREF());
+ try
+ {
+ m_xUpdateRoot->commitChanges();
+ }
+ catch (WrappedTargetException& e)
+ { // not allowed to leave this method
+
+ ::rtl::OUString sMessage;
+ sMessage = UNISTRING("The changes made could not be committed. Orginal exception message : ");
+ sMessage += e.Message;
+
+ // TODO : the specification of XFlushable has to be changed !!!!!
+ OSL_ENSHURE(sal_False, "OConfigurationRegistry::flush : caught an exception, could not flush the data !");
+ return;
+
+ // throw RuntimeException(sMessage, THISREF());
+ }
}
}
- EventObject aFlushed(THISREF());
- ::cppu::OInterfaceIteratorHelper aIter(m_aFlushListeners);
- while (aIter.hasMoreElements())
- static_cast< XFlushListener* >(aIter.next())->flushed(aFlushed);
+ Reference< XFlushListener > const * const pSelector = 0;
+ if (OInterfaceContainerHelper* pContainer = this->rBHelper.getContainer(::getCppuType(pSelector)) )
+ {
+ ::cppu::OInterfaceIteratorHelper aIter( *pContainer );
+
+ EventObject aFlushed(THISREF());
+ while (aIter.hasMoreElements())
+ static_cast< XFlushListener* >(aIter.next())->flushed(aFlushed);
+ }
}
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistry::addFlushListener( const Reference< XFlushListener >& _rxListener ) throw(RuntimeException)
{
- m_aFlushListeners.addInterface(_rxListener);
+ this->rBHelper.addListener(::getCppuType(&_rxListener),_rxListener);
}
//--------------------------------------------------------------------------
void SAL_CALL OConfigurationRegistry::removeFlushListener( const Reference< XFlushListener >& _rxListener ) throw(RuntimeException)
{
- m_aFlushListeners.removeInterface(_rxListener);
+ this->rBHelper.removeListener(::getCppuType(&_rxListener),_rxListener);
}
//..........................................................................
diff --git a/configmgr/source/registry/configregistry.hxx b/configmgr/source/registry/configregistry.hxx
index a8b39efaa1..d60a664a2e 100644
--- a/configmgr/source/registry/configregistry.hxx
+++ b/configmgr/source/registry/configregistry.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: configregistry.hxx,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: lla $ $Date: 2001-01-26 07:54:22 $
+ * last change: $Author: jb $ $Date: 2001-02-23 10:39:30 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -122,9 +122,6 @@ protected:
m_xUpdateRoot; /// the update access to the root of the sub tree, valid if opened for writing
::rtl::OUString m_sLocation; /// URL of the configuration node we're representing, if any
- ::cppu::OInterfaceContainerHelper
- m_aFlushListeners;
-
public:
OConfigurationRegistry(
@@ -156,15 +153,13 @@ public:
virtual void SAL_CALL removeFlushListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XFlushListener >& l ) throw(::com::sun::star::uno::RuntimeException);
protected:
- virtual void SAL_CALL disposing() {
- ServiceComponentImpl::disposing();
- }
+ virtual void SAL_CALL disposing();
/// translates the given URL into a nodepath which may be used with the configuration provider
::rtl::OUString getNodePathFromURL(const ::rtl::OUString& _rURL);
- void checkOpen() throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
+ void implCheckOpen() throw(::com::sun::star::registry::InvalidRegistryException, ::com::sun::star::uno::RuntimeException);
- sal_Bool isOpen() { return isValid(); }
+ sal_Bool implIsOpen();
};