LibreOffice Module configmgr (master) 1
xcuparser.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 <algorithm>
23#include <cassert>
24#include <set>
25
26#include <com/sun/star/uno/Any.hxx>
27#include <com/sun/star/uno/RuntimeException.hpp>
28#include <rtl/ref.hxx>
29#include <rtl/strbuf.hxx>
30#include <rtl/string.hxx>
31#include <rtl/ustring.hxx>
32#include <sal/log.hxx>
33#include <xmlreader/span.hxx>
35
36#include "data.hxx"
39#include "groupnode.hxx"
40#include "modifications.hxx"
41#include "node.hxx"
42#include "nodemap.hxx"
43#include "parsemanager.hxx"
44#include "partial.hxx"
45#include "propertynode.hxx"
46#include "setnode.hxx"
47#include "xcuparser.hxx"
48#include "xmldata.hxx"
49
50namespace configmgr {
51
53 int layer, Data & data, Partial const * partial,
54 Modifications * broadcastModifications, Additions * additions):
55 valueParser_(layer), data_(data),
56 partial_(partial), broadcastModifications_(broadcastModifications),
57 additions_(additions), recordModifications_(layer == Data::NO_LAYER),
58 trackPath_(
59 partial_ != nullptr || broadcastModifications_ != nullptr || additions_ != nullptr ||
60 recordModifications_)
61{}
62
64
67}
68
70 xmlreader::XmlReader & reader, int nsId, xmlreader::Span const & name,
71 std::set< OUString > const * /*existingDependencies*/)
72{
73 if (valueParser_.startElement(reader, nsId, name)) {
74 return true;
75 }
76 if (state_.empty()) {
77 if (nsId == ParseManager::NAMESPACE_OOR &&
78 name == "component-data")
79 {
80 handleComponentData(reader);
81 } else if (nsId == ParseManager::NAMESPACE_OOR && name == "items")
82 {
84 } else {
85 throw css::uno::RuntimeException(
86 "bad root element <" + name.convertFromUtf8() + "> in " +
87 reader.getUrl());
88 }
89 } else if (state_.top().ignore) {
90 state_.push(State::Ignore(false));
91 } else if (!state_.top().node.is()) {
92 if (nsId != xmlreader::XmlReader::NAMESPACE_NONE || name != "item")
93 {
94 throw css::uno::RuntimeException(
95 "bad items node member <" + name.convertFromUtf8() + "> in " +
96 reader.getUrl());
97 }
98 handleItem(reader);
99 } else {
100 switch (state_.top().node->kind()) {
103 name != "value")
104 {
105 throw css::uno::RuntimeException(
106 "bad property node member <" + name.convertFromUtf8() +
107 "> in " + reader.getUrl());
108 }
110 reader,
111 static_cast< PropertyNode * >(state_.top().node.get()));
112 break;
115 name != "value")
116 {
117 throw css::uno::RuntimeException(
118 "bad localized property node member <" +
119 name.convertFromUtf8() + "> in " + reader.getUrl());
120 }
122 reader,
123 static_cast< LocalizedPropertyNode * >(
124 state_.top().node.get()));
125 break;
127 throw css::uno::RuntimeException(
128 "bad member <" + name.convertFromUtf8() + "> in " +
129 reader.getUrl());
130 case Node::KIND_GROUP:
132 name == "prop")
133 {
135 reader,
136 static_cast< GroupNode * >(state_.top().node.get()));
137 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
138 name == "node")
139 {
140 handleGroupNode(reader, state_.top().node);
141 } else {
142 throw css::uno::RuntimeException(
143 "bad group node member <" + name.convertFromUtf8() +
144 "> in " + reader.getUrl());
145 }
146 break;
147 case Node::KIND_SET:
149 name == "node")
150 {
152 reader, static_cast< SetNode * >(state_.top().node.get()));
153 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
154 name == "prop")
155 {
156 SAL_WARN(
157 "configmgr",
158 "bad set node <prop> member in \"" << reader.getUrl()
159 << '"');
160 state_.push(State::Ignore(false));
161 } else {
162 throw css::uno::RuntimeException(
163 "bad set node member <" + name.convertFromUtf8() +
164 "> in " + reader.getUrl());
165 }
166 break;
167 case Node::KIND_ROOT:
168 assert(false); // this cannot happen
169 break;
170 }
171 }
172 return true;
173}
174
176 if (valueParser_.endElement()) {
177 return;
178 }
179 assert(!state_.empty());
180 bool pop = state_.top().pop;
182 OUString name;
183 if (state_.top().insert) {
184 insert = state_.top().node;
185 assert(insert.is());
186 name = state_.top().name;
187 }
188 state_.pop();
189 if (insert.is()) {
190 assert(!state_.empty() && state_.top().node.is());
191 state_.top().node->getMembers()[name] = insert;
192 }
193 if (pop && !path_.empty()) {
194 path_.pop_back();
195 // </item> will pop less than <item> pushed, but that is harmless,
196 // as the next <item> will reset path_
197 }
198}
199
202}
203
205 assert(text.is());
206 if (text == "modify") {
207 return OPERATION_MODIFY;
208 }
209 if (text == "replace") {
210 return OPERATION_REPLACE;
211 }
212 if (text == "fuse") {
213 return OPERATION_FUSE;
214 }
215 if (text == "remove") {
216 return OPERATION_REMOVE;
217 }
218 throw css::uno::RuntimeException(
219 "invalid op " + text.convertFromUtf8());
220}
221
223 OStringBuffer buf(256);
224 buf.append('.');
225 bool hasPackage = false;
226 bool hasName = false;
228 bool finalized = false;
229 for (;;) {
230 int attrNsId;
231 xmlreader::Span attrLn;
232 if (!reader.nextAttribute(&attrNsId, &attrLn)) {
233 break;
234 }
235 if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn == "package")
236 {
237 if (hasPackage) {
238 throw css::uno::RuntimeException(
239 "multiple component-update package attributes in " +
240 reader.getUrl());
241 }
242 hasPackage = true;
243 xmlreader::Span s(reader.getAttributeValue(false));
244 buf.insert(0, s.begin, s.length);
245 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
246 attrLn == "name")
247 {
248 if (hasName) {
249 throw css::uno::RuntimeException(
250 "multiple component-update name attributes in " +
251 reader.getUrl());
252 }
253 hasName = true;
254 xmlreader::Span s(reader.getAttributeValue(false));
255 buf.append(s.begin, s.length);
256 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
257 attrLn == "op")
258 {
259 op = parseOperation(reader.getAttributeValue(true));
260 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
261 attrLn == "finalized")
262 {
263 finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
264 }
265 }
266 if (!hasPackage) {
267 throw css::uno::RuntimeException(
268 "no component-data package attribute in " + reader.getUrl());
269 }
270 if (!hasName) {
271 throw css::uno::RuntimeException(
272 "no component-data name attribute in " + reader.getUrl());
273 }
274 componentName_ = xmlreader::Span(buf.getStr(), buf.getLength()).
275 convertFromUtf8();
276 if (trackPath_) {
277 assert(path_.empty());
278 path_.push_back(componentName_);
280 {
281 state_.push(State::Ignore(true));
282 return;
283 }
284 }
288 if (!node.is()) {
289 SAL_WARN(
290 "configmgr",
291 "unknown component \"" << componentName_ << "\" in \""
292 << reader.getUrl() << '"');
293 state_.push(State::Ignore(true));
294 return;
295 }
296 switch (op) {
297 case OPERATION_MODIFY:
298 case OPERATION_FUSE:
299 break;
300 default:
301 throw css::uno::RuntimeException(
302 "invalid operation on root node in " + reader.getUrl());
303 }
304 int finalizedLayer = std::min(
305 finalized ? valueParser_.getLayer() : Data::NO_LAYER,
306 node->getFinalized());
307 node->setFinalized(finalizedLayer);
308 if (finalizedLayer < valueParser_.getLayer()) {
309 state_.push(State::Ignore(true));
310 return;
311 }
312 state_.push(State::Modify(node));
313}
314
316 xmlreader::Span attrPath;
317 for (;;) {
318 int attrNsId;
319 xmlreader::Span attrLn;
320 if (!reader.nextAttribute(&attrNsId, &attrLn)) {
321 break;
322 }
323 if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn == "path") {
324 attrPath = reader.getAttributeValue(false);
325 }
326 }
327 if (!attrPath.is()) {
328 throw css::uno::RuntimeException(
329 "missing path attribute in " + reader.getUrl());
330 }
331 OUString path(attrPath.convertFromUtf8());
332 int finalizedLayer;
335 path, nullptr, &path_, &finalizedLayer));
336 if (!node.is()) {
337 SAL_WARN(
338 "configmgr",
339 "unknown item \"" << path << "\" in \"" << reader.getUrl() << '"');
340 state_.push(State::Ignore(true));
341 return;
342 }
343 assert(!path_.empty());
344 componentName_ = path_.front();
345 if (trackPath_) {
347 {
348 state_.push(State::Ignore(true));
349 return;
350 }
351 } else {
352 path_.clear();
353 }
354 switch (node->kind()) {
357 SAL_WARN(
358 "configmgr",
359 "item of bad type \"" << path << "\" in \"" << reader.getUrl()
360 << '"');
361 state_.push(State::Ignore(true));
362 return;
364 valueParser_.type_ = static_cast< LocalizedPropertyNode * >(
365 node.get())->getStaticType();
366 break;
367 default:
368 break;
369 }
370 if (finalizedLayer < valueParser_.getLayer()) {
371 state_.push(State::Ignore(true));
372 return;
373 }
374 state_.push(State::Modify(node));
375}
376
378 xmlreader::XmlReader & reader, PropertyNode * prop)
379 {
380 bool nil = false;
381 OString separator;
382 OUString external;
383 for (;;) {
384 int attrNsId;
385 xmlreader::Span attrLn;
386 if (!reader.nextAttribute(&attrNsId, &attrLn)) {
387 break;
388 }
389 if (attrNsId == ParseManager::NAMESPACE_XSI && attrLn == "nil") {
390 nil = xmldata::parseBoolean(reader.getAttributeValue(true));
391 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
392 attrLn == "type")
393 {
395 reader, reader.getAttributeValue(true));
397 throw css::uno::RuntimeException(
398 "invalid value type in " + reader.getUrl());
399 }
401 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
402 attrLn == "separator")
403 {
404 xmlreader::Span s(reader.getAttributeValue(false));
405 if (s.length == 0) {
406 throw css::uno::RuntimeException(
407 "bad oor:separator attribute in " + reader.getUrl());
408 }
409 separator = OString(s.begin, s.length);
410 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
411 attrLn == "external")
412 {
413 external = reader.getAttributeValue(true).convertFromUtf8();
414 if (external.isEmpty()) {
415 throw css::uno::RuntimeException(
416 "bad oor:external attribute value in " + reader.getUrl());
417 }
418 }
419 }
420 if (nil) {
421 if (!prop->isNillable()) {
422 throw css::uno::RuntimeException(
423 "xsi:nil attribute for non-nillable prop in " + reader.getUrl());
424 }
425 if (!external.isEmpty()) {
426 throw css::uno::RuntimeException(
427 "xsi:nil and oor:external attributes for prop in " +
428 reader.getUrl());
429 }
430 prop->setValue(valueParser_.getLayer(), css::uno::Any());
431 state_.push(State::Ignore(false));
432 } else if (external.isEmpty()) {
434 valueParser_.start(prop);
435 } else {
436 prop->setExternal(valueParser_.getLayer(), external);
437 state_.push(State::Ignore(false));
438 }
439}
440
443{
444 OUString name;
445 bool nil = false;
446 OString separator;
448 for (;;) {
449 int attrNsId;
450 xmlreader::Span attrLn;
451 if (!reader.nextAttribute(&attrNsId, &attrLn)) {
452 break;
453 }
454 if (attrNsId == xmlreader::XmlReader::NAMESPACE_XML &&
455 attrLn == "lang")
456 {
457 name = reader.getAttributeValue(false).convertFromUtf8();
458 } else if (attrNsId == ParseManager::NAMESPACE_XSI &&
459 attrLn == "nil")
460 {
461 nil = xmldata::parseBoolean(reader.getAttributeValue(true));
462 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
463 attrLn == "type")
464 {
466 reader, reader.getAttributeValue(true));
468 throw css::uno::RuntimeException(
469 "invalid value type in " + reader.getUrl());
470 }
472 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
473 attrLn == "separator")
474 {
475 xmlreader::Span s(reader.getAttributeValue(false));
476 if (s.length == 0) {
477 throw css::uno::RuntimeException(
478 "bad oor:separator attribute in " + reader.getUrl());
479 }
480 separator = OString(s.begin, s.length);
481 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
482 attrLn == "op")
483 {
484 op = parseOperation(reader.getAttributeValue(true));
485 }
486 }
487 if (trackPath_) {
488 path_.push_back(name);
489 if (partial_ != nullptr &&
491 {
492 state_.push(State::Ignore(true));
493 return;
494 }
495 }
496 NodeMap & members = locprop->getMembers();
498 if (i != members.end() && i->second->getLayer() > valueParser_.getLayer()) {
499 state_.push(State::Ignore(true));
500 return;
501 }
502 if (nil && !locprop->isNillable()) {
503 throw css::uno::RuntimeException(
504 "xsi:nil attribute for non-nillable prop in " + reader.getUrl());
505 }
506 switch (op) {
507 case OPERATION_FUSE:
508 {
509 bool pop = false;
510 if (nil) {
511 if (i == members.end()) {
513 valueParser_.getLayer(), css::uno::Any());
514 } else {
515 static_cast< LocalizedValueNode * >(
516 i->second.get())->setValue(
517 valueParser_.getLayer(), css::uno::Any());
518 }
519 state_.push(State::Ignore(true));
520 } else {
522 valueParser_.start(locprop, name);
523 pop = true;
524 }
525 if (trackPath_) {
526 recordModification(false);
527 if (pop) {
528 path_.pop_back();
529 }
530 }
531 }
532 break;
533 case OPERATION_REMOVE:
534 //TODO: only allow if parent.op == OPERATION_FUSE
535 //TODO: disallow removing when e.g. lang=""?
536 if (i != members.end()) {
537 members.erase(i);
538 }
539 state_.push(State::Ignore(true));
540 recordModification(false);
541 break;
542 default:
543 throw css::uno::RuntimeException(
544 "bad op attribute for value element in " + reader.getUrl());
545 }
546}
547
549 xmlreader::XmlReader & reader, GroupNode * group)
550{
551 bool hasName = false;
552 OUString name;
555 bool finalized = false;
556 for (;;) {
557 int attrNsId;
558 xmlreader::Span attrLn;
559 if (!reader.nextAttribute(&attrNsId, &attrLn)) {
560 break;
561 }
562 if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn == "name") {
563 hasName = true;
564 name = reader.getAttributeValue(false).convertFromUtf8();
565 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
566 attrLn == "type")
567 {
568 type = xmldata::parseType(reader, reader.getAttributeValue(true));
569 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
570 attrLn == "op")
571 {
572 op = parseOperation(reader.getAttributeValue(true));
573 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
574 attrLn == "finalized")
575 {
576 finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
577 }
578 }
579 if (!hasName) {
580 throw css::uno::RuntimeException(
581 "no prop name attribute in " + reader.getUrl());
582 }
583 if (trackPath_) {
584 path_.push_back(name);
585 //TODO: This ignores locprop values for which specific include paths
586 // exist (i.e., for which contains(locprop path) = CONTAINS_SUBNODES):
587 if (partial_ != nullptr &&
589 {
590 state_.push(State::Ignore(true));
591 return;
592 }
593 }
594 NodeMap & members = group->getMembers();
596 if (i == members.end()) {
597 handleUnknownGroupProp(reader, group, name, type, op, finalized);
598 } else {
599 switch (i->second->kind()) {
601 handlePlainGroupProp(reader, group, i, name, type, op, finalized);
602 break;
605 reader,
606 static_cast< LocalizedPropertyNode * >(i->second.get()), name,
607 type, op, finalized);
608 break;
609 default:
610 throw css::uno::RuntimeException(
611 "inappropriate prop " + name + " in " + reader.getUrl());
612 }
613 }
614}
615
617 xmlreader::XmlReader const & reader, GroupNode const * group,
618 OUString const & name, Type type, Operation operation, bool finalized)
619{
620 switch (operation) {
622 case OPERATION_FUSE:
623 if (group->isExtensible()) {
624 if (type == TYPE_ERROR) {
625 throw css::uno::RuntimeException(
626 "missing type attribute for prop " + name + " in " +
627 reader.getUrl());
628 }
631 new PropertyNode(
632 valueParser_.getLayer(), TYPE_ANY, true, css::uno::Any(),
633 true));
634 if (finalized) {
635 prop->setFinalized(valueParser_.getLayer());
636 }
637 state_.push(State::Insert(prop, name));
638 recordModification(false);
639 break;
640 }
641 [[fallthrough]];
642 default:
643 SAL_WARN(
644 "configmgr",
645 "unknown property \"" << name << "\" in \"" << reader.getUrl()
646 << '"');
647 state_.push(State::Ignore(true));
648 break;
649 }
650}
651
653 xmlreader::XmlReader const & reader, GroupNode * group,
654 NodeMap::iterator const & propertyIndex, std::u16string_view name,
655 Type type, Operation operation, bool finalized)
656{
657 PropertyNode * property = static_cast< PropertyNode * >(
658 propertyIndex->second.get());
659 if (property->getLayer() > valueParser_.getLayer()) {
660 state_.push(State::Ignore(true));
661 return;
662 }
663 int finalizedLayer = std::min(
664 finalized ? valueParser_.getLayer() : Data::NO_LAYER,
665 property->getFinalized());
666 property->setFinalized(finalizedLayer);
667 if (finalizedLayer < valueParser_.getLayer()) {
668 state_.push(State::Ignore(true));
669 return;
670 }
671 if (type != TYPE_ERROR && property->getStaticType() != TYPE_ANY &&
672 type != property->getStaticType())
673 {
674 throw css::uno::RuntimeException(
675 OUString::Concat("invalid type for prop ") + name + " in " + reader.getUrl());
676 }
677 valueParser_.type_ = type == TYPE_ERROR ? property->getStaticType() : type;
678 switch (operation) {
679 case OPERATION_MODIFY:
681 case OPERATION_FUSE:
683 recordModification(false);
684 break;
685 case OPERATION_REMOVE:
686 if (!property->isExtension()) {
687 throw css::uno::RuntimeException(
688 OUString::Concat("invalid remove of non-extension prop ") + name + " in " +
689 reader.getUrl());
690 }
691 group->getMembers().erase(propertyIndex);
692 state_.push(State::Ignore(true));
693 recordModification(false);
694 break;
695 }
696}
697
700 OUString const & name, Type type, Operation operation, bool finalized)
701{
702 if (property->getLayer() > valueParser_.getLayer()) {
703 state_.push(State::Ignore(true));
704 return;
705 }
706 int finalizedLayer = std::min(
707 finalized ? valueParser_.getLayer() : Data::NO_LAYER,
708 property->getFinalized());
709 property->setFinalized(finalizedLayer);
710 if (finalizedLayer < valueParser_.getLayer()) {
711 state_.push(State::Ignore(true));
712 return;
713 }
714 if (type != TYPE_ERROR && property->getStaticType() != TYPE_ANY &&
715 type != property->getStaticType())
716 {
717 throw css::uno::RuntimeException(
718 "invalid type for prop " + name + " in " + reader.getUrl());
719 }
720 valueParser_.type_ = type == TYPE_ERROR ? property->getStaticType() : type;
721 switch (operation) {
722 case OPERATION_MODIFY:
723 case OPERATION_FUSE:
725 break;
727 {
728 rtl::Reference< Node > replacement(
730 valueParser_.getLayer(), property->getStaticType(),
731 property->isNillable()));
732 replacement->setFinalized(property->getFinalized());
733 state_.push(State::Insert(replacement, name));
734 recordModification(false);
735 }
736 break;
737 case OPERATION_REMOVE:
738 throw css::uno::RuntimeException(
739 "invalid remove of non-extension prop " + name + " in " +
740 reader.getUrl());
741 }
742}
743
745 xmlreader::XmlReader & reader, rtl::Reference< Node > const & group)
746{
747 bool hasName = false;
748 OUString name;
750 bool finalized = false;
751 for (;;) {
752 int attrNsId;
753 xmlreader::Span attrLn;
754 if (!reader.nextAttribute(&attrNsId, &attrLn)) {
755 break;
756 }
757 if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn == "name") {
758 hasName = true;
759 name = reader.getAttributeValue(false).convertFromUtf8();
760 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
761 attrLn == "op")
762 {
763 op = parseOperation(reader.getAttributeValue(true));
764 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
765 attrLn == "finalized")
766 {
767 finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
768 }
769 }
770 if (!hasName) {
771 throw css::uno::RuntimeException(
772 "no node name attribute in " + reader.getUrl());
773 }
774 if (trackPath_) {
775 path_.push_back(name);
777 {
778 state_.push(State::Ignore(true));
779 return;
780 }
781 }
783 group->getMembers().findNode(valueParser_.getLayer(), name));
784 if (!child.is()) {
785 SAL_WARN(
786 "configmgr",
787 "unknown node \"" << name << "\" in \"" << reader.getUrl() << '"');
788 state_.push(State::Ignore(true));
789 return;
790 }
791 Node::Kind kind = child->kind();
792 if (kind != Node::KIND_GROUP && kind != Node::KIND_SET) {
793 throw css::uno::RuntimeException(
794 "bad <node> \"" + name + "\" of non group/set kind in " +
795 reader.getUrl());
796 }
797 if (op != OPERATION_MODIFY && op != OPERATION_FUSE) {
798 throw css::uno::RuntimeException(
799 "invalid operation on group node in " + reader.getUrl());
800 }
801 int finalizedLayer = std::min(
802 finalized ? valueParser_.getLayer() : Data::NO_LAYER,
803 child->getFinalized());
804 child->setFinalized(finalizedLayer);
805 if (finalizedLayer < valueParser_.getLayer()) {
806 state_.push(State::Ignore(true));
807 return;
808 }
809 state_.push(State::Modify(child));
810}
811
813 bool hasName = false;
814 OUString name;
815 OUString component(componentName_);
816 bool hasNodeType = false;
817 OUString nodeType;
819 bool finalized = false;
820 bool mandatory = false;
821 for (;;) {
822 int attrNsId;
823 xmlreader::Span attrLn;
824 if (!reader.nextAttribute(&attrNsId, &attrLn)) {
825 break;
826 }
827 if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn == "name") {
828 hasName = true;
829 name = reader.getAttributeValue(false).convertFromUtf8();
830 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
831 attrLn == "component")
832 {
833 component = reader.getAttributeValue(false).convertFromUtf8();
834 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
835 attrLn == "node-type")
836 {
837 hasNodeType = true;
838 nodeType = reader.getAttributeValue(false).convertFromUtf8();
839 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
840 attrLn == "op")
841 {
842 op = parseOperation(reader.getAttributeValue(true));
843 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
844 attrLn == "finalized")
845 {
846 finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
847 } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
848 attrLn == "mandatory")
849 {
850 mandatory = xmldata::parseBoolean(reader.getAttributeValue(true));
851 }
852 }
853 if (!hasName) {
854 throw css::uno::RuntimeException(
855 "no node name attribute in " + reader.getUrl());
856 }
857 if (trackPath_) {
858 path_.push_back(name);
860 {
861 state_.push(State::Ignore(true));
862 return;
863 }
864 }
865 OUString templateName(
867 component, hasNodeType, nodeType, &set->getDefaultTemplateName()));
868 if (!set->isValidTemplate(templateName)) {
869 throw css::uno::RuntimeException(
870 "set member node " + name + " references invalid template " +
871 templateName + " in " + reader.getUrl());
872 }
874 data_.getTemplate(valueParser_.getLayer(), templateName));
875 if (!tmpl.is()) {
876 throw css::uno::RuntimeException(
877 "set member node " + name + " references undefined template " +
878 templateName + " in " + reader.getUrl());
879 }
880 int finalizedLayer = finalized ? valueParser_.getLayer() : Data::NO_LAYER;
881 int mandatoryLayer = mandatory ? valueParser_.getLayer() : Data::NO_LAYER;
882 NodeMap & members = set->getMembers();
884 if (i != members.end()) {
885 finalizedLayer = std::min(finalizedLayer, i->second->getFinalized());
886 i->second->setFinalized(finalizedLayer);
887 mandatoryLayer = std::min(mandatoryLayer, i->second->getMandatory());
888 i->second->setMandatory(mandatoryLayer);
889 if (i->second->getLayer() > valueParser_.getLayer()) {
890 state_.push(State::Ignore(true));
891 return;
892 }
893 }
894 if (finalizedLayer < valueParser_.getLayer()) {
895 state_.push(State::Ignore(true));
896 return;
897 }
898 switch (op) {
899 case OPERATION_MODIFY:
900 if (i == members.end()) {
901 SAL_WARN(
902 "configmgr",
903 "ignoring modify of unknown set member node \"" << name
904 << "\" in \"" << reader.getUrl() << '"');
905 state_.push(State::Ignore(true));
906 } else {
907 state_.push(State::Modify(i->second));
908 }
909 break;
911 {
912 rtl::Reference< Node > member(tmpl->clone(true));
913 member->setLayer(valueParser_.getLayer());
914 member->setFinalized(finalizedLayer);
915 member->setMandatory(mandatoryLayer);
916 state_.push(State::Insert(member, name));
917 recordModification(i == members.end());
918 }
919 break;
920 case OPERATION_FUSE:
921 if (i == members.end()) {
922 rtl::Reference< Node > member(tmpl->clone(true));
923 member->setLayer(valueParser_.getLayer());
924 member->setFinalized(finalizedLayer);
925 member->setMandatory(mandatoryLayer);
926 state_.push(State::Insert(member, name));
927 recordModification(true);
928 } else {
929 state_.push(State::Modify(i->second));
930 }
931 break;
932 case OPERATION_REMOVE:
933 {
934 // Ignore removal of unknown members and members made mandatory in
935 // this or a lower layer; forget about user-layer removals that no
936 // longer remove anything (so that paired additions/removals in the
937 // user layer do not grow registrymodifications.xcu unbounded):
938 bool known = i != members.end();
939 if (known &&
940 (mandatoryLayer == Data::NO_LAYER ||
941 mandatoryLayer > valueParser_.getLayer()))
942 {
943 members.erase(i);
944 }
945 state_.push(State::Ignore(true));
946 if (known) {
947 recordModification(false);
948 }
949 break;
950 }
951 }
952}
953
954void XcuParser::recordModification(bool addition) {
955 if (broadcastModifications_ != nullptr) {
957 }
958 if (addition && additions_ != nullptr) {
959 additions_->push_back(path_);
960 }
963 }
964}
965
966}
967
968/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual NodeMap & getMembers() override
void add(std::vector< OUString > const &path)
NodeMapImpl::iterator iterator
Definition: nodemap.hxx:37
rtl::Reference< Node > findNode(int layer, OUString const &name) const
Definition: nodemap.cxx:43
@ KIND_LOCALIZED_PROPERTY
Definition: node.hxx:35
@ KIND_LOCALIZED_VALUE
Definition: node.hxx:35
Containment contains(std::vector< OUString > const &path) const
Definition: partial.cxx:106
void setExternal(int layer, OUString const &descriptor)
void setValue(int layer, css::uno::Any const &value)
void characters(xmlreader::Span const &text)
bool startElement(xmlreader::XmlReader &reader, int nsId, xmlreader::Span const &name)
xmlreader::XmlReader::Text getTextMode() const
void start(rtl::Reference< Node > const &property, OUString const &localizedName=OUString())
ValueParser valueParser_
Definition: xcuparser.hxx:138
void handleLocpropValue(xmlreader::XmlReader &reader, LocalizedPropertyNode *locprop)
Definition: xcuparser.cxx:441
void handlePropValue(xmlreader::XmlReader &reader, PropertyNode *prop)
Definition: xcuparser.cxx:377
void recordModification(bool addition)
Definition: xcuparser.cxx:954
virtual void endElement(xmlreader::XmlReader const &reader) override
Definition: xcuparser.cxx:175
Partial const * partial_
Definition: xcuparser.hxx:140
void handlePlainGroupProp(xmlreader::XmlReader const &reader, GroupNode *group, NodeMap::iterator const &propertyIndex, std::u16string_view name, Type type, Operation operation, bool finalized)
Definition: xcuparser.cxx:652
void handleSetNode(xmlreader::XmlReader &reader, SetNode *set)
Definition: xcuparser.cxx:812
virtual bool startElement(xmlreader::XmlReader &reader, int nsId, xmlreader::Span const &name, std::set< OUString > const *existingDependencies) override
Definition: xcuparser.cxx:69
virtual xmlreader::XmlReader::Text getTextMode() override
Definition: xcuparser.cxx:65
void handleGroupProp(xmlreader::XmlReader &reader, GroupNode *group)
Definition: xcuparser.cxx:548
Additions * additions_
Definition: xcuparser.hxx:142
void handleComponentData(xmlreader::XmlReader &reader)
Definition: xcuparser.cxx:222
XcuParser(int layer, Data &data, Partial const *partial, Modifications *broadcastModifications, Additions *additions)
Definition: xcuparser.cxx:52
void handleUnknownGroupProp(xmlreader::XmlReader const &reader, GroupNode const *group, OUString const &name, Type type, Operation operation, bool finalized)
Definition: xcuparser.cxx:616
void handleItem(xmlreader::XmlReader &reader)
Definition: xcuparser.cxx:315
Modifications * broadcastModifications_
Definition: xcuparser.hxx:141
void handleLocalizedGroupProp(xmlreader::XmlReader const &reader, LocalizedPropertyNode *property, OUString const &name, Type type, Operation operation, bool finalized)
Definition: xcuparser.cxx:698
virtual void characters(xmlreader::Span const &span) override
Definition: xcuparser.cxx:200
void handleGroupNode(xmlreader::XmlReader &reader, rtl::Reference< Node > const &group)
Definition: xcuparser.cxx:744
std::vector< OUString > path_
Definition: xcuparser.hxx:147
std::stack< State > state_
Definition: xcuparser.hxx:146
virtual ~XcuParser() override
Definition: xcuparser.cxx:63
static Operation parseOperation(xmlreader::Span const &text)
Definition: xcuparser.cxx:204
const OUString & getUrl() const
bool nextAttribute(int *nsId, Span *localName)
Span getAttributeValue(bool fullyNormalize)
OUString name
Definition: components.cxx:85
#define SAL_WARN(area, stream)
def text(shape, orig_st)
void set(css::uno::UnoInterfaceReference const &value)
Type parseType(xmlreader::XmlReader const &reader, xmlreader::Span const &text)
Definition: xmldata.cxx:38
bool parseBoolean(xmlreader::Span const &text)
Definition: xmldata.cxx:105
OUString parseTemplateReference(std::u16string_view component, bool hasNodeType, std::u16string_view nodeType, OUString const *defaultTemplateName)
Definition: xmldata.cxx:117
std::vector< std::vector< OUString > > Additions
Definition: additions.hxx:31
@ TYPE_ANY
Definition: type.hxx:33
@ TYPE_ERROR
Definition: type.hxx:33
int i
group
PyObject_HEAD PyUNO_callable_Internals * members
RegError REGISTRY_CALLTYPE setValue(RegKeyHandle hKey, rtl_uString *keyName, RegValueType valueType, RegValue pData, sal_uInt32 valueSize)
Modifications modifications
Definition: data.hxx:51
rtl::Reference< Node > resolvePathRepresentation(OUString const &pathRepresentation, OUString *canonicRepresentation, std::vector< OUString > *path, int *finalizedLayer) const
Definition: data.cxx:181
NodeMap & getComponents() const
Definition: data.cxx:293
rtl::Reference< Node > getTemplate(int layer, OUString const &fullName) const
Definition: data.cxx:287
static State Modify(rtl::Reference< Node > const &theNode)
Definition: xcuparser.hxx:118
static State Insert(rtl::Reference< Node > const &theNode, OUString const &theName)
Definition: xcuparser.hxx:121
static State Ignore(bool thePop)
Definition: xcuparser.hxx:116
rtl::OUString convertFromUtf8() const
char const * begin
bool is() const
sal_Int32 length
ResultType type