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