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 114 oslInterlockedCount Access::acquireCounting() { 115 return osl_incrementInterlockedCount(&m_refCount); 116 } 117 118 void Access::releaseNondeleting() { 119 osl_decrementInterlockedCount(&m_refCount); 120 } 121 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 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 152 void Access::releaseChild(rtl::OUString const & name) { 153 cachedChildren_.erase(name); 154 } 155 156 void Access::initBroadcaster( 157 Modifications::Node const & modifications, Broadcaster * broadcaster) 158 { 159 initBroadcasterAndChanges(modifications, broadcaster, 0); 160 } 161 162 Access::Access(Components & components): 163 components_(components), disposed_(false) 164 {} 165 166 Access::~Access() {} 167 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 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 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 301 Components & Access::getComponents() const { 302 return components_; 303 } 304 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 317 rtl::Reference< Node > Access::getParentNode() { 318 rtl::Reference< Access > parent(getParentAccess()); 319 return parent.is() ? parent->getNode() : rtl::Reference< Node >(); 320 } 321 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 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 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 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 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 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 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 834 bool Access::isDisposed() const { 835 return disposed_; 836 } 837 838 Access::ModifiedChild::ModifiedChild() {} 839 840 Access::ModifiedChild::ModifiedChild( 841 rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified): 842 child(theChild), directlyModified(theDirectlyModified) 843 {} 844 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 > 1633 Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException) { 1634 OSL_ASSERT(thisIs(IS_GROUP)); 1635 return this; 1636 } 1637 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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