merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / registry / cfgregistrykey.cxx
blob6b2f6e566cd321c831d06094f674a2f5fcd3aa9a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cfgregistrykey.cxx,v $
10 * $Revision: 1.18 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
33 #include "cfgregistrykey.hxx"
34 #include "datalock.hxx"
35 #include "typeconverter.hxx"
36 #include <osl/diagnose.h>
37 #include <cppuhelper/extract.hxx>
38 #include <com/sun/star/container/XNameContainer.hpp>
39 #include <com/sun/star/container/XNamed.hpp>
40 #include <com/sun/star/container/XChild.hpp>
41 #include <com/sun/star/container/XHierarchicalName.hpp>
42 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
43 #include <com/sun/star/lang/XServiceInfo.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/beans/Property.hpp>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/beans/XProperty.hpp>
48 #include <com/sun/star/util/XStringEscape.hpp>
49 #include <com/sun/star/uno/Sequence.hxx>
50 #include <typelib/typedescription.hxx>
52 #include <limits>
54 #define THISREF() static_cast< ::cppu::OWeakObject* >(this)
55 #define UNISTRING(c) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(c) )
57 //..........................................................................
58 namespace configmgr
60 //..........................................................................
62 //--------------------------------------------------------------------------
63 namespace {
64 inline
65 com::sun::star::uno::Type getBinaryDataType()
67 com::sun::star::uno::Sequence<sal_Int8> const * const p= 0;
68 return ::getCppuType(p);
70 inline
71 bool isAscii(sal_Unicode ch)
73 return 0 < ch && ch < 128;
75 inline
76 bool isAscii(sal_Unicode const * ps, sal_Int32 nLen )
78 for (int i= 0; i< nLen; ++i)
79 if ( !isAscii( ps[i] ) )
80 return false;
81 return true;
83 inline
84 bool isAscii(rtl::OUString const& str)
86 return isAscii(str.getStr(),str.getLength());
88 inline
89 bool isAscii(com::sun::star::uno::Sequence< rtl::OUString > const& strList)
91 for (int i= 0; i< strList.getLength(); ++i)
92 if ( !isAscii( strList[i] ) )
93 return false;
94 return true;
97 // temporary helper
98 inline static void checkNullable() {}
100 //==========================================================================
101 //= OConfigurationRegistryKey
102 //==========================================================================
104 static
105 rtl::OUString getNodeName(const com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >& _xNode)
107 com::sun::star::uno::Reference< com::sun::star::container::XNamed > xName( _xNode, com::sun::star::uno::UNO_QUERY );
108 if (xName.is())
109 return xName->getName();
111 OSL_ENSURE( !_xNode.is(), "Cannot get name of node");
112 return rtl::OUString();
114 //--------------------------------------------------------------------------
116 static bool splitPath(const rtl::OUString& _sPath, rtl::OUString& _rsParentPath, rtl::OUString& _rsLocalName);
117 //--------------------------------------------------------------------------
119 OConfigurationRegistryKey::OConfigurationRegistryKey
120 (const com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >& _rxRootNode
121 ,sal_Bool _bWriteable
122 ,SubtreeRoot
124 :m_bReadOnly(!_bWriteable)
125 ,m_xNode(_rxRootNode)
126 ,m_xParentNode()
127 ,m_sLocalName() // this will be treated as root - maybe use hierarchical name (ß)
129 OSL_ENSURE(m_xNode.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid config node param !");
132 //--------------------------------------------------------------------------
133 OConfigurationRegistryKey::OConfigurationRegistryKey
134 (const com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >& _rxNode
135 ,sal_Bool _bWriteable
137 :m_bReadOnly(!_bWriteable)
138 ,m_xNode(_rxNode)
139 ,m_xParentNode()
140 ,m_sLocalName( getNodeName(_rxNode) ) // this will not be treated as root
142 OSL_ENSURE(m_xNode.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid config node param !");
145 //--------------------------------------------------------------------------
146 OConfigurationRegistryKey::OConfigurationRegistryKey(
147 com::sun::star::uno::Any _rCurrentValue,
148 const com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >& _rxParentNode,
149 const ::rtl::OUString& _rLocalName,
150 sal_Bool _bWriteable)
151 :m_bReadOnly(!_bWriteable)
152 ,m_xNode()
153 ,m_xParentNode(_rxParentNode)
154 ,m_sLocalName(_rLocalName)
156 OSL_ENSURE(m_xParentNode.is(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid parent node param !");
157 OSL_ENSURE(m_sLocalName.getLength(), "OConfigurationRegistryKey::OConfigurationRegistryKey : invalid relative name !");
158 OSL_ENSURE(m_xParentNode->hasByName( m_sLocalName ), "OConfigurationRegistryKey::OConfigurationRegistryKey : key not found in parent node !" ); //
159 OSL_ENSURE(m_xParentNode->getByName( m_sLocalName ) == _rCurrentValue, "OConfigurationRegistryKey::OConfigurationRegistryKey : wrong value parameter !" ); //
161 _rCurrentValue >>= m_xNode; // we don't care if that fails
163 //--------------------------------------------------------------------------
165 com::sun::star::uno::Reference<com::sun::star::beans::XPropertySetInfo> OConfigurationRegistryKey::implGetParentPropertyInfo() throw(com::sun::star::uno::RuntimeException)
167 if (!m_xParentNode.is())
169 com::sun::star::uno::Reference< com::sun::star::container::XChild > xChild(m_xNode, com::sun::star::uno::UNO_QUERY);
170 if (xChild.is())
171 m_xParentNode = m_xParentNode.query(xChild->getParent());
174 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > xParentInfo; // the result
176 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xParentProperties(m_xParentNode, com::sun::star::uno::UNO_QUERY);
177 if (xParentProperties.is())
179 xParentInfo = xParentProperties->getPropertySetInfo();
180 if (xParentInfo.is() && !xParentInfo->hasPropertyByName(m_sLocalName))
182 OSL_ENSURE(false, "OConfigurationRegistryKey: This key is unknown in the parent node's PropertySetInfo !");
183 xParentInfo.clear(); // this key is unknow, so don't return the info
187 return xParentInfo;
189 //--------------------------------------------------------------------------
191 static
192 sal_Bool isNodeReadOnly(com::sun::star::uno::Reference< com::sun::star::uno::XInterface > const& _xNode) throw(com::sun::star::uno::RuntimeException)
194 OSL_ASSERT( _xNode.is() );
196 com::sun::star::uno::Reference< com::sun::star::beans::XProperty > xProperty(_xNode, com::sun::star::uno::UNO_QUERY);
197 if (xProperty.is())
199 com::sun::star::beans::Property aProperty = xProperty->getAsProperty();
201 return (aProperty.Attributes & com::sun::star::beans::PropertyAttribute::READONLY) != 0;
204 com::sun::star::uno::Reference< com::sun::star::lang::XServiceInfo > xServiceInfo( _xNode, com::sun::star::uno::UNO_QUERY );
205 if (xServiceInfo.is())
207 // does it announce update capability ?
208 if (xServiceInfo->supportsService(UNISTRING("com.sun.star.configuration.ConfigurationUpdateAccess")))
209 return false;
211 // else does it announce the expected service at all ?
212 else if (xServiceInfo->supportsService(UNISTRING("com.sun.star.configuration.ConfigurationAccess")))
213 return true;
216 // no XProperty, no (meaningful) ServiceInfo - what can we do
217 return false;
220 //--------------------------------------------------------------------------
222 sal_Bool OConfigurationRegistryKey::implIsReadOnly() throw (com::sun::star::uno::RuntimeException)
224 sal_Bool bResult = m_bReadOnly;;
226 // do checks only if this was requested to be writable
227 if (m_bReadOnly)
229 // nothing to check
232 // try to ask the node itself
233 else if (m_xNode.is())
235 bResult = m_bReadOnly = isNodeReadOnly( m_xNode );
238 // else use the parent
239 else if (m_xParentNode.is())
241 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > xParentInfo = implGetParentPropertyInfo();
243 if (xParentInfo.is())
245 com::sun::star::beans::Property aProperty = xParentInfo->getPropertyByName(m_sLocalName);
247 bResult = m_bReadOnly = ((aProperty.Attributes & com::sun::star::beans::PropertyAttribute::READONLY) != 0);
249 else
251 // no property info about this key ? - check if the parent itself is writable
253 // NOTE: do not set m_bReadOnly here, as we haven't really found out about this object
254 bResult = isNodeReadOnly( m_xParentNode );
257 else
259 // no data at all
260 OSL_ENSURE(false, "implIsReadOnly called for invalid object");
261 bResult = true; // no object is certainly not writable ;-)
264 return bResult;
266 //--------------------------------------------------------------------------
268 sal_Bool OConfigurationRegistryKey::implEnsureNode() throw (com::sun::star::registry::InvalidRegistryException,com::sun::star::uno::RuntimeException)
270 if (!m_xNode.is())
272 OSL_ENSURE( m_xParentNode.is(), "implEnsureNode called for invalid registry key");
273 if (m_xParentNode.is())
277 com::sun::star::uno::Any aNode = m_xParentNode->getByName( m_sLocalName );
279 if ( !(aNode >>= m_xNode) )
280 OSL_ENSURE( ! (aNode.hasValue() && aNode.getValueTypeClass() == com::sun::star::uno::TypeClass_INTERFACE),
281 "OConfigurationRegistryKey: Node object does not implement expected interface");
283 catch (com::sun::star::container::NoSuchElementException& e)
285 m_xParentNode.clear();
287 rtl::OUString sMessage = UNISTRING("Invalid OConfigurationRegistryKey. The node \"");
288 sMessage += m_sLocalName;
289 sMessage += UNISTRING("\" was not found in the parent. Parent error message: \n");
290 sMessage += e.Message;
292 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
296 return m_xNode.is();
298 //--------------------------------------------------------------------------
300 com::sun::star::uno::Type OConfigurationRegistryKey::implGetUnoType() throw (com::sun::star::uno::RuntimeException)
302 com::sun::star::uno::Type aType;
303 if (m_xNode.is())
305 aType = getCppuType(&m_xNode); // Its just an interface type
307 else if (m_xParentNode.is())
310 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > xParentInfo = implGetParentPropertyInfo();
311 if (xParentInfo.is())
313 aType = xParentInfo->getPropertyByName( m_sLocalName ).Type;
315 else
317 aType = m_xParentNode->getElementType();
320 else
322 OSL_ASSERT( aType.getTypeClass() == com::sun::star::uno::TypeClass_VOID );
323 OSL_ENSURE( false, "implGetUnoType called for invalid registry key");
325 return aType;
327 //--------------------------------------------------------------------------
329 sal_Bool OConfigurationRegistryKey::implEnsureValue() throw (com::sun::star::uno::RuntimeException)
331 if (m_xNode.is())
332 return false;
334 OSL_ENSURE( m_xParentNode.is(), "implEnsureValue called for invalid registry key");
335 if (!m_xParentNode.is())
336 return false;
338 switch (implGetUnoType().getTypeClass())
340 case com::sun::star::uno::TypeClass_INTERFACE:
341 return false;
343 case com::sun::star::uno::TypeClass_BYTE:
344 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT:
345 case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
346 case com::sun::star::uno::TypeClass_UNSIGNED_HYPER:
347 case com::sun::star::uno::TypeClass_FLOAT:
348 OSL_ENSURE(false, "Unexpected (UNSIGNED INTERGRAL or FLOAT) type found for configuration node");
350 case com::sun::star::uno::TypeClass_STRING:
351 case com::sun::star::uno::TypeClass_BOOLEAN:
352 case com::sun::star::uno::TypeClass_SHORT:
353 case com::sun::star::uno::TypeClass_LONG:
354 case com::sun::star::uno::TypeClass_HYPER:
355 case com::sun::star::uno::TypeClass_DOUBLE:
356 case com::sun::star::uno::TypeClass_SEQUENCE:
357 return true;
359 case com::sun::star::uno::TypeClass_ANY:
360 return true;
362 case com::sun::star::uno::TypeClass_VOID:
363 OSL_ENSURE(false, "OConfigurationRegistryKey: Key does not exist or has VOID type");
364 return false;
366 default:
367 OSL_ENSURE(false, "OConfigurationRegistryKey: Key has unexpected UNO type (class)");
368 return false;
371 //--------------------------------------------------------------------------
373 sal_Bool OConfigurationRegistryKey::implIsValid() throw ()
375 return m_xNode.is() || (m_xParentNode.is() && m_xParentNode->hasByName( m_sLocalName ) );
377 //--------------------------------------------------------------------------
379 void OConfigurationRegistryKey::checkValid(KEY_ACCESS_TYPE _eIntentedAccess) throw (com::sun::star::registry::InvalidRegistryException,com::sun::star::uno::RuntimeException)
381 if (!implIsValid())
382 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The registry is not bound to a configuration node anymore."), THISREF());
383 // "anymore", because at the moment the ctor was called it probably was bound ....
385 switch (_eIntentedAccess)
387 case KAT_VALUE_WRITE:
388 if (implIsReadOnly())
389 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This configuration node is not writeable."), THISREF());
391 // !!! NO !!! BREAK !!!
392 case KAT_VALUE:
393 if (m_xNode.is())
394 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This configuration node is not a value, but an internal container."), THISREF());
396 if (!m_xParentNode.is())
397 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This configuration node is invalid. It has no parent."), THISREF());
399 if (!implEnsureValue())
400 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This configuration does not have a legal value type."), THISREF());
401 break;
403 case KAT_CHILD:
404 if (!implEnsureNode())
405 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This configuration node does not have children, it is a value node."), THISREF());
406 break;
408 case KAT_META:
409 break;
413 //--------------------------------------------------------------------------
414 com::sun::star::uno::Any OConfigurationRegistryKey::implCreateDefaultElement(com::sun::star::uno::Type const& _aValueType) throw (com::sun::star::uno::RuntimeException)
416 com::sun::star::uno::Any aReturn;
418 switch (_aValueType.getTypeClass())
420 case com::sun::star::uno::TypeClass_STRING:
421 aReturn <<= rtl::OUString();
422 break;
424 // we don't distinguish between the different integer types or boolean
425 // (the RegistryKeyType is not granular enough),
426 // but we can't handle them all the same way here
427 case com::sun::star::uno::TypeClass_BYTE:
428 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT:
429 case com::sun::star::uno::TypeClass_SHORT:
430 aReturn <<= (sal_Int16)0;
431 break;
433 case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
434 case com::sun::star::uno::TypeClass_LONG:
435 aReturn <<= (sal_Int32)0;
436 break;
438 case com::sun::star::uno::TypeClass_BOOLEAN:
439 aReturn <<= sal_Bool(false);
440 break;
442 // we cannot really handle 64-bit ints in the registry (but here we can)
443 case com::sun::star::uno::TypeClass_UNSIGNED_HYPER:
444 case com::sun::star::uno::TypeClass_HYPER:
445 OSL_ENSURE(false, "Warning: cannot handle 64-bit values correctly in registry");
446 aReturn <<= (sal_Int64)0;
447 break;
449 // we cannot really handle doubles in the registry (but here we can)
450 case com::sun::star::uno::TypeClass_FLOAT:
451 case com::sun::star::uno::TypeClass_DOUBLE:
452 OSL_ENSURE(false, "Warning: cannot handle DOUBLE correctly in registry");
453 aReturn <<= (double)0;
454 break;
456 // we really want to leave an Any as NULL - hopefully this is acceptable to the set
457 case com::sun::star::uno::TypeClass_ANY:
458 break;
460 case com::sun::star::uno::TypeClass_SEQUENCE:
461 if (_aValueType == getBinaryDataType())
462 aReturn <<= com::sun::star::uno::Sequence< sal_Int8 >();
464 else
466 com::sun::star::uno::Type aElementType = getSequenceElementType(_aValueType);
467 switch (aElementType.getTypeClass())
469 case com::sun::star::uno::TypeClass_STRING:
470 aReturn <<= com::sun::star::uno::Sequence< rtl::OUString >();
471 break;
473 case com::sun::star::uno::TypeClass_BYTE:
474 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT:
475 case com::sun::star::uno::TypeClass_SHORT:
476 aReturn <<= com::sun::star::uno::Sequence< sal_Int16 >();
477 break;
479 case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
480 case com::sun::star::uno::TypeClass_LONG:
481 aReturn <<= com::sun::star::uno::Sequence< sal_Int32 >();
482 break;
484 case com::sun::star::uno::TypeClass_BOOLEAN:
485 aReturn <<= com::sun::star::uno::Sequence< sal_Bool >();
486 break;
488 case com::sun::star::uno::TypeClass_UNSIGNED_HYPER:
489 case com::sun::star::uno::TypeClass_HYPER:
490 aReturn <<= com::sun::star::uno::Sequence< sal_Int64 >();
491 break;
493 case com::sun::star::uno::TypeClass_FLOAT:
494 case com::sun::star::uno::TypeClass_DOUBLE:
495 aReturn <<= com::sun::star::uno::Sequence< double >();
496 break;
498 case com::sun::star::uno::TypeClass_SEQUENCE:
499 OSL_ENSURE(false, "Warning: cannot handle Sequence< BINARY > correctly in registry");
500 if (aElementType == getBinaryDataType())
502 OSL_ENSURE(false, "Warning: cannot handle Sequence< BINARY > correctly in registry");
503 aReturn <<= com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< sal_Int8 > >();
504 break;
507 // else FALL THRU to default
508 default:
509 OSL_ENSURE(false, "Unexpected sequence element type for configuration node - returning NULL");
510 // throw here ??
511 break;
514 break;
516 case com::sun::star::uno::TypeClass_INTERFACE:
517 OSL_ENSURE(false, "Invalid call to OConfigurationRegistryKey::implCreateDefaultElement. Inner nodes must be created by a factory");
518 break;
520 default:
521 OSL_ENSURE(false, "Unexpected value type for configuration node - returning NULL");
522 // throw here ??
523 break;
526 OSL_ENSURE( aReturn.getValueType() == _aValueType || (_aValueType.getTypeClass() == com::sun::star::uno::TypeClass_ANY && !aReturn.hasValue()),
527 "Warning: Unexpected data type found in Registry - returning similar value or NULL");
528 return aReturn;
531 //--------------------------------------------------------------------------
532 com::sun::star::uno::Any OConfigurationRegistryKey::implGetDescendant(const rtl::OUString& _rDescendantName) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
534 com::sun::star::uno::Any aElementReturn;
538 if (!m_xNode.is())
540 // implEnsureNode should have been called before this method
541 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getDescendant : invalid call !");
543 // this method should not be called if the object does not represent a container node ...
544 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("invalid object."), THISREF());
549 // look for a local member first
550 aElementReturn = m_xNode->getByName(_rDescendantName);
552 catch(com::sun::star::container::NoSuchElementException&)
554 // is it a (possibly) hierarchical name ?
555 if ( _rDescendantName.indexOf('/') <0 ) throw;
557 // Yes, so try deep access
558 com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess > xDeepAccess( m_xNode, com::sun::star::uno::UNO_QUERY );
559 if (!xDeepAccess.is())
560 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("Nested element access not supported by this node."), THISREF());
562 aElementReturn = xDeepAccess->getByHierarchicalName(_rDescendantName);
565 catch(com::sun::star::container::NoSuchElementException&)
566 { // not allowed to leave the method, wrap it
567 rtl::OUString sMessage(UNISTRING("There is no element named "));
568 sMessage += _rDescendantName;
569 sMessage += UNISTRING(".");
570 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
572 catch(com::sun::star::lang::WrappedTargetException& wte)
573 { // allowed to be thrown by XNameAccess::getByName, but not allowed to leave this method
574 rtl::OUString sMessage(UNISTRING("The configuration node could not provide an element for "));
575 sMessage += _rDescendantName;
576 sMessage += UNISTRING(". Original Error: ");
577 sMessage += wte.Message;
578 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
581 return aElementReturn;
584 //--------------------------------------------------------------------------
585 void OConfigurationRegistryKey::implSetValue(const com::sun::star::uno::Any& _rValue) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
587 checkValid(KAT_VALUE_WRITE);
589 // one possible interface
590 com::sun::star::uno::Reference< com::sun::star::container::XNameReplace > xParentValueAccess(m_xParentNode, com::sun::star::uno::UNO_QUERY);
591 if (xParentValueAccess.is())
595 xParentValueAccess->replaceByName(m_sLocalName, _rValue);
597 catch(com::sun::star::lang::IllegalArgumentException& iae)
599 rtl::OUString sMessage = UNISTRING("Unable to replace the old value. The configuration node threw an ");
600 sMessage += UNISTRING("IllegalArgumentException: ");
601 sMessage += iae.Message;
602 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
604 catch(com::sun::star::container::NoSuchElementException& nse)
606 OSL_ENSURE(false, "OConfigurationRegistryKey::writeValueNode : a NoSuchElementException should be impossible !");
608 rtl::OUString sMessage = UNISTRING("Unable to replace the old value. The configuration node threw an ");
609 sMessage += UNISTRING("NoSuchElementException: ");
610 sMessage += nse.Message;
611 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
613 catch(com::sun::star::lang::WrappedTargetException& wte)
615 rtl::OUString sMessage = UNISTRING("Unable to replace the old value. The configuration node threw an ");
616 sMessage += UNISTRING("WrappedTargetException: ");
617 sMessage += wte.Message;
618 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
620 return;
623 // not found - try other interface
624 com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xParentPropertySet(m_xParentNode, com::sun::star::uno::UNO_QUERY);
625 if (xParentPropertySet.is())
629 xParentPropertySet->setPropertyValue(m_sLocalName, _rValue);
631 catch(com::sun::star::lang::IllegalArgumentException& iae)
633 rtl::OUString sMessage = UNISTRING("Unable to set a new value. The configuration node threw an ");
634 sMessage += UNISTRING("IllegalArgumentException: ");
635 sMessage += iae.Message;
636 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
638 catch(com::sun::star::beans::UnknownPropertyException& upe)
640 OSL_ENSURE(false, "OConfigurationRegistryKey::writeValueNode : a UnknownPropertyException should be impossible !");
642 rtl::OUString sMessage = UNISTRING("Unable to set a new value. The configuration node threw an ");
643 sMessage += UNISTRING("UnknownPropertyException: ");
644 sMessage += upe.Message;
645 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
647 catch(com::sun::star::beans::PropertyVetoException& pve)
649 rtl::OUString sMessage = UNISTRING("Unable to set a new value. The configuration node threw an ");
650 sMessage += UNISTRING("PropertyVetoException: ");
651 sMessage += pve.Message;
652 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
654 catch(com::sun::star::lang::WrappedTargetException& wte)
656 rtl::OUString sMessage = UNISTRING("Unable to set a new value. The configuration node threw an ");
657 sMessage += UNISTRING("WrappedTargetException: ");
658 sMessage += wte.Message;
659 throw com::sun::star::registry::InvalidRegistryException(sMessage, THISREF());
661 return;
664 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("No interface found on parent node for writing to configuration value node."), THISREF());
667 //--------------------------------------------------------------------------
668 ::rtl::OUString SAL_CALL OConfigurationRegistryKey::getKeyName() throw(com::sun::star::uno::RuntimeException)
670 return m_sLocalName;
673 //--------------------------------------------------------------------------
674 sal_Bool SAL_CALL OConfigurationRegistryKey::isReadOnly() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
676 OSL_ASSERT(UnoApiLock::isHeld());
677 checkValid(KAT_META);
678 return m_bReadOnly;
681 //--------------------------------------------------------------------------
682 sal_Bool SAL_CALL OConfigurationRegistryKey::isValid() throw(com::sun::star::uno::RuntimeException)
684 OSL_ASSERT(UnoApiLock::isHeld());
685 // TODO : perhaps if the registry we're a part of is closed ....
686 return implIsValid();
689 //--------------------------------------------------------------------------
690 com::sun::star::registry::RegistryKeyType SAL_CALL OConfigurationRegistryKey::getKeyType( const ::rtl::OUString& /*_rKeyName*/ ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
692 OSL_ASSERT(UnoApiLock::isHeld());
694 // no further checks are made (for performance reasons) ...
695 // Maybe we should check only KAT_META for consistency ?
696 checkValid(KAT_CHILD);
698 return com::sun::star::registry::RegistryKeyType_KEY;
701 //--------------------------------------------------------------------------
702 com::sun::star::registry::RegistryValueType SAL_CALL OConfigurationRegistryKey::getValueType() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
704 checkValid(KAT_META);
706 const com::sun::star::uno::Type aUnoType = implGetUnoType();
708 switch (aUnoType.getTypeClass())
710 case com::sun::star::uno::TypeClass_INTERFACE: // this is really a case of 'no value type'
711 return com::sun::star::registry::RegistryValueType_NOT_DEFINED;
713 case com::sun::star::uno::TypeClass_ANY: // this is really a case of 'all value types allowed'
714 return com::sun::star::registry::RegistryValueType_NOT_DEFINED;
716 case com::sun::star::uno::TypeClass_STRING:
717 return com::sun::star::registry::RegistryValueType_STRING;
719 case com::sun::star::uno::TypeClass_BYTE:
720 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT:
721 case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
722 OSL_ENSURE(false, "Unexpected UNSIGNED type found for configuration node");
723 // FALL THRU
725 case com::sun::star::uno::TypeClass_BOOLEAN:
726 case com::sun::star::uno::TypeClass_SHORT:
727 case com::sun::star::uno::TypeClass_LONG:
728 return com::sun::star::registry::RegistryValueType_LONG;
730 case com::sun::star::uno::TypeClass_FLOAT:
731 case com::sun::star::uno::TypeClass_DOUBLE:
732 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support floating point numbers !");
733 return com::sun::star::registry::RegistryValueType_LONG;
735 case com::sun::star::uno::TypeClass_UNSIGNED_HYPER:
736 case com::sun::star::uno::TypeClass_HYPER:
737 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support 64-bit integer numbers !");
738 return com::sun::star::registry::RegistryValueType_LONG;
740 case com::sun::star::uno::TypeClass_SEQUENCE:
741 if ( aUnoType.equals( getBinaryDataType() ) )
742 return com::sun::star::registry::RegistryValueType_BINARY;
744 else
746 com::sun::star::uno::Type aElementType = getSequenceElementType(aUnoType);
748 switch (aElementType.getTypeClass())
750 case com::sun::star::uno::TypeClass_STRING:
751 return com::sun::star::registry::RegistryValueType_STRINGLIST;
753 case com::sun::star::uno::TypeClass_BYTE:
754 OSL_ASSERT(false); // this is caught by the 'binary' case
756 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT:
757 case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
758 OSL_ENSURE(false, "Unexpected UNSIGNED-List type found for configuration node");
759 // FALL THRU
761 case com::sun::star::uno::TypeClass_BOOLEAN:
762 case com::sun::star::uno::TypeClass_SHORT:
763 case com::sun::star::uno::TypeClass_LONG:
764 return com::sun::star::registry::RegistryValueType_LONGLIST;
766 case com::sun::star::uno::TypeClass_FLOAT:
767 case com::sun::star::uno::TypeClass_DOUBLE:
768 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support floating point number lists !");
769 return com::sun::star::registry::RegistryValueType_LONGLIST;
771 case com::sun::star::uno::TypeClass_UNSIGNED_HYPER:
772 case com::sun::star::uno::TypeClass_HYPER:
773 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : registry does not support 64-bit integer number lists !");
774 return com::sun::star::registry::RegistryValueType_LONGLIST;
776 case com::sun::star::uno::TypeClass_ANY:
777 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : Unexpected: Any as sequence element type !");
778 return com::sun::star::registry::RegistryValueType_NOT_DEFINED;
780 default:
781 if (aElementType.equals(getBinaryDataType()))
782 OSL_ENSURE(sal_False,"OConfigurationRegistryKey::getValueType : Registry cannot support LIST of BINARY");
783 else
784 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : unknown sequence element type !");
786 return com::sun::star::registry::RegistryValueType_NOT_DEFINED;
790 default:
791 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::getValueType : unknown entry type !");
792 return com::sun::star::registry::RegistryValueType_NOT_DEFINED;
796 //--------------------------------------------------------------------------
798 com::sun::star::uno::Any OConfigurationRegistryKey::implGetValue() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
800 checkValid(KAT_VALUE);
802 return m_xParentNode->getByName( m_sLocalName );
805 //--------------------------------------------------------------------------
806 sal_Int32 SAL_CALL OConfigurationRegistryKey::getLongValue() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::registry::InvalidValueException, com::sun::star::uno::RuntimeException)
808 com::sun::star::uno::Any aValue = implGetValue();
810 sal_Int32 nLongValue(0);
811 switch (aValue.getValueTypeClass())
813 // integral types that are small enough are straightforward
814 case com::sun::star::uno::TypeClass_BYTE : { sal_Int8 nNativeValue = 0; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
815 case com::sun::star::uno::TypeClass_BOOLEAN : { sal_Bool nNativeValue = false; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
816 case com::sun::star::uno::TypeClass_SHORT : { sal_Int16 nNativeValue; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
817 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT : { sal_uInt16 nNativeValue; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
818 case com::sun::star::uno::TypeClass_LONG : { sal_Int32 nNativeValue; aValue >>= nNativeValue; nLongValue = nNativeValue; } break;
820 // this is lossless, but not value-preserving - use cast to avoid warnings
821 case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
823 sal_uInt32 nNativeValue;
824 aValue >>= nNativeValue;
825 nLongValue = sal_Int32(nNativeValue);
827 break;
829 // the following are larger than Long - check for loss and throw if applicable
830 case com::sun::star::uno::TypeClass_HYPER:
832 sal_Int64 nNativeValue;
833 aValue >>= nNativeValue;
834 nLongValue = sal_Int32(nNativeValue);
836 // check for data loss
837 if (sal_Int64(nLongValue) != nNativeValue)
838 throw com::sun::star::registry::InvalidValueException(UNISTRING("Unsigned Hyper value too large for long; Value cannot be retrieved using registry."), THISREF());
840 break;
842 case com::sun::star::uno::TypeClass_UNSIGNED_HYPER:
844 sal_uInt64 nNativeValue;
845 aValue >>= nNativeValue;
846 nLongValue = sal_Int32(nNativeValue);
848 // check for data loss
849 if (sal_uInt64(sal_uInt32(nLongValue)) != nNativeValue)
850 throw com::sun::star::registry::InvalidValueException(UNISTRING("Unsigned Hyper value too large for long; Value cannot be retrieved using registry."), THISREF());
852 break;
854 // for floating point types we need a limit for loss checking
855 case com::sun::star::uno::TypeClass_FLOAT:
856 OSL_ENSURE(false, "Unexpected type FLOAT in configuration node");
858 // treat as double
859 float fNativeValue = 0;
860 if (aValue >>= fNativeValue)
861 aValue <<= double(fNativeValue);
863 // fall thru
865 case com::sun::star::uno::TypeClass_DOUBLE:
867 double fNativeValue = 0;
868 aValue >>= fNativeValue;
870 // find a reasonable allowed imprecision
871 const double fEps = (2.*fNativeValue + 5.) * std::numeric_limits<double>::epsilon();
873 // should be rounding here
874 nLongValue = sal_Int32(fNativeValue);
876 // check for data loss
877 bool bRecheck = false;
879 double diff = fNativeValue-double(nLongValue);
880 if ( diff > fEps)
882 // substitute for rounding here
883 if (diff > .5)
885 ++nLongValue;
886 diff = fNativeValue-double(nLongValue);
888 bRecheck = true;
890 else if ( diff < -fEps)
892 // substitute for rounding here
893 if (diff < -.5)
895 --nLongValue;
896 diff = fNativeValue-double(nLongValue);
898 bRecheck = true;
901 if (bRecheck)
903 if (diff > fEps || diff < -fEps)
904 throw com::sun::star::registry::InvalidValueException(UNISTRING("Double value cannot fit in Long; Value cannot be retrieved using registry."), THISREF());
907 break;
909 case com::sun::star::uno::TypeClass_VOID:
910 // allow NULL values, if we maybe advertise this node as long
911 if (this->getValueType() == com::sun::star::registry::RegistryValueType_LONG)
912 break;
913 // else FALL THRU to exception
915 default:
916 throw com::sun::star::registry::InvalidValueException(UNISTRING("This node does not contain a long (or a compatible) value."), THISREF());
918 return nLongValue;
921 //--------------------------------------------------------------------------
922 void SAL_CALL OConfigurationRegistryKey::setLongValue( sal_Int32 _nValue ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
924 implSetValue(com::sun::star::uno::makeAny(_nValue));
927 //--------------------------------------------------------------------------
928 com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL OConfigurationRegistryKey::getLongListValue() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::registry::InvalidValueException, com::sun::star::uno::RuntimeException)
930 com::sun::star::uno::Any aValue = implGetValue();
932 com::sun::star::uno::Sequence< sal_Int32 > aReturn;
933 if (!aValue.hasValue())
934 checkNullable();// let NULL values pass
936 else if (!(aValue >>= aReturn))
938 // TODO : maybe it's a sequence of sal_Int8 or anything like that which we're able to convert ....
940 throw com::sun::star::registry::InvalidValueException(UNISTRING("This configuration node does not contain a list of longs !"), THISREF());
943 return aReturn;
946 //--------------------------------------------------------------------------
947 void SAL_CALL OConfigurationRegistryKey::setLongListValue( const com::sun::star::uno::Sequence< sal_Int32 >& _seqValue ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
949 implSetValue(com::sun::star::uno::makeAny(_seqValue));
952 //--------------------------------------------------------------------------
953 rtl::OUString SAL_CALL OConfigurationRegistryKey::getAsciiValue() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::registry::InvalidValueException, com::sun::star::uno::RuntimeException)
955 rtl::OUString sReturn = getStringValue();
957 if (!isAscii(sReturn))
958 throw com::sun::star::registry::InvalidValueException(UNISTRING("This configuration node value (a string) is not pure ASCII !"), THISREF());
960 return sReturn;
963 //--------------------------------------------------------------------------
964 void SAL_CALL OConfigurationRegistryKey::setAsciiValue( const ::rtl::OUString& _rValue ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
966 OSL_ENSURE( isAscii(_rValue), "The string passesd to OConfigurationRegistryKey::setAsciiValue is not pure ASCII");
968 setStringValue(_rValue);
971 //--------------------------------------------------------------------------
972 com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL OConfigurationRegistryKey::getAsciiListValue() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::registry::InvalidValueException, com::sun::star::uno::RuntimeException)
974 com::sun::star::uno::Sequence<rtl::OUString> aReturn = getStringListValue();
976 if (!isAscii(aReturn))
977 throw com::sun::star::registry::InvalidValueException(UNISTRING("This configuration node value (a string list) is not pure ASCII !"), THISREF());
979 return aReturn;
982 //--------------------------------------------------------------------------
983 void SAL_CALL OConfigurationRegistryKey::setAsciiListValue( const com::sun::star::uno::Sequence< ::rtl::OUString >& _seqValue ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
985 OSL_ENSURE( isAscii(_seqValue), "The string passesd to OConfigurationRegistryKey::setAsciiValue is not pure ASCII");
987 setStringListValue(_seqValue);
990 //--------------------------------------------------------------------------
991 ::rtl::OUString SAL_CALL OConfigurationRegistryKey::getStringValue() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::registry::InvalidValueException, com::sun::star::uno::RuntimeException)
993 com::sun::star::uno::Any aValue = implGetValue();
995 rtl::OUString sReturn;
996 if (!aValue.hasValue())
997 checkNullable();// let NULL values pass
999 else if (!(aValue >>= sReturn))
1000 throw com::sun::star::registry::InvalidValueException(UNISTRING("This node does not contain a string value."), THISREF());
1002 return sReturn;
1005 //--------------------------------------------------------------------------
1006 void SAL_CALL OConfigurationRegistryKey::setStringValue( const ::rtl::OUString& _rValue ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1008 implSetValue(com::sun::star::uno::makeAny(_rValue));
1011 //--------------------------------------------------------------------------
1012 com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OConfigurationRegistryKey::getStringListValue() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::registry::InvalidValueException, com::sun::star::uno::RuntimeException)
1014 com::sun::star::uno::Any aValue = implGetValue();
1016 com::sun::star::uno::Sequence< rtl::OUString > aReturn;
1017 if (!aValue.hasValue())
1018 checkNullable();// let NULL values pass
1020 else if (!(aValue >>= aReturn))
1021 throw com::sun::star::registry::InvalidValueException(UNISTRING("This configuration node does not contain a list of strings !"), THISREF());
1023 return aReturn;
1026 //--------------------------------------------------------------------------
1027 void SAL_CALL OConfigurationRegistryKey::setStringListValue( const com::sun::star::uno::Sequence< ::rtl::OUString >& _seqValue ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1029 implSetValue(com::sun::star::uno::makeAny(_seqValue));
1032 //--------------------------------------------------------------------------
1033 com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL OConfigurationRegistryKey::getBinaryValue() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::registry::InvalidValueException, com::sun::star::uno::RuntimeException)
1035 com::sun::star::uno::Any aValue = implGetValue();
1037 com::sun::star::uno::Sequence< sal_Int8 > aReturn;
1038 if (!aValue.hasValue())
1039 checkNullable();// let NULL values pass
1041 else if (!(aValue >>= aReturn))
1042 return aReturn;
1044 throw com::sun::star::registry::InvalidValueException(UNISTRING("This configuration node does not contain a list of strings !"), THISREF());
1047 //--------------------------------------------------------------------------
1048 void SAL_CALL OConfigurationRegistryKey::setBinaryValue( const com::sun::star::uno::Sequence< sal_Int8 >& _rValue ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1050 implSetValue(com::sun::star::uno::makeAny(_rValue));
1053 //--------------------------------------------------------------------------
1054 com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > OConfigurationRegistryKey::implGetKey( const ::rtl::OUString& _rKeyName )
1055 throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1057 com::sun::star::uno::Any aDescendant = implGetDescendant(_rKeyName);
1058 if (aDescendant.getValueType().getTypeClass() == com::sun::star::uno::TypeClass_INTERFACE)
1060 com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > xNode;
1061 ::cppu::extractInterface(xNode, aDescendant);
1062 if (!xNode.is())
1063 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("invalid descendant node. No XNameAccess found."), THISREF());
1064 return new OConfigurationRegistryKey(xNode, !m_bReadOnly);
1066 else
1068 #if OSL_DEBUG_LEVEL > 1
1069 switch (aDescendant.getValueType().getTypeClass())
1071 case com::sun::star::uno::TypeClass_STRING:
1072 case com::sun::star::uno::TypeClass_SHORT:
1073 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT:
1074 case com::sun::star::uno::TypeClass_BYTE:
1075 case com::sun::star::uno::TypeClass_LONG:
1076 case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
1077 case com::sun::star::uno::TypeClass_BOOLEAN:
1078 case com::sun::star::uno::TypeClass_SEQUENCE:
1079 break;
1080 case com::sun::star::uno::TypeClass_VOID: // NULL value found
1081 break;
1082 default:
1083 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::openKey : unknown, invalid or unhandled descendant value type !");
1085 #endif
1087 OSL_ASSERT(m_xNode.is());
1089 com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > xDescParent(m_xNode); // the parent config node of the descandent
1090 rtl::OUString sDescRelativeName( _rKeyName ); // local name of the descendant within xDescParent
1092 if (!m_xNode->hasByName(_rKeyName)) // it is a hierarchical Path -> more work
1094 rtl::OUString sParentLocation;
1096 if ( !splitPath(_rKeyName, sParentLocation, sDescRelativeName) )
1098 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("Cannot split path for value. The internal registry structure seems to be corrupt."), THISREF());
1101 if (sParentLocation.getLength())
1103 com::sun::star::uno::Any aDescParent = implGetDescendant(sParentLocation);
1104 ::cppu::extractInterface(xDescParent, aDescParent);
1105 if (!xDescParent.is())
1106 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The internal registry structure seems to be corrupt."), THISREF());
1110 OSL_ENSURE(xDescParent.is(), "No Parent Node found for value ?");
1111 OSL_ENSURE(xDescParent->hasByName(sDescRelativeName), "Parent Node does not contain found value ?");
1113 return new OConfigurationRegistryKey(aDescendant, xDescParent, sDescRelativeName, !m_bReadOnly);
1117 //--------------------------------------------------------------------------
1118 com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > SAL_CALL OConfigurationRegistryKey::openKey( const ::rtl::OUString& _rKeyName ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1120 checkValid(KAT_CHILD);
1122 return implGetKey(_rKeyName);
1124 //--------------------------------------------------------------------------
1125 bool OConfigurationRegistryKey::checkRelativeKeyName(rtl::OUString& _rKeyName) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1127 // no empty names allowed
1128 if (!_rKeyName.getLength())
1129 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The key name is invalid."), THISREF());
1131 bool bCleanPath = true;
1133 // cut trailing slashes
1134 sal_Int32 nCleanEnd = _rKeyName.getLength();
1135 while (nCleanEnd > 0 && _rKeyName[nCleanEnd - 1] == '/' )
1136 --nCleanEnd;
1138 if (m_xNode.is())
1140 if (m_xNode-> hasByName(_rKeyName))
1142 bCleanPath = false;
1145 else
1147 com::sun::star::uno::Reference< com::sun::star::util::XStringEscape > xSE(m_xNode, com::sun::star::uno::UNO_QUERY);
1149 sal_Bool bPreferLocal = xSE.is();
1151 if (!bPreferLocal)
1153 com::sun::star::uno::Reference< com::sun::star::lang::XServiceInfo > xSI(m_xNode, com::sun::star::uno::UNO_QUERY);
1154 if (xSI.is() && xSI->supportsService(rtl::OUString::createFromAscii("com.sun.star.configuration.SetAccess")))
1155 bPreferLocal = true;
1158 if (bPreferLocal)
1160 com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess > xHA(m_xNode, com::sun::star::uno::UNO_QUERY);
1161 rtl::OUString sCleanName = _rKeyName.copy(0, nCleanEnd);
1163 if (xHA.is() && xHA->hasByHierarchicalName(sCleanName))
1164 bPreferLocal = false;
1167 if (bPreferLocal && xSE.is())
1169 _rKeyName = xSE->escapeString(_rKeyName);
1171 bCleanPath = !bPreferLocal;
1175 if (bCleanPath)
1177 // no absolute names ("/...") allowed
1178 if (_rKeyName.getStr()[0] == '/')
1179 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The key name is invalid. It must be a relative, not an absolute name."), THISREF());
1181 if (nCleanEnd <= 0)
1182 // the original name consists of slashes only
1183 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The key name is invalid."), THISREF());
1186 _rKeyName = _rKeyName.copy(0, nCleanEnd);
1188 return bCleanPath;
1191 //--------------------------------------------------------------------------
1192 com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > SAL_CALL OConfigurationRegistryKey::createKey( const ::rtl::OUString& _rKeyName ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1194 checkValid(KAT_CHILD);
1196 if (m_bReadOnly)
1197 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The key is read only."), THISREF());
1199 OSL_ENSURE(m_xNode.is(), "OConfigurationRegistryKey::createKey : somebody changed the checkValid(KAT_CHILD) behaviour !");
1201 rtl::OUString sKeyName(_rKeyName);
1202 if (checkRelativeKeyName(sKeyName))
1204 rtl::OUString sParentName, sLocalName;
1206 if (!splitPath(sKeyName,sParentName, sLocalName))
1207 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The key name is invalid."), THISREF());
1209 if (sParentName.getLength()) // it's a nested key name
1211 // check if we have the key already
1212 com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess > xDeepAccess(m_xNode, com::sun::star::uno::UNO_QUERY);
1213 if (xDeepAccess.is() && xDeepAccess->hasByHierarchicalName(sKeyName))
1215 // already there - just open it
1216 return implGetKey(sKeyName);
1219 // deep access, but not found. delegate it to a registry key which is one level above the to-be-created one
1220 com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > xSetNode = implGetKey(sParentName);
1221 if (!xSetNode.is())
1223 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::createKey : somebody changed the implGetKey behaviour !");
1224 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("An internal error occured."), THISREF());
1226 return xSetNode->createKey(sLocalName); // problem: request for a/['b/c'] might find a/b/c
1228 else
1229 sKeyName = sLocalName;
1232 // The requested new key is one level below ourself. Can't delegate the creation.
1233 if (m_xNode->hasByName(sKeyName) )
1235 // already there - just open it
1236 return implGetKey(sKeyName);
1239 com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > xContainer(m_xNode, com::sun::star::uno::UNO_QUERY);
1240 if (!xContainer.is())
1241 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The configuration node represented by this key is not a set node, you can't insert keys."), THISREF());
1243 com::sun::star::uno::Any aValueToInsert;
1245 com::sun::star::uno::Reference< com::sun::star::lang::XSingleServiceFactory > xChildFactory(xContainer, com::sun::star::uno::UNO_QUERY);
1246 if (xChildFactory.is())
1248 // In the configuration API, the creation of a new child is two-stage process : first you create a child which
1249 // is "floating", i.e. does not belong to the configuration tree, yet. After filling it with values, you insert
1250 // it into the container node which was used for the creation.
1251 // We can't map this behaviour with the registry API, so we have to combine both steps
1253 // create a new floating child for the container node
1256 com::sun::star::uno::Reference< com::sun::star::uno::XInterface > xFloatingChild = xChildFactory->createInstance();
1257 OSL_ENSURE( xFloatingChild.is(), "The newly created element is NULL !");
1259 com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > xInsertedChild(xFloatingChild, com::sun::star::uno::UNO_QUERY);
1260 OSL_ENSURE( xInsertedChild.is(), "The newly created element does not provide the required interface");
1262 if (!xInsertedChild.is())
1263 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("An internal error occured. The objects provided by the configuration API are invalid."), THISREF());
1265 aValueToInsert <<= xInsertedChild; // xFloatingChild;
1267 catch (com::sun::star::uno::RuntimeException&)
1268 { // allowed to leave this method
1269 throw;
1271 catch (com::sun::star::uno::Exception& e)
1272 { // not allowed to leave this method
1273 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("Unable to create a new child for the configuration node. Original error message as provided by the configuration API : ") += e.Message,
1274 THISREF());
1276 OSL_ENSURE(aValueToInsert.hasValue(), "New Child node did not get into the Any ?");
1278 else
1280 // If the elements of the set are simple values, we need to create a matching value
1281 com::sun::star::uno::Type aElementType = xContainer->getElementType();
1282 aValueToInsert = implCreateDefaultElement(aElementType);
1284 OSL_ENSURE(aValueToInsert.hasValue() || aElementType.getTypeClass() == com::sun::star::uno::TypeClass_ANY, "Internal error: NULL value created for new value element ?");
1287 // and immediately insert it into the container
1290 xContainer->insertByName(sKeyName, aValueToInsert);
1292 catch (com::sun::star::lang::IllegalArgumentException& e)
1294 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("illegal argument to InsertByName: ") += e.Message, THISREF());
1296 catch (com::sun::star::container::ElementExistException& e)
1298 OSL_ENSURE(false, "There was an element of the same name inserted just now");
1300 // try to return that one
1301 try { return implGetKey(sKeyName); }
1302 catch (com::sun::star::uno::Exception&) { OSL_ENSURE(false, "But the other element cannot be retrieved"); }
1305 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("Inserting raised a NoSuchElementException for an unavailable element ! Original error message : ") += e.Message, THISREF());
1307 catch (com::sun::star::lang::WrappedTargetException& e)
1309 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("Inserting raised a WrappedTargetException. Original error message : ") += e.Message, THISREF());
1312 return new OConfigurationRegistryKey(aValueToInsert, m_xNode, sKeyName, !m_bReadOnly);
1315 //--------------------------------------------------------------------------
1316 void SAL_CALL OConfigurationRegistryKey::closeKey() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1318 OSL_ASSERT(UnoApiLock::isHeld());
1319 checkValid(KAT_META);
1321 bool bRoot = (m_sLocalName.getLength() == 0);
1323 if (!bRoot) // don't close, if this is the root key ..
1325 m_xNode.clear();
1326 m_xParentNode.clear();
1327 // m_sLocalName = rtl::OUString(); - local name is const ...
1331 //--------------------------------------------------------------------------
1332 void SAL_CALL OConfigurationRegistryKey::deleteKey( const rtl::OUString& _rKeyName ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1334 checkValid(KAT_CHILD);
1335 if (m_bReadOnly)
1336 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The key is read only."), THISREF());
1338 rtl::OUString sKeyName(_rKeyName);
1339 if (checkRelativeKeyName(sKeyName))
1341 rtl::OUString sParentName, sLocalName;
1343 if (!splitPath(sKeyName,sParentName, sLocalName))
1344 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The key name is invalid."), THISREF());
1346 if (sParentName.getLength()) // it's a nested key name
1348 com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > xSetNode = implGetKey(sParentName);
1349 if (!xSetNode.is())
1351 OSL_ENSURE(sal_False, "OConfigurationRegistryKey::createKey : somebody changed the implGetKey behaviour !");
1352 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("An internal error occured."), THISREF());
1354 xSetNode->deleteKey(sLocalName);
1355 return;
1357 else
1358 sKeyName = sLocalName;
1361 // The requested new key is one level below ourself. Can't delegate the creation.
1362 com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > xContainer(m_xNode, com::sun::star::uno::UNO_QUERY);
1363 if (!xContainer.is())
1364 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("The configuration node represented by this key is not a set node, you can't remove keys."), THISREF());
1366 // and immediately remove it from the container
1369 xContainer->removeByName(sKeyName);
1371 catch (com::sun::star::container::NoSuchElementException& e)
1373 if (e.Message.getLength())
1374 throw com::sun::star::registry::InvalidRegistryException(e.Message, THISREF());
1375 else
1376 throw com::sun::star::registry::InvalidRegistryException((UNISTRING("There is no element named ") += sKeyName) += UNISTRING(" to remove."), THISREF());
1378 catch (com::sun::star::lang::WrappedTargetException& e)
1380 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("Removing a node caused a WrappedTargetException. Original error message : ") += e.Message, THISREF());
1384 //--------------------------------------------------------------------------
1385 com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > > SAL_CALL OConfigurationRegistryKey::openKeys() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1387 checkValid(KAT_CHILD);
1389 com::sun::star::uno::Sequence< ::rtl::OUString > aNames(m_xNode->getElementNames());
1391 sal_Int32 const nCount = aNames.getLength();
1393 com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > > aReturn(nCount);
1395 for (sal_Int32 i=0; i<nCount; ++i)
1396 aReturn[i] = implGetKey(aNames[i]);
1398 return aReturn;
1401 //--------------------------------------------------------------------------
1402 com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OConfigurationRegistryKey::getKeyNames() throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1404 checkValid(KAT_CHILD);
1405 return m_xNode->getElementNames();
1408 //--------------------------------------------------------------------------
1409 sal_Bool SAL_CALL OConfigurationRegistryKey::createLink( const ::rtl::OUString& /*aLinkName*/, const ::rtl::OUString& /*aLinkTarget*/ ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1411 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This registry, which is base on a configuration tree, does not support links."), THISREF());
1414 //--------------------------------------------------------------------------
1415 void SAL_CALL OConfigurationRegistryKey::deleteLink( const ::rtl::OUString& /*rLinkName*/ ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1417 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This registry, which is base on a configuration tree, does not support links."), THISREF());
1420 //--------------------------------------------------------------------------
1421 ::rtl::OUString SAL_CALL OConfigurationRegistryKey::getLinkTarget( const ::rtl::OUString& /*rLinkName*/ ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1423 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This registry, which is base on a configuration tree, does not support links."), THISREF());
1426 //--------------------------------------------------------------------------
1427 ::rtl::OUString SAL_CALL OConfigurationRegistryKey::getResolvedName( const ::rtl::OUString& /*aKeyName*/ ) throw(com::sun::star::registry::InvalidRegistryException, com::sun::star::uno::RuntimeException)
1429 throw com::sun::star::registry::InvalidRegistryException(UNISTRING("This registry, which is base on a configuration tree, does not support links."), THISREF());
1431 //--------------------------------------------------------------------------
1432 //..........................................................................
1433 } // namespace configmgr
1434 //..........................................................................
1435 // split path
1436 #include "configpath.hxx"
1437 #include "configexcept.hxx"
1439 bool configmgr::splitPath(const rtl::OUString& _sPath, rtl::OUString& _rsParentPath, rtl::OUString& _rsLocalName)
1441 bool bResult = false;
1444 bool bAbsolute = configmgr::configuration::Path::isAbsolutePath(_sPath);
1445 configmgr::configuration::Path::Rep aPath ;
1447 if (bAbsolute)
1449 configmgr::configuration::AbsolutePath parsedPath = configmgr::configuration::AbsolutePath::parse(_sPath) ;
1451 aPath = parsedPath.rep() ;
1453 else
1455 configmgr::configuration::RelativePath parsedPath = configmgr::configuration::RelativePath::parse(_sPath) ;
1457 aPath = parsedPath.rep() ;
1459 //configmgr::configuration::Path::Rep aPath = bAbsolute ? configmgr::configuration::AbsolutePath::parse(_sPath).rep() : configmgr::configuration::RelativePath::parse(_sPath).rep();
1461 OSL_ENSURE(!aPath.isEmpty(), "Trying to split an empty or root path");
1462 std::vector<configuration::Path::Component>::const_reverse_iterator aFirst = aPath.begin(), aLast = aPath.end();
1464 if (aFirst != aLast)
1466 --aLast;
1468 _rsLocalName = aLast->getName();
1469 _rsParentPath = configmgr::configuration::Path::Rep(aFirst,aLast).toString(bAbsolute);
1471 bResult = true;
1473 // else go on to fail
1475 catch (configuration::Exception&)
1478 return bResult;
1480 //..........................................................................