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