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: cacheline.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"
34 #include "cacheline.hxx"
35 #include "builddata.hxx"
36 #include "treechangefactory.hxx"
37 #include "mergechange.hxx"
38 #include "configexcept.hxx"
40 #include <osl/diagnose.h>
44 // -----------------------------------------------------------------------------
45 static inline rtl::OUString
implExtractModuleName(configuration::AbsolutePath
const& _aConfigPath
)
47 return _aConfigPath
.getModuleName();
51 // -----------------------------------------------------------------------------
53 // -----------------------------------------------------------------------------
55 // -----------------------------------------------------------------------------
57 CacheLine::CacheLine(rtl::OUString
const & _aModuleName
)
59 , m_name(_aModuleName
)
63 // -----------------------------------------------------------------------------
65 CacheLine::CacheLine(rtl::OUString
const & _aModuleName
, sharable::TreeFragment
* _pSegment
)
67 , m_name(_aModuleName
)
72 // -----------------------------------------------------------------------------
74 void CacheLine::setBase(sharable::TreeFragment
* _base
)
76 OSL_PRECOND(m_base
== NULL
, "CacheLine: Data base address was already set");
77 OSL_PRECOND( _base
!= NULL
, "CacheLine: Cannot set NULL base address");
80 // -----------------------------------------------------------------------------
82 rtl::Reference
<CacheLine
> CacheLine::createAttached( rtl::OUString
const & _aModuleName
,
83 sharable::TreeFragment
* _aSegment
84 ) SAL_THROW((com::sun::star::uno::RuntimeException
))
86 if (_aModuleName
.getLength() == 0)
88 OSL_ENSURE(false, "Cannot make a cache line without a name");
91 if (_aSegment
== NULL
)
93 OSL_ENSURE(false, "Cannot attach a cache line to a NULL segment");
97 rtl::Reference
<CacheLine
> xResult
= new CacheLine(_aModuleName
,_aSegment
);
101 // -----------------------------------------------------------------------------
103 rtl::Reference
<CacheLine
> CacheLine::createNew( rtl::OUString
const & _aModuleName
104 ) SAL_THROW((com::sun::star::uno::RuntimeException
))
106 if (_aModuleName
.getLength() == 0)
108 OSL_ENSURE(false, "Cannot make a cache line without a name");
112 rtl::Reference
<CacheLine
> xResult
= new CacheLine(_aModuleName
);
116 // -------------------------------------------------------------------------
118 rtl::OUString
CacheLine::getModuleName() const
122 // -----------------------------------------------------------------------------
124 sharable::TreeFragment
* CacheLine::getPartialTree(configuration::AbsolutePath
const& aConfigName
) const
126 sharable::Node
* parent
= internalGetNode(aConfigName
.getParentPath());
128 if (parent
!= 0 && parent
->isSet())
129 return parent
->set
.getElement(aConfigName
.getLocalName().getName());
133 // -----------------------------------------------------------------------------
135 bool CacheLine::hasDefaults() const
137 return m_base
!= 0 && m_base
->hasDefaultsAvailable();
139 // -----------------------------------------------------------------------------
140 sharable::Node
* CacheLine::internalGetNode(configuration::AbsolutePath
const& aConfigName
) const
142 OSL_ASSERT(m_base
!= 0);
143 sharable::Node
* node
= m_base
->getRootNode();
144 OSL_ASSERT(node
!= 0);
145 std::vector
< configuration::Path::Component
>::const_reverse_iterator
i(
146 aConfigName
.begin());
148 i
!= aConfigName
.end() && node
->getName() == i
->getInternalName());
149 while (node
!= 0 && ++i
!= aConfigName
.end()) {
150 node
= node
->getSubnode(i
->getName());
154 // -----------------------------------------------------------------------------
156 sharable::Node
* CacheLine::getNode(configuration::AbsolutePath
const& aConfigName
) const
158 return internalGetNode(aConfigName
);
160 // -------------------------------------------------------------------------
162 sharable::TreeFragment
* CacheLine::setComponentData( backend::ComponentDataStruct
const & _aComponentInstance
,
164 ) SAL_THROW((com::sun::star::uno::RuntimeException
))
166 OSL_PRECOND(_aComponentInstance
.data
.get(), "CacheLine::insertDefaults: inserting NULL defaults !");
167 OSL_PRECOND(_aComponentInstance
.name
== this->getModuleName(),"Data location does not match module");
169 OSL_PRECOND(base() == NULL
, "Data is already loaded");
171 if (base() == NULL
) // no data yet
173 this->setBase( data::buildTree(_aComponentInstance
.data
->getName(), *_aComponentInstance
.data
, _bWithDefaults
) );
178 // -----------------------------------------------------------------------------
180 sharable::TreeFragment
* CacheLine::insertDefaults( backend::NodeInstance
const & _aDefaultInstance
181 ) SAL_THROW((com::sun::star::uno::RuntimeException
))
183 OSL_PRECOND(_aDefaultInstance
.data().get(), "CacheLine::insertDefaults: inserting NULL defaults !");
184 OSL_PRECOND(_aDefaultInstance
.root().getDepth() == 1, "Should have complete component to fill tree with defaults");
185 OSL_PRECOND(_aDefaultInstance
.root().getModuleName() == this->getModuleName(),"Data location does not match module");
187 OSL_PRECOND(m_base
!= NULL
, "Data must already be loaded to insert defaults");
191 data::mergeDefaults(m_base
,*_aDefaultInstance
.data());
196 // -----------------------------------------------------------------------------
197 // -----------------------------------------------------------------------------
199 ExtendedCacheLine::ExtendedCacheLine(rtl::OUString
const & _aModuleName
)
200 : CacheLine(_aModuleName
)
205 // -----------------------------------------------------------------------------
207 ExtendedCacheLine::ExtendedCacheLine(rtl::OUString
const & _aModuleName
,
208 sharable::TreeFragment
* _aSegment
)
209 : CacheLine(_aModuleName
,_aSegment
)
214 // -----------------------------------------------------------------------------
216 rtl::Reference
<ExtendedCacheLine
> ExtendedCacheLine::createAttached( rtl::OUString
const & _aModuleName
,
217 sharable::TreeFragment
* _aSegment
218 ) SAL_THROW((com::sun::star::uno::RuntimeException
))
220 if (_aModuleName
.getLength() == 0)
222 OSL_ENSURE(false, "Cannot make a cache line without a name");
225 if (_aSegment
== NULL
)
227 OSL_ENSURE(false, "Cannot attach a cache line to a NULL segment");
231 rtl::Reference
<ExtendedCacheLine
> xResult
= new ExtendedCacheLine(_aModuleName
,_aSegment
);
235 // -----------------------------------------------------------------------------
237 rtl::Reference
<ExtendedCacheLine
> ExtendedCacheLine::createNew( rtl::OUString
const & _aModuleName
238 ) SAL_THROW((com::sun::star::uno::RuntimeException
))
240 if (_aModuleName
.getLength() == 0)
242 OSL_ENSURE(false, "Cannot make a cache line without a name");
246 rtl::Reference
<ExtendedCacheLine
> xResult
= new ExtendedCacheLine(_aModuleName
);
250 // -------------------------------------------------------------------------
252 void ExtendedCacheLine::addPending(backend::ConstUpdateInstance
const & _anUpdate
) SAL_THROW((com::sun::star::uno::RuntimeException
))
254 configuration::AbsolutePath aRootLocation
= _anUpdate
.root();
256 OSL_PRECOND(!aRootLocation
.isRoot(),"Pending change cannot be located at root");
257 OSL_PRECOND(aRootLocation
.getModuleName() == this->getModuleName(),"Pending change location does not match module");
259 OSL_PRECOND(_anUpdate
.data() != NULL
,"Adding NULL 'pending' change");
260 OSL_PRECOND(_anUpdate
.data()->getNodeName() == aRootLocation
.getLocalName().getName(),
261 "Path to pending change does not match change name");
265 // first make the _pSubtreeChange a full tree starting at the module root
266 auto_ptr
<SubtreeChange
> pRootChange
;
267 SubtreeChange
*pExistingEntry
= NULL
;
269 std::vector
<configuration::Path::Component
>::const_reverse_iterator last
= aRootLocation
.end();
271 OSL_ASSERT(last
!= aRootLocation
.begin());
274 for (std::vector
<configuration::Path::Component
>::const_reverse_iterator it
= aRootLocation
.begin();
278 OSL_ASSERT( it
!= aRootLocation
.end());
279 OSL_ASSERT( it
+1 != aRootLocation
.end());
280 // We need to create a new SubtreeChange
281 rtl::OUString
const aChangeName
= it
->getName();
282 rtl::OUString
const aElementTypeName
= (it
+1)->getTypeName();
284 auto_ptr
<SubtreeChange
> pNewChange
=
285 OTreeChangeFactory::createDummyChange(aChangeName
, aElementTypeName
);
287 if (pExistingEntry
== NULL
)
289 OSL_ASSERT(pRootChange
.get() == NULL
);
291 pRootChange
= pNewChange
;
292 pExistingEntry
= pRootChange
.get();
296 OSL_ASSERT(pRootChange
.get() != NULL
);
298 pExistingEntry
->addChange(base_ptr(pNewChange
));
300 Change
* pChange
= pExistingEntry
->getChange(aChangeName
);
301 pExistingEntry
= static_cast<SubtreeChange
*>(pChange
);
303 OSL_ENSURE(dynamic_cast< SubtreeChange
* >(pChange
) != 0, "ERROR: Cannot recover change just added");
307 auto_ptr
<SubtreeChange
> pAddedChange( new SubtreeChange(*_anUpdate
.data(), treeop::DeepChildCopy()) );
309 if (aRootLocation
.getDepth() > 1)
311 OSL_ASSERT(pRootChange
.get() != NULL
&& pExistingEntry
!= NULL
);
313 // the _pSubtreeChange did not start at root, so add its clone to the built dummies
314 pExistingEntry
->addChange(base_ptr(pAddedChange
));
318 OSL_ASSERT(pRootChange
.get() == NULL
&& pExistingEntry
== NULL
);
320 // the _pSubtreeChange starts at root, so just reset pRootChange
321 pRootChange
= pAddedChange
;
323 OSL_ASSERT(pRootChange
.get() != NULL
);
325 if (m_pPending
.get() == NULL
)
327 // no merge is need, because the existing pending changes are empty
328 m_pPending
= pRootChange
;
334 // We need to merge the new rebased changes into the m_pPending
335 combineUpdates(*pRootChange
,*m_pPending
);
337 catch (configuration::Exception
& e
)
339 rtl::OUString
sMessage(RTL_CONSTASCII_USTRINGPARAM("Update cache for module: Could not add pending changes at"));
341 sMessage
+= aRootLocation
.toString();
343 sMessage
+= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(". Internal Exception:")) + e
.message();
345 throw uno::RuntimeException(sMessage
,0);
349 OSL_POSTCOND(m_pPending
.get() != NULL
, "Could not insert new pending changes");
351 // -----------------------------------------------------------------------------
354 } // namespace configmgr