1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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!");
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
);
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
);
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())
120 OUString
OConfigurationNode::getLocalName() const
125 Reference
< XNamed
> xNamed( m_xDirectAccess
, UNO_QUERY_THROW
);
126 sLocalName
= xNamed
->getName();
128 catch( const Exception
& )
130 DBG_UNHANDLED_EXCEPTION();
135 OUString
OConfigurationNode::getNodePath() const
140 Reference
< XHierarchicalName
> xNamed( m_xDirectAccess
, UNO_QUERY_THROW
);
141 sNodePath
= xNamed
->getHierarchicalName();
143 catch( const Exception
& )
145 DBG_UNHANDLED_EXCEPTION();
150 OUString
OConfigurationNode::normalizeName(const OUString
& _rName
, NAMEORIGIN _eOrigin
) const
152 OUString
sName(_rName
);
155 Reference
< XStringEscape
> xEscaper(m_xDirectAccess
, UNO_QUERY
);
156 if (xEscaper
.is() && !sName
.isEmpty())
160 if (NO_CALLER
== _eOrigin
)
161 sName
= xEscaper
->escapeString(sName
);
163 sName
= xEscaper
->unescapeString(sName
);
167 DBG_UNHANDLED_EXCEPTION();
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
);
190 OSL_FAIL("OConfigurationNode::getNodeNames: caught a generic exception!");
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
);
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
) );
215 OSL_FAIL(aBuf
.getStr());
218 catch (WrappedTargetException
&)
220 OSL_FAIL("OConfigurationNode::removeNode: caught a WrappedTargetException!");
224 OSL_FAIL("OConfigurationNode::removeNode: caught a generic exception!");
230 OConfigurationNode
OConfigurationNode::insertNode(const OUString
& _rName
,const Reference
< XInterface
>& _xNode
) const throw()
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
);
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
))
289 m_xDirectAccess
->getByName(sNormalized
), css::uno::UNO_QUERY
);
291 OSL_FAIL("OConfigurationNode::openNode: could not open the node!");
293 else if (m_xHierarchyAccess
.is())
296 m_xHierarchyAccess
->getByHierarchicalName(_rPath
),
297 css::uno::UNO_QUERY
);
299 OSL_FAIL("OConfigurationNode::openNode: could not open the node!");
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
) );
311 OSL_FAIL(aBuf
.getStr());
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
329 Reference
< XServiceInfo
> xSI(m_xHierarchyAccess
, UNO_QUERY
);
332 try { bIsSet
= xSI
->supportsService("com.sun.star.configuration.SetAccess"); }
333 catch(Exception
&) { }
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
);
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
);
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
);
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
);
402 m_xReplaceAccess
->replaceByName(sLocalName
, _rValue
);
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!");
422 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught a generic Exception!");
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!");
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();
453 void OConfigurationNode::clear() throw()
455 m_xHierarchyAccess
.clear();
456 m_xDirectAccess
.clear();
457 m_xReplaceAccess
.clear();
458 m_xContainerAccess
.clear();
466 Reference
< XMultiServiceFactory
> lcl_getConfigProvider( const Reference
<XComponentContext
> & i_rContext
)
470 Reference
< XMultiServiceFactory
> xProvider
= theDefaultProvider::get( i_rContext
);
473 catch ( const Exception
& )
475 DBG_UNHANDLED_EXCEPTION();
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() ),
501 catch ( const Exception
& )
503 DBG_UNHANDLED_EXCEPTION();
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() )
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!");
538 OSL_ENSURE(m_xCommitter
.is(), "OConfigurationTreeRoot::commit: I'm a readonly node!");
539 if (!m_xCommitter
.is())
544 m_xCommitter
->commitChanges();
547 catch(const Exception
&)
549 DBG_UNHANDLED_EXCEPTION();
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
) );
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();
586 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */