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