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