1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: apitreeimplobj.cxx,v $
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"
35 #include "apitreeimplobj.hxx"
36 #include "confignotifier.hxx"
37 #include "notifierimpl.hxx"
38 #include "apifactory.hxx"
39 #include "apitreeaccess.hxx"
40 #include "nodechangeinfo.hxx"
41 #include "broadcaster.hxx"
43 #include "providerimpl.hxx"
44 #include "roottree.hxx"
45 #include "noderef.hxx"
46 #include "anynoderef.hxx"
48 #include "treemanager.hxx"
49 #include <cppuhelper/queryinterface.hxx>
50 #include <vos/refernce.hxx>
54 //-----------------------------------------------------------------------------
57 //-----------------------------------------------------------------------------
58 namespace lang
= ::com::sun::star::lang
;
59 //-----------------------------------------------------------------------------
62 //-----------------------------------------------------------------------------
63 class ApiTreeImpl::ComponentAdapter
: public lang::XEventListener
65 vos::ORefCount m_refs
;
69 uno::Reference
< lang::XComponent
> xProvider
;
70 uno::Reference
< lang::XComponent
> xParent
;
72 ComponentAdapter(ApiTreeImpl
& rParent
) : pOwner(&rParent
) {}
73 virtual ~ComponentAdapter() {}
77 void setProvider(uno::Reference
< lang::XComponent
> const& xProvider
);
78 void setParent(uno::Reference
< lang::XComponent
> const& xParent
);
79 uno::Reference
< lang::XComponent
> getProvider() const;
82 virtual void SAL_CALL
acquire() throw();
83 virtual void SAL_CALL
release() throw();
85 void setComponent(uno::Reference
< lang::XComponent
>& rxSlot
,uno::Reference
< lang::XComponent
> const& xComp
);
86 uno::Reference
< lang::XComponent
> getComponent(uno::Reference
< lang::XComponent
> const& rxSlot
) const;
88 virtual uno::Any SAL_CALL
queryInterface(uno::Type
const& rType
) throw();
89 virtual void SAL_CALL
disposing(com::sun::star::lang::EventObject
const& rEvt
) throw();
91 //-----------------------------------------------------------------------------
93 uno::Reference
< lang::XComponent
>
94 ApiTreeImpl::ComponentAdapter::getComponent(
95 uno::Reference
< lang::XComponent
> const& rxSlot
100 //-----------------------------------------------------------------------------
102 void ApiTreeImpl::ComponentAdapter::setComponent(
103 uno::Reference
< lang::XComponent
>& rxSlot
,
104 uno::Reference
< lang::XComponent
> const& xComp
107 UnoApiLockClearable aGuard
;
109 uno::Reference
< lang::XComponent
> xOld
= rxSlot
;
116 if (xOld
.is()) try { xOld
->removeEventListener(this); } catch (uno::Exception
& ) {}
117 if (xComp
.is()) xComp
->addEventListener(this);
120 //-----------------------------------------------------------------------------
121 uno::Reference
< lang::XComponent
> ApiTreeImpl::ComponentAdapter::getProvider() const
123 return this->getComponent( this->xProvider
);
125 void ApiTreeImpl::ComponentAdapter::setProvider(uno::Reference
< lang::XComponent
> const& rProvider
)
127 this->setComponent( this->xProvider
, rProvider
);
129 void ApiTreeImpl::ComponentAdapter::setParent(uno::Reference
< lang::XComponent
> const& rParent
)
131 this->setComponent( this->xParent
, rParent
);
133 //-----------------------------------------------------------------------------
135 void SAL_CALL
ApiTreeImpl::ComponentAdapter::acquire() throw()
139 //-------------------------------------------------------------------------
141 void SAL_CALL
ApiTreeImpl::ComponentAdapter::release() throw()
146 //-------------------------------------------------------------------------
148 uno::Any SAL_CALL
ApiTreeImpl::ComponentAdapter::queryInterface(uno::Type
const& rType
) throw()
150 return cppu::queryInterface( rType
151 , static_cast< com::sun::star::lang::XEventListener
*>(this)
152 , static_cast< uno::XInterface
*>(this)
155 //-------------------------------------------------------------------------
157 void SAL_CALL
ApiTreeImpl::ComponentAdapter::disposing(com::sun::star::lang::EventObject
const& rEvt
) throw()
159 UnoApiLockClearable aGuard
;
161 if (this->pOwner
!= NULL
)
163 CFG_TRACE_INFO("ApiTreeImpl:ComponentAdapter: Providing UNO object is disposed - relaying to my owner");
164 // ensure our owner stays alive
165 uno::Reference
<uno::XInterface
> xKeepOwnerAlive( this->pOwner
->getUnoInstance() );
166 // and we stay alive too
167 rtl::Reference
< ApiTreeImpl::ComponentAdapter
> xKeepAlive( this );
171 pOwner
->disposing( rEvt
);
173 UnoApiLock aClearGuard
;
174 if (rEvt
.Source
== this->xParent
) this->xParent
.clear();
175 if (rEvt
.Source
== this->xProvider
) this->xProvider
.clear();
178 CFG_TRACE_INFO("ApiTreeImpl:ComponentAdapter: Providing UNO object is disposed - but my owner is already gone");
181 //-------------------------------------------------------------------------
183 void ApiTreeImpl::ComponentAdapter::clear()
185 UnoApiLockClearable aGuard
;
189 uno::Reference
< lang::XComponent
> aProvider
= this->xProvider
;
190 uno::Reference
< lang::XComponent
> aParent
= this->xParent
;
196 if (aParent
.is()) try { aParent
->removeEventListener(this); } catch (uno::Exception
& ) {}
197 if (aProvider
.is()) try { aProvider
->removeEventListener(this); } catch (uno::Exception
& ) {}
200 //-----------------------------------------------------------------------------
201 class ApiRootTreeImpl::NodeListener
: public INodeListener
203 ApiRootTreeImpl
* pParent
;
204 TreeManager
* pSource
;
206 vos::ORef
< OOptions
> m_xOptions
;
207 configuration::AbsolutePath m_aLocationPath
;
209 NodeListener(ApiRootTreeImpl
& _rParent
)
212 , m_aLocationPath( configuration::AbsolutePath::root() )
219 TreeManager
* getSource()
225 void setSource(TreeManager
* pNew
)
232 OSL_ENSURE(m_xOptions
.isValid(),"Cannot set IConfigListener without Options");
233 if (m_xOptions
.isValid())
236 pSource
->removeListener(m_xOptions
->getRequestOptions(), this);
241 OSL_ENSURE(!m_aLocationPath
.isRoot(), "Cannot register for notifications: no location set");
242 pNew
->addListener(m_aLocationPath
, m_xOptions
->getRequestOptions(), this);
251 void setLocation(configuration::AbsolutePath
const& _aLocation
, vos::ORef
< OOptions
> const& _xOptions
)
253 OSL_ASSERT(_xOptions
.isValid());
257 if (pSource
&& pParent
)
259 OSL_ASSERT(m_xOptions
.isValid());
260 pSource
->removeListener(m_xOptions
->getRequestOptions(), this);
263 m_aLocationPath
= _aLocation
;
264 m_xOptions
= _xOptions
;
266 if (pSource
&& pParent
)
267 pSource
->addListener(m_aLocationPath
, m_xOptions
->getRequestOptions(), this);
273 OSL_ASSERT(pParent
== 0);
277 OSL_ASSERT(m_xOptions
.isValid());
278 pSource
->removeListener(m_xOptions
->getRequestOptions(), this);
280 m_aLocationPath
= configuration::AbsolutePath::root();
287 UnoApiLockClearable aGuard
;
294 TreeManager
* pOrgSource
= pSource
;
295 vos::ORef
< OOptions
> xOptions
= m_xOptions
;
299 m_aLocationPath
= configuration::AbsolutePath::root();
303 OSL_ASSERT(xOptions
.isValid());
304 pOrgSource
->removeListener(xOptions
->getRequestOptions(), this);
310 virtual void disposing(TreeManager
* pSource
);
311 virtual void nodeChanged(Change
const& aChange
, configuration::AbsolutePath
const& sPath
, TreeManager
* pSource
);
312 virtual void nodeDeleted(configuration::AbsolutePath
const& sPath
, TreeManager
* pSource
);
315 //-------------------------------------------------------------------------
317 //-----------------------------------------------------------------------------
318 // API object implementation wrappers
319 //-------------------------------------------------------------------------
320 ApiProvider::ApiProvider(Factory
& rFactory
, OProviderImpl
& rProviderImpl
)
321 : m_rFactory(rFactory
)
322 , m_rProviderImpl(rProviderImpl
)
324 //-------------------------------------------------------------------------
326 uno::Reference
<com::sun::star::script::XTypeConverter
> ApiProvider::getTypeConverter() const
328 return m_rProviderImpl
.getTypeConverter();
330 //-------------------------------------------------------------------------
333 configuration::DefaultProvider
createDefaultProvider(
334 ApiProvider
& rProvider
,
335 rtl::Reference
< configuration::Tree
> const& aTree
,
336 vos::ORef
< OOptions
> const& _xOptions
339 OProviderImpl
& rProviderImpl
= rProvider
.getProviderImpl();
340 rtl::Reference
< TreeManager
> xDefaultProvider
= rProviderImpl
.getDefaultProvider();
342 OSL_ASSERT(_xOptions
.isValid());
343 RequestOptions
const aOptions
= _xOptions
.isValid() ? _xOptions
->getRequestOptions() : RequestOptions();
345 return configuration::DefaultProvider::create(aTree
,aOptions
,xDefaultProvider
,&rProviderImpl
);
347 //-------------------------------------------------------------------------
350 configuration::DefaultProvider
extractDefaultProvider(ApiTreeImpl
* pParentTree
)
353 return pParentTree
->getDefaultProvider();
356 return configuration::DefaultProvider::createEmpty();
358 //-------------------------------------------------------------------------
359 ApiTreeImpl::ApiTreeImpl(uno::XInterface
* pInstance
, ApiProvider
& rProvider
, rtl::Reference
< configuration::Tree
> const& aTree
, ApiTreeImpl
* pParentTree
)
361 , m_aNotifier(new NotifierImpl(aTree
))
362 , m_aDefaultProvider(extractDefaultProvider(pParentTree
))
364 , m_rProvider(rProvider
)
366 , m_pInstance(pInstance
)
368 OSL_ENSURE(pParentTree
== NULL
|| &rProvider
== &pParentTree
->m_rProvider
,"WARNING: Parent tree has a different provider - trouble may be ahead");
369 setNodeInstance(aTree
->getRootNode(), pInstance
);
372 //-------------------------------------------------------------------------
373 ApiTreeImpl::ApiTreeImpl(uno::XInterface
* _pInstance
, ApiProvider
& _rProvider
, rtl::Reference
< configuration::Tree
> const& _aTree
, configuration::DefaultProvider
const& _aDefaultProvider
)
375 , m_aNotifier(new NotifierImpl(_aTree
))
376 , m_aDefaultProvider(_aDefaultProvider
)
378 , m_rProvider(_rProvider
)
380 , m_pInstance(_pInstance
)
382 setNodeInstance(_aTree
->getRootNode(), _pInstance
);
385 //-------------------------------------------------------------------------
387 ApiTreeImpl::~ApiTreeImpl()
389 OSL_ENSURE(m_aNotifier
->m_aListeners
.isDisposed(),"ApiTree Object was not disposed properly");
392 //-------------------------------------------------------------------------
394 ApiRootTreeImpl::ApiRootTreeImpl(uno::XInterface
* pInstance
, ApiProvider
& rProvider
, rtl::Reference
< configuration::Tree
> const& aTree
, vos::ORef
< OOptions
> const& _xOptions
)
395 : m_aTreeImpl(pInstance
, rProvider
, aTree
, createDefaultProvider(rProvider
, aTree
, _xOptions
))
396 , m_aLocationPath( configuration::Path::Rep() )
397 , m_pNotificationListener(NULL
)
398 , m_xOptions(_xOptions
)
400 implSetLocation(aTree
);
401 enableNotification(true);
403 //-------------------------------------------------------------------------
404 ApiRootTreeImpl::~ApiRootTreeImpl()
406 if (m_pNotificationListener
.is())
408 m_pNotificationListener
->setSource(0);
409 m_pNotificationListener
->clearParent();
412 //-------------------------------------------------------------------------
414 void ApiTreeImpl::setNodeInstance(configuration::NodeRef
const& aNode
, uno::XInterface
* pInstance
)
416 OSL_ENSURE(aNode
.isValid(),"ERROR: adding invalid node to ApiTree");
417 OSL_ENSURE(m_aTree
->isValidNode(aNode
.getOffset()),"ERROR: foreign node being added to ApiTree");
418 m_aNotifier
->m_aListeners
.setObjectAt( configuration::NodeID(m_aTree
, aNode
).toIndex(), pInstance
);
421 //-------------------------------------------------------------------------
423 bool ApiTreeImpl::isAlive() const
425 return m_aNotifier
->m_aListeners
.isAlive();
427 //-------------------------------------------------------------------------
428 void ApiTreeImpl::checkAlive() const
430 m_aNotifier
->m_aListeners
.checkAlive( getUnoInstance() );
433 //-------------------------------------------------------------------------
435 Notifier
ApiTreeImpl::getNotifier() const
437 return Notifier(m_aNotifier
,this);
439 //-------------------------------------------------------------------------
441 bool ApiRootTreeImpl::enableNotification(bool bEnable
)
443 TreeManager
* pSource
= bEnable
? getApiTree().getProvider().getProviderImpl().getNotifier() : 0;
445 TreeManager
* pOld
= this->implSetNotificationSource(pSource
);
449 //-------------------------------------------------------------------------
451 bool ApiTreeImpl::disposeTree(bool bForce
)
453 CFG_TRACE_INFO("ApiTreeImpl: Disposing Tree (may throw if already disposed)");
455 // ensure our provider stays alive
456 uno::Reference
<uno::XInterface
> xKeepParentAlive(this->getParentComponent());
457 // ensure we stay alive too
458 uno::Reference
<uno::XInterface
> xKeepAlive(this->getUnoInstance());
460 // #109077# If already disposed, we may have no source data or data lock
466 if (m_pParentTree
!= 0)
469 // recheck after having the mutex
470 checkAlive(); // may throw
472 else if (m_pParentTree
)
476 OSL_ASSERT(!isAlive()); // post condition
480 //-------------------------------------------------------------------------
482 bool ApiTreeImpl::disposeTreeNow()
484 CFG_TRACE_INFO("ApiTreeImpl: Disposing Tree Now (unless disposed)");
486 return implDisposeTree();
490 //-------------------------------------------------------------------------
491 bool ApiRootTreeImpl::disposeTree()
493 CFG_TRACE_INFO("Api Root Tree: Disposing Tree And Releasing (unless disposed)");
494 // ensure our provider stays alive
495 uno::Reference
<uno::XInterface
> xKeepProvider( m_aTreeImpl
.getUnoProviderInstance() );
497 rtl::Reference
<NodeListener
> xListener
= m_pNotificationListener
;
500 xListener
->clearParent();
504 bool bDisposed
= m_aTreeImpl
.disposeTreeNow();
506 if (bDisposed
) releaseData();
508 if (!m_xOptions
.isEmpty())
510 OSL_ENSURE(!bDisposed
, "Disposing/Releasing should clear the options");
511 CFG_TRACE_INFO2("Api Root Tree: data was not released in disposeTree");
516 //-------------------------------------------------------------------------
517 bool ApiTreeImpl::implDisposeTree()
519 OSL_ENSURE(m_pParentTree
== 0,"WARNING: Disposing a tree that still has a parent tree set");
521 SpecialListenerContainer
<configuration::SubNodeID
,SubNodeHash
,SubNodeEq
,SubNodeToIndex
>& aContainer
= m_aNotifier
->m_aListeners
;
522 if (aContainer
.beginDisposing())
524 CFG_TRACE_INFO("ApiTreeImpl: Tree is now disposed");
526 Factory
& rFactory
= getFactory();
528 std::vector
<configuration::NodeID
> aChildNodes
;
529 configuration::getAllContainedNodes( m_aTree
, aChildNodes
);
531 for (std::vector
<configuration::NodeID
>::reverse_iterator it
= aChildNodes
.rbegin(), stop
= aChildNodes
.rend();
535 rFactory
.revokeElement( *it
);
538 CFG_TRACE_INFO_NI("ApiTreeImpl: Listeners are now informed");
539 aContainer
.notifyDisposing();
541 OSL_ASSERT(!aContainer
.isDisposed());
543 CFG_TRACE_INFO_NI("ApiTreeImpl: Deinitializing");
544 deinit(); // releases the provider and parent
545 aContainer
.endDisposing();
547 OSL_ASSERT(aContainer
.isDisposed());
553 CFG_TRACE_INFO("ApiTreeImpl: Tree was already disposed.");
557 //-------------------------------------------------------------------------
558 void ApiTreeImpl::disposeNode(configuration::NodeRef
const& aNode
, uno::XInterface
* pInstance
)
560 // This used to contain 3 nested 'isAlive()' calls; why !?
562 implDisposeNode(aNode
,pInstance
);
564 //-------------------------------------------------------------------------
565 void ApiTreeImpl::implDisposeNode(configuration::NodeRef
const& aNode
, uno::XInterface
* )
567 CFG_TRACE_INFO("ApiTreeImpl: Disposing a single node.");
568 OSL_ENSURE(aNode
.isValid(),"INTERNAL ERROR: Disposing NULL node");
569 OSL_ENSURE(m_aTree
->isValidNode(aNode
.getOffset()),"INTERNAL ERROR: Disposing: node does not match tree");
570 OSL_ENSURE( !m_aTree
->isRootNode(aNode
),"INTERNAL ERROR: Disposing the root node of the tree");
572 configuration::NodeID
aNodeID(m_aTree
,aNode
);
574 if (m_aNotifier
->m_aListeners
.disposeOne(aNodeID
.toIndex()) )
576 getFactory().revokeElement(aNodeID
);
579 //-------------------------------------------------------------------------
580 void ApiTreeImpl::init(ApiTreeImpl
* pParentTree
)
582 m_xProvider
= new ComponentAdapter(*this);
583 m_xProvider
->setProvider( this->getProviderComponent() );
585 OSL_ENSURE(m_xProvider
->getProvider().is(),"WARNING: Provider is no Component - Lifetime trouble ahead");
587 OSL_ASSERT(m_pParentTree
== 0);
588 setParentTree(pParentTree
);
590 //-------------------------------------------------------------------------
591 void ApiTreeImpl::deinit()
595 uno::Reference
<ComponentAdapter
> xAdapter
= m_xProvider
;
601 //-------------------------------------------------------------------------
602 void ApiTreeImpl::haveNewParent(ApiTreeImpl
* pNewParent
) // public interface
604 setParentTree(pNewParent
);
607 //-------------------------------------------------------------------------
609 ApiTreeImpl
const* ApiTreeImpl::getRootTreeImpl() const
611 ApiTreeImpl
const* pRet
= this;
612 while (pRet
->m_pParentTree
)
613 pRet
= pRet
->m_pParentTree
;
618 //-------------------------------------------------------------------------
619 void ApiTreeImpl::setParentTree(ApiTreeImpl
* pParentTree
) // internal implementation
621 #if OSL_DEBUG_LEVEL > 0
624 rtl::Reference
< configuration::Tree
> aContext
= m_aTree
->getContextTree();
625 rtl::Reference
< configuration::Tree
> aParent
= pParentTree
->m_aTree
;
627 configuration::NodeID
aContextID( aContext
, aContext
->getRootNode() );
628 configuration::NodeID
aParentID( aParent
, aParent
->getRootNode() );
630 OSL_ENSURE( aContextID
== aParentID
, "Parent relationship mismatch !");
634 if (m_pParentTree
!= pParentTree
)
636 uno::Reference
<ComponentAdapter
> xAdapter
= m_xProvider
;
638 m_pParentTree
= pParentTree
;
640 uno::Reference
<com::sun::star::lang::XComponent
> xNew
= getParentComponent();
641 OSL_ENSURE( xNew
.is() == (pParentTree
!= 0), "WARNING: Parent Tree is no Component");
644 xAdapter
->setParent(xNew
);
646 OSL_ENSURE( pParentTree
== 0, "ERROR: Setting New Parent at deinitialized ApiTreeImpl");
650 //-------------------------------------------------------------------------
652 uno::Reference
<uno::XInterface
> ApiTreeImpl::getUnoProviderInstance() const
654 uno::Reference
<ComponentAdapter
> xAdapter
= m_xProvider
;
656 uno::Reference
<uno::XInterface
> xReturn
;
658 xReturn
= xAdapter
->getProvider();
662 //-------------------------------------------------------------------------
663 uno::Reference
<com::sun::star::lang::XComponent
> ApiTreeImpl::getParentComponent()
665 uno::XInterface
* pInterface
= m_pParentTree
? m_pParentTree
->getUnoInstance() : 0;
666 return uno::Reference
<com::sun::star::lang::XComponent
>::query(pInterface
);
668 //-------------------------------------------------------------------------
670 uno::Reference
<com::sun::star::lang::XComponent
> ApiTreeImpl::getProviderComponent()
672 uno::XInterface
* pInterface
= m_rProvider
.getProviderImpl().getProviderInstance();
673 return uno::Reference
<com::sun::star::lang::XComponent
>::query(pInterface
);
676 //-------------------------------------------------------------------------
678 void ApiTreeImpl::disposing(com::sun::star::lang::EventObject
const& ) throw()
680 // this is a non-UNO external entry point - we need to keep this object alive for the duration of the call
681 CFG_TRACE_INFO("ApiTreeImpl: Providing UNO object is disposed - disposing the tree");
683 // Tree write Lock should be set by sender
685 CFG_TRACE_INFO_NI("Clearing parent reference");
688 CFG_TRACE_INFO_NI("Trying to dispose");
692 CFG_TRACE_INFO_NI("Done disposing Tree");
693 // uno::Reference<com::sun::star::lang::XComponent> xThis(getUnoInstance(),UNO_QUERY);
694 // if (xThis.is()) xThis->dispose();
696 //-------------------------------------------------------------------------
697 TreeManager
* ApiRootTreeImpl::implSetNotificationSource(TreeManager
* pNew
)
699 TreeManager
* pOld
= m_pNotificationListener
.is() ? m_pNotificationListener
->getSource() : 0;
702 OSL_ENSURE(m_xOptions
.isValid(), "Cannot change notification source without options");
704 if (!m_pNotificationListener
.is())
705 m_pNotificationListener
= new NodeListener(*this);
707 m_pNotificationListener
->setSource(pNew
);
712 // ---------------------------------------------------------------------------------------------------
714 void ApiRootTreeImpl::implSetLocation(rtl::Reference
< configuration::Tree
> const& _aTree
)
716 OSL_ASSERT(_aTree
== getApiTree().getTree());
717 if (!configuration::isEmpty(_aTree
.get()))
719 m_aLocationPath
= _aTree
->getRootPath();
720 OSL_ENSURE(!m_aLocationPath
.isRoot(), "Setting up a root tree without location");
724 OSL_ENSURE(false, "Setting up a root tree without data");
725 m_aLocationPath
= configuration::AbsolutePath::root();
728 if (!m_pNotificationListener
.is())
729 m_pNotificationListener
= new NodeListener(*this);
731 OSL_ENSURE(!m_aLocationPath
.isRoot() && !m_aLocationPath
.isDetached(), "Cannot reregister for notifications: setting empty location");
732 OSL_ENSURE( m_xOptions
.isValid(), "Cannot reregister for notifications: no options available" );
734 m_pNotificationListener
->setLocation(m_aLocationPath
, m_xOptions
);
736 // ---------------------------------------------------------------------------------------------------
738 void ApiRootTreeImpl::releaseData()
740 CFG_TRACE_INFO("Api Root Tree at %s: releasing the Data",OUSTRING2ASCII(m_aLocationPath
.toString()));
741 rtl::Reference
< configuration::Tree
> aTree( m_aTreeImpl
.getTree() );
744 aTree
->disposeData();
746 OSL_ASSERT(configuration::isEmpty(aTree
.get()));
748 OSL_ENSURE( !m_aLocationPath
.isRoot() && !m_aLocationPath
.isDetached(), "Location still needed to release data" );
749 OSL_ENSURE( m_xOptions
.isValid(), "Options still needed to release data" );
751 getApiTree().getProvider().getProviderImpl().releaseSubtree(m_aLocationPath
,m_xOptions
->getRequestOptions());
754 m_aLocationPath
= configuration::AbsolutePath::detachedRoot();
756 // ---------------------------------------------------------------------------------------------------
758 void ApiRootTreeImpl::NodeListener::disposing(TreeManager
* _pSource
)
760 UnoApiLockClearable aGuard
;
762 OSL_ASSERT( !pSource
|| _pSource
== pSource
);
765 // this is a non-UNO external entry point - we need to keep this object alive for the duration of the call
766 uno::Reference
<uno::XInterface
> xKeepAlive( pParent
->m_aTreeImpl
.getUnoInstance() );
767 ApiRootTreeImpl
* pKeepParent
= pParent
;
770 pKeepParent
->disposing(_pSource
);
773 void ApiRootTreeImpl::disposing(TreeManager
*)
775 CFG_TRACE_INFO("Api Root Tree at %s: Cache data is disposed - dispose and release own data",
776 OUSTRING2ASCII(m_aLocationPath
.toString()));
777 // ensure our provider stays alive
778 uno::Reference
<uno::XInterface
> xKeepProvider( m_aTreeImpl
.getUnoProviderInstance() );
780 rtl::Reference
<NodeListener
> xListener
= m_pNotificationListener
;
783 xListener
->clearParent();
787 if (m_aTreeImpl
.disposeTreeNow())
788 releaseData(); // not really needed: the whole data is going away anyways
790 // ---------------------------------------------------------------------------------------------------
793 void disposeOneRemovedNode(configuration::NodeChangeInformation
const& aRemoveInfo
, Factory
& aFactory
)
795 if (aRemoveInfo
.change
.element
.oldValue
.is())
797 OSL_ENSURE(aRemoveInfo
.change
.element
.isDataChange(), "ERROR: Disposing replaced element: Element did not really change !");
799 rtl::Reference
< configuration::ElementTree
> aElementRef( aRemoveInfo
.change
.element
.oldValue
.get() );
801 SetElement
* pSetElement
= aFactory
.findSetElement(aElementRef
);
804 // factory always does an extra acquire
805 uno::Reference
<uno::XInterface
> xReleaseSetElement(pSetElement
->getUnoInstance(), uno::UNO_REF_NO_ACQUIRE
);
807 pSetElement
->haveNewParent(0);
808 pSetElement
->disposeTree(true);
813 // This must apply to a node for which no element tree had been loaded in this view
814 // thus there should not be one now after the change (even if the change was replacing)
815 OSL_ENSURE(!aRemoveInfo
.change
.element
.newValue
.is(), "Cannot dispose replaced element: No tree object available");
818 // ---------------------------------------------------------------------------------------------------
821 void disposeRemovedNodes(configuration::NodeChangesInformation
const& aChanges
, Factory
& aFactory
)
823 for (std::vector
< configuration::NodeChangeInformation
>::const_iterator it
= aChanges
.begin(); it
!= aChanges
.end(); ++it
)
825 switch (it
->change
.type
)
827 case configuration::NodeChangeData::eReplaceElement
:
828 // check if element is actually unchanged !
829 // (cannot dispose of the tree, if it is still in use)
830 if (! it
->change
.element
.isDataChange()) break;
832 // else dispose the old one: fall thru
834 case configuration::NodeChangeData::eRemoveElement
:
835 disposeOneRemovedNode( *it
, aFactory
);
842 // ---------------------------------------------------------------------------------------------------
843 //INodeListener : IConfigListener
844 void ApiRootTreeImpl::NodeListener::nodeChanged(Change
const& aChange
, configuration::AbsolutePath
const& sPath
, TreeManager
* _pSource
)
846 UnoApiLockClearable aGuard
;
848 OSL_ASSERT( !pSource
|| _pSource
== pSource
);
851 // this is a non-UNO external entry point - we need to keep this object alive for the duration of the call
852 uno::Reference
<uno::XInterface
> xKeepAlive( pParent
->m_aTreeImpl
.getUnoInstance() );
853 ApiRootTreeImpl
* pKeepParent
= pParent
;
856 pKeepParent
->nodeChanged(aChange
,sPath
,_pSource
);
859 // ---------------------------------------------------------------------------------------------------
861 //INodeListener : IConfigListener
862 void ApiRootTreeImpl::nodeChanged(Change
const& aChange
, configuration::AbsolutePath
const& aChangePath
, TreeManager
*)
864 // do not dipatch if we are dying/dead anyway
865 if (m_aTreeImpl
.isAlive())
868 rtl::Reference
< configuration::Tree
> aTree(m_aTreeImpl
.getTree());
870 OSL_ENSURE(configuration::Path::hasPrefix(aChangePath
, m_aLocationPath
),
871 "'changed' Path does not indicate this tree or its context: ");
873 configuration::RelativePath aLocalChangePath
= configuration::Path::stripPrefix(aChangePath
,m_aLocationPath
);
875 // find the node and change
876 configuration::NodeRef aNode
;
878 if ( !aLocalChangePath
.isEmpty() )
880 configuration::NodeRef aBaseNode
= aTree
->getRootNode();
884 configuration::RelativePath aLocalPathOld
= configuration::validateAndReducePath(aChangePath
.toString(), aTree
, aBaseNode
);
885 OSL_ENSURE( configuration::matches(aLocalPathOld
,aLocalChangePath
),
886 "New local path different from validateAndReducePath(...) result in notification dispatch");
888 catch (configuration::Exception
& e
) {
889 rtl::OString
sMsg("Cannot validate new path handling for notification dispatch: ");
891 OSL_ENSURE(false, sMsg
.getStr() );
895 configuration::AnyNodeRef aFoundNode
= configuration::getDeepDescendant(aTree
, aBaseNode
, aLocalChangePath
);
896 if ( aFoundNode
.isValid() )
898 if (aFoundNode
.isNode())
900 aNode
= aFoundNode
.toNode();
904 // TODO: Notify using parent node and temporary dummy change
905 OSL_ENSURE( false, "Notification broken: Node being adressed is a Value");
911 aNode
= aTree
->getRootNode();
914 SubtreeChange
const* pTreeChange
= NULL
;
917 pTreeChange
= dynamic_cast<SubtreeChange
const*>(&aChange
);
918 OSL_ENSURE(pTreeChange
!= 0, "Notification broken: Change to inner node is not a subtree change"); // TODO: Notify set change using parent (if available) and temporary dummy change
921 if (pTreeChange
!= NULL
) // implies aNode.isValid()
923 OSL_ENSURE( aChange
.getNodeName() == aTree
->getSimpleNodeName(aNode
.getOffset()),
924 "Change's node-name does not match found node's name - erratic notification");
926 configuration::NodeChangesInformation aChanges
;
928 if (configuration::adjustToChanges(aChanges
, aTree
,aNode
, *pTreeChange
))
930 OSL_ASSERT(aChanges
.size() > 0);
932 Broadcaster
aSender(m_aTreeImpl
.getNotifier(),aChanges
,false);
934 // Should be improved later. Maybe this is the wrong lock for disposeTree ?
935 // aLocalGuard.downgrade(); // partial clear for broadcast
937 aSender
.notifyListeners(aChanges
, false);
939 disposeRemovedNodes(aChanges
, m_aTreeImpl
.getFactory());
943 catch (configuration::InvalidName
& i
)
945 rtl::OString
sMsg("Cannot locate change within this tree: ");
947 OSL_ENSURE(false, sMsg
.getStr() );
949 catch (configuration::Exception
& e
)
951 rtl::OString
sMsg("Unexpected error trying to react on update: ");
953 OSL_ENSURE(false, sMsg
.getStr() );
956 // ---------------------------------------------------------------------------------------------------
958 void ApiRootTreeImpl::NodeListener::nodeDeleted(configuration::AbsolutePath
const& _aPath
, TreeManager
* _pSource
)
960 UnoApiLockClearable aGuard
;
962 OSL_ASSERT( !pSource
|| _pSource
== pSource
);
965 // this is a non-UNO external entry point - we need to keep this object alive for the duration of the call
966 uno::Reference
<uno::XInterface
> xKeepAlive( pParent
->m_aTreeImpl
.getUnoInstance() );
967 ApiRootTreeImpl
* pKeepParent
= pParent
;
970 pKeepParent
->nodeDeleted(_aPath
,_pSource
);
973 // ---------------------------------------------------------------------------------------------------
974 void ApiRootTreeImpl::nodeDeleted(configuration::AbsolutePath
const& _aDeletedPath
, TreeManager
*)
976 { (void)_aDeletedPath
; }
978 // this is a non-UNO external entry point - we need to keep this object alive for the duration of the call
979 uno::Reference
<uno::XInterface
> xKeepAlive( m_aTreeImpl
.getUnoInstance() );
982 OSL_ENSURE(configuration::Path::hasPrefix(m_aLocationPath
, _aDeletedPath
),
983 "'deleted' Path does not indicate this tree or its context: ");
985 // ensure our provider stays alive
986 uno::Reference
<uno::XInterface
> xKeepProvider( m_aTreeImpl
.getUnoProviderInstance() );
988 rtl::Reference
<NodeListener
> xListener
= m_pNotificationListener
;
991 xListener
->clearParent();
995 if (m_aTreeImpl
.disposeTreeNow())
999 // ---------------------------------------------------------------------------------------------------
1001 //-----------------------------------------------------------------------------