Updated core
[LibreOffice.git] / unotools / source / config / confignode.cxx
blob93220536110cb9beabbedaeb3dbdf6087cf0e01e
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 .
21 #include <unotools/confignode.hxx>
22 #include <unotools/configpaths.hxx>
23 #include <tools/diagnose_ex.h>
24 #include <osl/diagnose.h>
25 #include <com/sun/star/container/XHierarchicalName.hpp>
26 #include <com/sun/star/beans/PropertyValue.hpp>
27 #include <com/sun/star/configuration/theDefaultProvider.hpp>
28 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
29 #include <com/sun/star/lang/XComponent.hpp>
30 #include <com/sun/star/util/XStringEscape.hpp>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/container/XNamed.hpp>
33 #include <comphelper/extract.hxx>
34 #include <comphelper/componentcontext.hxx>
35 #include <comphelper/namedvaluecollection.hxx>
36 #include <rtl/string.hxx>
37 #if OSL_DEBUG_LEVEL > 0
38 #include <rtl/strbuf.hxx>
39 #endif
41 //........................................................................
42 namespace utl
44 //........................................................................
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::util;
49 using namespace ::com::sun::star::beans;
50 using namespace ::com::sun::star::container;
51 using namespace ::com::sun::star::configuration;
53 //========================================================================
54 //= OConfigurationNode
55 //========================================================================
56 //------------------------------------------------------------------------
57 OConfigurationNode::OConfigurationNode(const Reference< XInterface >& _rxNode )
58 :m_bEscapeNames(sal_False)
60 OSL_ENSURE(_rxNode.is(), "OConfigurationNode::OConfigurationNode: invalid node interface!");
61 if (_rxNode.is())
63 // collect all interfaces necessary
64 m_xHierarchyAccess = Reference< XHierarchicalNameAccess >(_rxNode, UNO_QUERY);
65 m_xDirectAccess = Reference< XNameAccess >(_rxNode, UNO_QUERY);
67 // reset _all_ interfaces if _one_ of them is not supported
68 if (!m_xHierarchyAccess.is() || !m_xDirectAccess.is())
70 m_xHierarchyAccess = NULL;
71 m_xDirectAccess = NULL;
74 // now for the non-critical interfaces
75 m_xReplaceAccess = Reference< XNameReplace >(_rxNode, UNO_QUERY);
76 m_xContainerAccess = Reference< XNameContainer >(_rxNode, UNO_QUERY);
79 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
80 if (xConfigNodeComp.is())
81 startComponentListening(xConfigNodeComp);
83 if (isValid())
84 setEscape(isSetNode());
87 //------------------------------------------------------------------------
88 OConfigurationNode::OConfigurationNode(const OConfigurationNode& _rSource)
89 :OEventListenerAdapter()
90 ,m_xHierarchyAccess(_rSource.m_xHierarchyAccess)
91 ,m_xDirectAccess(_rSource.m_xDirectAccess)
92 ,m_xReplaceAccess(_rSource.m_xReplaceAccess)
93 ,m_xContainerAccess(_rSource.m_xContainerAccess)
94 ,m_bEscapeNames(_rSource.m_bEscapeNames)
95 ,m_sCompletePath(_rSource.m_sCompletePath)
97 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
98 if (xConfigNodeComp.is())
99 startComponentListening(xConfigNodeComp);
102 //------------------------------------------------------------------------
103 const OConfigurationNode& OConfigurationNode::operator=(const OConfigurationNode& _rSource)
105 stopAllComponentListening();
107 m_xHierarchyAccess = _rSource.m_xHierarchyAccess;
108 m_xDirectAccess = _rSource.m_xDirectAccess;
109 m_xContainerAccess = _rSource.m_xContainerAccess;
110 m_xReplaceAccess = _rSource.m_xReplaceAccess;
111 m_bEscapeNames = _rSource.m_bEscapeNames;
112 m_sCompletePath = _rSource.m_sCompletePath;
114 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
115 if (xConfigNodeComp.is())
116 startComponentListening(xConfigNodeComp);
118 return *this;
121 //------------------------------------------------------------------------
122 void OConfigurationNode::_disposing( const EventObject& _rSource )
124 Reference< XComponent > xDisposingSource(_rSource.Source, UNO_QUERY);
125 Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY);
126 if (xDisposingSource.get() == xConfigNodeComp.get())
127 clear();
130 //------------------------------------------------------------------------
131 OUString OConfigurationNode::getLocalName() const
133 OUString sLocalName;
136 Reference< XNamed > xNamed( m_xDirectAccess, UNO_QUERY_THROW );
137 sLocalName = xNamed->getName();
139 catch( const Exception& )
141 DBG_UNHANDLED_EXCEPTION();
143 return sLocalName;
146 //------------------------------------------------------------------------
147 OUString OConfigurationNode::getNodePath() const
149 OUString sNodePath;
152 Reference< XHierarchicalName > xNamed( m_xDirectAccess, UNO_QUERY_THROW );
153 sNodePath = xNamed->getHierarchicalName();
155 catch( const Exception& )
157 DBG_UNHANDLED_EXCEPTION();
159 return sNodePath;
162 //------------------------------------------------------------------------
163 OUString OConfigurationNode::normalizeName(const OUString& _rName, NAMEORIGIN _eOrigin) const
165 OUString sName(_rName);
166 if (getEscape())
168 Reference< XStringEscape > xEscaper(m_xDirectAccess, UNO_QUERY);
169 if (xEscaper.is() && !sName.isEmpty())
173 if (NO_CALLER == _eOrigin)
174 sName = xEscaper->escapeString(sName);
175 else
176 sName = xEscaper->unescapeString(sName);
178 catch(Exception&)
180 DBG_UNHANDLED_EXCEPTION();
184 return sName;
187 //------------------------------------------------------------------------
188 Sequence< OUString > OConfigurationNode::getNodeNames() const throw()
190 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::getNodeNames: object is invalid!");
191 Sequence< OUString > aReturn;
192 if (m_xDirectAccess.is())
196 aReturn = m_xDirectAccess->getElementNames();
197 // normalize the names
198 OUString* pNames = aReturn.getArray();
199 for (sal_Int32 i=0; i<aReturn.getLength(); ++i, ++pNames)
200 *pNames = normalizeName(*pNames, NO_CONFIGURATION);
202 catch(Exception&)
204 OSL_FAIL("OConfigurationNode::getNodeNames: caught a generic exception!");
208 return aReturn;
211 //------------------------------------------------------------------------
212 sal_Bool OConfigurationNode::removeNode(const OUString& _rName) const throw()
214 OSL_ENSURE(m_xContainerAccess.is(), "OConfigurationNode::removeNode: object is invalid!");
215 if (m_xContainerAccess.is())
219 OUString sName = normalizeName(_rName, NO_CALLER);
220 m_xContainerAccess->removeByName(sName);
221 return sal_True;
223 catch (NoSuchElementException&)
225 #if OSL_DEBUG_LEVEL > 0
226 OStringBuffer aBuf( 256 );
227 aBuf.append("OConfigurationNode::removeNode: there is no element named!");
228 aBuf.append( OUStringToOString( _rName, RTL_TEXTENCODING_ASCII_US ) );
229 aBuf.append( "!" );
230 OSL_FAIL(aBuf.getStr());
231 #endif
233 catch (WrappedTargetException&)
235 OSL_FAIL("OConfigurationNode::removeNode: caught a WrappedTargetException!");
237 catch(Exception&)
239 OSL_FAIL("OConfigurationNode::removeNode: caught a generic exception!");
242 return sal_False;
244 //------------------------------------------------------------------------
245 OConfigurationNode OConfigurationNode::insertNode(const OUString& _rName,const Reference< XInterface >& _xNode) const throw()
247 if(_xNode.is())
251 OUString sName = normalizeName(_rName, NO_CALLER);
252 m_xContainerAccess->insertByName(sName, makeAny(_xNode));
253 // if we're here, all was ok ...
254 return OConfigurationNode( _xNode );
256 catch(const Exception&)
258 DBG_UNHANDLED_EXCEPTION();
261 // dispose the child if it has already been created, but could not be inserted
262 Reference< XComponent > xChildComp(_xNode, UNO_QUERY);
263 if (xChildComp.is())
264 try { xChildComp->dispose(); } catch(Exception&) { }
267 return OConfigurationNode();
269 //------------------------------------------------------------------------
270 OConfigurationNode OConfigurationNode::createNode(const OUString& _rName) const throw()
272 Reference< XSingleServiceFactory > xChildFactory(m_xContainerAccess, UNO_QUERY);
273 OSL_ENSURE(xChildFactory.is(), "OConfigurationNode::createNode: object is invalid or read-only!");
275 if (xChildFactory.is()) // implies m_xContainerAccess.is()
277 Reference< XInterface > xNewChild;
280 xNewChild = xChildFactory->createInstance();
282 catch(const Exception&)
284 DBG_UNHANDLED_EXCEPTION();
286 return insertNode(_rName,xNewChild);
289 return OConfigurationNode();
292 //------------------------------------------------------------------------
293 OConfigurationNode OConfigurationNode::openNode(const OUString& _rPath) const throw()
295 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::openNode: object is invalid!");
296 OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::openNode: object is invalid!");
299 OUString sNormalized = normalizeName(_rPath, NO_CALLER);
301 Reference< XInterface > xNode;
302 if (m_xDirectAccess.is() && m_xDirectAccess->hasByName(sNormalized))
304 if (!::cppu::extractInterface(xNode, m_xDirectAccess->getByName(sNormalized)))
305 OSL_FAIL("OConfigurationNode::openNode: could not open the node!");
307 else if (m_xHierarchyAccess.is())
309 if (!::cppu::extractInterface(xNode, m_xHierarchyAccess->getByHierarchicalName(_rPath)))
310 OSL_FAIL("OConfigurationNode::openNode: could not open the node!");
312 if (xNode.is())
313 return OConfigurationNode( xNode );
315 catch(const NoSuchElementException&)
317 #if OSL_DEBUG_LEVEL > 0
318 OStringBuffer aBuf( 256 );
319 aBuf.append("OConfigurationNode::openNode: there is no element named ");
320 aBuf.append( OUStringToOString( _rPath, RTL_TEXTENCODING_ASCII_US ) );
321 aBuf.append("!");
322 OSL_FAIL(aBuf.getStr());
323 #endif
325 catch(Exception&)
327 OSL_FAIL("OConfigurationNode::openNode: caught an exception while retrieving the node!");
329 return OConfigurationNode();
332 //------------------------------------------------------------------------
333 void OConfigurationNode::setEscape(sal_Bool _bEnable)
335 m_bEscapeNames = _bEnable && Reference< XStringEscape >::query(m_xDirectAccess).is();
338 //------------------------------------------------------------------------
339 sal_Bool OConfigurationNode::isSetNode() const
341 sal_Bool bIsSet = sal_False;
342 Reference< XServiceInfo > xSI(m_xHierarchyAccess, UNO_QUERY);
343 if (xSI.is())
345 try { bIsSet = xSI->supportsService(OUString("com.sun.star.configuration.SetAccess")); }
346 catch(Exception&) { }
348 return bIsSet;
351 sal_Bool OConfigurationNode::hasByHierarchicalName( const OUString& _rName ) const throw()
353 OSL_ENSURE( m_xHierarchyAccess.is(), "OConfigurationNode::hasByHierarchicalName: no hierarchy access!" );
356 if ( m_xHierarchyAccess.is() )
358 OUString sName = normalizeName( _rName, NO_CALLER );
359 return m_xHierarchyAccess->hasByHierarchicalName( sName );
362 catch(Exception&)
365 return sal_False;
368 //------------------------------------------------------------------------
369 sal_Bool OConfigurationNode::hasByName(const OUString& _rName) const throw()
371 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
374 OUString sName = normalizeName(_rName, NO_CALLER);
375 if (m_xDirectAccess.is())
376 return m_xDirectAccess->hasByName(sName);
378 catch(Exception&)
381 return sal_False;
384 //------------------------------------------------------------------------
385 sal_Bool OConfigurationNode::setNodeValue(const OUString& _rPath, const Any& _rValue) const throw()
387 sal_Bool bResult = false;
389 OSL_ENSURE(m_xReplaceAccess.is(), "OConfigurationNode::setNodeValue: object is invalid!");
390 if (m_xReplaceAccess.is())
394 // check if _rPath is a level-1 path
395 OUString sNormalizedName = normalizeName(_rPath, NO_CALLER);
396 if (m_xReplaceAccess->hasByName(sNormalizedName))
398 m_xReplaceAccess->replaceByName(sNormalizedName, _rValue);
399 bResult = true;
402 // check if the name refers to a indirect descendant
403 else if (m_xHierarchyAccess.is() && m_xHierarchyAccess->hasByHierarchicalName(_rPath))
405 OSL_ASSERT(!_rPath.isEmpty());
407 OUString sParentPath, sLocalName;
409 if ( splitLastFromConfigurationPath(_rPath, sParentPath, sLocalName) )
411 OConfigurationNode aParentAccess = openNode(sParentPath);
412 if (aParentAccess.isValid())
413 bResult = aParentAccess.setNodeValue(sLocalName, _rValue);
415 else
417 m_xReplaceAccess->replaceByName(sLocalName, _rValue);
418 bResult = true;
423 catch(IllegalArgumentException&)
425 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught an IllegalArgumentException!");
427 catch(NoSuchElementException&)
429 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught a NoSuchElementException!");
431 catch(WrappedTargetException&)
433 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught a WrappedTargetException!");
435 catch(Exception&)
437 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught a generic Exception!");
442 return bResult;
445 //------------------------------------------------------------------------
446 Any OConfigurationNode::getNodeValue(const OUString& _rPath) const throw()
448 OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
449 OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::hasByName: object is invalid!");
450 Any aReturn;
453 OUString sNormalizedPath = normalizeName(_rPath, NO_CALLER);
454 if (m_xDirectAccess.is() && m_xDirectAccess->hasByName(sNormalizedPath) )
456 aReturn = m_xDirectAccess->getByName(sNormalizedPath);
458 else if (m_xHierarchyAccess.is())
460 aReturn = m_xHierarchyAccess->getByHierarchicalName(_rPath);
463 catch(const NoSuchElementException&)
465 DBG_UNHANDLED_EXCEPTION();
467 return aReturn;
470 //------------------------------------------------------------------------
471 void OConfigurationNode::clear() throw()
473 m_xHierarchyAccess.clear();
474 m_xDirectAccess.clear();
475 m_xReplaceAccess.clear();
476 m_xContainerAccess.clear();
479 //========================================================================
480 //= helper
481 //========================================================================
482 namespace
484 //--------------------------------------------------------------------
485 Reference< XMultiServiceFactory > lcl_getConfigProvider( const Reference<XComponentContext> & i_rContext )
489 Reference< XMultiServiceFactory > xProvider = theDefaultProvider::get( i_rContext );
490 return xProvider;
492 catch ( const Exception& )
494 DBG_UNHANDLED_EXCEPTION();
496 return NULL;
499 //--------------------------------------------------------------------
500 Reference< XInterface > lcl_createConfigurationRoot( const Reference< XMultiServiceFactory >& i_rxConfigProvider,
501 const OUString& i_rNodePath, const bool i_bUpdatable, const sal_Int32 i_nDepth, const bool i_bLazyWrite )
503 ENSURE_OR_RETURN( i_rxConfigProvider.is(), "invalid provider", NULL );
506 ::comphelper::NamedValueCollection aArgs;
507 aArgs.put( "nodepath", i_rNodePath );
508 aArgs.put( "lazywrite", i_bLazyWrite );
509 aArgs.put( "depth", i_nDepth );
511 OUString sAccessService( i_bUpdatable ?
512 OUString( "com.sun.star.configuration.ConfigurationUpdateAccess" ) :
513 OUString( "com.sun.star.configuration.ConfigurationAccess" ));
515 Reference< XInterface > xRoot(
516 i_rxConfigProvider->createInstanceWithArguments( sAccessService, aArgs.getWrappedPropertyValues() ),
517 UNO_SET_THROW
519 return xRoot;
521 catch ( const Exception& )
523 DBG_UNHANDLED_EXCEPTION();
525 return NULL;
529 //------------------------------------------------------------------------
530 OConfigurationTreeRoot::OConfigurationTreeRoot( const Reference< XInterface >& _rxRootNode )
531 :OConfigurationNode( _rxRootNode )
532 ,m_xCommitter( _rxRootNode, UNO_QUERY )
536 //------------------------------------------------------------------------
537 OConfigurationTreeRoot::OConfigurationTreeRoot( const Reference<XComponentContext> & i_rContext, const OUString& i_rNodePath, const bool i_bUpdatable )
538 :OConfigurationNode( lcl_createConfigurationRoot( lcl_getConfigProvider( i_rContext ),
539 i_rNodePath, i_bUpdatable, -1, false ).get() )
540 ,m_xCommitter()
542 if ( i_bUpdatable )
544 m_xCommitter.set( getUNONode(), UNO_QUERY );
545 OSL_ENSURE( m_xCommitter.is(), "OConfigurationTreeRoot::OConfigurationTreeRoot: could not create an updatable node!" );
549 //------------------------------------------------------------------------
550 void OConfigurationTreeRoot::clear() throw()
552 OConfigurationNode::clear();
553 m_xCommitter.clear();
556 //------------------------------------------------------------------------
557 sal_Bool OConfigurationTreeRoot::commit() const throw()
559 OSL_ENSURE(isValid(), "OConfigurationTreeRoot::commit: object is invalid!");
560 if (!isValid())
561 return sal_False;
562 OSL_ENSURE(m_xCommitter.is(), "OConfigurationTreeRoot::commit: I'm a readonly node!");
563 if (!m_xCommitter.is())
564 return sal_False;
568 m_xCommitter->commitChanges();
569 return sal_True;
571 catch(const Exception&)
573 DBG_UNHANDLED_EXCEPTION();
575 return sal_False;
578 //------------------------------------------------------------------------
579 OConfigurationTreeRoot OConfigurationTreeRoot::createWithProvider(const Reference< XMultiServiceFactory >& _rxConfProvider, const OUString& _rPath, sal_Int32 _nDepth, CREATION_MODE _eMode, sal_Bool _bLazyWrite)
581 Reference< XInterface > xRoot( lcl_createConfigurationRoot(
582 _rxConfProvider, _rPath, _eMode != CM_READONLY, _nDepth, _bLazyWrite ) );
583 if ( xRoot.is() )
584 return OConfigurationTreeRoot( xRoot );
585 return OConfigurationTreeRoot();
588 //------------------------------------------------------------------------
589 OConfigurationTreeRoot OConfigurationTreeRoot::createWithComponentContext( const Reference< XComponentContext >& _rxContext, const OUString& _rPath, sal_Int32 _nDepth, CREATION_MODE _eMode, sal_Bool _bLazyWrite )
591 return createWithProvider( lcl_getConfigProvider( _rxContext ), _rPath, _nDepth, _eMode, _bLazyWrite );
594 //------------------------------------------------------------------------
595 OConfigurationTreeRoot OConfigurationTreeRoot::tryCreateWithComponentContext( const Reference< XComponentContext >& rxContext,
596 const OUString& _rPath, sal_Int32 _nDepth , CREATION_MODE _eMode , sal_Bool _bLazyWrite )
598 OSL_ENSURE( rxContext.is(), "OConfigurationTreeRoot::tryCreateWithComponentContext: invalid XComponentContext!" );
601 Reference< XMultiServiceFactory > xConfigFactory = theDefaultProvider::get( rxContext );
602 return createWithProvider( xConfigFactory, _rPath, _nDepth, _eMode, _bLazyWrite );
604 catch(const Exception&)
606 // silence this, 'cause the contract of this method states "no assertions"
608 return OConfigurationTreeRoot();
611 //........................................................................
612 } // namespace utl
613 //........................................................................
615 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */