Bump version to 4.3-4
[LibreOffice.git] / unotools / source / config / confignode.cxx
blobdfd10cb1c03121a9e068b7475dea3b59ff82dc9a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <unotools/confignode.hxx>
21 #include <unotools/configpaths.hxx>
22 #include <tools/diagnose_ex.h>
23 #include <osl/diagnose.h>
24 #include <com/sun/star/container/XHierarchicalName.hpp>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/configuration/theDefaultProvider.hpp>
27 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
28 #include <com/sun/star/lang/XComponent.hpp>
29 #include <com/sun/star/util/XStringEscape.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <com/sun/star/container/XNamed.hpp>
32 #include <comphelper/namedvaluecollection.hxx>
33 #include <rtl/string.hxx>
34 #if OSL_DEBUG_LEVEL > 0
35 #include <rtl/strbuf.hxx>
36 #endif
38 namespace utl
41 using namespace ::com::sun::star::uno;
42 using namespace ::com::sun::star::lang;
43 using namespace ::com::sun::star::util;
44 using namespace ::com::sun::star::beans;
45 using namespace ::com::sun::star::container;
46 using namespace ::com::sun::star::configuration;
48 //= OConfigurationNode
50 OConfigurationNode::OConfigurationNode(const Reference< XInterface >& _rxNode )
51 :m_bEscapeNames(false)
53 OSL_ENSURE(_rxNode.is(), "OConfigurationNode::OConfigurationNode: invalid node interface!");
54 if (_rxNode.is())
56 // collect all interfaces necessary
57 m_xHierarchyAccess = Reference< XHierarchicalNameAccess >(_rxNode, UNO_QUERY);
58 m_xDirectAccess = Reference< XNameAccess >(_rxNode, UNO_QUERY);
60 // reset _all_ interfaces if _one_ of them is not supported
61 if (!m_xHierarchyAccess.is() || !m_xDirectAccess.is())
63 m_xHierarchyAccess = NULL;
64 m_xDirectAccess = NULL;
67 // now for the non-critical interfaces
68 m_xReplaceAccess = Reference< XNameReplace >(_rxNode, UNO_QUERY);
69 m_xContainerAccess = Reference< XNameContainer >(_rxNode, UNO_QUERY);
72 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
73 if (xConfigNodeComp.is())
74 startComponentListening(xConfigNodeComp);
76 if (isValid())
77 setEscape(isSetNode());
80 OConfigurationNode::OConfigurationNode(const OConfigurationNode& _rSource)
81 :OEventListenerAdapter()
82 ,m_xHierarchyAccess(_rSource.m_xHierarchyAccess)
83 ,m_xDirectAccess(_rSource.m_xDirectAccess)
84 ,m_xReplaceAccess(_rSource.m_xReplaceAccess)
85 ,m_xContainerAccess(_rSource.m_xContainerAccess)
86 ,m_bEscapeNames(_rSource.m_bEscapeNames)
87 ,m_sCompletePath(_rSource.m_sCompletePath)
89 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
90 if (xConfigNodeComp.is())
91 startComponentListening(xConfigNodeComp);
94 const OConfigurationNode& OConfigurationNode::operator=(const OConfigurationNode& _rSource)
96 stopAllComponentListening();
98 m_xHierarchyAccess = _rSource.m_xHierarchyAccess;
99 m_xDirectAccess = _rSource.m_xDirectAccess;
100 m_xContainerAccess = _rSource.m_xContainerAccess;
101 m_xReplaceAccess = _rSource.m_xReplaceAccess;
102 m_bEscapeNames = _rSource.m_bEscapeNames;
103 m_sCompletePath = _rSource.m_sCompletePath;
105 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
106 if (xConfigNodeComp.is())
107 startComponentListening(xConfigNodeComp);
109 return *this;
112 void OConfigurationNode::_disposing( const EventObject& _rSource )
114 Reference< XComponent > xDisposingSource(_rSource.Source, UNO_QUERY);
115 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
116 if (xDisposingSource.get() == xConfigNodeComp.get())
117 clear();
120 OUString OConfigurationNode::getLocalName() const
122 OUString sLocalName;
125 Reference< XNamed > xNamed( m_xDirectAccess, UNO_QUERY_THROW );
126 sLocalName = xNamed->getName();
128 catch( const Exception& )
130 DBG_UNHANDLED_EXCEPTION();
132 return sLocalName;
135 OUString OConfigurationNode::getNodePath() const
137 OUString sNodePath;
140 Reference< XHierarchicalName > xNamed( m_xDirectAccess, UNO_QUERY_THROW );
141 sNodePath = xNamed->getHierarchicalName();
143 catch( const Exception& )
145 DBG_UNHANDLED_EXCEPTION();
147 return sNodePath;
150 OUString OConfigurationNode::normalizeName(const OUString& _rName, NAMEORIGIN _eOrigin) const
152 OUString sName(_rName);
153 if (getEscape())
155 Reference< XStringEscape > xEscaper(m_xDirectAccess, UNO_QUERY);
156 if (xEscaper.is() && !sName.isEmpty())
160 if (NO_CALLER == _eOrigin)
161 sName = xEscaper->escapeString(sName);
162 else
163 sName = xEscaper->unescapeString(sName);
165 catch(Exception&)
167 DBG_UNHANDLED_EXCEPTION();
171 return sName;
174 Sequence< OUString > OConfigurationNode::getNodeNames() const throw()
176 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::getNodeNames: object is invalid!");
177 Sequence< OUString > aReturn;
178 if (m_xDirectAccess.is())
182 aReturn = m_xDirectAccess->getElementNames();
183 // normalize the names
184 OUString* pNames = aReturn.getArray();
185 for (sal_Int32 i=0; i<aReturn.getLength(); ++i, ++pNames)
186 *pNames = normalizeName(*pNames, NO_CONFIGURATION);
188 catch(Exception&)
190 OSL_FAIL("OConfigurationNode::getNodeNames: caught a generic exception!");
194 return aReturn;
197 bool OConfigurationNode::removeNode(const OUString& _rName) const throw()
199 OSL_ENSURE(m_xContainerAccess.is(), "OConfigurationNode::removeNode: object is invalid!");
200 if (m_xContainerAccess.is())
204 OUString sName = normalizeName(_rName, NO_CALLER);
205 m_xContainerAccess->removeByName(sName);
206 return true;
208 catch (NoSuchElementException&)
210 #if OSL_DEBUG_LEVEL > 0
211 OStringBuffer aBuf( 256 );
212 aBuf.append("OConfigurationNode::removeNode: there is no element named!");
213 aBuf.append( OUStringToOString( _rName, RTL_TEXTENCODING_ASCII_US ) );
214 aBuf.append( "!" );
215 OSL_FAIL(aBuf.getStr());
216 #endif
218 catch (WrappedTargetException&)
220 OSL_FAIL("OConfigurationNode::removeNode: caught a WrappedTargetException!");
222 catch(Exception&)
224 OSL_FAIL("OConfigurationNode::removeNode: caught a generic exception!");
227 return false;
230 OConfigurationNode OConfigurationNode::insertNode(const OUString& _rName,const Reference< XInterface >& _xNode) const throw()
232 if(_xNode.is())
236 OUString sName = normalizeName(_rName, NO_CALLER);
237 m_xContainerAccess->insertByName(sName, makeAny(_xNode));
238 // if we're here, all was ok ...
239 return OConfigurationNode( _xNode );
241 catch(const Exception&)
243 DBG_UNHANDLED_EXCEPTION();
246 // dispose the child if it has already been created, but could not be inserted
247 Reference< XComponent > xChildComp(_xNode, UNO_QUERY);
248 if (xChildComp.is())
249 try { xChildComp->dispose(); } catch(Exception&) { }
252 return OConfigurationNode();
255 OConfigurationNode OConfigurationNode::createNode(const OUString& _rName) const throw()
257 Reference< XSingleServiceFactory > xChildFactory(m_xContainerAccess, UNO_QUERY);
258 OSL_ENSURE(xChildFactory.is(), "OConfigurationNode::createNode: object is invalid or read-only!");
260 if (xChildFactory.is()) // implies m_xContainerAccess.is()
262 Reference< XInterface > xNewChild;
265 xNewChild = xChildFactory->createInstance();
267 catch(const Exception&)
269 DBG_UNHANDLED_EXCEPTION();
271 return insertNode(_rName,xNewChild);
274 return OConfigurationNode();
277 OConfigurationNode OConfigurationNode::openNode(const OUString& _rPath) const throw()
279 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::openNode: object is invalid!");
280 OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::openNode: object is invalid!");
283 OUString sNormalized = normalizeName(_rPath, NO_CALLER);
285 Reference< XInterface > xNode;
286 if (m_xDirectAccess.is() && m_xDirectAccess->hasByName(sNormalized))
288 xNode.set(
289 m_xDirectAccess->getByName(sNormalized), css::uno::UNO_QUERY);
290 if (!xNode.is())
291 OSL_FAIL("OConfigurationNode::openNode: could not open the node!");
293 else if (m_xHierarchyAccess.is())
295 xNode.set(
296 m_xHierarchyAccess->getByHierarchicalName(_rPath),
297 css::uno::UNO_QUERY);
298 if (!xNode.is())
299 OSL_FAIL("OConfigurationNode::openNode: could not open the node!");
301 if (xNode.is())
302 return OConfigurationNode( xNode );
304 catch(const NoSuchElementException&)
306 #if OSL_DEBUG_LEVEL > 0
307 OStringBuffer aBuf( 256 );
308 aBuf.append("OConfigurationNode::openNode: there is no element named ");
309 aBuf.append( OUStringToOString( _rPath, RTL_TEXTENCODING_ASCII_US ) );
310 aBuf.append("!");
311 OSL_FAIL(aBuf.getStr());
312 #endif
314 catch(Exception&)
316 OSL_FAIL("OConfigurationNode::openNode: caught an exception while retrieving the node!");
318 return OConfigurationNode();
321 void OConfigurationNode::setEscape(bool _bEnable)
323 m_bEscapeNames = _bEnable && Reference< XStringEscape >::query(m_xDirectAccess).is();
326 bool OConfigurationNode::isSetNode() const
328 bool bIsSet = false;
329 Reference< XServiceInfo > xSI(m_xHierarchyAccess, UNO_QUERY);
330 if (xSI.is())
332 try { bIsSet = xSI->supportsService("com.sun.star.configuration.SetAccess"); }
333 catch(Exception&) { }
335 return bIsSet;
338 bool OConfigurationNode::hasByHierarchicalName( const OUString& _rName ) const throw()
340 OSL_ENSURE( m_xHierarchyAccess.is(), "OConfigurationNode::hasByHierarchicalName: no hierarchy access!" );
343 if ( m_xHierarchyAccess.is() )
345 OUString sName = normalizeName( _rName, NO_CALLER );
346 return m_xHierarchyAccess->hasByHierarchicalName( sName );
349 catch(Exception&)
352 return false;
355 bool OConfigurationNode::hasByName(const OUString& _rName) const throw()
357 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
360 OUString sName = normalizeName(_rName, NO_CALLER);
361 if (m_xDirectAccess.is())
362 return m_xDirectAccess->hasByName(sName);
364 catch(Exception&)
367 return false;
370 bool OConfigurationNode::setNodeValue(const OUString& _rPath, const Any& _rValue) const throw()
372 bool bResult = false;
374 OSL_ENSURE(m_xReplaceAccess.is(), "OConfigurationNode::setNodeValue: object is invalid!");
375 if (m_xReplaceAccess.is())
379 // check if _rPath is a level-1 path
380 OUString sNormalizedName = normalizeName(_rPath, NO_CALLER);
381 if (m_xReplaceAccess->hasByName(sNormalizedName))
383 m_xReplaceAccess->replaceByName(sNormalizedName, _rValue);
384 bResult = true;
387 // check if the name refers to a indirect descendant
388 else if (m_xHierarchyAccess.is() && m_xHierarchyAccess->hasByHierarchicalName(_rPath))
390 OSL_ASSERT(!_rPath.isEmpty());
392 OUString sParentPath, sLocalName;
394 if ( splitLastFromConfigurationPath(_rPath, sParentPath, sLocalName) )
396 OConfigurationNode aParentAccess = openNode(sParentPath);
397 if (aParentAccess.isValid())
398 bResult = aParentAccess.setNodeValue(sLocalName, _rValue);
400 else
402 m_xReplaceAccess->replaceByName(sLocalName, _rValue);
403 bResult = true;
408 catch(IllegalArgumentException&)
410 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught an IllegalArgumentException!");
412 catch(NoSuchElementException&)
414 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught a NoSuchElementException!");
416 catch(WrappedTargetException&)
418 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught a WrappedTargetException!");
420 catch(Exception&)
422 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught a generic Exception!");
426 return bResult;
429 Any OConfigurationNode::getNodeValue(const OUString& _rPath) const throw()
431 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
432 OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
433 Any aReturn;
436 OUString sNormalizedPath = normalizeName(_rPath, NO_CALLER);
437 if (m_xDirectAccess.is() && m_xDirectAccess->hasByName(sNormalizedPath) )
439 aReturn = m_xDirectAccess->getByName(sNormalizedPath);
441 else if (m_xHierarchyAccess.is())
443 aReturn = m_xHierarchyAccess->getByHierarchicalName(_rPath);
446 catch(const NoSuchElementException&)
448 DBG_UNHANDLED_EXCEPTION();
450 return aReturn;
453 void OConfigurationNode::clear() throw()
455 m_xHierarchyAccess.clear();
456 m_xDirectAccess.clear();
457 m_xReplaceAccess.clear();
458 m_xContainerAccess.clear();
461 //= helper
463 namespace
466 Reference< XMultiServiceFactory > lcl_getConfigProvider( const Reference<XComponentContext> & i_rContext )
470 Reference< XMultiServiceFactory > xProvider = theDefaultProvider::get( i_rContext );
471 return xProvider;
473 catch ( const Exception& )
475 DBG_UNHANDLED_EXCEPTION();
477 return NULL;
480 Reference< XInterface > lcl_createConfigurationRoot( const Reference< XMultiServiceFactory >& i_rxConfigProvider,
481 const OUString& i_rNodePath, const bool i_bUpdatable, const sal_Int32 i_nDepth, const bool i_bLazyWrite )
483 ENSURE_OR_RETURN( i_rxConfigProvider.is(), "invalid provider", NULL );
486 ::comphelper::NamedValueCollection aArgs;
487 aArgs.put( "nodepath", i_rNodePath );
488 aArgs.put( "lazywrite", i_bLazyWrite );
489 aArgs.put( "depth", i_nDepth );
491 OUString sAccessService( i_bUpdatable ?
492 OUString( "com.sun.star.configuration.ConfigurationUpdateAccess" ) :
493 OUString( "com.sun.star.configuration.ConfigurationAccess" ));
495 Reference< XInterface > xRoot(
496 i_rxConfigProvider->createInstanceWithArguments( sAccessService, aArgs.getWrappedPropertyValues() ),
497 UNO_SET_THROW
499 return xRoot;
501 catch ( const Exception& )
503 DBG_UNHANDLED_EXCEPTION();
505 return NULL;
509 OConfigurationTreeRoot::OConfigurationTreeRoot( const Reference< XInterface >& _rxRootNode )
510 :OConfigurationNode( _rxRootNode )
511 ,m_xCommitter( _rxRootNode, UNO_QUERY )
515 OConfigurationTreeRoot::OConfigurationTreeRoot( const Reference<XComponentContext> & i_rContext, const OUString& i_rNodePath, const bool i_bUpdatable )
516 :OConfigurationNode( lcl_createConfigurationRoot( lcl_getConfigProvider( i_rContext ),
517 i_rNodePath, i_bUpdatable, -1, false ).get() )
518 ,m_xCommitter()
520 if ( i_bUpdatable )
522 m_xCommitter.set( getUNONode(), UNO_QUERY );
523 OSL_ENSURE( m_xCommitter.is(), "OConfigurationTreeRoot::OConfigurationTreeRoot: could not create an updatable node!" );
527 void OConfigurationTreeRoot::clear() throw()
529 OConfigurationNode::clear();
530 m_xCommitter.clear();
533 bool OConfigurationTreeRoot::commit() const throw()
535 OSL_ENSURE(isValid(), "OConfigurationTreeRoot::commit: object is invalid!");
536 if (!isValid())
537 return false;
538 OSL_ENSURE(m_xCommitter.is(), "OConfigurationTreeRoot::commit: I'm a readonly node!");
539 if (!m_xCommitter.is())
540 return false;
544 m_xCommitter->commitChanges();
545 return true;
547 catch(const Exception&)
549 DBG_UNHANDLED_EXCEPTION();
551 return false;
554 OConfigurationTreeRoot OConfigurationTreeRoot::createWithProvider(const Reference< XMultiServiceFactory >& _rxConfProvider, const OUString& _rPath, sal_Int32 _nDepth, CREATION_MODE _eMode, bool _bLazyWrite)
556 Reference< XInterface > xRoot( lcl_createConfigurationRoot(
557 _rxConfProvider, _rPath, _eMode != CM_READONLY, _nDepth, _bLazyWrite ) );
558 if ( xRoot.is() )
559 return OConfigurationTreeRoot( xRoot );
560 return OConfigurationTreeRoot();
563 OConfigurationTreeRoot OConfigurationTreeRoot::createWithComponentContext( const Reference< XComponentContext >& _rxContext, const OUString& _rPath, sal_Int32 _nDepth, CREATION_MODE _eMode, bool _bLazyWrite )
565 return createWithProvider( lcl_getConfigProvider( _rxContext ), _rPath, _nDepth, _eMode, _bLazyWrite );
568 OConfigurationTreeRoot OConfigurationTreeRoot::tryCreateWithComponentContext( const Reference< XComponentContext >& rxContext,
569 const OUString& _rPath, sal_Int32 _nDepth , CREATION_MODE _eMode , bool _bLazyWrite )
571 OSL_ENSURE( rxContext.is(), "OConfigurationTreeRoot::tryCreateWithComponentContext: invalid XComponentContext!" );
574 Reference< XMultiServiceFactory > xConfigFactory = theDefaultProvider::get( rxContext );
575 return createWithProvider( xConfigFactory, _rPath, _nDepth, _eMode, _bLazyWrite );
577 catch(const Exception&)
579 // silence this, 'cause the contract of this method states "no assertions"
581 return OConfigurationTreeRoot();
584 } // namespace utl
586 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */