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/uno/Any.hxx>
61 #include <com/sun/star/uno/Reference.hxx>
62 #include <com/sun/star/uno/RuntimeException.hpp>
63 #include <com/sun/star/uno/Sequence.hxx>
64 #include <com/sun/star/uno/Type.hxx>
65 #include <com/sun/star/uno/XInterface.hpp>
66 #include <com/sun/star/uno/XWeak.hpp>
67 #include <com/sun/star/util/ElementChange.hpp>
68 #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 { cppu::UnoType< css::uno::XInterface >::get(),
188  };
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 
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:
454  assert(thisIs(IS_UPDATE));
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 {
536  assert(thisIs(IS_GROUP));
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 {
550  assert(thisIs(IS_GROUP));
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 {
562  assert(thisIs(IS_GROUP));
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 {
691  assert(thisIs(IS_GROUP));
692  return this;
693 }
694 
696  OUString const & aPropertyName, css::uno::Any const & aValue)
697 {
698  assert(thisIs(IS_GROUP));
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 {
719  assert(thisIs(IS_GROUP));
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 {
734  assert(thisIs(IS_GROUP));
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 {
758  assert(thisIs(IS_GROUP));
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 {
779  assert(thisIs(IS_GROUP));
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 {
804  assert(thisIs(IS_GROUP));
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 {
824  assert(thisIs(IS_GROUP));
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 {
855  assert(thisIs(IS_GROUP));
856  osl::MutexGuard g(*lock_);
857  css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength());
858  auto aValsRange = asNonConstRange(vals);
859  for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i)
860  {
861  if (!getByNameFast(aPropertyNames[i], aValsRange[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 {
875  assert(thisIs(IS_GROUP));
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 {
897  assert(thisIs(IS_GROUP));
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 {
911  assert(thisIs(IS_GROUP));
912  css::uno::Sequence< css::beans::PropertyChangeEvent > events(
913  aPropertyNames.getLength());
914  auto aEventsRange = asNonConstRange(events);
915  for (sal_Int32 i = 0; i < events.getLength(); ++i) {
916  aEventsRange[i].Source = static_cast< cppu::OWeakObject * >(this);
917  aEventsRange[i].PropertyName = aPropertyNames[i];
918  aEventsRange[i].Further = false;
919  aEventsRange[i].PropertyHandle = -1;
920  }
921  xListener->propertiesChange(events);
922 }
923 
924 css::uno::Reference< css::beans::XHierarchicalPropertySetInfo >
926  assert(thisIs(IS_GROUP));
927  return this;
928 }
929 
931  OUString const & aHierarchicalPropertyName,
932  css::uno::Any const & aValue)
933 {
934  assert(thisIs(IS_GROUP));
935  Broadcaster bc;
936  {
937  osl::MutexGuard g(*lock_);
938  if (!getRootAccess()->isUpdate()) {
939  throw css::uno::RuntimeException(
940  "configmgr setHierarchicalPropertyName on non-update access",
941  static_cast< cppu::OWeakObject * >(this));
942  }
944  getSubChild(aHierarchicalPropertyName));
945  if (!child.is()) {
946  throw css::beans::UnknownPropertyException(
947  aHierarchicalPropertyName,
948  static_cast< cppu::OWeakObject * >(this));
949  }
950  child->checkFinalized();
951  Modifications localMods;
952  child->setProperty(aValue, &localMods);
953  getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
954  }
955  bc.send();
956 }
957 
959  OUString const & aHierarchicalPropertyName)
960 {
961  assert(thisIs(IS_GROUP));
962  osl::MutexGuard g(*lock_);
963  rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName));
964  if (!child.is()) {
965  throw css::beans::UnknownPropertyException(
966  aHierarchicalPropertyName,
967  static_cast< cppu::OWeakObject * >(this));
968  }
969  return child->asValue();
970 }
971 
973  css::uno::Sequence< OUString > const & aHierarchicalPropertyNames,
974  css::uno::Sequence< css::uno::Any > const & Values)
975 {
976  assert(thisIs(IS_GROUP));
977  Broadcaster bc;
978  {
979  osl::MutexGuard g(*lock_);
980  if (!getRootAccess()->isUpdate()) {
981  throw css::uno::RuntimeException(
982  "configmgr setPropertyValues on non-update access",
983  static_cast< cppu::OWeakObject * >(this));
984  }
985  if (aHierarchicalPropertyNames.getLength() != Values.getLength()) {
986  throw css::lang::IllegalArgumentException(
987  ("configmgr setHierarchicalPropertyValues:"
988  " aHierarchicalPropertyNames/Values of different length"),
989  static_cast< cppu::OWeakObject * >(this), -1);
990  }
991  Modifications localMods;
992  for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
994  getSubChild(aHierarchicalPropertyNames[i]));
995  if (!child.is()) {
996  throw css::lang::IllegalArgumentException(
997  ("configmgr setHierarchicalPropertyValues inappropriate"
998  " property name"),
999  static_cast< cppu::OWeakObject * >(this), -1);
1000  }
1001  child->checkFinalized();
1002  child->setProperty(Values[i], &localMods);
1003  }
1004  getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1005  }
1006  bc.send();
1007 }
1008 
1009 css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues(
1010  css::uno::Sequence< OUString > const & aHierarchicalPropertyNames)
1011 {
1012  assert(thisIs(IS_GROUP));
1013  osl::MutexGuard g(*lock_);
1014  css::uno::Sequence< css::uno::Any > vals(
1015  aHierarchicalPropertyNames.getLength());
1016  auto aValsRange = asNonConstRange(vals);
1017  for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
1019  getSubChild(aHierarchicalPropertyNames[i]));
1020  if (!child.is()) {
1021  throw css::lang::IllegalArgumentException(
1022  ("configmgr getHierarchicalPropertyValues inappropriate"
1023  " hierarchical property name"),
1024  static_cast< cppu::OWeakObject * >(this), -1);
1025  }
1026  aValsRange[i] = child->asValue();
1027  }
1028  return vals;
1029 }
1030 
1032  OUString const & aHierarchicalName)
1033 {
1034  assert(thisIs(IS_GROUP));
1035  osl::MutexGuard g(*lock_);
1036  rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName));
1037  if (!child.is()) {
1038  throw css::beans::UnknownPropertyException(
1039  aHierarchicalName, static_cast< cppu::OWeakObject * >(this));
1040  }
1041  return child->asProperty();
1042 }
1043 
1045  OUString const & aHierarchicalName)
1046 {
1047  assert(thisIs(IS_GROUP));
1048  osl::MutexGuard g(*lock_);
1049  return getSubChild(aHierarchicalName).is();
1050 }
1051 
1053  OUString const & aName, css::uno::Any const & aElement)
1054 {
1055  assert(thisIs(IS_UPDATE));
1056  Broadcaster bc;
1057  {
1058  osl::MutexGuard g(*lock_);
1061  if (!child.is()) {
1062  throw css::container::NoSuchElementException(
1063  aName, static_cast< cppu::OWeakObject * >(this));
1064  }
1065  child->checkFinalized();
1066  Modifications localMods;
1067  switch (getNode()->kind()) {
1069  case Node::KIND_GROUP:
1070  child->setProperty(aElement, &localMods);
1071  break;
1072  case Node::KIND_SET:
1073  {
1075  getFreeSetMember(aElement));
1077  localMods.add(child->getRelativePath());
1078  child->unbind(); // must not throw
1079  freeAcc->bind(root, this, aName); // must not throw
1080  markChildAsModified(freeAcc); //TODO: must not throw
1081  }
1082  break;
1083  default:
1084  assert(false); // this cannot happen
1085  break;
1086  }
1087  getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1088  }
1089  bc.send();
1090 }
1091 
1093  OUString const & aName, css::uno::Any const & aElement)
1094 {
1095  assert(thisIs(IS_EXTENSIBLE|IS_UPDATE));
1096  Broadcaster bc;
1097  {
1098  osl::MutexGuard g(*lock_);
1100  checkFinalized();
1101  if (getChild(aName).is()) {
1102  throw css::container::ElementExistException(
1103  aName, static_cast< cppu::OWeakObject * >(this));
1104  }
1105  Modifications localMods;
1106  switch (getNode()->kind()) {
1108  if (!isValidName(aName, false)) {
1109  throw css::lang::IllegalArgumentException(
1110  aName, static_cast<cppu::OWeakObject *>(this), 0);
1111  }
1112  insertLocalizedValueChild(aName, aElement, &localMods);
1113  break;
1114  case Node::KIND_GROUP:
1115  {
1116  if (!isValidName(aName, false)) {
1117  throw css::lang::IllegalArgumentException(
1118  aName, static_cast<cppu::OWeakObject *>(this), 0);
1119  }
1120  checkValue(aElement, TYPE_ANY, true);
1121  rtl::Reference child(
1122  new ChildAccess(
1123  components_, getRootAccess(), this, aName,
1124  new PropertyNode(
1125  Data::NO_LAYER, TYPE_ANY, true, aElement, true)));
1126  markChildAsModified(child);
1127  localMods.add(child->getRelativePath());
1128  }
1129  break;
1130  case Node::KIND_SET:
1131  {
1132  if (!isValidName(aName, true)) {
1133  throw css::lang::IllegalArgumentException(
1134  aName, static_cast<cppu::OWeakObject *>(this), 0);
1135  }
1137  getFreeSetMember(aElement));
1138  freeAcc->bind(getRootAccess(), this, aName); // must not throw
1139  markChildAsModified(freeAcc); //TODO: must not throw
1140  localMods.add(freeAcc->getRelativePath());
1141  }
1142  break;
1143  default:
1144  assert(false); // this cannot happen
1145  break;
1146  }
1147  getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1148  }
1149  bc.send();
1150 }
1151 
1152 void Access::removeByName(OUString const & aName)
1153 {
1154  assert(thisIs(IS_EXTENSIBLE|IS_UPDATE));
1155  Broadcaster bc;
1156  {
1157  osl::MutexGuard g(*lock_);
1160  if (!child.is() || child->isFinalized() ||
1161  child->getNode()->getMandatory() != Data::NO_LAYER)
1162  {
1163  throw css::container::NoSuchElementException(
1164  aName, static_cast< cppu::OWeakObject * >(this));
1165  }
1166  if (getNode()->kind() == Node::KIND_GROUP) {
1167  rtl::Reference< Node > p(child->getNode());
1168  if (p->kind() != Node::KIND_PROPERTY ||
1169  !static_cast< PropertyNode * >(p.get())->isExtension())
1170  {
1171  throw css::container::NoSuchElementException(
1172  aName, static_cast< cppu::OWeakObject * >(this));
1173  }
1174  }
1175  Modifications localMods;
1176  localMods.add(child->getRelativePath());
1177  // unbind() modifies the parent chain that markChildAsModified() walks,
1178  // so order is important:
1179  markChildAsModified(child); //TODO: must not throw
1180  child->unbind();
1181  getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1182  }
1183  bc.send();
1184 }
1185 
1186 css::uno::Reference< css::uno::XInterface > Access::createInstance()
1187 {
1188  assert(thisIs(IS_SET|IS_UPDATE));
1189  OUString tmplName(
1190  static_cast< SetNode * >(getNode().get())->getDefaultTemplateName());
1192  components_.getTemplate(tmplName));
1193  if (!tmpl.is()) {
1194  throw css::uno::Exception(
1195  "unknown template " + tmplName,
1196  static_cast< cppu::OWeakObject * >(this));
1197  }
1198  rtl::Reference< Node > node(tmpl->clone(true));
1199  node->setLayer(Data::NO_LAYER);
1200  return static_cast< cppu::OWeakObject * >(
1201  new ChildAccess(components_, getRootAccess(), node));
1202 }
1203 
1204 css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments(
1205  css::uno::Sequence< css::uno::Any > const & aArguments)
1206 {
1207  assert(thisIs(IS_SET|IS_UPDATE));
1208  if (aArguments.hasElements()) {
1209  throw css::uno::Exception(
1210  ("configuration SimpleSetUpdate createInstanceWithArguments"
1211  " must not specify any arguments"),
1212  static_cast< cppu::OWeakObject * >(this));
1213  }
1214  return createInstance();
1215 }
1216 
1218  components_(components), disposed_(false), lock_( lock() )
1219 {
1220 }
1221 
1223 
1225  assert(broadcaster != nullptr);
1226  for (auto const& disposeListener : disposeListeners_)
1227  {
1228  broadcaster->addDisposeNotification(
1229  disposeListener,
1230  css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
1231  }
1232  for (auto const& containerListener : containerListeners_)
1233  {
1234  broadcaster->addDisposeNotification(
1235  containerListener,
1236  css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
1237  }
1238  for (auto const& propertyChangeListener : propertyChangeListeners_)
1239  {
1240  for (auto const& propertyChangeListenerElement : propertyChangeListener.second)
1241  {
1242  broadcaster->addDisposeNotification(
1243  propertyChangeListenerElement,
1244  css::lang::EventObject(
1245  static_cast< cppu::OWeakObject * >(this)));
1246  }
1247  }
1248  for (auto const& vetoableChangeListener : vetoableChangeListeners_)
1249  {
1250  for (auto const& vetoableChangeListenerElement : vetoableChangeListener.second)
1251  {
1252  broadcaster->addDisposeNotification(
1253  vetoableChangeListenerElement,
1254  css::lang::EventObject(
1255  static_cast< cppu::OWeakObject * >(this)));
1256  }
1257  }
1258  for (auto const& propertiesChangeListener : propertiesChangeListeners_)
1259  {
1260  broadcaster->addDisposeNotification(
1261  propertiesChangeListener,
1262  css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
1263  }
1264  //TODO: iterate over children w/ listeners (incl. unmodified ones):
1265  for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1266  i != modifiedChildren_.end(); ++i)
1267  {
1269  if (child.is()) {
1270  child->initDisposeBroadcaster(broadcaster);
1271  }
1272  }
1273 }
1274 
1275 void Access::clearListeners() noexcept {
1276  disposeListeners_.clear();
1277  containerListeners_.clear();
1278  propertyChangeListeners_.clear();
1279  vetoableChangeListeners_.clear();
1281  //TODO: iterate over children w/ listeners (incl. unmodified ones):
1282  for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1283  i != modifiedChildren_.end(); ++i)
1284  {
1286  if (child.is()) {
1287  child->clearListeners();
1288  }
1289  }
1290 }
1291 
1292 css::uno::Any Access::queryInterface(css::uno::Type const & aType)
1293 {
1294  css::uno::Any res(OWeakObject::queryInterface(aType));
1295  if (res.hasValue()) {
1296  return res;
1297  }
1298  res = cppu::queryInterface(
1299  aType, static_cast< css::lang::XTypeProvider * >(this),
1300  static_cast< css::lang::XServiceInfo * >(this),
1301  static_cast< css::lang::XComponent * >(this),
1302  static_cast< css::container::XHierarchicalNameAccess * >(this),
1303  static_cast< css::container::XContainer * >(this),
1304  static_cast< css::beans::XExactName * >(this),
1305  static_cast< css::container::XHierarchicalName * >(this),
1306  static_cast< css::container::XNamed * >(this),
1307  static_cast< css::beans::XProperty * >(this),
1308  static_cast< css::container::XElementAccess * >(this),
1309  static_cast< css::container::XNameAccess * >(this));
1310  if (res.hasValue()) {
1311  return res;
1312  }
1313  if (getNode()->kind() == Node::KIND_GROUP) {
1314  res = cppu::queryInterface(
1315  aType, static_cast< css::beans::XPropertySetInfo * >(this),
1316  static_cast< css::beans::XPropertySet * >(this),
1317  static_cast< css::beans::XMultiPropertySet * >(this),
1318  static_cast< css::beans::XHierarchicalPropertySet * >(this),
1319  static_cast< css::beans::XMultiHierarchicalPropertySet * >(this),
1320  static_cast< css::beans::XHierarchicalPropertySetInfo * >(this));
1321  if (res.hasValue()) {
1322  return res;
1323  }
1324  }
1325  if (getRootAccess()->isUpdate()) {
1326  res = cppu::queryInterface(
1327  aType, static_cast< css::container::XNameReplace * >(this),
1328  static_cast< css::container::XHierarchicalNameReplace * >(this));
1329  if (res.hasValue()) {
1330  return res;
1331  }
1332  if (getNode()->kind() != Node::KIND_GROUP ||
1333  static_cast< GroupNode * >(getNode().get())->isExtensible())
1334  {
1335  res = cppu::queryInterface(
1336  aType, static_cast< css::container::XNameContainer * >(this));
1337  if (res.hasValue()) {
1338  return res;
1339  }
1340  }
1341  if (getNode()->kind() == Node::KIND_SET) {
1342  res = cppu::queryInterface(
1343  aType, static_cast< css::lang::XSingleServiceFactory * >(this));
1344  }
1345  }
1346  return res;
1347 }
1348 
1349 
1351  if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY &&
1353  {
1354  throw css::uno::RuntimeException(
1355  "configmgr Access to specialized LocalizedPropertyNode",
1356  static_cast< cppu::OWeakObject * >(this));
1357  }
1358 }
1359 
1362  return parent.is() ? parent->getNode() : rtl::Reference< Node >();
1363 }
1364 
1366  OUString locale;
1367  if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
1368  && name.startsWith("*", &locale))
1369  {
1370  if (locale.startsWith("*")) {
1371  SAL_WARN(
1372  "configmgr",
1373  ("access best-matching localized property value via"
1374  " \"*<locale>\" with <locale> \"")
1375  << locale << "\" recursively starting with \"*\"");
1376  return getChild(locale);
1377  }
1378  SAL_WARN_IF(
1379  locale.isEmpty(), "configmgr",
1380  ("access best-matching localized property value via \"*<locale>\""
1381  " with empty <locale>; falling back to defaults"));
1382 
1383  // Since the locale given to us is the one used at initialization,
1384  // here we override it with the actual current-user's language to
1385  // support per-view localization in LOK.
1388 
1389  if (!locale.isEmpty()) {
1390  // Try exact match first, avoiding all fallback overhead.
1391  rtl::Reference<ChildAccess> directChild(getChild(locale));
1392  if (directChild.is())
1393  return directChild;
1394 
1395  // Find the best match using the LanguageTag fallback mechanism,
1396  // excluding the original tag.
1397  std::vector<OUString> aFallbacks = LanguageTag(locale).getFallbackStrings(false);
1398  for (const OUString& rFallback : aFallbacks)
1399  {
1400  rtl::Reference<ChildAccess> child(getChild(rFallback));
1401  if (child.is())
1402  return child;
1403  }
1404 
1405  // As a workaround for broken xcu data that does not use shortest
1406  // xml:lang attributes, look for the first entry with the same first
1407  // segment as the requested language tag before falling back to
1408  // defaults (see fdo#33638):
1409  if (aFallbacks.size() > 0)
1410  locale = aFallbacks[aFallbacks.size() - 1];
1411  assert(
1412  !locale.isEmpty() && locale.indexOf('-') == -1 &&
1413  locale.indexOf('_') == -1);
1414 
1415  std::vector< rtl::Reference< ChildAccess > > children(
1416  getAllChildren());
1417  for (auto const& child : children)
1418  {
1419  OUString name2(child->getNameInternal());
1420  if (name2.startsWith(locale) &&
1421  (name2.getLength() == locale.getLength() ||
1422  name2[locale.getLength()] == '-' ||
1423  name2[locale.getLength()] == '_'))
1424  {
1425  return child;
1426  }
1427  }
1428  }
1429  // Defaults are the "en-US" locale, the "en" locale, the empty string locale, the first child (if
1430  // any, and if the property is non-nillable), or a null ChildAccess, in that order:
1431  rtl::Reference< ChildAccess > child(getChild("en-US"));
1432  if (child.is()) {
1433  return child;
1434  }
1435  child = getChild("en");
1436  if (child.is()) {
1437  return child;
1438  }
1439  child = getChild("");
1440  if (child.is()) {
1441  return child;
1442  }
1443  if (!static_cast<LocalizedPropertyNode *>(getNode().get())->isNillable()) {
1444  std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
1445  if (!children.empty()) {
1446  return children.front();
1447  }
1448  }
1450  }
1451  ModifiedChildren::iterator i(modifiedChildren_.find(name));
1452  return i == modifiedChildren_.end()
1453  ? getUnmodifiedChild(name) : getModifiedChild(i);
1454 }
1455 
1456 std::vector< rtl::Reference< ChildAccess > > Access::getAllChildren() {
1457  std::vector< rtl::Reference< ChildAccess > > vec;
1458  NodeMap const & members = getNode()->getMembers();
1459  for (auto const& member : members)
1460  {
1461  if (modifiedChildren_.find(member.first) == modifiedChildren_.end()) {
1462  vec.push_back(getUnmodifiedChild(member.first));
1463  assert(vec.back().is());
1464  }
1465  }
1466  for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1467  i != modifiedChildren_.end(); ++i)
1468  {
1470  if (child.is()) {
1471  vec.push_back(child);
1472  }
1473  }
1474  return vec;
1475 }
1476 
1477 void Access::checkValue(css::uno::Any const & value, Type type, bool nillable) {
1478  bool ok;
1479  switch (type) {
1480  case TYPE_ERROR:
1481  ok = false;
1482  break;
1483  case TYPE_ANY:
1484  switch (getDynamicType(value)) {
1485  case TYPE_ERROR:
1486  ok = false;
1487  break;
1488  case TYPE_NIL:
1489  ok = nillable;
1490  break;
1491  default:
1492  ok = true;
1493  break;
1494  case TYPE_ANY:
1495  for (;;) std::abort(); // cannot happen
1496  }
1497  break;
1498  default:
1499  ok = value.hasValue() ? value.isExtractableTo(mapType(type)) : nillable;
1500  break;
1501  case TYPE_NIL:
1502  for (;;) std::abort(); // cannot happen
1503  }
1504  if (!ok) {
1505  throw css::lang::IllegalArgumentException(
1506  "configmgr inappropriate property value",
1507  static_cast< cppu::OWeakObject * >(this), -1);
1508  }
1509 }
1510 
1512  OUString const & name, css::uno::Any const & value,
1513  Modifications * localModifications)
1514 {
1515  assert(localModifications != nullptr);
1516  LocalizedPropertyNode * locprop = static_cast< LocalizedPropertyNode * >(
1517  getNode().get());
1518  checkValue(value, locprop->getStaticType(), locprop->isNillable());
1519  rtl::Reference child(
1520  new ChildAccess(
1521  components_, getRootAccess(), this, name,
1522  new LocalizedValueNode(Data::NO_LAYER, value)));
1523  markChildAsModified(child);
1524  localModifications->add(child->getRelativePath());
1525 }
1526 
1528  std::vector< css::util::ElementChange > * changes)
1529 {
1530  assert(changes != nullptr);
1531  for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1532  i != modifiedChildren_.end(); ++i)
1533  {
1535  if (child.is()) {
1536  child->reportChildChanges(changes);
1537  changes->push_back(css::util::ElementChange());
1538  //TODO: changed value and/or inserted node
1539  } else {
1540  changes->push_back(css::util::ElementChange()); //TODO: removed node
1541  }
1542  }
1543 }
1544 
1546  bool valid, Modifications * globalModifications)
1547 {
1548  assert(globalModifications != nullptr);
1549  while (!modifiedChildren_.empty()) {
1550  bool childValid = valid;
1551  ModifiedChildren::iterator i(modifiedChildren_.begin());
1553  if (child.is()) {
1554  childValid = childValid && !child->isFinalized();
1555  child->commitChanges(childValid, globalModifications);
1556  //TODO: currently, this is called here for directly inserted
1557  // children as well as for children whose sub-children were
1558  // modified (and should never be called for directly removed
1559  // children); clarify what exactly should happen here for
1560  // directly inserted children
1561  }
1562  NodeMap & members = getNode()->getMembers();
1563  NodeMap::iterator j(members.find(i->first));
1564  if (child.is()) {
1565  // Inserted:
1566  if (j != members.end()) {
1567  childValid = childValid &&
1568  j->second->getFinalized() == Data::NO_LAYER;
1569  if (childValid) {
1570  child->getNode()->setMandatory(j->second->getMandatory());
1571  }
1572  }
1573  if (childValid) {
1574  members[i->first] = child->getNode();
1575  }
1576  } else {
1577  // Removed:
1578  childValid = childValid && j != members.end() &&
1579  j->second->getFinalized() == Data::NO_LAYER &&
1580  j->second->getMandatory() == Data::NO_LAYER;
1581  if (childValid) {
1582  members.erase(j);
1583  }
1584  }
1585  if (childValid && i->second.directlyModified) {
1586  std::vector<OUString> path(getAbsolutePath());
1587  path.push_back(i->first);
1589  globalModifications->add(path);
1590  }
1591  i->second.child->committed();
1592  modifiedChildren_.erase(i);
1593  }
1594 }
1595 
1597  Modifications::Node const & modifications, Broadcaster * broadcaster,
1598  std::vector< css::util::ElementChange > * allChanges)
1599 {
1600  assert(broadcaster != nullptr);
1601  std::vector< css::beans::PropertyChangeEvent > propChanges;
1602  bool collectPropChanges = !propertiesChangeListeners_.empty();
1603  for (const auto & i : modifications.children)
1604  {
1606  if (child.is()) {
1607  switch (child->getNode()->kind()) {
1609  if (!i.second.children.empty()) {
1611  child->initBroadcasterAndChanges(
1612  i.second, broadcaster, allChanges);
1613  //TODO: if allChanges==0, recurse only into children
1614  // w/ listeners
1615  } else {
1616  //TODO: filter child mods that are irrelevant for
1617  // locale:
1618  for (auto const& containerListener : containerListeners_)
1619  {
1620  broadcaster->
1621  addContainerElementReplacedNotification(
1622  containerListener,
1623  css::container::ContainerEvent(
1624  static_cast< cppu::OWeakObject * >(
1625  this),
1626  css::uno::Any(i.first),
1627  css::uno::Any(), css::uno::Any()));
1628  //TODO: non-void Element, ReplacedElement
1629  }
1630  PropertyChangeListeners::iterator j(
1631  propertyChangeListeners_.find(i.first));
1632  if (j != propertyChangeListeners_.end()) {
1633  for (auto const& propertyChangeListenerElement : j->second)
1634  {
1635  broadcaster->addPropertyChangeNotification(
1636  propertyChangeListenerElement,
1637  css::beans::PropertyChangeEvent(
1638  static_cast< cppu::OWeakObject * >(
1639  this),
1640  i.first, false, -1, css::uno::Any(),
1641  css::uno::Any()));
1642  }
1643  }
1644  j = propertyChangeListeners_.find("");
1645  if (j != propertyChangeListeners_.end()) {
1646  for (auto const& propertyChangeListenerElement : j->second)
1647  {
1648  broadcaster->addPropertyChangeNotification(
1649  propertyChangeListenerElement,
1650  css::beans::PropertyChangeEvent(
1651  static_cast< cppu::OWeakObject * >(
1652  this),
1653  i.first, false, -1, css::uno::Any(),
1654  css::uno::Any()));
1655  }
1656  }
1657  if (allChanges != nullptr) {
1658  allChanges->push_back(
1659  css::util::ElementChange(
1660  css::uno::Any(
1661  child->getRelativePathRepresentation()),
1662  css::uno::Any(), css::uno::Any()));
1663  //TODO: non-void Element, ReplacedElement
1664  }
1665  if (collectPropChanges) {
1666  propChanges.emplace_back(
1667  static_cast< cppu::OWeakObject * >(this),
1668  i.first, false, -1, css::uno::Any(),
1669  css::uno::Any());
1670  }
1671  }
1672  }
1673  // else: spurious Modifications::Node not representing a change
1674  break;
1677  for (auto const& containerListener : containerListeners_)
1678  {
1680  containerListener,
1681  css::container::ContainerEvent(
1682  static_cast< cppu::OWeakObject * >(this),
1683  css::uno::Any(i.first), child->asValue(),
1684  css::uno::Any()));
1685  //TODO: distinguish add/modify; non-void ReplacedElement
1686  }
1687  if (allChanges != nullptr) {
1688  allChanges->push_back(
1689  css::util::ElementChange(
1690  css::uno::Any(
1691  child->getRelativePathRepresentation()),
1692  child->asValue(), css::uno::Any()));
1693  //TODO: non-void ReplacedElement
1694  }
1695  assert(!collectPropChanges);
1696  break;
1697  case Node::KIND_PROPERTY:
1698  {
1699  for (auto const& containerListener : containerListeners_)
1700  {
1702  containerListener,
1703  css::container::ContainerEvent(
1704  static_cast< cppu::OWeakObject * >(this),
1705  css::uno::Any(i.first), child->asValue(),
1706  css::uno::Any()));
1707  //TODO: distinguish add/remove/modify; non-void
1708  // ReplacedElement
1709  }
1710  PropertyChangeListeners::iterator j(
1711  propertyChangeListeners_.find(i.first));
1712  if (j != propertyChangeListeners_.end()) {
1713  for (auto const& propertyChangeListenerElement : j->second)
1714  {
1715  broadcaster->addPropertyChangeNotification(
1716  propertyChangeListenerElement,
1717  css::beans::PropertyChangeEvent(
1718  static_cast< cppu::OWeakObject * >(this),
1719  i.first, false, -1, css::uno::Any(),
1720  css::uno::Any()));
1721  }
1722  }
1723  j = propertyChangeListeners_.find("");
1724  if (j != propertyChangeListeners_.end()) {
1725  for (auto const& propertyChangeListenerElement : j->second)
1726  {
1727  broadcaster->addPropertyChangeNotification(
1728  propertyChangeListenerElement,
1729  css::beans::PropertyChangeEvent(
1730  static_cast< cppu::OWeakObject * >(this),
1731  i.first, false, -1, css::uno::Any(),
1732  css::uno::Any()));
1733  }
1734  }
1735  if (allChanges != nullptr) {
1736  allChanges->push_back(
1737  css::util::ElementChange(
1738  css::uno::Any(
1739  child->getRelativePathRepresentation()),
1740  child->asValue(), css::uno::Any()));
1741  //TODO: non-void ReplacedElement
1742  }
1743  if (collectPropChanges) {
1744  propChanges.emplace_back(
1745  static_cast< cppu::OWeakObject * >(this),
1746  i.first, false, -1, css::uno::Any(),
1747  css::uno::Any());
1748  }
1749  }
1750  break;
1751  case Node::KIND_GROUP:
1752  case Node::KIND_SET:
1753  if (i.second.children.empty()) {
1754  if (!child->getNode()->getTemplateName().isEmpty()) {
1755  for (auto const& containerListener : containerListeners_)
1756  {
1757  broadcaster->
1758  addContainerElementInsertedNotification(
1759  containerListener,
1760  css::container::ContainerEvent(
1761  static_cast< cppu::OWeakObject * >(
1762  this),
1763  css::uno::Any(i.first),
1764  child->asValue(), css::uno::Any()));
1765  }
1766  if (allChanges != nullptr) {
1767  allChanges->push_back(
1768  css::util::ElementChange(
1769  css::uno::Any(
1770  child->getRelativePathRepresentation()),
1771  css::uno::Any(), css::uno::Any()));
1772  //TODO: non-void Element, ReplacedElement
1773  }
1774  }
1775  // else: spurious Modifications::Node not representing a
1776  // change
1777  } else {
1778  child->initBroadcasterAndChanges(
1779  i.second, broadcaster, allChanges);
1780  //TODO: if allChanges==0, recurse only into children w/
1781  // listeners
1782  }
1783  break;
1784  case Node::KIND_ROOT:
1785  assert(false); // this cannot happen
1786  break;
1787  }
1788  } else {
1789  switch (getNode()->kind()) {
1791  // Removed localized property value:
1793  for (auto const& containerListener : containerListeners_)
1794  {
1796  containerListener,
1797  css::container::ContainerEvent(
1798  static_cast< cppu::OWeakObject * >(this),
1799  css::uno::Any(i.first), css::uno::Any(),
1800  css::uno::Any()));
1801  //TODO: non-void ReplacedElement
1802  }
1803  if (allChanges != nullptr) {
1804  OUStringBuffer path(getRelativePathRepresentation());
1805  if (!path.isEmpty()) {
1806  path.append('/');
1807  }
1808  path.append(Data::createSegment(u"*", i.first));
1809  allChanges->push_back(
1810  css::util::ElementChange(
1811  css::uno::Any(path.makeStringAndClear()),
1812  css::uno::Any(), css::uno::Any()));
1813  //TODO: non-void ReplacedElement
1814  }
1815  assert(!collectPropChanges);
1816  break;
1817  case Node::KIND_GROUP:
1818  {
1819  // Removed (non-localized) extension property:
1820  for (auto const& containerListener : containerListeners_)
1821  {
1823  containerListener,
1824  css::container::ContainerEvent(
1825  static_cast< cppu::OWeakObject * >(this),
1826  css::uno::Any(i.first), css::uno::Any(),
1827  css::uno::Any()));
1828  //TODO: non-void ReplacedElement
1829  }
1830  PropertyChangeListeners::iterator j(
1831  propertyChangeListeners_.find(i.first));
1832  if (j != propertyChangeListeners_.end()) {
1833  for (auto const& propertyChangeListenerElement : j->second)
1834  {
1835  broadcaster->addPropertyChangeNotification(
1836  propertyChangeListenerElement,
1837  css::beans::PropertyChangeEvent(
1838  static_cast< cppu::OWeakObject * >(this),
1839  i.first, false, -1, css::uno::Any(),
1840  css::uno::Any()));
1841  }
1842  }
1843  j = propertyChangeListeners_.find("");
1844  if (j != propertyChangeListeners_.end()) {
1845  for (auto const& propertyChangeListenerElement : j->second)
1846  {
1847  broadcaster->addPropertyChangeNotification(
1848  propertyChangeListenerElement,
1849  css::beans::PropertyChangeEvent(
1850  static_cast< cppu::OWeakObject * >(this),
1851  i.first, false, -1, css::uno::Any(),
1852  css::uno::Any()));
1853  }
1854  }
1855  if (allChanges != nullptr) {
1856  OUStringBuffer path(
1858  if (!path.isEmpty()) {
1859  path.append('/');
1860  }
1861  path.append(i.first);
1862  allChanges->push_back(
1863  css::util::ElementChange(
1864  css::uno::Any(path.makeStringAndClear()),
1865  css::uno::Any(), css::uno::Any()));
1866  //TODO: non-void ReplacedElement
1867  }
1868  if (collectPropChanges) {
1869  propChanges.emplace_back(
1870  static_cast< cppu::OWeakObject * >(this),
1871  i.first, false, -1, css::uno::Any(),
1872  css::uno::Any());
1873  }
1874  }
1875  break;
1876  case Node::KIND_SET:
1877  // Removed set member:
1878  if (i.second.children.empty()) {
1879  for (auto const& containerListener : containerListeners_)
1880  {
1882  containerListener,
1883  css::container::ContainerEvent(
1884  static_cast< cppu::OWeakObject * >(this),
1885  css::uno::Any(i.first),
1886  css::uno::Any(), css::uno::Any()));
1887  //TODO: non-void ReplacedElement
1888  }
1889  if (allChanges != nullptr) {
1890  OUStringBuffer path(
1892  if (!path.isEmpty()) {
1893  path.append('/');
1894  }
1895  path.append(Data::createSegment(u"*", i.first));
1896  allChanges->push_back(
1897  css::util::ElementChange(
1898  css::uno::Any(path.makeStringAndClear()),
1899  css::uno::Any(), css::uno::Any()));
1900  //TODO: non-void ReplacedElement
1901  }
1902  }
1903  // else: spurious Modifications::Node not representing a change
1904  break;
1905  default:
1906  assert(false); // this cannot happen
1907  break;
1908  }
1909  }
1910  }
1911  if (!propChanges.empty()) {
1912  css::uno::Sequence< css::beans::PropertyChangeEvent > seq(
1913  comphelper::containerToSequence(propChanges));
1914  for (auto const& propertyChangeListener : propertiesChangeListeners_)
1915  {
1916  broadcaster->addPropertiesChangeNotification(propertyChangeListener, seq);
1917  }
1918  }
1919 }
1920 
1921 
1923  directlyModified(false)
1924 {}
1925 
1927  rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified):
1928  child(theChild), directlyModified(theDirectlyModified)
1929 {}
1930 
1932  ModifiedChildren::iterator const & childIterator)
1933 {
1934  return (childIterator->second.child->getParentAccess() == this &&
1935  (childIterator->second.child->getNameInternal() ==
1936  childIterator->first))
1937  ? childIterator->second.child : rtl::Reference< ChildAccess >();
1938 }
1939 
1941  const OUString &name, const rtl::Reference< Node > &node)
1942 {
1943  rtl::Reference child(
1944  new ChildAccess(components_, getRootAccess(), this, name, node));
1945  cachedChildren_[name] = child.get();
1946  return child;
1947 }
1948 
1950  OUString const & name)
1951 {
1952  assert(modifiedChildren_.find(name) == modifiedChildren_.end());
1953  rtl::Reference< Node > node(getNode()->getMember(name));
1954  if (!node.is()) {
1956  }
1957  WeakChildMap::iterator i(cachedChildren_.find(name));
1958  if (i != cachedChildren_.end()) {
1960  if (i->second->acquireCounting() > 1) {
1961  child.set(i->second); // must not throw
1962  }
1963  i->second->releaseNondeleting();
1964  if (child.is()) {
1965  child->setNode(node);
1966  return child;
1967  }
1968  }
1969  return createUnmodifiedChild(name,node);
1970 }
1971 
1973  sal_Int32 i = 0;
1974  // For backwards compatibility, allow absolute paths where meaningful:
1975  if( path.startsWith("/") ) {
1976  ++i;
1977  if (!getRootAccess().is()) {
1979  }
1980  std::vector<OUString> abs(getAbsolutePath());
1981  for (auto const& elem : abs)
1982  {
1983  OUString name1;
1984  bool setElement1;
1985  OUString templateName1;
1986  i = Data::parseSegment(
1987  path, i, &name1, &setElement1, &templateName1);
1988  if (i == -1 || (i != path.getLength() && path[i] != '/')) {
1990  }
1991  OUString name2;
1992  bool setElement2;
1993  OUString templateName2;
1994  Data::parseSegment(elem, 0, &name2, &setElement2, &templateName2);
1995  if (name1 != name2 || setElement1 != setElement2 ||
1996  (setElement1 &&
1997  !Data::equalTemplateNames(templateName1, templateName2)))
1998  {
2000  }
2001  if (i != path.getLength()) {
2002  ++i;
2003  }
2004  }
2005  }
2006  for (rtl::Reference< Access > parent(this);;) {
2007  OUString name;
2008  bool setElement;
2009  OUString templateName;
2010  i = Data::parseSegment(path, i, &name, &setElement, &templateName);
2011  if (i == -1 || (i != path.getLength() && path[i] != '/')) {
2013  }
2014  rtl::Reference< ChildAccess > child(parent->getChild(name));
2015  if (!child.is()) {
2017  }
2018  if (setElement) {
2019  rtl::Reference< Node > p(parent->getNode());
2020  switch (p->kind()) {
2023  !templateName.isEmpty())
2024  {
2026  }
2027  break;
2028  case Node::KIND_SET:
2029  if (!templateName.isEmpty() &&
2030  !static_cast< SetNode * >(p.get())->isValidTemplate(
2031  templateName))
2032  {
2034  }
2035  break;
2036  default:
2038  }
2039  }
2040  // For backwards compatibility, ignore a final slash after non-value
2041  // nodes:
2042  if (child->isValue()) {
2043  return i == path.getLength()
2044  ? child : rtl::Reference< ChildAccess >();
2045  } else if (i >= path.getLength() - 1) {
2046  return child;
2047  }
2048  ++i;
2049  parent = child.get();
2050  }
2051 }
2052 
2054  OUString const & name, css::uno::Any const & value,
2055  Modifications * localModifications)
2056 {
2057  assert(localModifications != nullptr);
2059  if (!child.is()) {
2060  return false;
2061  }
2062  child->checkFinalized();
2063  child->setProperty(value, localModifications);
2064  return true;
2065 }
2066 
2067 css::beans::Property Access::asProperty() {
2069  bool nillable;
2070  bool removable;
2072  switch (p->kind()) {
2073  case Node::KIND_PROPERTY:
2074  {
2075  PropertyNode * prop = static_cast< PropertyNode * >(p.get());
2076  type = mapType(prop->getStaticType());
2077  nillable = prop->isNillable();
2078  removable = prop->isExtension();
2079  }
2080  break;
2082  {
2083  LocalizedPropertyNode * locprop =
2084  static_cast< LocalizedPropertyNode *>(p.get());
2087  //TODO: correct?
2088  removable = false;
2089  } else {
2090  type = mapType(locprop->getStaticType());
2091  removable = false; //TODO ???
2092  }
2093  nillable = locprop->isNillable();
2094  }
2095  break;
2097  {
2098  LocalizedPropertyNode * locprop =
2099  static_cast< LocalizedPropertyNode * >(getParentNode().get());
2100  type = mapType(locprop->getStaticType());
2101  nillable = locprop->isNillable();
2102  removable = false; //TODO ???
2103  }
2104  break;
2105  default:
2106  type = cppu::UnoType< css::uno::XInterface >::get(); //TODO: correct?
2107  nillable = false;
2109  removable = parent.is() && parent->kind() == Node::KIND_SET;
2110  break;
2111  }
2112  return css::beans::Property(
2113  getNameInternal(), -1, type,
2114  (css::beans::PropertyAttribute::BOUND | //TODO: correct for group/set?
2115  css::beans::PropertyAttribute::CONSTRAINED |
2116  (nillable ? css::beans::PropertyAttribute::MAYBEVOID : 0) |
2117  (getRootAccess()->isUpdate() && removable
2118  ? css::beans::PropertyAttribute::REMOVABLE : 0) |
2119  (!getRootAccess()->isUpdate() || p->getFinalized() != Data::NO_LAYER
2120  ? css::beans::PropertyAttribute::READONLY : 0))); //TODO: MAYBEDEFAULT
2121 }
2122 
2124  if (isFinalized()) {
2125  throw css::lang::IllegalArgumentException(
2126  "configmgr modification of finalized item",
2127  static_cast< cppu::OWeakObject * >(this), -1);
2128  }
2129 }
2130 
2131 void Access::checkKnownProperty(OUString const & descriptor) {
2132  if (descriptor.isEmpty()) {
2133  return;
2134  }
2135  rtl::Reference< ChildAccess > child(getChild(descriptor));
2136  if (child.is()) {
2137  switch (child->getNode()->kind()) {
2138  case Node::KIND_PROPERTY:
2139  return;
2142  return;
2143  }
2144  break;
2147  return;
2148  }
2149  break;
2150  default:
2151  break;
2152  }
2153  }
2154  throw css::beans::UnknownPropertyException(
2155  descriptor, static_cast< cppu::OWeakObject * >(this));
2156 }
2157 
2159  css::uno::Any const & value)
2160 {
2161  rtl::Reference< ChildAccess > freeAcc = comphelper::getFromUnoTunnel<ChildAccess>(value);
2162  if (!freeAcc.is() || freeAcc->getParentAccess().is() ||
2163  (freeAcc->isInTransaction() &&
2164  freeAcc->getRootAccess() != getRootAccess()))
2165  {
2166  throw css::lang::IllegalArgumentException(
2167  "configmgr inappropriate set element",
2168  static_cast< cppu::OWeakObject * >(this), 1);
2169  }
2170  assert(dynamic_cast< SetNode * >(getNode().get()) != nullptr);
2171  if (!static_cast< SetNode * >(getNode().get())->isValidTemplate(
2172  freeAcc->getNode()->getTemplateName()))
2173  {
2174  throw css::lang::IllegalArgumentException(
2175  "configmgr inappropriate set element",
2176  static_cast< cppu::OWeakObject * >(this), 1);
2177  }
2178  return freeAcc;
2179 }
2180 
2182  for (rtl::Reference< Access > p(this);;) {
2183  rtl::Reference< Access > parent(p->getParentAccess());
2184  if (!parent.is()) {
2185  return p;
2186  }
2187  p = parent;
2188  }
2189 }
2190 
2191 #if !defined NDEBUG
2192 bool Access::thisIs(int what) {
2193  osl::MutexGuard g(*lock_);
2195  Node::Kind k(p->kind());
2196  return (k != Node::KIND_PROPERTY && k != Node::KIND_LOCALIZED_VALUE &&
2197  ((what & IS_GROUP) == 0 || k == Node::KIND_GROUP) &&
2198  ((what & IS_SET) == 0 || k == Node::KIND_SET) &&
2199  ((what & IS_EXTENSIBLE) == 0 || k != Node::KIND_GROUP ||
2200  static_cast< GroupNode * >(p.get())->isExtensible()) &&
2201  ((what & IS_GROUP_MEMBER) == 0 ||
2202  getParentNode()->kind() == Node::KIND_GROUP)) ||
2203  ((what & IS_SET_MEMBER) == 0 ||
2204  getParentNode()->kind() == Node::KIND_SET) ||
2205  ((what & IS_UPDATE) == 0 || getRootAccess()->isUpdate());
2206 }
2207 #endif
2208 
2209 }
2210 
2211 /* 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:1360
Node const & getRoot() const
static bool allLocales(std::u16string_view locale)
Definition: components.cxx:205
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:1217
virtual sal_Bool SAL_CALL hasPropertyByHierarchicalName(OUString const &aHierarchicalName) override
Definition: access.cxx:1044
css::beans::Property asProperty()
Definition: access.cxx:2067
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:1204
ContainerListeners containerListeners_
Definition: access.hxx:431
virtual rtl::Reference< RootAccess > getRootAccess()=0
static OUString createSegment(std::u16string_view templateName, OUString const &name)
Definition: data.cxx:79
virtual void SAL_CALL replaceByName(OUString const &aName, css::uno::Any const &aElement) override
Definition: access.cxx:1052
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:930
void addContainerElementRemovedNotification(css::uno::Reference< css::container::XContainerListener > const &listener, css::container::ContainerEvent const &event)
Definition: broadcaster.cxx:75
SwNodeOffset abs(const SwNodeOffset &a)
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:1545
virtual sal_Bool SAL_CALL supportsService(OUString const &ServiceName) override
Definition: access.cxx:238
std::vector< rtl::Reference< ChildAccess > > getAllChildren()
Definition: access.cxx:1456
virtual void SAL_CALL setPropertyValues(css::uno::Sequence< OUString > const &aPropertyNames, css::uno::Sequence< css::uno::Any > const &aValues) override
Definition: access.cxx:820
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:972
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:1222
virtual bool isFinalized()=0
virtual OUString SAL_CALL getHierarchicalName() override
Definition: access.cxx:567
rtl::Reference< ChildAccess > getChild(OUString const &name)
Definition: access.cxx:1365
virtual void addTypes(std::vector< css::uno::Type > *types) const =0
void reportChildChanges(std::vector< css::util::ElementChange > *changes)
Definition: access.cxx:1527
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:1511
bool setChildProperty(OUString const &name, css::uno::Any const &value, Modifications *localModifications)
Definition: access.cxx:2053
virtual css::uno::Reference< css::beans::XHierarchicalPropertySetInfo > SAL_CALL getHierarchicalPropertySetInfo() override
Definition: access.cxx:925
virtual std::vector< OUString > getAbsolutePath()=0
void checkFinalized()
Definition: access.cxx:2123
void checkValue(css::uno::Any const &value, Type type, bool nillable)
Definition: access.cxx:1477
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:1092
bool isExtension() const
rtl::Reference< ChildAccess > getSubChild(OUString const &path)
Definition: access.cxx:1972
void checkLocalizedPropertyAccess()
Definition: access.cxx:1350
virtual OUString getNameInternal()=0
virtual css::beans::Property SAL_CALL getPropertyByName(OUString const &aName) override
Definition: access.cxx:548
float u
unsigned char sal_Bool
rtl::Reference< Access > getNotificationRoot()
Definition: access.cxx:2181
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &aType) override
Definition: access.cxx:1292
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:1224
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:2131
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:1031
const LanguageTag & getLocale()
rtl::Reference< ChildAccess > createUnmodifiedChild(const OUString &name, const rtl::Reference< Node > &node)
Definition: access.cxx:1940
void initBroadcasterAndChanges(Modifications::Node const &modifications, Broadcaster *broadcaster, std::vector< css::util::ElementChange > *changes)
Definition: access.cxx:1596
NodeMapImpl::iterator iterator
Definition: nodemap.hxx:37
virtual void SAL_CALL removeByName(OUString const &aName) override
Definition: access.cxx:1152
exports com.sun.star.xml.dom. events
bool thisIs(int what)
Definition: access.cxx:2192
virtual std::vector< OUString > getRelativePath()=0
virtual css::uno::Any SAL_CALL getHierarchicalPropertyValue(OUString const &aHierarchicalPropertyName) override
Definition: access.cxx:958
oslInterlockedCount m_refCount
virtual void SAL_CALL setPropertyValue(OUString const &aPropertyName, css::uno::Any const &aValue) override
Definition: access.cxx:695
virtual void clearListeners() noexcept
Definition: access.cxx:1275
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:1931
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance() override
Definition: access.cxx:1186
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:2158
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)
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
rtl::Reference< ChildAccess > getUnmodifiedChild(OUString const &name)
Definition: access.cxx:1949
iterator end()
Definition: nodemap.hxx:49
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:1009
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