Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <cassert>
23 : #include <vector>
24 :
25 : #include "com/sun/star/beans/Property.hpp"
26 : #include "com/sun/star/beans/PropertyAttribute.hpp"
27 : #include "com/sun/star/beans/PropertyChangeEvent.hpp"
28 : #include "com/sun/star/beans/PropertyVetoException.hpp"
29 : #include "com/sun/star/beans/UnknownPropertyException.hpp"
30 : #include "com/sun/star/beans/XExactName.hpp"
31 : #include "com/sun/star/beans/XHierarchicalPropertySet.hpp"
32 : #include "com/sun/star/beans/XHierarchicalPropertySetInfo.hpp"
33 : #include "com/sun/star/beans/XMultiHierarchicalPropertySet.hpp"
34 : #include "com/sun/star/beans/XMultiPropertySet.hpp"
35 : #include "com/sun/star/beans/XPropertiesChangeListener.hpp"
36 : #include "com/sun/star/beans/XProperty.hpp"
37 : #include "com/sun/star/beans/XPropertyChangeListener.hpp"
38 : #include "com/sun/star/beans/XPropertySet.hpp"
39 : #include "com/sun/star/beans/XPropertySetInfo.hpp"
40 : #include "com/sun/star/beans/XVetoableChangeListener.hpp"
41 : #include "com/sun/star/container/ContainerEvent.hpp"
42 : #include "com/sun/star/container/NoSuchElementException.hpp"
43 : #include "com/sun/star/container/XContainer.hpp"
44 : #include "com/sun/star/container/XContainerListener.hpp"
45 : #include "com/sun/star/container/XElementAccess.hpp"
46 : #include "com/sun/star/container/XHierarchicalName.hpp"
47 : #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
48 : #include "com/sun/star/container/XHierarchicalNameReplace.hpp"
49 : #include "com/sun/star/container/XNameAccess.hpp"
50 : #include "com/sun/star/container/XNameContainer.hpp"
51 : #include "com/sun/star/container/XNamed.hpp"
52 : #include "com/sun/star/lang/DisposedException.hpp"
53 : #include "com/sun/star/lang/EventObject.hpp"
54 : #include "com/sun/star/lang/IllegalArgumentException.hpp"
55 : #include "com/sun/star/lang/NoSupportException.hpp"
56 : #include "com/sun/star/lang/WrappedTargetException.hpp"
57 : #include "com/sun/star/lang/XComponent.hpp"
58 : #include "com/sun/star/lang/XEventListener.hpp"
59 : #include "com/sun/star/lang/XServiceInfo.hpp"
60 : #include "com/sun/star/lang/XSingleServiceFactory.hpp"
61 : #include "com/sun/star/lang/XTypeProvider.hpp"
62 : #include "com/sun/star/lang/XUnoTunnel.hpp"
63 : #include "com/sun/star/uno/Any.hxx"
64 : #include "com/sun/star/uno/Reference.hxx"
65 : #include "com/sun/star/uno/RuntimeException.hpp"
66 : #include "com/sun/star/uno/Sequence.hxx"
67 : #include "com/sun/star/uno/Type.hxx"
68 : #include "com/sun/star/uno/TypeClass.hpp"
69 : #include "com/sun/star/uno/XInterface.hpp"
70 : #include "com/sun/star/uno/XWeak.hpp"
71 : #include "com/sun/star/util/ElementChange.hpp"
72 : #include "comphelper/sequenceasvector.hxx"
73 : #include "cppu/unotype.hxx"
74 : #include "cppuhelper/queryinterface.hxx"
75 : #include "cppuhelper/weak.hxx"
76 : #include "osl/interlck.h"
77 : #include "osl/mutex.hxx"
78 : #include "rtl/ref.hxx"
79 : #include "rtl/ustrbuf.hxx"
80 : #include "rtl/ustring.h"
81 : #include "rtl/ustring.hxx"
82 : #include "sal/types.h"
83 :
84 : #include "access.hxx"
85 : #include "broadcaster.hxx"
86 : #include "childaccess.hxx"
87 : #include "components.hxx"
88 : #include "data.hxx"
89 : #include "groupnode.hxx"
90 : #include "localizedpropertynode.hxx"
91 : #include "localizedvaluenode.hxx"
92 : #include "lock.hxx"
93 : #include "modifications.hxx"
94 : #include "node.hxx"
95 : #include "nodemap.hxx"
96 : #include "path.hxx"
97 : #include "propertynode.hxx"
98 : #include "rootaccess.hxx"
99 : #include "setnode.hxx"
100 : #include "type.hxx"
101 :
102 : namespace configmgr {
103 :
104 110522 : oslInterlockedCount Access::acquireCounting() {
105 110522 : return osl_atomic_increment(&m_refCount);
106 : }
107 :
108 110522 : void Access::releaseNondeleting() {
109 110522 : osl_atomic_decrement(&m_refCount);
110 110522 : }
111 :
112 84302 : bool Access::isValue() {
113 84302 : rtl::Reference< Node > p(getNode());
114 84302 : switch (p->kind()) {
115 : case Node::KIND_PROPERTY:
116 : case Node::KIND_LOCALIZED_VALUE:
117 25908 : return true;
118 : case Node::KIND_LOCALIZED_PROPERTY:
119 426 : return !Components::allLocales(getRootAccess()->getLocale());
120 : default:
121 57968 : return false;
122 84302 : }
123 : }
124 :
125 5110 : void Access::markChildAsModified(rtl::Reference< ChildAccess > const & child) {
126 : assert(child.is() && child->getParentAccess() == this);
127 5110 : modifiedChildren_[child->getNameInternal()] = ModifiedChild(child, true);
128 19563 : for (rtl::Reference< Access > p(this);;) {
129 19563 : rtl::Reference< Access > parent(p->getParentAccess());
130 19563 : if (!parent.is()) {
131 : break;
132 : }
133 : assert(dynamic_cast< ChildAccess * >(p.get()) != 0);
134 14453 : parent->modifiedChildren_.insert(
135 : ModifiedChildren::value_type(
136 14453 : p->getNameInternal(),
137 43359 : ModifiedChild(dynamic_cast< ChildAccess * >(p.get()), false)));
138 14453 : p = parent;
139 24673 : }
140 5110 : }
141 :
142 379154 : void Access::releaseChild(OUString const & name) {
143 379154 : cachedChildren_.erase(name);
144 379154 : }
145 :
146 0 : void Access::initBroadcaster(
147 : Modifications::Node const & modifications, Broadcaster * broadcaster)
148 : {
149 0 : initBroadcasterAndChanges(modifications, broadcaster, 0);
150 0 : }
151 :
152 0 : css::uno::Sequence< css::uno::Type > Access::getTypes()
153 : throw (css::uno::RuntimeException)
154 : {
155 : assert(thisIs(IS_ANY));
156 0 : osl::MutexGuard g(*lock_);
157 0 : checkLocalizedPropertyAccess();
158 0 : comphelper::SequenceAsVector< css::uno::Type > types;
159 0 : types.push_back(cppu::UnoType< css::uno::XInterface >::get());
160 0 : types.push_back(cppu::UnoType< css::uno::XWeak >::get());
161 0 : types.push_back(cppu::UnoType< css::lang::XTypeProvider >::get());
162 0 : types.push_back(cppu::UnoType< css::lang::XServiceInfo >::get());
163 0 : types.push_back(cppu::UnoType< css::lang::XComponent >::get());
164 0 : types.push_back(cppu::UnoType< css::container::XContainer >::get());
165 0 : types.push_back(cppu::UnoType< css::beans::XExactName >::get());
166 0 : types.push_back(cppu::UnoType< css::container::XHierarchicalName >::get());
167 0 : types.push_back(cppu::UnoType< css::container::XNamed >::get());
168 0 : types.push_back(cppu::UnoType< css::beans::XProperty >::get());
169 0 : types.push_back(cppu::UnoType< css::container::XElementAccess >::get());
170 0 : types.push_back(cppu::UnoType< css::container::XNameAccess >::get());
171 0 : if (getNode()->kind() == Node::KIND_GROUP) {
172 0 : types.push_back(cppu::UnoType< css::beans::XPropertySetInfo >::get());
173 0 : types.push_back(cppu::UnoType< css::beans::XPropertySet >::get());
174 0 : types.push_back(cppu::UnoType< css::beans::XMultiPropertySet >::get());
175 : types.push_back(
176 0 : cppu::UnoType< css::beans::XHierarchicalPropertySet >::get());
177 : types.push_back(
178 0 : cppu::UnoType< css::beans::XMultiHierarchicalPropertySet >::get());
179 : types.push_back(
180 0 : cppu::UnoType< css::beans::XHierarchicalPropertySetInfo >::get());
181 : }
182 0 : if (getRootAccess()->isUpdate()) {
183 0 : types.push_back(cppu::UnoType< css::container::XNameReplace >::get());
184 : types.push_back(
185 0 : cppu::UnoType< css::container::XHierarchicalNameReplace >::get());
186 0 : if (getNode()->kind() != Node::KIND_GROUP ||
187 0 : dynamic_cast< GroupNode * >(getNode().get())->isExtensible())
188 : {
189 : types.push_back(
190 0 : cppu::UnoType< css::container::XNameContainer >::get());
191 : }
192 0 : if (getNode()->kind() == Node::KIND_SET) {
193 : types.push_back(
194 0 : cppu::UnoType< css::lang::XSingleServiceFactory >::get());
195 : }
196 : } else {
197 : types.push_back(
198 0 : cppu::UnoType< css::container::XHierarchicalNameAccess >::get());
199 : }
200 0 : addTypes(&types);
201 0 : return types.getAsConstList();
202 : }
203 :
204 0 : css::uno::Sequence< sal_Int8 > Access::getImplementationId()
205 : throw (css::uno::RuntimeException)
206 : {
207 : assert(thisIs(IS_ANY));
208 0 : osl::MutexGuard g(*lock_);
209 0 : checkLocalizedPropertyAccess();
210 0 : return css::uno::Sequence< sal_Int8 >();
211 : }
212 :
213 0 : OUString Access::getImplementationName() throw (css::uno::RuntimeException)
214 : {
215 : assert(thisIs(IS_ANY));
216 0 : osl::MutexGuard g(*lock_);
217 0 : checkLocalizedPropertyAccess();
218 0 : return OUString("org.openoffice-configmgr::Access");
219 : }
220 :
221 111 : sal_Bool Access::supportsService(OUString const & ServiceName)
222 : throw (css::uno::RuntimeException)
223 : {
224 : assert(thisIs(IS_ANY));
225 111 : osl::MutexGuard g(*lock_);
226 111 : checkLocalizedPropertyAccess();
227 111 : css::uno::Sequence< OUString > names(getSupportedServiceNames());
228 725 : for (sal_Int32 i = 0; i < names.getLength(); ++i) {
229 691 : if (names[i] == ServiceName) {
230 77 : return true;
231 : }
232 : }
233 34 : return false;
234 : }
235 :
236 111 : css::uno::Sequence< OUString > Access::getSupportedServiceNames()
237 : throw (css::uno::RuntimeException)
238 : {
239 : assert(thisIs(IS_ANY));
240 111 : osl::MutexGuard g(*lock_);
241 111 : checkLocalizedPropertyAccess();
242 111 : comphelper::SequenceAsVector< OUString > services;
243 : services.push_back(
244 111 : OUString("com.sun.star.configuration.ConfigurationAccess"));
245 111 : if (getRootAccess()->isUpdate()) {
246 : services.push_back(
247 111 : OUString("com.sun.star.configuration.ConfigurationUpdateAccess"));
248 : }
249 : services.push_back(
250 111 : OUString("com.sun.star.configuration.HierarchyAccess"));
251 : services.push_back(
252 111 : OUString("com.sun.star.configuration.HierarchyElement"));
253 111 : if (getNode()->kind() == Node::KIND_GROUP) {
254 : services.push_back(
255 34 : OUString("com.sun.star.configuration.GroupAccess"));
256 : services.push_back(
257 34 : OUString("com.sun.star.configuration.PropertyHierarchy"));
258 34 : if (getRootAccess()->isUpdate()) {
259 : services.push_back(
260 34 : OUString("com.sun.star.configuration.GroupUpdate"));
261 : }
262 : } else {
263 : services.push_back(
264 77 : OUString("com.sun.star.configuration.SetAccess"));
265 : services.push_back(
266 77 : OUString("com.sun.star.configuration.SimpleSetAccess"));
267 77 : if (getRootAccess()->isUpdate()) {
268 : services.push_back(
269 77 : OUString("com.sun.star.configuration.SetUpdate"));
270 : services.push_back(
271 77 : OUString("com.sun.star.configuration.SimpleSetUpdate"));
272 : }
273 : }
274 111 : addSupportedServiceNames(&services);
275 111 : return services.getAsConstList();
276 : }
277 :
278 0 : void Access::dispose() throw (css::uno::RuntimeException) {
279 : assert(thisIs(IS_ANY));
280 0 : Broadcaster bc;
281 : {
282 0 : osl::MutexGuard g(*lock_);
283 0 : checkLocalizedPropertyAccess();
284 0 : if (getParentAccess().is()) {
285 : throw css::uno::RuntimeException(
286 : OUString("configmgr dispose inappropriate Access"),
287 0 : static_cast< cppu::OWeakObject * >(this));
288 : }
289 0 : if (disposed_) {
290 0 : return;
291 : }
292 0 : initDisposeBroadcaster(&bc);
293 0 : clearListeners();
294 0 : disposed_ = true;
295 : }
296 0 : bc.send();
297 : }
298 :
299 68 : void Access::addEventListener(
300 : css::uno::Reference< css::lang::XEventListener > const & xListener)
301 : throw (css::uno::RuntimeException)
302 : {
303 : assert(thisIs(IS_ANY));
304 : {
305 68 : osl::MutexGuard g(*lock_);
306 68 : checkLocalizedPropertyAccess();
307 68 : if (!xListener.is()) {
308 : throw css::uno::RuntimeException(
309 : OUString("null listener"),
310 0 : static_cast< cppu::OWeakObject * >(this));
311 : }
312 68 : if (!disposed_) {
313 68 : disposeListeners_.insert(xListener);
314 68 : return;
315 68 : }
316 : }
317 : try {
318 0 : xListener->disposing(
319 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
320 0 : } catch (css::lang::DisposedException &) {}
321 : }
322 :
323 68 : void Access::removeEventListener(
324 : css::uno::Reference< css::lang::XEventListener > const & aListener)
325 : throw (css::uno::RuntimeException)
326 : {
327 : assert(thisIs(IS_ANY));
328 68 : osl::MutexGuard g(*lock_);
329 68 : checkLocalizedPropertyAccess();
330 68 : DisposeListeners::iterator i(disposeListeners_.find(aListener));
331 68 : if (i != disposeListeners_.end()) {
332 68 : disposeListeners_.erase(i);
333 68 : }
334 68 : }
335 :
336 0 : css::uno::Type Access::getElementType() throw (css::uno::RuntimeException) {
337 : assert(thisIs(IS_ANY));
338 0 : osl::MutexGuard g(*lock_);
339 0 : checkLocalizedPropertyAccess();
340 0 : rtl::Reference< Node > p(getNode());
341 0 : switch (p->kind()) {
342 : case Node::KIND_LOCALIZED_PROPERTY:
343 : return mapType(
344 0 : dynamic_cast< LocalizedPropertyNode * >(p.get())->getStaticType());
345 : case Node::KIND_GROUP:
346 : //TODO: Should a specific type be returned for a non-extensible group
347 : // with homogeneous members or for an extensible group that currently
348 : // has only homegeneous members?
349 0 : return cppu::UnoType< cppu::UnoVoidType >::get();
350 : case Node::KIND_SET:
351 0 : return cppu::UnoType< cppu::UnoVoidType >::get(); //TODO: correct?
352 : default:
353 : assert(false);
354 : throw css::uno::RuntimeException(
355 : OUString("this cannot happen"),
356 0 : static_cast< cppu::OWeakObject * >(this));
357 0 : }
358 : }
359 :
360 0 : sal_Bool Access::hasElements() throw (css::uno::RuntimeException) {
361 : assert(thisIs(IS_ANY));
362 0 : osl::MutexGuard g(*lock_);
363 0 : checkLocalizedPropertyAccess();
364 0 : return !getAllChildren().empty(); //TODO: optimize
365 : }
366 :
367 173746 : css::uno::Any Access::getByName(OUString const & aName)
368 : throw (
369 : css::container::NoSuchElementException,
370 : css::lang::WrappedTargetException, css::uno::RuntimeException)
371 : {
372 : assert(thisIs(IS_ANY));
373 173746 : osl::MutexGuard g(*lock_);
374 173746 : checkLocalizedPropertyAccess();
375 173746 : rtl::Reference< ChildAccess > child(getChild(aName));
376 173746 : if (!child.is()) {
377 : throw css::container::NoSuchElementException(
378 20 : aName, static_cast< cppu::OWeakObject * >(this));
379 : }
380 173746 : return child->asValue();
381 : }
382 :
383 8762 : css::uno::Sequence< OUString > Access::getElementNames()
384 : throw (css::uno::RuntimeException)
385 : {
386 : assert(thisIs(IS_ANY));
387 8762 : osl::MutexGuard g(*lock_);
388 8762 : checkLocalizedPropertyAccess();
389 8762 : std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
390 8762 : comphelper::SequenceAsVector< OUString > names;
391 184548 : for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
392 8762 : children.begin());
393 123032 : i != children.end(); ++i)
394 : {
395 52754 : names.push_back((*i)->getNameInternal());
396 : }
397 8762 : return names.getAsConstList();
398 : }
399 :
400 70926 : sal_Bool Access::hasByName(OUString const & aName)
401 : throw (css::uno::RuntimeException)
402 : {
403 : assert(thisIs(IS_ANY));
404 70926 : osl::MutexGuard g(*lock_);
405 70926 : checkLocalizedPropertyAccess();
406 70926 : return getChild(aName).is();
407 : }
408 :
409 30566 : css::uno::Any Access::getByHierarchicalName(OUString const & aName)
410 : throw (css::container::NoSuchElementException, css::uno::RuntimeException)
411 : {
412 : assert(thisIs(IS_ANY));
413 30566 : osl::MutexGuard g(*lock_);
414 30566 : checkLocalizedPropertyAccess();
415 30566 : rtl::Reference< ChildAccess > child(getSubChild(aName));
416 30566 : if (!child.is()) {
417 : throw css::container::NoSuchElementException(
418 4 : aName, static_cast< cppu::OWeakObject * >(this));
419 : }
420 30566 : return child->asValue();
421 : }
422 :
423 124 : sal_Bool Access::hasByHierarchicalName(OUString const & aName)
424 : throw (css::uno::RuntimeException)
425 : {
426 : assert(thisIs(IS_ANY));
427 124 : osl::MutexGuard g(*lock_);
428 124 : checkLocalizedPropertyAccess();
429 124 : return getSubChild(aName).is();
430 : }
431 :
432 0 : void Access::replaceByHierarchicalName(
433 : OUString const & aName, css::uno::Any const & aElement)
434 : throw (
435 : css::lang::IllegalArgumentException,
436 : css::container::NoSuchElementException,
437 : css::lang::WrappedTargetException, css::uno::RuntimeException)
438 : {
439 : //TODO: Actually support sets and combine with replaceByName:
440 : assert(thisIs(IS_UPDATE));
441 0 : Broadcaster bc;
442 : {
443 0 : osl::MutexGuard g(*lock_);
444 0 : checkLocalizedPropertyAccess();
445 0 : rtl::Reference< ChildAccess > child(getSubChild(aName));
446 0 : if (!child.is()) {
447 : throw css::container::NoSuchElementException(
448 0 : aName, static_cast< cppu::OWeakObject * >(this));
449 : }
450 0 : child->checkFinalized();
451 0 : rtl::Reference< Node > parent(child->getParentNode());
452 : assert(parent.is());
453 0 : Modifications localMods;
454 0 : switch (parent->kind()) {
455 : case Node::KIND_LOCALIZED_PROPERTY:
456 : case Node::KIND_GROUP:
457 0 : child->setProperty(aElement, &localMods);
458 0 : break;
459 : case Node::KIND_SET:
460 : throw css::lang::IllegalArgumentException(
461 : OUString("configmgr::Access::replaceByHierarchicalName does not"
462 : " currently support set members"),
463 0 : static_cast< cppu::OWeakObject * >(this), 0);
464 : case Node::KIND_ROOT:
465 : throw css::lang::IllegalArgumentException(
466 : (OUString("configmgr::Access::replaceByHierarchicalName does not"
467 : " allow changing component ")
468 0 : + aName),
469 0 : static_cast< cppu::OWeakObject * >(this), 0);
470 : default:
471 : assert(false); // this cannot happen
472 0 : break;
473 : }
474 0 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
475 : }
476 0 : bc.send();
477 0 : }
478 :
479 42 : void Access::addContainerListener(
480 : css::uno::Reference< css::container::XContainerListener > const & xListener)
481 : throw (css::uno::RuntimeException)
482 : {
483 : assert(thisIs(IS_ANY));
484 : {
485 42 : osl::MutexGuard g(*lock_);
486 42 : checkLocalizedPropertyAccess();
487 42 : if (!xListener.is()) {
488 : throw css::uno::RuntimeException(
489 : OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
490 0 : static_cast< cppu::OWeakObject * >(this));
491 : }
492 42 : if (!disposed_) {
493 42 : containerListeners_.insert(xListener);
494 42 : return;
495 42 : }
496 : }
497 : try {
498 0 : xListener->disposing(
499 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
500 0 : } catch (css::lang::DisposedException &) {}
501 : }
502 :
503 5 : void Access::removeContainerListener(
504 : css::uno::Reference< css::container::XContainerListener > const & xListener)
505 : throw (css::uno::RuntimeException)
506 : {
507 : assert(thisIs(IS_ANY));
508 5 : osl::MutexGuard g(*lock_);
509 5 : checkLocalizedPropertyAccess();
510 5 : ContainerListeners::iterator i(containerListeners_.find(xListener));
511 5 : if (i != containerListeners_.end()) {
512 5 : containerListeners_.erase(i);
513 5 : }
514 5 : }
515 :
516 0 : OUString Access::getExactName(OUString const & aApproximateName)
517 : throw (css::uno::RuntimeException)
518 : {
519 : assert(thisIs(IS_ANY));
520 0 : osl::MutexGuard g(*lock_);
521 0 : checkLocalizedPropertyAccess();
522 0 : return aApproximateName;
523 : }
524 :
525 0 : css::uno::Sequence< css::beans::Property > Access::getProperties()
526 : throw (css::uno::RuntimeException)
527 : {
528 : assert(thisIs(IS_GROUP));
529 0 : osl::MutexGuard g(*lock_);
530 0 : std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
531 0 : comphelper::SequenceAsVector< css::beans::Property > properties;
532 0 : for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
533 0 : children.begin());
534 0 : i != children.end(); ++i)
535 : {
536 0 : properties.push_back((*i)->asProperty());
537 : }
538 0 : return properties.getAsConstList();
539 : }
540 :
541 1437 : css::beans::Property Access::getPropertyByName(OUString const & aName)
542 : throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
543 : {
544 : assert(thisIs(IS_GROUP));
545 1437 : osl::MutexGuard g(*lock_);
546 1437 : rtl::Reference< ChildAccess > child(getChild(aName));
547 1437 : if (!child.is()) {
548 : throw css::beans::UnknownPropertyException(
549 0 : aName, static_cast< cppu::OWeakObject * >(this));
550 : }
551 1437 : return child->asProperty();
552 : }
553 :
554 0 : sal_Bool Access::hasPropertyByName(OUString const & Name)
555 : throw (css::uno::RuntimeException)
556 : {
557 : assert(thisIs(IS_GROUP));
558 0 : osl::MutexGuard g(*lock_);
559 0 : return getChild(Name).is();
560 : }
561 :
562 0 : OUString Access::getHierarchicalName() throw (css::uno::RuntimeException) {
563 : assert(thisIs(IS_ANY));
564 0 : osl::MutexGuard g(*lock_);
565 0 : checkLocalizedPropertyAccess();
566 : // For backwards compatibility, return an absolute path representation where
567 : // available:
568 0 : OUStringBuffer path;
569 0 : rtl::Reference< RootAccess > root(getRootAccess());
570 0 : if (root.is()) {
571 0 : path.append(root->getAbsolutePathRepresentation());
572 : }
573 0 : OUString rel(getRelativePathRepresentation());
574 0 : if (path.getLength() != 0 && !rel.isEmpty()) {
575 0 : path.append(sal_Unicode('/'));
576 : }
577 0 : path.append(rel);
578 0 : return path.makeStringAndClear();
579 : }
580 :
581 0 : OUString Access::composeHierarchicalName(
582 : OUString const & aRelativeName)
583 : throw (
584 : css::lang::IllegalArgumentException, css::lang::NoSupportException,
585 : css::uno::RuntimeException)
586 : {
587 : assert(thisIs(IS_ANY));
588 0 : osl::MutexGuard g(*lock_);
589 0 : checkLocalizedPropertyAccess();
590 0 : if (aRelativeName.isEmpty() || aRelativeName[0] == '/') {
591 : throw css::lang::IllegalArgumentException(
592 : OUString("configmgr composeHierarchicalName inappropriate relative"
593 : " name"),
594 0 : static_cast< cppu::OWeakObject * >(this), -1);
595 : }
596 0 : OUStringBuffer path(getRelativePathRepresentation());
597 0 : if (path.getLength() != 0) {
598 0 : path.append(sal_Unicode('/'));
599 : }
600 0 : path.append(aRelativeName);
601 0 : return path.makeStringAndClear();
602 : }
603 :
604 0 : OUString Access::getName() throw (css::uno::RuntimeException) {
605 : assert(thisIs(IS_ANY));
606 0 : osl::MutexGuard g(*lock_);
607 0 : checkLocalizedPropertyAccess();
608 0 : return getNameInternal();
609 : }
610 :
611 0 : void Access::setName(OUString const & aName)
612 : throw (css::uno::RuntimeException)
613 : {
614 : assert(thisIs(IS_ANY));
615 0 : Broadcaster bc;
616 : {
617 0 : osl::MutexGuard g(*lock_);
618 0 : checkLocalizedPropertyAccess();
619 0 : checkFinalized();
620 0 : Modifications localMods;
621 0 : switch (getNode()->kind()) {
622 : case Node::KIND_GROUP:
623 : case Node::KIND_SET:
624 : {
625 0 : rtl::Reference< Access > parent(getParentAccess());
626 0 : if (parent.is()) {
627 0 : rtl::Reference< Node > node(getNode());
628 0 : if (! node->getTemplateName().isEmpty()) {
629 : rtl::Reference< ChildAccess > other(
630 0 : parent->getChild(aName));
631 0 : if (other.get() == this) {
632 : break;
633 : }
634 0 : if (node->getMandatory() == Data::NO_LAYER &&
635 0 : !(other.is() && other->isFinalized()))
636 : {
637 0 : rtl::Reference< RootAccess > root(getRootAccess());
638 : rtl::Reference< ChildAccess > childAccess(
639 0 : dynamic_cast< ChildAccess * >(this));
640 0 : localMods.add(getRelativePath());
641 : // unbind() modifies the parent chain that
642 : // markChildAsModified() walks, so order is
643 : // important:
644 0 : parent->markChildAsModified(childAccess);
645 : //TODO: must not throw
646 0 : childAccess->unbind(); // must not throw
647 0 : if (other.is()) {
648 0 : other->unbind(); // must not throw
649 : }
650 0 : childAccess->bind(root, parent, aName);
651 : // must not throw
652 0 : parent->markChildAsModified(childAccess);
653 : //TODO: must not throw
654 0 : localMods.add(getRelativePath());
655 0 : break;
656 0 : }
657 0 : }
658 0 : }
659 : }
660 : // fall through
661 : case Node::KIND_LOCALIZED_PROPERTY:
662 : // renaming a property could only work for an extension property,
663 : // but a localized property is never an extension property
664 : throw css::uno::RuntimeException(
665 : OUString("configmgr setName inappropriate node"),
666 0 : static_cast< cppu::OWeakObject * >(this));
667 : default:
668 : assert(false); // this cannot happen
669 0 : break;
670 : }
671 0 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
672 : }
673 0 : bc.send();
674 0 : }
675 :
676 4656 : css::beans::Property Access::getAsProperty() throw (css::uno::RuntimeException)
677 : {
678 : assert(thisIs(IS_ANY));
679 4656 : osl::MutexGuard g(*lock_);
680 4656 : checkLocalizedPropertyAccess();
681 4656 : return asProperty();
682 : }
683 :
684 1437 : css::uno::Reference< css::beans::XPropertySetInfo > Access::getPropertySetInfo()
685 : throw (css::uno::RuntimeException)
686 : {
687 : assert(thisIs(IS_GROUP));
688 1437 : return this;
689 : }
690 :
691 4147 : void Access::setPropertyValue(
692 : OUString const & aPropertyName, css::uno::Any const & aValue)
693 : throw (
694 : css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
695 : css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
696 : css::uno::RuntimeException)
697 : {
698 : assert(thisIs(IS_GROUP));
699 4147 : Broadcaster bc;
700 : {
701 4147 : osl::MutexGuard g(*lock_);
702 4147 : if (!getRootAccess()->isUpdate()) {
703 : throw css::uno::RuntimeException(
704 : OUString("configmgr setPropertyValue on non-update access"),
705 0 : static_cast< cppu::OWeakObject * >(this));
706 : }
707 4147 : Modifications localMods;
708 4147 : if (!setChildProperty(aPropertyName, aValue, &localMods)) {
709 : throw css::beans::UnknownPropertyException(
710 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
711 : }
712 4147 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
713 : }
714 4147 : bc.send();
715 4147 : }
716 :
717 12649 : css::uno::Any Access::getPropertyValue(OUString const & PropertyName)
718 : throw (
719 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
720 : css::uno::RuntimeException)
721 : {
722 : assert(thisIs(IS_GROUP));
723 12649 : osl::MutexGuard g(*lock_);
724 12649 : rtl::Reference< ChildAccess > child(getChild(PropertyName));
725 12649 : if (!child.is()) {
726 : throw css::beans::UnknownPropertyException(
727 0 : PropertyName, static_cast< cppu::OWeakObject * >(this));
728 : }
729 12649 : return child->asValue();
730 : }
731 :
732 0 : void Access::addPropertyChangeListener(
733 : OUString const & aPropertyName,
734 : css::uno::Reference< css::beans::XPropertyChangeListener > const &
735 : xListener)
736 : throw (
737 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
738 : css::uno::RuntimeException)
739 : {
740 : assert(thisIs(IS_GROUP));
741 : {
742 0 : osl::MutexGuard g(*lock_);
743 0 : if (!xListener.is()) {
744 : throw css::uno::RuntimeException(
745 : OUString("null listener"),
746 0 : static_cast< cppu::OWeakObject * >(this));
747 : }
748 0 : checkKnownProperty(aPropertyName);
749 0 : if (!disposed_) {
750 0 : propertyChangeListeners_[aPropertyName].insert(xListener);
751 0 : return;
752 0 : }
753 : }
754 : try {
755 0 : xListener->disposing(
756 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
757 0 : } catch (css::lang::DisposedException &) {}
758 : }
759 :
760 0 : void Access::removePropertyChangeListener(
761 : OUString const & aPropertyName,
762 : css::uno::Reference< css::beans::XPropertyChangeListener > const &
763 : aListener)
764 : throw (
765 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
766 : css::uno::RuntimeException)
767 : {
768 : assert(thisIs(IS_GROUP));
769 0 : osl::MutexGuard g(*lock_);
770 0 : checkKnownProperty(aPropertyName);
771 : PropertyChangeListeners::iterator i(
772 0 : propertyChangeListeners_.find(aPropertyName));
773 0 : if (i != propertyChangeListeners_.end()) {
774 0 : PropertyChangeListenersElement::iterator j(i->second.find(aListener));
775 0 : if (j != i->second.end()) {
776 0 : i->second.erase(j);
777 0 : if (i->second.empty()) {
778 0 : propertyChangeListeners_.erase(i);
779 : }
780 : }
781 0 : }
782 0 : }
783 :
784 0 : void Access::addVetoableChangeListener(
785 : OUString const & PropertyName,
786 : css::uno::Reference< css::beans::XVetoableChangeListener > const &
787 : aListener)
788 : throw (
789 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
790 : css::uno::RuntimeException)
791 : {
792 : assert(thisIs(IS_GROUP));
793 : {
794 0 : osl::MutexGuard g(*lock_);
795 0 : if (!aListener.is()) {
796 : throw css::uno::RuntimeException(
797 : OUString("null listener"),
798 0 : static_cast< cppu::OWeakObject * >(this));
799 : }
800 0 : checkKnownProperty(PropertyName);
801 0 : if (!disposed_) {
802 0 : vetoableChangeListeners_[PropertyName].insert(aListener);
803 : //TODO: actually call vetoableChangeListeners_
804 0 : return;
805 0 : }
806 : }
807 : try {
808 0 : aListener->disposing(
809 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
810 0 : } catch (css::lang::DisposedException &) {}
811 : }
812 :
813 0 : void Access::removeVetoableChangeListener(
814 : OUString const & PropertyName,
815 : css::uno::Reference< css::beans::XVetoableChangeListener > const &
816 : aListener)
817 : throw (
818 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
819 : css::uno::RuntimeException)
820 : {
821 : assert(thisIs(IS_GROUP));
822 0 : osl::MutexGuard g(*lock_);
823 0 : checkKnownProperty(PropertyName);
824 : VetoableChangeListeners::iterator i(
825 0 : vetoableChangeListeners_.find(PropertyName));
826 0 : if (i != vetoableChangeListeners_.end()) {
827 0 : VetoableChangeListenersElement::iterator j(i->second.find(aListener));
828 0 : if (j != i->second.end()) {
829 0 : i->second.erase(j);
830 0 : if (i->second.empty()) {
831 0 : vetoableChangeListeners_.erase(i);
832 : }
833 : }
834 0 : }
835 0 : }
836 :
837 0 : void Access::setPropertyValues(
838 : css::uno::Sequence< OUString > const & aPropertyNames,
839 : css::uno::Sequence< css::uno::Any > const & aValues)
840 : throw (
841 : css::beans::PropertyVetoException, css::lang::IllegalArgumentException,
842 : css::lang::WrappedTargetException, css::uno::RuntimeException)
843 : {
844 : assert(thisIs(IS_GROUP));
845 0 : Broadcaster bc;
846 : {
847 0 : osl::MutexGuard g(*lock_);
848 0 : if (!getRootAccess()->isUpdate()) {
849 : throw css::uno::RuntimeException(
850 : OUString("configmgr setPropertyValues on non-update access"),
851 0 : static_cast< cppu::OWeakObject * >(this));
852 : }
853 0 : if (aPropertyNames.getLength() != aValues.getLength()) {
854 : throw css::lang::IllegalArgumentException(
855 : OUString("configmgr setPropertyValues: aPropertyNames/aValues of"
856 : " different length"),
857 0 : static_cast< cppu::OWeakObject * >(this), -1);
858 : }
859 0 : Modifications localMods;
860 0 : for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) {
861 0 : if (!setChildProperty(aPropertyNames[i], aValues[i], &localMods)) {
862 : throw css::lang::IllegalArgumentException(
863 : OUString("configmgr setPropertyValues inappropriate property"
864 : " name"),
865 0 : static_cast< cppu::OWeakObject * >(this), -1);
866 : }
867 : }
868 0 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
869 : }
870 0 : bc.send();
871 0 : }
872 :
873 0 : css::uno::Sequence< css::uno::Any > Access::getPropertyValues(
874 : css::uno::Sequence< OUString > const & aPropertyNames)
875 : throw (css::uno::RuntimeException)
876 : {
877 : assert(thisIs(IS_GROUP));
878 0 : osl::MutexGuard g(*lock_);
879 0 : css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength());
880 0 : for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) {
881 0 : rtl::Reference< ChildAccess > child(getChild(aPropertyNames[i]));
882 0 : if (!child.is()) {
883 : throw css::uno::RuntimeException(
884 : OUString("configmgr getPropertyValues inappropriate property"
885 : " name"),
886 0 : static_cast< cppu::OWeakObject * >(this));
887 : }
888 0 : vals[i] = child->asValue();
889 0 : }
890 0 : return vals;
891 : }
892 :
893 0 : void Access::addPropertiesChangeListener(
894 : css::uno::Sequence< OUString > const &,
895 : css::uno::Reference< css::beans::XPropertiesChangeListener > const &
896 : xListener)
897 : throw (css::uno::RuntimeException)
898 : {
899 : assert(thisIs(IS_GROUP));
900 : {
901 0 : osl::MutexGuard g(*lock_);
902 0 : if (!xListener.is()) {
903 : throw css::uno::RuntimeException(
904 : OUString("null listener"),
905 0 : static_cast< cppu::OWeakObject * >(this));
906 : }
907 0 : if (!disposed_) {
908 0 : propertiesChangeListeners_.insert(xListener);
909 0 : return;
910 0 : }
911 : }
912 : try {
913 0 : xListener->disposing(
914 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
915 0 : } catch (css::lang::DisposedException &) {}
916 : }
917 :
918 0 : void Access::removePropertiesChangeListener(
919 : css::uno::Reference< css::beans::XPropertiesChangeListener > const &
920 : xListener)
921 : throw (css::uno::RuntimeException)
922 : {
923 : assert(thisIs(IS_GROUP));
924 0 : osl::MutexGuard g(*lock_);
925 : PropertiesChangeListeners::iterator i(
926 0 : propertiesChangeListeners_.find(xListener));
927 0 : if (i != propertiesChangeListeners_.end()) {
928 0 : propertiesChangeListeners_.erase(i);
929 0 : }
930 0 : }
931 :
932 0 : void Access::firePropertiesChangeEvent(
933 : css::uno::Sequence< OUString > const & aPropertyNames,
934 : css::uno::Reference< css::beans::XPropertiesChangeListener > const &
935 : xListener)
936 : throw (css::uno::RuntimeException)
937 : {
938 : assert(thisIs(IS_GROUP));
939 : css::uno::Sequence< css::beans::PropertyChangeEvent > events(
940 0 : aPropertyNames.getLength());
941 0 : for (sal_Int32 i = 0; i < events.getLength(); ++i) {
942 0 : events[i].Source = static_cast< cppu::OWeakObject * >(this);
943 0 : events[i].PropertyName = aPropertyNames[i];
944 0 : events[i].Further = false;
945 0 : events[i].PropertyHandle = -1;
946 : }
947 0 : xListener->propertiesChange(events);
948 0 : }
949 :
950 : css::uno::Reference< css::beans::XHierarchicalPropertySetInfo >
951 0 : Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException) {
952 : assert(thisIs(IS_GROUP));
953 0 : return this;
954 : }
955 :
956 0 : void Access::setHierarchicalPropertyValue(
957 : OUString const & aHierarchicalPropertyName,
958 : css::uno::Any const & aValue)
959 : throw (
960 : css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
961 : css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
962 : css::uno::RuntimeException)
963 : {
964 : assert(thisIs(IS_GROUP));
965 0 : Broadcaster bc;
966 : {
967 0 : osl::MutexGuard g(*lock_);
968 0 : if (!getRootAccess()->isUpdate()) {
969 : throw css::uno::RuntimeException(
970 : OUString("configmgr setHierarchicalPropertyName on non-update"
971 : " access"),
972 0 : static_cast< cppu::OWeakObject * >(this));
973 : }
974 : rtl::Reference< ChildAccess > child(
975 0 : getSubChild(aHierarchicalPropertyName));
976 0 : if (!child.is()) {
977 : throw css::beans::UnknownPropertyException(
978 : aHierarchicalPropertyName,
979 0 : static_cast< cppu::OWeakObject * >(this));
980 : }
981 0 : child->checkFinalized();
982 0 : Modifications localMods;
983 0 : child->setProperty(aValue, &localMods);
984 0 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
985 : }
986 0 : bc.send();
987 0 : }
988 :
989 0 : css::uno::Any Access::getHierarchicalPropertyValue(
990 : OUString const & aHierarchicalPropertyName)
991 : throw (
992 : css::beans::UnknownPropertyException,
993 : css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
994 : css::uno::RuntimeException)
995 : {
996 : assert(thisIs(IS_GROUP));
997 0 : osl::MutexGuard g(*lock_);
998 0 : rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName));
999 0 : if (!child.is()) {
1000 : throw css::beans::UnknownPropertyException(
1001 : aHierarchicalPropertyName,
1002 0 : static_cast< cppu::OWeakObject * >(this));
1003 : }
1004 0 : return child->asValue();
1005 : }
1006 :
1007 0 : void Access::setHierarchicalPropertyValues(
1008 : css::uno::Sequence< OUString > const & aHierarchicalPropertyNames,
1009 : css::uno::Sequence< css::uno::Any > const & Values)
1010 : throw (
1011 : css::beans::PropertyVetoException, css::lang::IllegalArgumentException,
1012 : css::lang::WrappedTargetException, css::uno::RuntimeException)
1013 : {
1014 : assert(thisIs(IS_GROUP));
1015 0 : Broadcaster bc;
1016 : {
1017 0 : osl::MutexGuard g(*lock_);
1018 0 : if (!getRootAccess()->isUpdate()) {
1019 : throw css::uno::RuntimeException(
1020 : OUString("configmgr setPropertyValues on non-update access"),
1021 0 : static_cast< cppu::OWeakObject * >(this));
1022 : }
1023 0 : if (aHierarchicalPropertyNames.getLength() != Values.getLength()) {
1024 : throw css::lang::IllegalArgumentException(
1025 : OUString("configmgr setHierarchicalPropertyValues:"
1026 : " aHierarchicalPropertyNames/Values of different"
1027 : " length"),
1028 0 : static_cast< cppu::OWeakObject * >(this), -1);
1029 : }
1030 0 : Modifications localMods;
1031 0 : for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
1032 : rtl::Reference< ChildAccess > child(
1033 0 : getSubChild(aHierarchicalPropertyNames[i]));
1034 0 : if (!child.is()) {
1035 : throw css::lang::IllegalArgumentException(
1036 : OUString("configmgr setHierarchicalPropertyValues"
1037 : " inappropriate property name"),
1038 0 : static_cast< cppu::OWeakObject * >(this), -1);
1039 : }
1040 0 : child->checkFinalized();
1041 0 : child->setProperty(Values[i], &localMods);
1042 0 : }
1043 0 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1044 : }
1045 0 : bc.send();
1046 0 : }
1047 :
1048 0 : css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues(
1049 : css::uno::Sequence< OUString > const & aHierarchicalPropertyNames)
1050 : throw (
1051 : css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
1052 : css::uno::RuntimeException)
1053 : {
1054 : assert(thisIs(IS_GROUP));
1055 0 : osl::MutexGuard g(*lock_);
1056 : css::uno::Sequence< css::uno::Any > vals(
1057 0 : aHierarchicalPropertyNames.getLength());
1058 0 : for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
1059 : rtl::Reference< ChildAccess > child(
1060 0 : getSubChild(aHierarchicalPropertyNames[i]));
1061 0 : if (!child.is()) {
1062 : throw css::lang::IllegalArgumentException(
1063 : OUString("configmgr getHierarchicalPropertyValues inappropriate"
1064 : " hierarchical property name"),
1065 0 : static_cast< cppu::OWeakObject * >(this), -1);
1066 : }
1067 0 : vals[i] = child->asValue();
1068 0 : }
1069 0 : return vals;
1070 : }
1071 :
1072 0 : css::beans::Property Access::getPropertyByHierarchicalName(
1073 : OUString const & aHierarchicalName)
1074 : throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
1075 : {
1076 : assert(thisIs(IS_GROUP));
1077 0 : osl::MutexGuard g(*lock_);
1078 0 : rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName));
1079 0 : if (!child.is()) {
1080 : throw css::beans::UnknownPropertyException(
1081 0 : aHierarchicalName, static_cast< cppu::OWeakObject * >(this));
1082 : }
1083 0 : return child->asProperty();
1084 : }
1085 :
1086 0 : sal_Bool Access::hasPropertyByHierarchicalName(
1087 : OUString const & aHierarchicalName)
1088 : throw (css::uno::RuntimeException)
1089 : {
1090 : assert(thisIs(IS_GROUP));
1091 0 : osl::MutexGuard g(*lock_);
1092 0 : return getSubChild(aHierarchicalName).is();
1093 : }
1094 :
1095 511 : void Access::replaceByName(
1096 : OUString const & aName, css::uno::Any const & aElement)
1097 : throw (
1098 : css::lang::IllegalArgumentException,
1099 : css::container::NoSuchElementException,
1100 : css::lang::WrappedTargetException, css::uno::RuntimeException)
1101 : {
1102 : assert(thisIs(IS_UPDATE));
1103 511 : Broadcaster bc;
1104 : {
1105 511 : osl::MutexGuard g(*lock_);
1106 511 : checkLocalizedPropertyAccess();
1107 511 : rtl::Reference< ChildAccess > child(getChild(aName));
1108 511 : if (!child.is()) {
1109 : throw css::container::NoSuchElementException(
1110 0 : aName, static_cast< cppu::OWeakObject * >(this));
1111 : }
1112 511 : child->checkFinalized();
1113 511 : Modifications localMods;
1114 511 : switch (getNode()->kind()) {
1115 : case Node::KIND_LOCALIZED_PROPERTY:
1116 : case Node::KIND_GROUP:
1117 511 : child->setProperty(aElement, &localMods);
1118 511 : break;
1119 : case Node::KIND_SET:
1120 : {
1121 : rtl::Reference< ChildAccess > freeAcc(
1122 0 : getFreeSetMember(aElement));
1123 0 : rtl::Reference< RootAccess > root(getRootAccess());
1124 0 : localMods.add(child->getRelativePath());
1125 0 : child->unbind(); // must not throw
1126 0 : freeAcc->bind(root, this, aName); // must not throw
1127 0 : markChildAsModified(freeAcc); //TODO: must not throw
1128 : }
1129 0 : break;
1130 : default:
1131 : assert(false); // this cannot happen
1132 0 : break;
1133 : }
1134 511 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1135 : }
1136 511 : bc.send();
1137 511 : }
1138 :
1139 417 : void Access::insertByName(
1140 : OUString const & aName, css::uno::Any const & aElement)
1141 : throw (
1142 : css::lang::IllegalArgumentException,
1143 : css::container::ElementExistException,
1144 : css::lang::WrappedTargetException, css::uno::RuntimeException)
1145 : {
1146 : assert(thisIs(IS_EXTENSIBLE|IS_UPDATE));
1147 417 : Broadcaster bc;
1148 : {
1149 417 : osl::MutexGuard g(*lock_);
1150 417 : checkLocalizedPropertyAccess();
1151 417 : checkFinalized();
1152 417 : if (getChild(aName).is()) {
1153 : throw css::container::ElementExistException(
1154 0 : aName, static_cast< cppu::OWeakObject * >(this));
1155 : }
1156 417 : Modifications localMods;
1157 417 : switch (getNode()->kind()) {
1158 : case Node::KIND_LOCALIZED_PROPERTY:
1159 0 : insertLocalizedValueChild(aName, aElement, &localMods);
1160 0 : break;
1161 : case Node::KIND_GROUP:
1162 : {
1163 40 : checkValue(aElement, TYPE_ANY, true);
1164 : rtl::Reference< ChildAccess > child(
1165 : new ChildAccess(
1166 40 : components_, getRootAccess(), this, aName,
1167 : new PropertyNode(
1168 40 : Data::NO_LAYER, TYPE_ANY, true, aElement, true)));
1169 40 : markChildAsModified(child);
1170 40 : localMods.add(child->getRelativePath());
1171 : }
1172 40 : break;
1173 : case Node::KIND_SET:
1174 : {
1175 : rtl::Reference< ChildAccess > freeAcc(
1176 377 : getFreeSetMember(aElement));
1177 377 : freeAcc->bind(getRootAccess(), this, aName); // must not throw
1178 377 : markChildAsModified(freeAcc); //TODO: must not throw
1179 377 : localMods.add(freeAcc->getRelativePath());
1180 : }
1181 377 : break;
1182 : default:
1183 : assert(false); // this cannot happen
1184 0 : break;
1185 : }
1186 417 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1187 : }
1188 417 : bc.send();
1189 417 : }
1190 :
1191 35 : void Access::removeByName(OUString const & aName)
1192 : throw (
1193 : css::container::NoSuchElementException,
1194 : css::lang::WrappedTargetException, css::uno::RuntimeException)
1195 : {
1196 : assert(thisIs(IS_EXTENSIBLE|IS_UPDATE));
1197 35 : Broadcaster bc;
1198 : {
1199 35 : osl::MutexGuard g(*lock_);
1200 35 : checkLocalizedPropertyAccess();
1201 35 : rtl::Reference< ChildAccess > child(getChild(aName));
1202 140 : if (!child.is() || child->isFinalized() ||
1203 105 : child->getNode()->getMandatory() != Data::NO_LAYER)
1204 : {
1205 : throw css::container::NoSuchElementException(
1206 0 : aName, static_cast< cppu::OWeakObject * >(this));
1207 : }
1208 35 : if (getNode()->kind() == Node::KIND_GROUP) {
1209 0 : rtl::Reference< Node > p(child->getNode());
1210 0 : if (p->kind() != Node::KIND_PROPERTY ||
1211 0 : !dynamic_cast< PropertyNode * >(p.get())->isExtension())
1212 : {
1213 : throw css::container::NoSuchElementException(
1214 0 : aName, static_cast< cppu::OWeakObject * >(this));
1215 0 : }
1216 : }
1217 35 : Modifications localMods;
1218 35 : localMods.add(child->getRelativePath());
1219 : // unbind() modifies the parent chain that markChildAsModified() walks,
1220 : // so order is important:
1221 35 : markChildAsModified(child); //TODO: must not throw
1222 35 : child->unbind();
1223 35 : getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1224 : }
1225 35 : bc.send();
1226 35 : }
1227 :
1228 377 : css::uno::Reference< css::uno::XInterface > Access::createInstance()
1229 : throw (css::uno::Exception, css::uno::RuntimeException)
1230 : {
1231 : assert(thisIs(IS_SET|IS_UPDATE));
1232 : OUString tmplName(
1233 377 : dynamic_cast< SetNode * >(getNode().get())->getDefaultTemplateName());
1234 : rtl::Reference< Node > tmpl(
1235 377 : components_.getTemplate(Data::NO_LAYER, tmplName));
1236 377 : if (!tmpl.is()) {
1237 : throw css::uno::Exception(
1238 : (OUString("unknown template ") +
1239 0 : tmplName),
1240 0 : static_cast< cppu::OWeakObject * >(this));
1241 : }
1242 377 : rtl::Reference< Node > node(tmpl->clone(true));
1243 377 : node->setLayer(Data::NO_LAYER);
1244 : return static_cast< cppu::OWeakObject * >(
1245 377 : new ChildAccess(components_, getRootAccess(), node));
1246 : }
1247 :
1248 0 : css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments(
1249 : css::uno::Sequence< css::uno::Any > const & aArguments)
1250 : throw (css::uno::Exception, css::uno::RuntimeException)
1251 : {
1252 : assert(thisIs(IS_SET|IS_UPDATE));
1253 0 : if (aArguments.getLength() != 0) {
1254 : throw css::uno::Exception(
1255 : OUString("configuration SimpleSetUpdate createInstanceWithArguments"
1256 : " must not specify any arguments"),
1257 0 : static_cast< cppu::OWeakObject * >(this));
1258 : }
1259 0 : return createInstance();
1260 : }
1261 :
1262 388336 : Access::Access(Components & components):
1263 388336 : components_(components), disposed_(false)
1264 : {
1265 388336 : lock_ = lock();
1266 388336 : }
1267 :
1268 387493 : Access::~Access() {}
1269 :
1270 0 : void Access::initDisposeBroadcaster(Broadcaster * broadcaster) {
1271 : assert(broadcaster != 0);
1272 0 : for (DisposeListeners::iterator i(disposeListeners_.begin());
1273 0 : i != disposeListeners_.end(); ++i)
1274 : {
1275 : broadcaster->addDisposeNotification(
1276 0 : *i,
1277 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
1278 : }
1279 0 : for (ContainerListeners::iterator i(containerListeners_.begin());
1280 0 : i != containerListeners_.end(); ++i)
1281 : {
1282 : broadcaster->addDisposeNotification(
1283 0 : i->get(),
1284 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
1285 : }
1286 0 : for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin());
1287 0 : i != propertyChangeListeners_.end(); ++i)
1288 : {
1289 0 : for (PropertyChangeListenersElement::iterator j(i->second.begin());
1290 0 : j != i->second.end(); ++j)
1291 : {
1292 : broadcaster->addDisposeNotification(
1293 0 : j->get(),
1294 : css::lang::EventObject(
1295 0 : static_cast< cppu::OWeakObject * >(this)));
1296 : }
1297 : }
1298 0 : for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin());
1299 0 : i != vetoableChangeListeners_.end(); ++i)
1300 : {
1301 0 : for (VetoableChangeListenersElement::iterator j(i->second.begin());
1302 0 : j != i->second.end(); ++j)
1303 : {
1304 : broadcaster->addDisposeNotification(
1305 0 : j->get(),
1306 : css::lang::EventObject(
1307 0 : static_cast< cppu::OWeakObject * >(this)));
1308 : }
1309 : }
1310 0 : for (PropertiesChangeListeners::iterator i(
1311 0 : propertiesChangeListeners_.begin());
1312 0 : i != propertiesChangeListeners_.end(); ++i)
1313 : {
1314 : broadcaster->addDisposeNotification(
1315 0 : i->get(),
1316 0 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
1317 : }
1318 : //TODO: iterate over children w/ listeners (incl. unmodified ones):
1319 0 : for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1320 0 : i != modifiedChildren_.end(); ++i)
1321 : {
1322 0 : rtl::Reference< ChildAccess > child(getModifiedChild(i));
1323 0 : if (child.is()) {
1324 0 : child->initDisposeBroadcaster(broadcaster);
1325 : }
1326 0 : }
1327 0 : }
1328 :
1329 0 : void Access::clearListeners() throw() {
1330 0 : disposeListeners_.clear();
1331 0 : containerListeners_.clear();
1332 0 : propertyChangeListeners_.clear();
1333 0 : vetoableChangeListeners_.clear();
1334 0 : propertiesChangeListeners_.clear();
1335 : //TODO: iterate over children w/ listeners (incl. unmodified ones):
1336 0 : for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1337 0 : i != modifiedChildren_.end(); ++i)
1338 : {
1339 0 : rtl::Reference< ChildAccess > child(getModifiedChild(i));
1340 0 : if (child.is()) {
1341 0 : child->clearListeners();
1342 : }
1343 0 : }
1344 0 : }
1345 :
1346 77255 : css::uno::Any Access::queryInterface(css::uno::Type const & aType)
1347 : throw (css::uno::RuntimeException)
1348 : {
1349 77255 : css::uno::Any res(OWeakObject::queryInterface(aType));
1350 77255 : if (res.hasValue()) {
1351 743 : return res;
1352 : }
1353 : res = cppu::queryInterface(
1354 : aType, static_cast< css::lang::XTypeProvider * >(this),
1355 : static_cast< css::lang::XServiceInfo * >(this),
1356 : static_cast< css::lang::XComponent * >(this),
1357 : static_cast< css::container::XHierarchicalNameAccess * >(this),
1358 : static_cast< css::container::XContainer * >(this),
1359 : static_cast< css::beans::XExactName * >(this),
1360 : static_cast< css::container::XHierarchicalName * >(this),
1361 : static_cast< css::container::XNamed * >(this),
1362 : static_cast< css::beans::XProperty * >(this),
1363 : static_cast< css::container::XElementAccess * >(this),
1364 76512 : static_cast< css::container::XNameAccess * >(this));
1365 76512 : if (res.hasValue()) {
1366 55998 : return res;
1367 : }
1368 20514 : if (getNode()->kind() == Node::KIND_GROUP) {
1369 : res = cppu::queryInterface(
1370 : aType, static_cast< css::beans::XPropertySetInfo * >(this),
1371 : static_cast< css::beans::XPropertySet * >(this),
1372 : static_cast< css::beans::XMultiPropertySet * >(this),
1373 : static_cast< css::beans::XHierarchicalPropertySet * >(this),
1374 : static_cast< css::beans::XMultiHierarchicalPropertySet * >(this),
1375 18611 : static_cast< css::beans::XHierarchicalPropertySetInfo * >(this));
1376 18611 : if (res.hasValue()) {
1377 14347 : return res;
1378 : }
1379 : }
1380 6167 : if (getRootAccess()->isUpdate()) {
1381 : res = cppu::queryInterface(
1382 : aType, static_cast< css::container::XNameReplace * >(this),
1383 5915 : static_cast< css::container::XHierarchicalNameReplace * >(this));
1384 5915 : if (res.hasValue()) {
1385 41 : return res;
1386 : }
1387 15847 : if (getNode()->kind() != Node::KIND_GROUP ||
1388 9973 : dynamic_cast< GroupNode * >(getNode().get())->isExtensible())
1389 : {
1390 : res = cppu::queryInterface(
1391 2439 : aType, static_cast< css::container::XNameContainer * >(this));
1392 2439 : if (res.hasValue()) {
1393 1580 : return res;
1394 : }
1395 : }
1396 4294 : if (getNode()->kind() == Node::KIND_SET) {
1397 : res = cppu::queryInterface(
1398 771 : aType, static_cast< css::lang::XSingleServiceFactory * >(this));
1399 : }
1400 : }
1401 4546 : return res;
1402 : }
1403 :
1404 190500 : Components & Access::getComponents() const {
1405 190500 : return components_;
1406 : }
1407 :
1408 370198 : void Access::checkLocalizedPropertyAccess() {
1409 763470 : if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY &&
1410 393272 : !Components::allLocales(getRootAccess()->getLocale()))
1411 : {
1412 : throw css::uno::RuntimeException(
1413 : OUString("configmgr Access to specialized LocalizedPropertyNode"),
1414 0 : static_cast< cppu::OWeakObject * >(this));
1415 : }
1416 370198 : }
1417 :
1418 4748 : rtl::Reference< Node > Access::getParentNode() {
1419 4748 : rtl::Reference< Access > parent(getParentAccess());
1420 4748 : return parent.is() ? parent->getNode() : rtl::Reference< Node >();
1421 : }
1422 :
1423 388157 : rtl::Reference< ChildAccess > Access::getChild(OUString const & name) {
1424 388157 : if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY && name.match("*")) {
1425 2768 : OUString locale(name.copy(1));
1426 2768 : if (locale.match("*")) {
1427 : SAL_WARN(
1428 : "configmgr",
1429 : ("access best-matching localized property value via"
1430 : " \"*<locale>\" with <locale> \"")
1431 : << locale << "\" recursively starting with \"*\"");
1432 0 : return getChild(locale);
1433 : }
1434 : SAL_WARN_IF(
1435 : locale.isEmpty(), "configmgr",
1436 : ("access best-matching localized property value via \"*<locale>\""
1437 : " with empty <locale>; falling back to defaults"));
1438 2768 : if (!locale.isEmpty()) {
1439 : // Find best match using an adaption of RFC 4647 lookup matching
1440 : // rules, removing "-" or "_" delimited segments from the end:
1441 854 : for (;;) {
1442 3511 : rtl::Reference< ChildAccess > child(getChild(locale));
1443 3511 : if (child.is()) {
1444 1803 : return child;
1445 : }
1446 1708 : sal_Int32 i = locale.getLength() - 1;
1447 5978 : while (i > 0 && locale[i] != '-' && locale[i] != '_') {
1448 2562 : --i;
1449 : }
1450 1708 : if (i <= 0) {
1451 : break;
1452 : }
1453 854 : locale = locale.copy(0, i);
1454 3511 : }
1455 : // As a workaround for broken xcu data that does not use shortest
1456 : // xml:lang attributes, look for the first entry with the same first
1457 : // segment as the requested language tag before falling back to
1458 : // defaults (see fdo#33638):
1459 : assert(
1460 : !locale.isEmpty() && locale.indexOf('-') == -1 &&
1461 : locale.indexOf('_') == -1);
1462 : std::vector< rtl::Reference< ChildAccess > > children(
1463 854 : getAllChildren());
1464 4270 : for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
1465 854 : children.begin());
1466 3416 : i != children.end(); ++i)
1467 : {
1468 854 : OUString name2((*i)->getNameInternal());
1469 854 : if (name2.match(locale) &&
1470 0 : (name2.getLength() == locale.getLength() ||
1471 0 : name2[locale.getLength()] == '-' ||
1472 0 : name2[locale.getLength()] == '_'))
1473 : {
1474 0 : return *i;
1475 : }
1476 1708 : }
1477 : }
1478 : // Defaults are the "en-US" locale, the "en" locale, the empty string
1479 : // locale, the first child (if any), or a null ChildAccess, in that
1480 : // order:
1481 965 : rtl::Reference< ChildAccess > child(getChild("en-US"));
1482 965 : if (child.is()) {
1483 111 : return child;
1484 : }
1485 854 : child = getChild("en");
1486 854 : if (child.is()) {
1487 0 : return child;
1488 : }
1489 854 : child = getChild(OUString());
1490 854 : if (child.is()) {
1491 854 : return child;
1492 : }
1493 0 : std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
1494 0 : if (!children.empty()) {
1495 0 : return children.front();
1496 : }
1497 0 : return rtl::Reference< ChildAccess >();
1498 : }
1499 385389 : ModifiedChildren::iterator i(modifiedChildren_.find(name));
1500 770778 : return i == modifiedChildren_.end()
1501 385389 : ? getUnmodifiedChild(name) : getModifiedChild(i);
1502 : }
1503 :
1504 9616 : std::vector< rtl::Reference< ChildAccess > > Access::getAllChildren() {
1505 9616 : std::vector< rtl::Reference< ChildAccess > > vec;
1506 9616 : NodeMap const & members = getNode()->getMembers();
1507 63224 : for (NodeMap::const_iterator i(members.begin()); i != members.end(); ++i) {
1508 53608 : if (modifiedChildren_.find(i->first) == modifiedChildren_.end()) {
1509 53608 : vec.push_back(getUnmodifiedChild(i->first));
1510 : assert(vec.back().is());
1511 : }
1512 : }
1513 28848 : for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1514 19232 : i != modifiedChildren_.end(); ++i)
1515 : {
1516 0 : rtl::Reference< ChildAccess > child(getModifiedChild(i));
1517 0 : if (child.is()) {
1518 0 : vec.push_back(child);
1519 : }
1520 0 : }
1521 9616 : return vec;
1522 : }
1523 :
1524 4698 : void Access::checkValue(css::uno::Any const & value, Type type, bool nillable) {
1525 : bool ok;
1526 4698 : switch (type) {
1527 : case TYPE_NIL:
1528 : assert(false);
1529 : // fall through (cannot happen)
1530 : case TYPE_ERROR:
1531 0 : ok = false;
1532 0 : break;
1533 : case TYPE_ANY:
1534 488 : switch (getDynamicType(value)) {
1535 : case TYPE_ANY:
1536 : assert(false);
1537 : // fall through (cannot happen)
1538 : case TYPE_ERROR:
1539 0 : ok = false;
1540 0 : break;
1541 : case TYPE_NIL:
1542 0 : ok = nillable;
1543 0 : break;
1544 : default:
1545 488 : ok = true;
1546 488 : break;
1547 : }
1548 488 : break;
1549 : default:
1550 4210 : ok = value.hasValue() ? value.isExtractableTo(mapType(type)) : nillable;
1551 4210 : break;
1552 : }
1553 4698 : if (!ok) {
1554 : throw css::lang::IllegalArgumentException(
1555 : OUString("configmgr inappropriate property value"),
1556 0 : static_cast< cppu::OWeakObject * >(this), -1);
1557 : }
1558 4698 : }
1559 :
1560 0 : void Access::insertLocalizedValueChild(
1561 : OUString const & name, css::uno::Any const & value,
1562 : Modifications * localModifications)
1563 : {
1564 : assert(localModifications != 0);
1565 : LocalizedPropertyNode * locprop = dynamic_cast< LocalizedPropertyNode * >(
1566 0 : getNode().get());
1567 0 : checkValue(value, locprop->getStaticType(), locprop->isNillable());
1568 : rtl::Reference< ChildAccess > child(
1569 : new ChildAccess(
1570 0 : components_, getRootAccess(), this, name,
1571 0 : new LocalizedValueNode(Data::NO_LAYER, value)));
1572 0 : markChildAsModified(child);
1573 0 : localModifications->add(child->getRelativePath());
1574 0 : }
1575 :
1576 0 : void Access::reportChildChanges(
1577 : std::vector< css::util::ElementChange > * changes)
1578 : {
1579 : assert(changes != 0);
1580 0 : for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1581 0 : i != modifiedChildren_.end(); ++i)
1582 : {
1583 0 : rtl::Reference< ChildAccess > child(getModifiedChild(i));
1584 0 : if (child.is()) {
1585 0 : child->reportChildChanges(changes);
1586 0 : changes->push_back(css::util::ElementChange());
1587 : //TODO: changed value and/or inserted node
1588 : } else {
1589 0 : changes->push_back(css::util::ElementChange()); //TODO: removed node
1590 : }
1591 0 : }
1592 0 : }
1593 :
1594 12178 : void Access::commitChildChanges(
1595 : bool valid, Modifications * globalModifications)
1596 : {
1597 : assert(globalModifications != 0);
1598 35358 : while (!modifiedChildren_.empty()) {
1599 11002 : bool childValid = valid;
1600 11002 : ModifiedChildren::iterator i(modifiedChildren_.begin());
1601 11002 : rtl::Reference< ChildAccess > child(getModifiedChild(i));
1602 11002 : if (child.is()) {
1603 10967 : childValid = childValid && !child->isFinalized();
1604 10967 : child->commitChanges(childValid, globalModifications);
1605 : //TODO: currently, this is called here for directly inserted
1606 : // children as well as for children whose sub-children were
1607 : // modified (and should never be called for directly removed
1608 : // children); clarify what exactly should happen here for
1609 : // directly inserted children
1610 : }
1611 11002 : NodeMap & members = getNode()->getMembers();
1612 11002 : NodeMap::iterator j(members.find(i->first));
1613 11002 : if (child.is()) {
1614 : // Inserted:
1615 10967 : if (j != members.end()) {
1616 : childValid = childValid &&
1617 10550 : j->second->getFinalized() == Data::NO_LAYER;
1618 10550 : if (childValid) {
1619 10550 : child->getNode()->setMandatory(j->second->getMandatory());
1620 : }
1621 : }
1622 10967 : if (childValid) {
1623 10967 : members[i->first] = child->getNode();
1624 : }
1625 : } else {
1626 : // Removed:
1627 105 : childValid = childValid && j != members.end() &&
1628 35 : j->second->getFinalized() == Data::NO_LAYER &&
1629 140 : j->second->getMandatory() == Data::NO_LAYER;
1630 35 : if (childValid) {
1631 35 : members.erase(j);
1632 : }
1633 : }
1634 11002 : if (childValid && i->second.directlyModified) {
1635 5110 : Path path(getAbsolutePath());
1636 5110 : path.push_back(i->first);
1637 5110 : components_.addModification(path);
1638 5110 : globalModifications->add(path);
1639 : }
1640 11002 : i->second.child->committed();
1641 11002 : modifiedChildren_.erase(i);
1642 11002 : }
1643 12178 : }
1644 :
1645 36172 : void Access::initBroadcasterAndChanges(
1646 : Modifications::Node const & modifications, Broadcaster * broadcaster,
1647 : std::vector< css::util::ElementChange > * allChanges)
1648 : {
1649 : assert(broadcaster != 0);
1650 36172 : comphelper::SequenceAsVector< css::beans::PropertyChangeEvent > propChanges;
1651 36172 : bool collectPropChanges = !propertiesChangeListeners_.empty();
1652 226485 : for (Modifications::Node::Children::const_iterator i(
1653 36172 : modifications.children.begin());
1654 150990 : i != modifications.children.end(); ++i)
1655 : {
1656 39323 : rtl::Reference< ChildAccess > child(getChild(i->first));
1657 39323 : if (child.is()) {
1658 39253 : switch (child->getNode()->kind()) {
1659 : case Node::KIND_LOCALIZED_PROPERTY:
1660 0 : if (!i->second.children.empty()) {
1661 0 : if (Components::allLocales(getRootAccess()->getLocale())) {
1662 0 : child->initBroadcasterAndChanges(
1663 0 : i->second, broadcaster, allChanges);
1664 : //TODO: if allChanges==0, recurse only into children
1665 : // w/ listeners
1666 : } else {
1667 : //TODO: filter child mods that are irrelevant for
1668 : // locale:
1669 0 : for (ContainerListeners::iterator j(
1670 0 : containerListeners_.begin());
1671 0 : j != containerListeners_.end(); ++j)
1672 : {
1673 : broadcaster->
1674 : addContainerElementReplacedNotification(
1675 0 : *j,
1676 : css::container::ContainerEvent(
1677 : static_cast< cppu::OWeakObject * >(
1678 : this),
1679 0 : css::uno::makeAny(i->first),
1680 0 : css::uno::Any(), css::uno::Any()));
1681 : //TODO: non-void Element, ReplacedElement
1682 : }
1683 : PropertyChangeListeners::iterator j(
1684 0 : propertyChangeListeners_.find(i->first));
1685 0 : if (j != propertyChangeListeners_.end()) {
1686 0 : for (PropertyChangeListenersElement::iterator k(
1687 0 : j->second.begin());
1688 0 : k != j->second.end(); ++k)
1689 : {
1690 : broadcaster->addPropertyChangeNotification(
1691 0 : *k,
1692 : css::beans::PropertyChangeEvent(
1693 : static_cast< cppu::OWeakObject * >(
1694 : this),
1695 0 : i->first, false, -1, css::uno::Any(),
1696 0 : css::uno::Any()));
1697 : }
1698 : }
1699 0 : j = propertyChangeListeners_.find(OUString());
1700 0 : if (j != propertyChangeListeners_.end()) {
1701 0 : for (PropertyChangeListenersElement::iterator k(
1702 0 : j->second.begin());
1703 0 : k != j->second.end(); ++k)
1704 : {
1705 : broadcaster->addPropertyChangeNotification(
1706 0 : *k,
1707 : css::beans::PropertyChangeEvent(
1708 : static_cast< cppu::OWeakObject * >(
1709 : this),
1710 0 : i->first, false, -1, css::uno::Any(),
1711 0 : css::uno::Any()));
1712 : }
1713 : }
1714 0 : if (allChanges != 0) {
1715 : allChanges->push_back(
1716 : css::util::ElementChange(
1717 : css::uno::makeAny(
1718 0 : child->getRelativePathRepresentation()),
1719 0 : css::uno::Any(), css::uno::Any()));
1720 : //TODO: non-void Element, ReplacedElement
1721 : }
1722 0 : if (collectPropChanges) {
1723 : propChanges.push_back(
1724 : css::beans::PropertyChangeEvent(
1725 : static_cast< cppu::OWeakObject * >(this),
1726 0 : i->first, false, -1, css::uno::Any(),
1727 0 : css::uno::Any()));
1728 : }
1729 : }
1730 : }
1731 : // else: spurious Modifications::Node not representing a change
1732 0 : break;
1733 : case Node::KIND_LOCALIZED_VALUE:
1734 : assert(Components::allLocales(getRootAccess()->getLocale()));
1735 0 : for (ContainerListeners::iterator j(
1736 0 : containerListeners_.begin());
1737 0 : j != containerListeners_.end(); ++j)
1738 : {
1739 : broadcaster->addContainerElementReplacedNotification(
1740 0 : *j,
1741 : css::container::ContainerEvent(
1742 : static_cast< cppu::OWeakObject * >(this),
1743 0 : css::uno::makeAny(i->first), child->asValue(),
1744 0 : css::uno::Any()));
1745 : //TODO: distinguish add/modify; non-void ReplacedElement
1746 : }
1747 0 : if (allChanges != 0) {
1748 : allChanges->push_back(
1749 : css::util::ElementChange(
1750 : css::uno::makeAny(
1751 0 : child->getRelativePathRepresentation()),
1752 0 : child->asValue(), css::uno::Any()));
1753 : //TODO: non-void ReplacedElement
1754 : }
1755 : assert(!collectPropChanges);
1756 0 : break;
1757 : case Node::KIND_PROPERTY:
1758 : {
1759 32844 : for (ContainerListeners::iterator j(
1760 10948 : containerListeners_.begin());
1761 21896 : j != containerListeners_.end(); ++j)
1762 : {
1763 : broadcaster->addContainerElementReplacedNotification(
1764 0 : *j,
1765 : css::container::ContainerEvent(
1766 : static_cast< cppu::OWeakObject * >(this),
1767 0 : css::uno::makeAny(i->first), child->asValue(),
1768 0 : css::uno::Any()));
1769 : //TODO: distinguish add/remove/modify; non-void
1770 : // ReplacedElement
1771 : }
1772 : PropertyChangeListeners::iterator j(
1773 10948 : propertyChangeListeners_.find(i->first));
1774 10948 : if (j != propertyChangeListeners_.end()) {
1775 0 : for (PropertyChangeListenersElement::iterator k(
1776 0 : j->second.begin());
1777 0 : k != j->second.end(); ++k)
1778 : {
1779 : broadcaster->addPropertyChangeNotification(
1780 0 : *k,
1781 : css::beans::PropertyChangeEvent(
1782 : static_cast< cppu::OWeakObject * >(this),
1783 0 : i->first, false, -1, css::uno::Any(),
1784 0 : css::uno::Any()));
1785 : }
1786 : }
1787 10948 : j = propertyChangeListeners_.find(OUString());
1788 10948 : if (j != propertyChangeListeners_.end()) {
1789 0 : for (PropertyChangeListenersElement::iterator k(
1790 0 : j->second.begin());
1791 0 : k != j->second.end(); ++k)
1792 : {
1793 : broadcaster->addPropertyChangeNotification(
1794 0 : *k,
1795 : css::beans::PropertyChangeEvent(
1796 : static_cast< cppu::OWeakObject * >(this),
1797 0 : i->first, false, -1, css::uno::Any(),
1798 0 : css::uno::Any()));
1799 : }
1800 : }
1801 10948 : if (allChanges != 0) {
1802 : allChanges->push_back(
1803 : css::util::ElementChange(
1804 : css::uno::makeAny(
1805 126 : child->getRelativePathRepresentation()),
1806 252 : child->asValue(), css::uno::Any()));
1807 : //TODO: non-void ReplacedElement
1808 : }
1809 10948 : if (collectPropChanges) {
1810 : propChanges.push_back(
1811 : css::beans::PropertyChangeEvent(
1812 : static_cast< cppu::OWeakObject * >(this),
1813 0 : i->first, false, -1, css::uno::Any(),
1814 0 : css::uno::Any()));
1815 : }
1816 : }
1817 10948 : break;
1818 : case Node::KIND_GROUP:
1819 : case Node::KIND_SET:
1820 28305 : if (i->second.children.empty()) {
1821 874 : if (!child->getNode()->getTemplateName().isEmpty()) {
1822 2622 : for (ContainerListeners::iterator j(
1823 874 : containerListeners_.begin());
1824 1748 : j != containerListeners_.end(); ++j)
1825 : {
1826 : broadcaster->
1827 : addContainerElementInsertedNotification(
1828 0 : *j,
1829 : css::container::ContainerEvent(
1830 : static_cast< cppu::OWeakObject * >(
1831 : this),
1832 0 : css::uno::makeAny(i->first),
1833 0 : child->asValue(), css::uno::Any()));
1834 : }
1835 874 : if (allChanges != 0) {
1836 : allChanges->push_back(
1837 : css::util::ElementChange(
1838 : css::uno::makeAny(
1839 0 : child->getRelativePathRepresentation()),
1840 0 : css::uno::Any(), css::uno::Any()));
1841 : //TODO: non-void Element, ReplacedElement
1842 : }
1843 : }
1844 : // else: spurious Modifications::Node not representing a
1845 : // change
1846 : } else {
1847 27431 : child->initBroadcasterAndChanges(
1848 54862 : i->second, broadcaster, allChanges);
1849 : //TODO: if allChanges==0, recurse only into children w/
1850 : // listeners
1851 : }
1852 28305 : break;
1853 : case Node::KIND_ROOT:
1854 : assert(false); // this cannot happen
1855 0 : break;
1856 : }
1857 : } else {
1858 70 : switch (getNode()->kind()) {
1859 : case Node::KIND_LOCALIZED_PROPERTY:
1860 : // Removed localized property value:
1861 : assert(Components::allLocales(getRootAccess()->getLocale()));
1862 0 : for (ContainerListeners::iterator j(
1863 0 : containerListeners_.begin());
1864 0 : j != containerListeners_.end(); ++j)
1865 : {
1866 : broadcaster->addContainerElementRemovedNotification(
1867 0 : *j,
1868 : css::container::ContainerEvent(
1869 : static_cast< cppu::OWeakObject * >(this),
1870 0 : css::uno::makeAny(i->first), css::uno::Any(),
1871 0 : css::uno::Any()));
1872 : //TODO: non-void ReplacedElement
1873 : }
1874 0 : if (allChanges != 0) {
1875 0 : OUStringBuffer path(getRelativePathRepresentation());
1876 0 : if (path.getLength() != 0) {
1877 0 : path.append(sal_Unicode('/'));
1878 : }
1879 : path.append(
1880 : Data::createSegment(
1881 : OUString("*"),
1882 0 : i->first));
1883 : allChanges->push_back(
1884 : css::util::ElementChange(
1885 : css::uno::makeAny(path.makeStringAndClear()),
1886 0 : css::uno::Any(), css::uno::Any()));
1887 : //TODO: non-void ReplacedElement
1888 : }
1889 : assert(!collectPropChanges);
1890 0 : break;
1891 : case Node::KIND_GROUP:
1892 : {
1893 : // Removed (non-localized) extension property:
1894 0 : for (ContainerListeners::iterator j(
1895 0 : containerListeners_.begin());
1896 0 : j != containerListeners_.end(); ++j)
1897 : {
1898 : broadcaster->addContainerElementRemovedNotification(
1899 0 : *j,
1900 : css::container::ContainerEvent(
1901 : static_cast< cppu::OWeakObject * >(this),
1902 0 : css::uno::makeAny(i->first), css::uno::Any(),
1903 0 : css::uno::Any()));
1904 : //TODO: non-void ReplacedElement
1905 : }
1906 : PropertyChangeListeners::iterator j(
1907 0 : propertyChangeListeners_.find(i->first));
1908 0 : if (j != propertyChangeListeners_.end()) {
1909 0 : for (PropertyChangeListenersElement::iterator k(
1910 0 : j->second.begin());
1911 0 : k != j->second.end(); ++k)
1912 : {
1913 : broadcaster->addPropertyChangeNotification(
1914 0 : *k,
1915 : css::beans::PropertyChangeEvent(
1916 : static_cast< cppu::OWeakObject * >(this),
1917 0 : i->first, false, -1, css::uno::Any(),
1918 0 : css::uno::Any()));
1919 : }
1920 : }
1921 0 : j = propertyChangeListeners_.find(OUString());
1922 0 : if (j != propertyChangeListeners_.end()) {
1923 0 : for (PropertyChangeListenersElement::iterator k(
1924 0 : j->second.begin());
1925 0 : k != j->second.end(); ++k)
1926 : {
1927 : broadcaster->addPropertyChangeNotification(
1928 0 : *k,
1929 : css::beans::PropertyChangeEvent(
1930 : static_cast< cppu::OWeakObject * >(this),
1931 0 : i->first, false, -1, css::uno::Any(),
1932 0 : css::uno::Any()));
1933 : }
1934 : }
1935 0 : if (allChanges != 0) {
1936 : OUStringBuffer path(
1937 0 : getRelativePathRepresentation());
1938 0 : if (path.getLength() != 0) {
1939 0 : path.append(sal_Unicode('/'));
1940 : }
1941 0 : path.append(i->first);
1942 : allChanges->push_back(
1943 : css::util::ElementChange(
1944 : css::uno::makeAny(path.makeStringAndClear()),
1945 0 : css::uno::Any(), css::uno::Any()));
1946 : //TODO: non-void ReplacedElement
1947 : }
1948 0 : if (collectPropChanges) {
1949 : propChanges.push_back(
1950 : css::beans::PropertyChangeEvent(
1951 : static_cast< cppu::OWeakObject * >(this),
1952 0 : i->first, false, -1, css::uno::Any(),
1953 0 : css::uno::Any()));
1954 : }
1955 : }
1956 0 : break;
1957 : case Node::KIND_SET:
1958 : // Removed set member:
1959 70 : if (i->second.children.empty()) {
1960 210 : for (ContainerListeners::iterator j(
1961 70 : containerListeners_.begin());
1962 140 : j != containerListeners_.end(); ++j)
1963 : {
1964 : broadcaster->addContainerElementRemovedNotification(
1965 0 : *j,
1966 : css::container::ContainerEvent(
1967 : static_cast< cppu::OWeakObject * >(this),
1968 0 : css::uno::makeAny(i->first),
1969 0 : css::uno::Any(), css::uno::Any()));
1970 : //TODO: non-void ReplacedElement
1971 : }
1972 70 : if (allChanges != 0) {
1973 : OUStringBuffer path(
1974 0 : getRelativePathRepresentation());
1975 0 : if (path.getLength() != 0) {
1976 0 : path.append(sal_Unicode('/'));
1977 : }
1978 : path.append(
1979 : Data::createSegment(
1980 : OUString("*"),
1981 0 : i->first));
1982 : allChanges->push_back(
1983 : css::util::ElementChange(
1984 : css::uno::makeAny(path.makeStringAndClear()),
1985 0 : css::uno::Any(), css::uno::Any()));
1986 : //TODO: non-void ReplacedElement
1987 : }
1988 : }
1989 : // else: spurious Modifications::Node not representing a change
1990 70 : break;
1991 : default:
1992 : assert(false); // this cannot happen
1993 0 : break;
1994 : }
1995 : }
1996 39323 : }
1997 36172 : if (!propChanges.empty()) {
1998 : css::uno::Sequence< css::beans::PropertyChangeEvent > seq(
1999 0 : propChanges.getAsConstList());
2000 0 : for (PropertiesChangeListeners::iterator i(
2001 0 : propertiesChangeListeners_.begin());
2002 0 : i != propertiesChangeListeners_.end(); ++i)
2003 : {
2004 0 : broadcaster->addPropertiesChangeNotification(*i, seq);
2005 0 : }
2006 36172 : }
2007 36172 : }
2008 :
2009 803 : bool Access::isDisposed() const {
2010 803 : return disposed_;
2011 : }
2012 :
2013 5110 : Access::ModifiedChild::ModifiedChild() {}
2014 :
2015 19563 : Access::ModifiedChild::ModifiedChild(
2016 : rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified):
2017 19563 : child(theChild), directlyModified(theDirectlyModified)
2018 19563 : {}
2019 :
2020 30716 : rtl::Reference< ChildAccess > Access::getModifiedChild(
2021 : ModifiedChildren::iterator const & childIterator)
2022 : {
2023 92148 : return (childIterator->second.child->getParentAccess() == this &&
2024 30646 : (childIterator->second.child->getNameInternal() ==
2025 122654 : childIterator->first))
2026 184156 : ? childIterator->second.child : rtl::Reference< ChildAccess >();
2027 : }
2028 :
2029 419283 : rtl::Reference< ChildAccess > Access::getUnmodifiedChild(
2030 : OUString const & name)
2031 : {
2032 : assert(modifiedChildren_.find(name) == modifiedChildren_.end());
2033 419283 : rtl::Reference< Node > node(getNode()->getMember(name));
2034 419283 : if (!node.is()) {
2035 36522 : return rtl::Reference< ChildAccess >();
2036 : }
2037 382761 : WeakChildMap::iterator i(cachedChildren_.find(name));
2038 382761 : if (i != cachedChildren_.end()) {
2039 3948 : rtl::Reference< ChildAccess > child;
2040 3948 : if (i->second->acquireCounting() > 1) {
2041 3948 : child.set(i->second); // must not throw
2042 : }
2043 3948 : i->second->releaseNondeleting();
2044 3948 : if (child.is()) {
2045 3948 : child->setNode(node);
2046 3948 : return child;
2047 3948 : }
2048 : }
2049 : rtl::Reference< ChildAccess > child(
2050 378813 : new ChildAccess(components_, getRootAccess(), this, name, node));
2051 378813 : cachedChildren_[name] = child.get();
2052 378813 : return child;
2053 : }
2054 :
2055 30690 : rtl::Reference< ChildAccess > Access::getSubChild(OUString const & path) {
2056 30690 : sal_Int32 i = 0;
2057 : // For backwards compatibility, allow absolute paths where meaningful:
2058 30690 : if (!path.isEmpty() && path[0] == '/') {
2059 6023 : ++i;
2060 6023 : if (!getRootAccess().is()) {
2061 0 : return rtl::Reference< ChildAccess >();
2062 : }
2063 6023 : Path abs(getAbsolutePath());
2064 6023 : for (Path::iterator j(abs.begin()); j != abs.end(); ++j) {
2065 0 : OUString name1;
2066 : bool setElement1;
2067 0 : OUString templateName1;
2068 : i = Data::parseSegment(
2069 0 : path, i, &name1, &setElement1, &templateName1);
2070 0 : if (i == -1 || (i != path.getLength() && path[i] != '/')) {
2071 0 : return rtl::Reference< ChildAccess >();
2072 : }
2073 0 : OUString name2;
2074 : bool setElement2;
2075 0 : OUString templateName2;
2076 0 : Data::parseSegment(*j, 0, &name2, &setElement2, &templateName2);
2077 0 : if (name1 != name2 || setElement1 != setElement2 ||
2078 : (setElement1 &&
2079 0 : !Data::equalTemplateNames(templateName1, templateName2)))
2080 : {
2081 0 : return rtl::Reference< ChildAccess >();
2082 : }
2083 0 : if (i != path.getLength()) {
2084 0 : ++i;
2085 : }
2086 6023 : }
2087 : }
2088 76014 : for (rtl::Reference< Access > parent(this);;) {
2089 76014 : OUString name;
2090 : bool setElement;
2091 76014 : OUString templateName;
2092 76014 : i = Data::parseSegment(path, i, &name, &setElement, &templateName);
2093 76014 : if (i == -1 || (i != path.getLength() && path[i] != '/')) {
2094 0 : return rtl::Reference< ChildAccess >();
2095 : }
2096 76014 : rtl::Reference< ChildAccess > child(parent->getChild(name));
2097 76014 : if (!child.is()) {
2098 4 : return rtl::Reference< ChildAccess >();
2099 : }
2100 76010 : if (setElement) {
2101 1437 : rtl::Reference< Node > p(parent->getNode());
2102 1437 : switch (p->kind()) {
2103 : case Node::KIND_LOCALIZED_PROPERTY:
2104 0 : if (!Components::allLocales(getRootAccess()->getLocale()) ||
2105 0 : !templateName.isEmpty())
2106 : {
2107 0 : return rtl::Reference< ChildAccess >();
2108 : }
2109 0 : break;
2110 : case Node::KIND_SET:
2111 1437 : if (!templateName.isEmpty() &&
2112 0 : !dynamic_cast< SetNode * >(p.get())->isValidTemplate(
2113 0 : templateName))
2114 : {
2115 0 : return rtl::Reference< ChildAccess >();
2116 : }
2117 1437 : break;
2118 : default:
2119 0 : return rtl::Reference< ChildAccess >();
2120 1437 : }
2121 : }
2122 : // For backwards compatibility, ignore a final slash after non-value
2123 : // nodes:
2124 76010 : if (child->isValue()) {
2125 26334 : return i == path.getLength()
2126 26334 : ? child : rtl::Reference< ChildAccess >();
2127 49676 : } else if (i >= path.getLength() - 1) {
2128 4352 : return child;
2129 : }
2130 45324 : ++i;
2131 45324 : parent = child.get();
2132 106704 : }
2133 : }
2134 :
2135 4147 : bool Access::setChildProperty(
2136 : OUString const & name, css::uno::Any const & value,
2137 : Modifications * localModifications)
2138 : {
2139 : assert(localModifications != 0);
2140 4147 : rtl::Reference< ChildAccess > child(getChild(name));
2141 4147 : if (!child.is()) {
2142 0 : return false;
2143 : }
2144 4147 : child->checkFinalized();
2145 4147 : child->setProperty(value, localModifications);
2146 4147 : return true;
2147 : }
2148 :
2149 6093 : css::beans::Property Access::asProperty() {
2150 6093 : css::uno::Type type;
2151 : bool nillable;
2152 : bool removable;
2153 6093 : rtl::Reference< Node > p(getNode());
2154 6093 : switch (p->kind()) {
2155 : case Node::KIND_PROPERTY:
2156 : {
2157 1422 : PropertyNode * prop = dynamic_cast< PropertyNode * >(p.get());
2158 1422 : type = mapType(prop->getStaticType());
2159 1422 : nillable = prop->isNillable();
2160 1422 : removable = prop->isExtension();
2161 : }
2162 : break;
2163 : case Node::KIND_LOCALIZED_PROPERTY:
2164 : {
2165 : LocalizedPropertyNode * locprop =
2166 0 : dynamic_cast< LocalizedPropertyNode *>(p.get());
2167 0 : if (Components::allLocales(getRootAccess()->getLocale())) {
2168 0 : type = cppu::UnoType< css::uno::XInterface >::get();
2169 : //TODO: correct?
2170 0 : removable = false;
2171 : } else {
2172 0 : type = mapType(locprop->getStaticType());
2173 0 : removable = false; //TODO ???
2174 : }
2175 0 : nillable = locprop->isNillable();
2176 : }
2177 : break;
2178 : case Node::KIND_LOCALIZED_VALUE:
2179 : {
2180 : LocalizedPropertyNode * locprop =
2181 0 : dynamic_cast< LocalizedPropertyNode * >(getParentNode().get());
2182 0 : type = mapType(locprop->getStaticType());
2183 0 : nillable = locprop->isNillable();
2184 0 : removable = false; //TODO ???
2185 : }
2186 : break;
2187 : default:
2188 4671 : type = cppu::UnoType< css::uno::XInterface >::get(); //TODO: correct?
2189 4671 : nillable = false;
2190 4671 : rtl::Reference< Node > parent(getParentNode());
2191 4671 : removable = parent.is() && parent->kind() == Node::KIND_SET;
2192 4671 : break;
2193 : }
2194 : return css::beans::Property(
2195 6093 : getNameInternal(), -1, type,
2196 : (css::beans::PropertyAttribute::BOUND | //TODO: correct for group/set?
2197 : css::beans::PropertyAttribute::CONSTRAINED |
2198 : (nillable ? css::beans::PropertyAttribute::MAYBEVOID : 0) |
2199 12186 : (getRootAccess()->isUpdate()
2200 : ? (removable ? css::beans::PropertyAttribute::REMOVEABLE : 0)
2201 24372 : : css::beans::PropertyAttribute::READONLY))); //TODO: MAYBEDEFAULT
2202 : }
2203 :
2204 5075 : void Access::checkFinalized() {
2205 5075 : if (isFinalized()) {
2206 : throw css::lang::IllegalArgumentException(
2207 : OUString("configmgr modification of finalized item"),
2208 0 : static_cast< cppu::OWeakObject * >(this), -1);
2209 : }
2210 5075 : }
2211 :
2212 0 : void Access::checkKnownProperty(OUString const & descriptor) {
2213 0 : if (descriptor.isEmpty()) {
2214 : return;
2215 : }
2216 0 : rtl::Reference< ChildAccess > child(getChild(descriptor));
2217 0 : if (child.is()) {
2218 0 : switch (child->getNode()->kind()) {
2219 : case Node::KIND_PROPERTY:
2220 : return;
2221 : case Node::KIND_LOCALIZED_PROPERTY:
2222 0 : if (!Components::allLocales(getRootAccess()->getLocale())) {
2223 : return;
2224 : }
2225 0 : break;
2226 : case Node::KIND_LOCALIZED_VALUE:
2227 0 : if (Components::allLocales(getRootAccess()->getLocale())) {
2228 : return;
2229 : }
2230 0 : break;
2231 : default:
2232 0 : break;
2233 : }
2234 : }
2235 : throw css::beans::UnknownPropertyException(
2236 0 : descriptor, static_cast< cppu::OWeakObject * >(this));
2237 : }
2238 :
2239 377 : rtl::Reference< ChildAccess > Access::getFreeSetMember(
2240 : css::uno::Any const & value)
2241 : {
2242 377 : rtl::Reference< ChildAccess > freeAcc;
2243 377 : css::uno::Reference< css::lang::XUnoTunnel > tunnel;
2244 377 : value >>= tunnel;
2245 377 : if (tunnel.is()) {
2246 : freeAcc.set(
2247 : reinterpret_cast< ChildAccess * >(
2248 377 : tunnel->getSomething(ChildAccess::getTunnelId())));
2249 : }
2250 1131 : if (!freeAcc.is() || freeAcc->getParentAccess().is() ||
2251 377 : (freeAcc->isInTransaction() &&
2252 377 : freeAcc->getRootAccess() != getRootAccess()))
2253 : {
2254 : throw css::lang::IllegalArgumentException(
2255 : OUString("configmgr inappropriate set element"),
2256 0 : static_cast< cppu::OWeakObject * >(this), 1);
2257 : }
2258 : assert(dynamic_cast< SetNode * >(getNode().get()) != 0);
2259 1131 : if (!dynamic_cast< SetNode * >(getNode().get())->isValidTemplate(
2260 1131 : freeAcc->getNode()->getTemplateName()))
2261 : {
2262 : throw css::lang::IllegalArgumentException(
2263 : OUString("configmgr inappropriate set element"),
2264 0 : static_cast< cppu::OWeakObject * >(this), 1);
2265 : }
2266 377 : return freeAcc;
2267 : }
2268 :
2269 5110 : rtl::Reference< Access > Access::getNotificationRoot() {
2270 19563 : for (rtl::Reference< Access > p(this);;) {
2271 19563 : rtl::Reference< Access > parent(p->getParentAccess());
2272 19563 : if (!parent.is()) {
2273 10220 : return p;
2274 : }
2275 14453 : p = parent;
2276 24673 : }
2277 : }
2278 :
2279 : #if !defined NDEBUG
2280 : bool Access::thisIs(int what) {
2281 : osl::MutexGuard g(*lock_);
2282 : rtl::Reference< Node > p(getNode());
2283 : Node::Kind k(p->kind());
2284 : return (k != Node::KIND_PROPERTY && k != Node::KIND_LOCALIZED_VALUE &&
2285 : ((what & IS_GROUP) == 0 || k == Node::KIND_GROUP) &&
2286 : ((what & IS_SET) == 0 || k == Node::KIND_SET) &&
2287 : ((what & IS_EXTENSIBLE) == 0 || k != Node::KIND_GROUP ||
2288 : dynamic_cast< GroupNode * >(p.get())->isExtensible()) &&
2289 : ((what & IS_GROUP_MEMBER) == 0 ||
2290 : getParentNode()->kind() == Node::KIND_GROUP)) ||
2291 : ((what & IS_SET_MEMBER) == 0 ||
2292 : getParentNode()->kind() == Node::KIND_SET) ||
2293 : ((what & IS_UPDATE) == 0 || getRootAccess()->isUpdate());
2294 : }
2295 : #endif
2296 :
2297 : }
2298 :
2299 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|