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