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