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