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 .
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>
41 //........................................................................
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!");
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
);
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
);
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())
130 //------------------------------------------------------------------------
131 OUString
OConfigurationNode::getLocalName() const
136 Reference
< XNamed
> xNamed( m_xDirectAccess
, UNO_QUERY_THROW
);
137 sLocalName
= xNamed
->getName();
139 catch( const Exception
& )
141 DBG_UNHANDLED_EXCEPTION();
146 //------------------------------------------------------------------------
147 OUString
OConfigurationNode::getNodePath() const
152 Reference
< XHierarchicalName
> xNamed( m_xDirectAccess
, UNO_QUERY_THROW
);
153 sNodePath
= xNamed
->getHierarchicalName();
155 catch( const Exception
& )
157 DBG_UNHANDLED_EXCEPTION();
162 //------------------------------------------------------------------------
163 OUString
OConfigurationNode::normalizeName(const OUString
& _rName
, NAMEORIGIN _eOrigin
) const
165 OUString
sName(_rName
);
168 Reference
< XStringEscape
> xEscaper(m_xDirectAccess
, UNO_QUERY
);
169 if (xEscaper
.is() && !sName
.isEmpty())
173 if (NO_CALLER
== _eOrigin
)
174 sName
= xEscaper
->escapeString(sName
);
176 sName
= xEscaper
->unescapeString(sName
);
180 DBG_UNHANDLED_EXCEPTION();
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
);
204 OSL_FAIL("OConfigurationNode::getNodeNames: caught a generic exception!");
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
);
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
) );
230 OSL_FAIL(aBuf
.getStr());
233 catch (WrappedTargetException
&)
235 OSL_FAIL("OConfigurationNode::removeNode: caught a WrappedTargetException!");
239 OSL_FAIL("OConfigurationNode::removeNode: caught a generic exception!");
244 //------------------------------------------------------------------------
245 OConfigurationNode
OConfigurationNode::insertNode(const OUString
& _rName
,const Reference
< XInterface
>& _xNode
) const throw()
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
);
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!");
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
) );
322 OSL_FAIL(aBuf
.getStr());
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
);
345 try { bIsSet
= xSI
->supportsService(OUString("com.sun.star.configuration.SetAccess")); }
346 catch(Exception
&) { }
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
);
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
);
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
);
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
);
417 m_xReplaceAccess
->replaceByName(sLocalName
, _rValue
);
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!");
437 OSL_FAIL("OConfigurationNode::setNodeValue: could not replace the value: caught a generic Exception!");
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!");
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();
470 //------------------------------------------------------------------------
471 void OConfigurationNode::clear() throw()
473 m_xHierarchyAccess
.clear();
474 m_xDirectAccess
.clear();
475 m_xReplaceAccess
.clear();
476 m_xContainerAccess
.clear();
479 //========================================================================
481 //========================================================================
484 //--------------------------------------------------------------------
485 Reference
< XMultiServiceFactory
> lcl_getConfigProvider( const Reference
<XComponentContext
> & i_rContext
)
489 Reference
< XMultiServiceFactory
> xProvider
= theDefaultProvider::get( i_rContext
);
492 catch ( const Exception
& )
494 DBG_UNHANDLED_EXCEPTION();
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() ),
521 catch ( const Exception
& )
523 DBG_UNHANDLED_EXCEPTION();
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() )
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!");
562 OSL_ENSURE(m_xCommitter
.is(), "OConfigurationTreeRoot::commit: I'm a readonly node!");
563 if (!m_xCommitter
.is())
568 m_xCommitter
->commitChanges();
571 catch(const Exception
&)
573 DBG_UNHANDLED_EXCEPTION();
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
) );
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 //........................................................................
613 //........................................................................
615 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */