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