merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / api2 / apitreeimplobj.cxx
blobff0453f17ee8bf653c9c243d4850c3f5bcc65056
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: apitreeimplobj.cxx,v $
10 * $Revision: 1.44 $
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"
33 #include <stdio.h>
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"
42 #include "change.hxx"
43 #include "providerimpl.hxx"
44 #include "roottree.hxx"
45 #include "noderef.hxx"
46 #include "anynoderef.hxx"
47 #include "tracer.hxx"
48 #include "treemanager.hxx"
49 #include <cppuhelper/queryinterface.hxx>
50 #include <vos/refernce.hxx>
52 namespace configmgr
54 //-----------------------------------------------------------------------------
55 namespace configapi
57 //-----------------------------------------------------------------------------
58 namespace lang = ::com::sun::star::lang;
59 //-----------------------------------------------------------------------------
60 class Factory;
61 class Notifier;
62 //-----------------------------------------------------------------------------
63 class ApiTreeImpl::ComponentAdapter : public lang::XEventListener
65 vos::ORefCount m_refs;
67 ApiTreeImpl* pOwner;
69 uno::Reference< lang::XComponent > xProvider;
70 uno::Reference< lang::XComponent > xParent;
71 public:
72 ComponentAdapter(ApiTreeImpl& rParent) : pOwner(&rParent) {}
73 virtual ~ComponentAdapter() {}
75 void clear();
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;
81 // XEventListener
82 virtual void SAL_CALL acquire() throw();
83 virtual void SAL_CALL release() throw();
84 private:
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 //-----------------------------------------------------------------------------
92 inline
93 uno::Reference< lang::XComponent >
94 ApiTreeImpl::ComponentAdapter::getComponent(
95 uno::Reference< lang::XComponent > const& rxSlot
96 ) const
98 return rxSlot;
100 //-----------------------------------------------------------------------------
101 inline
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;
110 if (xOld != xComp)
112 rxSlot = xComp;
114 aGuard.clear();
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()
137 ++m_refs;
139 //-------------------------------------------------------------------------
141 void SAL_CALL ApiTreeImpl::ComponentAdapter::release() throw()
143 if (--m_refs == 0)
144 delete this;
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 );
169 aGuard.clear();
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();
177 else
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;
187 this->pOwner = 0;
189 uno::Reference< lang::XComponent > aProvider = this->xProvider;
190 uno::Reference< lang::XComponent > aParent = this->xParent;
191 this->xProvider = 0;
192 this->xParent = 0;
194 aGuard.clear();
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;
208 public:
209 NodeListener(ApiRootTreeImpl& _rParent)
210 : pParent(&_rParent)
211 , pSource(NULL)
212 , m_aLocationPath( configuration::AbsolutePath::root() )
214 ~NodeListener()
216 unbind();
219 TreeManager * getSource()
221 UnoApiLock aGuard;
222 return pSource;
225 void setSource(TreeManager * pNew)
227 UnoApiLock aGuard;
228 if (pParent)
230 if (pNew != pSource)
232 OSL_ENSURE(m_xOptions.isValid(),"Cannot set IConfigListener without Options");
233 if (m_xOptions.isValid())
235 if (pSource)
236 pSource->removeListener(m_xOptions->getRequestOptions(), this);
238 pSource = pNew;
239 if (pNew)
241 OSL_ENSURE(!m_aLocationPath.isRoot(), "Cannot register for notifications: no location set");
242 pNew->addListener(m_aLocationPath, m_xOptions->getRequestOptions(), this);
245 else
246 pSource = 0;
251 void setLocation(configuration::AbsolutePath const& _aLocation, vos::ORef< OOptions > const& _xOptions)
253 OSL_ASSERT(_xOptions.isValid());
255 UnoApiLock aGuard;
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);
270 void unbind()
272 UnoApiLock aGuard;
273 OSL_ASSERT(pParent == 0);
274 pParent = 0;
275 if (pSource)
277 OSL_ASSERT(m_xOptions.isValid());
278 pSource->removeListener(m_xOptions->getRequestOptions(), this);
279 m_xOptions.unbind();
280 m_aLocationPath = configuration::AbsolutePath::root();
285 void clearParent()
287 UnoApiLockClearable aGuard;
288 if (pParent)
290 pParent = 0;
292 if (pSource)
294 TreeManager * pOrgSource = pSource;
295 vos::ORef< OOptions > xOptions = m_xOptions;
297 pSource = 0;
298 m_xOptions.unbind();
299 m_aLocationPath = configuration::AbsolutePath::root();
301 aGuard.clear();
303 OSL_ASSERT(xOptions.isValid());
304 pOrgSource->removeListener(xOptions->getRequestOptions(), this);
309 // Interfaces
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 //-------------------------------------------------------------------------
331 static
332 inline
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 //-------------------------------------------------------------------------
348 static
349 inline
350 configuration::DefaultProvider extractDefaultProvider(ApiTreeImpl* pParentTree)
352 if (pParentTree)
353 return pParentTree->getDefaultProvider();
355 else
356 return configuration::DefaultProvider::createEmpty();
358 //-------------------------------------------------------------------------
359 ApiTreeImpl::ApiTreeImpl(uno::XInterface* pInstance, ApiProvider& rProvider, rtl::Reference< configuration::Tree > const& aTree, ApiTreeImpl* pParentTree)
360 : m_aTree(aTree)
361 , m_aNotifier(new NotifierImpl(aTree))
362 , m_aDefaultProvider(extractDefaultProvider(pParentTree))
363 , m_xProvider()
364 , m_rProvider(rProvider)
365 , m_pParentTree(0)
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);
370 init(pParentTree);
372 //-------------------------------------------------------------------------
373 ApiTreeImpl::ApiTreeImpl(uno::XInterface* _pInstance, ApiProvider& _rProvider, rtl::Reference< configuration::Tree > const& _aTree, configuration::DefaultProvider const& _aDefaultProvider)
374 : m_aTree(_aTree)
375 , m_aNotifier(new NotifierImpl(_aTree))
376 , m_aDefaultProvider(_aDefaultProvider)
377 , m_xProvider()
378 , m_rProvider(_rProvider)
379 , m_pParentTree(0)
380 , m_pInstance(_pInstance)
382 setNodeInstance(_aTree->getRootNode(), _pInstance);
383 init(NULL);
385 //-------------------------------------------------------------------------
387 ApiTreeImpl::~ApiTreeImpl()
389 OSL_ENSURE(m_aNotifier->m_aListeners.isDisposed(),"ApiTree Object was not disposed properly");
390 deinit();
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);
447 return pOld != 0;
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
461 if (!isAlive())
462 return false;
464 if (!bForce)
466 if (m_pParentTree != 0)
467 return false;
469 // recheck after having the mutex
470 checkAlive(); // may throw
472 else if (m_pParentTree)
473 setParentTree(NULL);
475 implDisposeTree();
476 OSL_ASSERT(!isAlive()); // post condition
478 return true;
480 //-------------------------------------------------------------------------
482 bool ApiTreeImpl::disposeTreeNow()
484 CFG_TRACE_INFO("ApiTreeImpl: Disposing Tree Now (unless disposed)");
485 if (isAlive() )
486 return implDisposeTree();
487 else
488 return false;
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;
498 if (xListener.is())
500 xListener->clearParent();
501 xListener.clear();
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");
514 return bDisposed;
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();
532 it != stop;
533 ++it)
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());
549 return true;
551 else
553 CFG_TRACE_INFO("ApiTreeImpl: Tree was already disposed.");
554 return false;
557 //-------------------------------------------------------------------------
558 void ApiTreeImpl::disposeNode(configuration::NodeRef const& aNode, uno::XInterface* pInstance)
560 // This used to contain 3 nested 'isAlive()' calls; why !?
561 if (isAlive())
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()
593 setParentTree(0);
595 uno::Reference<ComponentAdapter> xAdapter = m_xProvider;
596 m_xProvider.clear();
598 if (xAdapter.is())
599 xAdapter->clear();
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;
615 return pRet;
618 //-------------------------------------------------------------------------
619 void ApiTreeImpl::setParentTree(ApiTreeImpl* pParentTree) // internal implementation
621 #if OSL_DEBUG_LEVEL > 0
622 if (pParentTree)
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 !");
632 #endif
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");
643 if (xAdapter.is())
644 xAdapter->setParent(xNew);
645 else
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;
657 if (xAdapter.is())
658 xReturn = xAdapter->getProvider();
659 return xReturn;
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");
686 setParentTree(0);
688 CFG_TRACE_INFO_NI("Trying to dispose");
689 //implDisposeTree();
690 disposeTreeNow();
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;
700 if (pOld != pNew)
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);
710 return pOld;
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");
722 else
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() );
743 if (aTree.is()) {
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());
752 m_xOptions.unbind();
754 m_aLocationPath = configuration::AbsolutePath::detachedRoot();
756 // ---------------------------------------------------------------------------------------------------
758 void ApiRootTreeImpl::NodeListener::disposing(TreeManager * _pSource)
760 UnoApiLockClearable aGuard;
762 OSL_ASSERT( !pSource || _pSource == pSource );
763 if (pParent)
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;
768 aGuard.clear();
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;
781 if (xListener.is())
783 xListener->clearParent();
784 xListener.clear();
787 if (m_aTreeImpl.disposeTreeNow())
788 releaseData(); // not really needed: the whole data is going away anyways
790 // ---------------------------------------------------------------------------------------------------
792 static
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 );
802 if (pSetElement)
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);
811 else
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 // ---------------------------------------------------------------------------------------------------
820 static
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 );
836 break;
838 default: break;
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 );
849 if (pParent)
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;
854 aGuard.clear();
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();
882 #ifdef DBG_UTIL
883 try {
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: ");
890 sMsg += e.what();
891 OSL_ENSURE(false, sMsg.getStr() );
893 #endif // DBG_UTIL
895 configuration::AnyNodeRef aFoundNode = configuration::getDeepDescendant(aTree, aBaseNode, aLocalChangePath);
896 if ( aFoundNode.isValid() )
898 if (aFoundNode.isNode())
900 aNode = aFoundNode.toNode();
902 else
904 // TODO: Notify using parent node and temporary dummy change
905 OSL_ENSURE( false, "Notification broken: Node being adressed is a Value");
909 else
911 aNode = aTree->getRootNode();
914 SubtreeChange const* pTreeChange = NULL;
915 if (aNode.isValid())
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: ");
946 sMsg += i.what();
947 OSL_ENSURE(false, sMsg.getStr() );
949 catch (configuration::Exception& e)
951 rtl::OString sMsg("Unexpected error trying to react on update: ");
952 sMsg += e.what();
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 );
963 if (pParent)
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;
968 aGuard.clear();
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() );
981 #ifdef DBG_UTIL
982 OSL_ENSURE(configuration::Path::hasPrefix(m_aLocationPath, _aDeletedPath),
983 "'deleted' Path does not indicate this tree or its context: ");
984 #endif
985 // ensure our provider stays alive
986 uno::Reference<uno::XInterface> xKeepProvider( m_aTreeImpl.getUnoProviderInstance() );
988 rtl::Reference<NodeListener> xListener = m_pNotificationListener;
989 if (xListener.is())
991 xListener->clearParent();
992 xListener.clear();
995 if (m_aTreeImpl.disposeTreeNow())
996 releaseData();
999 // ---------------------------------------------------------------------------------------------------
1001 //-----------------------------------------------------------------------------