Branch data Line data Source code
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 : :
25 : : #include "com/sun/star/uno/Any.hxx"
26 : : #include "com/sun/star/uno/Reference.hxx"
27 : : #include "com/sun/star/uno/RuntimeException.hpp"
28 : : #include "com/sun/star/uno/XInterface.hpp"
29 : : #include "rtl/oustringostreaminserter.hxx"
30 : : #include "rtl/ref.hxx"
31 : : #include "rtl/strbuf.hxx"
32 : : #include "rtl/string.h"
33 : : #include "rtl/string.hxx"
34 : : #include "rtl/ustring.h"
35 : : #include "rtl/ustring.hxx"
36 : : #include "sal/log.hxx"
37 : : #include "xmlreader/span.hxx"
38 : : #include "xmlreader/xmlreader.hxx"
39 : :
40 : : #include "data.hxx"
41 : : #include "localizedpropertynode.hxx"
42 : : #include "localizedvaluenode.hxx"
43 : : #include "groupnode.hxx"
44 : : #include "modifications.hxx"
45 : : #include "node.hxx"
46 : : #include "nodemap.hxx"
47 : : #include "parsemanager.hxx"
48 : : #include "partial.hxx"
49 : : #include "path.hxx"
50 : : #include "propertynode.hxx"
51 : : #include "setnode.hxx"
52 : : #include "xcuparser.hxx"
53 : : #include "xmldata.hxx"
54 : :
55 : : namespace configmgr {
56 : :
57 : : namespace {
58 : :
59 : : namespace css = com::sun::star;
60 : :
61 : : }
62 : :
63 : 48373 : XcuParser::XcuParser(
64 : : int layer, Data & data, Partial const * partial,
65 : : Modifications * broadcastModifications, Additions * additions):
66 : : valueParser_(layer), data_(data),
67 : : partial_(partial), broadcastModifications_(broadcastModifications),
68 : : additions_(additions), recordModifications_(layer == Data::NO_LAYER),
69 : : trackPath_(
70 : : partial_ != 0 || broadcastModifications_ != 0 || additions_ != 0 ||
71 [ + - ][ + - ]: 48373 : recordModifications_)
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
72 : 48373 : {}
73 : :
74 [ + - ][ - + ]: 96746 : XcuParser::~XcuParser() {}
75 : :
76 : 36606731 : xmlreader::XmlReader::Text XcuParser::getTextMode() {
77 : 36606731 : return valueParser_.getTextMode();
78 : : }
79 : :
80 : 15364408 : bool XcuParser::startElement(
81 : : xmlreader::XmlReader & reader, int nsId, xmlreader::Span const & name)
82 : : {
83 [ + + ]: 15364408 : if (valueParser_.startElement(reader, nsId, name)) {
84 : 25944 : return true;
85 : : }
86 [ + + ]: 15338464 : if (state_.empty()) {
87 [ + - + + ]: 96622 : if (nsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
88 : 48311 : name.equals(RTL_CONSTASCII_STRINGPARAM("component-data")))
89 : : {
90 : 48213 : handleComponentData(reader);
91 [ + - + - ]: 196 : } else if (nsId == ParseManager::NAMESPACE_OOR &&
[ + - ]
92 : 98 : name.equals(RTL_CONSTASCII_STRINGPARAM("items")))
93 : : {
94 [ + - ][ + - ]: 98 : state_.push(State(rtl::Reference< Node >(), false));
[ + - ]
95 : : } else {
96 : : throw css::uno::RuntimeException(
97 : : (rtl::OUString(
98 : : RTL_CONSTASCII_USTRINGPARAM("bad root element <")) +
99 : : name.convertFromUtf8() +
100 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
101 : : reader.getUrl()),
102 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
103 : : }
104 [ - + ]: 15290153 : } else if (state_.top().ignore) {
105 [ # # ]: 0 : state_.push(State(false));
106 [ + + ]: 15290153 : } else if (!state_.top().node.is()) {
107 [ + - + - ]: 24824 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
[ + - ]
108 : 12412 : name.equals(RTL_CONSTASCII_STRINGPARAM("item")))
109 : : {
110 : 12412 : handleItem(reader);
111 : : } else {
112 : : throw css::uno::RuntimeException(
113 : : (rtl::OUString(
114 : : RTL_CONSTASCII_USTRINGPARAM("bad items node member <")) +
115 : : name.convertFromUtf8() +
116 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
117 : : reader.getUrl()),
118 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
119 : : }
120 : : } else {
121 [ + + - + : 15277741 : switch (state_.top().node->kind()) {
+ - - ]
122 : : case Node::KIND_PROPERTY:
123 [ + - + - ]: 8685694 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
[ + - ]
124 : 4342847 : name.equals(RTL_CONSTASCII_STRINGPARAM("value")))
125 : : {
126 : : handlePropValue(
127 : : reader,
128 [ - + ]: 4342847 : dynamic_cast< PropertyNode * >(state_.top().node.get()));
129 : : } else {
130 : : throw css::uno::RuntimeException(
131 : : (rtl::OUString(
132 : : RTL_CONSTASCII_USTRINGPARAM(
133 : : "bad property node member <")) +
134 : : name.convertFromUtf8() +
135 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
136 : : reader.getUrl()),
137 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
138 : : }
139 : 4342847 : break;
140 : : case Node::KIND_LOCALIZED_PROPERTY:
141 [ + - + - ]: 3621880 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
[ + - ]
142 : 1810940 : name.equals(RTL_CONSTASCII_STRINGPARAM("value")))
143 : : {
144 : : handleLocpropValue(
145 : : reader,
146 : : dynamic_cast< LocalizedPropertyNode * >(
147 [ - + ]: 1810940 : state_.top().node.get()));
148 : : } else {
149 : : throw css::uno::RuntimeException(
150 : : (rtl::OUString(
151 : : RTL_CONSTASCII_USTRINGPARAM(
152 : : "bad localized property node member <")) +
153 : : name.convertFromUtf8() +
154 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
155 : : reader.getUrl()),
156 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
157 : : }
158 : 1810940 : break;
159 : : case Node::KIND_LOCALIZED_VALUE:
160 : : throw css::uno::RuntimeException(
161 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad member <")) +
162 : : name.convertFromUtf8() +
163 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
164 : : reader.getUrl()),
165 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
166 : : case Node::KIND_GROUP:
167 [ + - + + ]: 13212234 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
[ + + ]
168 : 6606117 : name.equals(RTL_CONSTASCII_STRINGPARAM("prop")))
169 : : {
170 : : handleGroupProp(
171 : : reader,
172 [ - + ]: 6426494 : dynamic_cast< GroupNode * >(state_.top().node.get()));
173 [ + - + - ]: 359246 : } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
[ + - ]
174 : 179623 : name.equals(RTL_CONSTASCII_STRINGPARAM("node")))
175 : : {
176 : 179623 : handleGroupNode(reader, state_.top().node);
177 : : } else {
178 : : throw css::uno::RuntimeException(
179 : : (rtl::OUString(
180 : : RTL_CONSTASCII_USTRINGPARAM(
181 : : "bad group node member <")) +
182 : : name.convertFromUtf8() +
183 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
184 : : reader.getUrl()),
185 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
186 : : }
187 : 6606117 : break;
188 : : case Node::KIND_SET:
189 [ + - + - ]: 5035674 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
[ + - ]
190 : 2517837 : name.equals(RTL_CONSTASCII_STRINGPARAM("node")))
191 : : {
192 : : handleSetNode(
193 [ - + ]: 2517837 : reader, dynamic_cast< SetNode * >(state_.top().node.get()));
194 [ # # # # ]: 0 : } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
[ # # ]
195 : 0 : name.equals(RTL_CONSTASCII_STRINGPARAM("prop")))
196 : : {
197 : : SAL_WARN(
198 : : "configmgr",
199 : : "bad set node <prop> member in \"" << reader.getUrl()
200 : : << '"');
201 [ # # ]: 0 : state_.push(State(true)); // ignored
202 : : } else {
203 : : throw css::uno::RuntimeException(
204 : : (rtl::OUString(
205 : : RTL_CONSTASCII_USTRINGPARAM("bad set node member <")) +
206 : : name.convertFromUtf8() +
207 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
208 : : reader.getUrl()),
209 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
210 : : }
211 : 2517837 : break;
212 : : case Node::KIND_ROOT:
213 : : assert(false); // this cannot happen
214 : 0 : break;
215 : : }
216 : : }
217 : 15364408 : return true;
218 : : }
219 : :
220 : 15364408 : void XcuParser::endElement(xmlreader::XmlReader const &) {
221 [ + - ][ + + ]: 15364408 : if (valueParser_.endElement()) {
222 : 15364408 : return;
223 : : }
224 : : assert(!state_.empty());
225 [ + - ]: 9193468 : bool pop = state_.top().pop;
226 : 9193468 : rtl::Reference< Node > insert;
227 : 9193468 : rtl::OUString name;
228 [ + + ][ + - ]: 9193468 : if (state_.top().insert) {
229 [ + - ][ + - ]: 2587095 : insert = state_.top().node;
230 : : assert(insert.is());
231 [ + - ]: 2587095 : name = state_.top().name;
232 : : }
233 [ + - ]: 9193468 : state_.pop();
234 [ + + ]: 9193468 : if (insert.is()) {
235 : : assert(!state_.empty() && state_.top().node.is());
236 [ + - ][ + - ]: 2587095 : state_.top().node->getMembers()[name] = insert;
[ + - ][ + - ]
237 : : }
238 [ + + ][ + + ]: 9193468 : if (pop && !path_.empty()) {
[ + + ]
239 [ + - ]: 27902 : path_.pop_back();
240 : : // </item> will pop less than <item> pushed, but that is harmless,
241 : : // as the next <item> will reset path_
242 [ + - ]: 15364408 : }
243 : : }
244 : :
245 : 5879180 : void XcuParser::characters(xmlreader::Span const & text) {
246 : 5879180 : valueParser_.characters(text);
247 : 5879180 : }
248 : :
249 : 2592619 : XcuParser::Operation XcuParser::parseOperation(xmlreader::Span const & text) {
250 : : assert(text.is());
251 [ - + ]: 2592619 : if (text.equals(RTL_CONSTASCII_STRINGPARAM("modify"))) {
252 : 0 : return OPERATION_MODIFY;
253 : : }
254 [ + + ]: 2592619 : if (text.equals(RTL_CONSTASCII_STRINGPARAM("replace"))) {
255 : 2561363 : return OPERATION_REPLACE;
256 : : }
257 [ + - ]: 31256 : if (text.equals(RTL_CONSTASCII_STRINGPARAM("fuse"))) {
258 : 31256 : return OPERATION_FUSE;
259 : : }
260 [ # # ]: 0 : if (text.equals(RTL_CONSTASCII_STRINGPARAM("remove"))) {
261 : 0 : return OPERATION_REMOVE;
262 : : }
263 : : throw css::uno::RuntimeException(
264 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid op ")) +
265 : : text.convertFromUtf8()),
266 [ # # ][ # # ]: 2592619 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
267 : : }
268 : :
269 : 48213 : void XcuParser::handleComponentData(xmlreader::XmlReader & reader) {
270 : 48213 : rtl::OStringBuffer buf;
271 [ + - ]: 48213 : buf.append('.');
272 : 48213 : bool hasPackage = false;
273 : 48213 : bool hasName = false;
274 : 48213 : Operation op = OPERATION_MODIFY;
275 : 48213 : bool finalized = false;
276 : 96426 : for (;;) {
277 : : int attrNsId;
278 : 144639 : xmlreader::Span attrLn;
279 [ + + ][ + - ]: 144639 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
280 : : break;
281 : : }
282 [ + - + + ]: 192852 : if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
283 : 96426 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("package")))
284 : : {
285 [ - + ]: 48213 : if (hasPackage) {
286 : : throw css::uno::RuntimeException(
287 : : (rtl::OUString(
288 : : RTL_CONSTASCII_USTRINGPARAM(
289 : : "multiple component-update package attributes"
290 : : " in ")) +
291 : : reader.getUrl()),
292 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
293 : : }
294 : 48213 : hasPackage = true;
295 [ + - ]: 48213 : xmlreader::Span s(reader.getAttributeValue(false));
296 [ + - ]: 48213 : buf.insert(0, s.begin, s.length);
297 [ + - + - ]: 96426 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + - ]
298 : 48213 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
299 : : {
300 [ - + ]: 48213 : if (hasName) {
301 : : throw css::uno::RuntimeException(
302 : : (rtl::OUString(
303 : : RTL_CONSTASCII_USTRINGPARAM(
304 : : "multiple component-update name attributes in ")) +
305 : : reader.getUrl()),
306 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
307 : : }
308 : 48213 : hasName = true;
309 [ + - ]: 48213 : xmlreader::Span s(reader.getAttributeValue(false));
310 [ + - ]: 48213 : buf.append(s.begin, s.length);
311 [ # # # # ]: 0 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ # # ]
312 : 0 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
313 : : {
314 [ # # ][ # # ]: 0 : op = parseOperation(reader.getAttributeValue(true));
315 [ # # # # ]: 0 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ # # ]
316 : 0 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
317 : : {
318 [ # # ][ # # ]: 0 : finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
319 : : }
320 : : }
321 [ - + ]: 48213 : if (!hasPackage) {
322 : : throw css::uno::RuntimeException(
323 : : (rtl::OUString(
324 : : RTL_CONSTASCII_USTRINGPARAM(
325 : : "no component-data package attribute in ")) +
326 : : reader.getUrl()),
327 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
328 : : }
329 [ - + ]: 48213 : if (!hasName) {
330 : : throw css::uno::RuntimeException(
331 : : (rtl::OUString(
332 : : RTL_CONSTASCII_USTRINGPARAM(
333 : : "no component-data name attribute in ")) +
334 : : reader.getUrl()),
335 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
336 : : }
337 : : componentName_ = xmlreader::Span(buf.getStr(), buf.getLength()).
338 [ + - ]: 48213 : convertFromUtf8();
339 [ - + ]: 48213 : if (trackPath_) {
340 : : assert(path_.empty());
341 [ # # ]: 0 : path_.push_back(componentName_);
342 [ # # ][ # # ]: 0 : if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
[ # # ][ # # ]
343 : : {
344 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
345 : : return;
346 : : }
347 : : }
348 : : rtl::Reference< Node > node(
349 : : Data::findNode(
350 [ + - ][ + - ]: 48213 : valueParser_.getLayer(), data_.getComponents(), componentName_));
[ + - ]
351 [ - + ]: 48213 : if (!node.is()) {
352 : : SAL_WARN(
353 : : "configmgr",
354 : : "unknown component \"" << componentName_ << "\" in \""
355 : : << reader.getUrl() << '"');
356 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
357 : : return;
358 : : }
359 [ + - ]: 48213 : switch (op) {
360 : : case OPERATION_MODIFY:
361 : : case OPERATION_FUSE:
362 : 48213 : break;
363 : : default:
364 : : throw css::uno::RuntimeException(
365 : : (rtl::OUString(
366 : : RTL_CONSTASCII_USTRINGPARAM(
367 : : "invalid operation on root node in ")) +
368 : : reader.getUrl()),
369 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
370 : : }
371 : : int finalizedLayer = std::min(
372 : 0 : finalized ? valueParser_.getLayer() : Data::NO_LAYER,
373 [ + - ][ - + ]: 48213 : node->getFinalized());
[ # # ][ + - ]
374 [ + - ]: 48213 : node->setFinalized(finalizedLayer);
375 [ + - ][ + - ]: 48213 : state_.push(State(node, finalizedLayer < valueParser_.getLayer()));
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ]
376 : : }
377 : :
378 : 12412 : void XcuParser::handleItem(xmlreader::XmlReader & reader) {
379 : 12412 : xmlreader::Span attrPath;
380 : 12412 : for (;;) {
381 : : int attrNsId;
382 : 24824 : xmlreader::Span attrLn;
383 [ + + ][ + - ]: 24824 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
384 : : break;
385 : : }
386 [ + - + - ]: 24824 : if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + - ]
387 : 12412 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("path")))
388 : : {
389 [ + - ]: 12412 : attrPath = reader.getAttributeValue(false);
390 : : }
391 : : }
392 [ - + ]: 12412 : if (!attrPath.is()) {
393 : : throw css::uno::RuntimeException(
394 : : (rtl::OUString(
395 : : RTL_CONSTASCII_USTRINGPARAM("missing path attribute in ")) +
396 : : reader.getUrl()),
397 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
398 : : }
399 [ + - ]: 12412 : rtl::OUString path(attrPath.convertFromUtf8());
400 : : int finalizedLayer;
401 : : rtl::Reference< Node > node(
402 : : data_.resolvePathRepresentation(
403 [ + - ]: 12412 : path, 0, &path_, &finalizedLayer));
404 [ - + ]: 12412 : if (!node.is()) {
405 : : SAL_WARN(
406 : : "configmgr",
407 : : "unknown item \"" << path << "\" in \"" << reader.getUrl() << '"');
408 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
409 : : return;
410 : : }
411 : : assert(!path_.empty());
412 [ + - ]: 12412 : componentName_ = path_.front();
413 [ + - ]: 12412 : if (trackPath_) {
414 [ - + ][ # # ]: 12412 : if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
[ # # ][ - + ]
415 : : {
416 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
417 : : return;
418 : : }
419 : : } else {
420 : 0 : path_.clear();
421 : : }
422 [ + - ]: 12412 : switch (node->kind()) {
[ - + + ]
423 : : case Node::KIND_PROPERTY:
424 : : case Node::KIND_LOCALIZED_VALUE:
425 : : SAL_WARN(
426 : : "configmgr",
427 : : "item of bad type \"" << path << "\" in \"" << reader.getUrl()
428 : : << '"');
429 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
430 : : return;
431 : : case Node::KIND_LOCALIZED_PROPERTY:
432 : : valueParser_.type_ = dynamic_cast< LocalizedPropertyNode * >(
433 [ - + ][ + - ]: 84 : node.get())->getStaticType();
434 : 84 : break;
435 : : default:
436 : 12328 : break;
437 : : }
438 [ + - ][ + - ]: 12412 : state_.push(State(node, finalizedLayer < valueParser_.getLayer()));
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ]
439 : : }
440 : :
441 : 4342847 : void XcuParser::handlePropValue(
442 : : xmlreader::XmlReader & reader, PropertyNode * prop)
443 : : {
444 : 4342847 : bool nil = false;
445 : 4342847 : rtl::OString separator;
446 : 4342847 : rtl::OUString external;
447 : 40657 : for (;;) {
448 : : int attrNsId;
449 : 4383504 : xmlreader::Span attrLn;
450 [ + + ][ + - ]: 4383504 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
451 : : break;
452 : : }
453 [ + + + - ]: 41003 : if (attrNsId == ParseManager::NAMESPACE_XSI &&
[ + + ]
454 : 346 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("nil")))
455 : : {
456 [ + - ][ + - ]: 346 : nil = xmldata::parseBoolean(reader.getAttributeValue(true));
457 [ + + - + ]: 71550 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ - + ]
458 : 31239 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
459 : : {
460 : : Type type = xmldata::parseType(
461 [ # # ][ # # ]: 0 : reader, reader.getAttributeValue(true));
462 [ # # ][ # # ]: 0 : if (valueParser_.type_ != TYPE_ANY && type != valueParser_.type_) {
463 : : throw css::uno::RuntimeException(
464 : : (rtl::OUString(
465 : : RTL_CONSTASCII_USTRINGPARAM("invalid value type in ")) +
466 : : reader.getUrl()),
467 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
468 : : }
469 : 0 : valueParser_.type_ = type;
470 [ + + + + ]: 71550 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
471 : 31239 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("separator")))
472 : : {
473 [ + - ]: 22794 : xmlreader::Span s(reader.getAttributeValue(false));
474 [ - + ]: 22794 : if (s.length == 0) {
475 : : throw css::uno::RuntimeException(
476 : : (rtl::OUString(
477 : : RTL_CONSTASCII_USTRINGPARAM(
478 : : "bad oor:separator attribute in ")) +
479 : : reader.getUrl()),
480 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
481 : : }
482 : 22794 : separator = rtl::OString(s.begin, s.length);
483 [ + + + - ]: 25962 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
484 : 8445 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("external")))
485 : : {
486 [ + - ][ + - ]: 8445 : external = reader.getAttributeValue(true).convertFromUtf8();
487 [ - + ]: 8445 : if (external.isEmpty()) {
488 : : throw css::uno::RuntimeException(
489 : : (rtl::OUString(
490 : : RTL_CONSTASCII_USTRINGPARAM(
491 : : "bad oor:external attribute value in ")) +
492 : : reader.getUrl()),
493 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
494 : : }
495 : : }
496 : : }
497 [ + + ]: 4342847 : if (nil) {
498 [ + - ][ - + ]: 346 : if (!prop->isNillable()) {
499 : : throw css::uno::RuntimeException(
500 : : (rtl::OUString(
501 : : RTL_CONSTASCII_USTRINGPARAM(
502 : : "xsi:nil attribute for non-nillable prop in ")) +
503 : : reader.getUrl()),
504 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
505 : : }
506 [ - + ]: 346 : if (!external.isEmpty()) {
507 : : throw css::uno::RuntimeException(
508 : : (rtl::OUString(
509 : : RTL_CONSTASCII_USTRINGPARAM(
510 : : "xsi:nil and oor:external attributes for prop in ")) +
511 : : reader.getUrl()),
512 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
513 : : }
514 [ + - ][ + - ]: 346 : prop->setValue(valueParser_.getLayer(), css::uno::Any());
515 [ + - ][ + - ]: 346 : state_.push(State(false));
[ + - ]
516 [ + + ]: 4342501 : } else if (external.isEmpty()) {
517 : 4334056 : valueParser_.separator_ = separator;
518 [ + - ][ + - ]: 4334056 : valueParser_.start(prop);
[ + - ]
519 : : } else {
520 [ + - ][ + - ]: 8445 : prop->setExternal(valueParser_.getLayer(), external);
521 [ + - ][ + - ]: 8445 : state_.push(State(false));
[ + - ]
522 : 4342847 : }
523 : 4342847 : }
524 : :
525 : 1810940 : void XcuParser::handleLocpropValue(
526 : : xmlreader::XmlReader & reader, LocalizedPropertyNode * locprop)
527 : : {
528 : 1810940 : rtl::OUString name;
529 : 1810940 : bool nil = false;
530 : 1810940 : rtl::OString separator;
531 : 1810940 : Operation op = OPERATION_FUSE;
532 : 1731012 : for (;;) {
533 : : int attrNsId;
534 : 3541952 : xmlreader::Span attrLn;
535 [ + + ][ + - ]: 3541952 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
536 : : break;
537 : : }
538 [ + + + - ]: 3460803 : if (attrNsId == xmlreader::XmlReader::NAMESPACE_XML &&
[ + + ]
539 : 1729791 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("lang")))
540 : : {
541 [ + - ][ + - ]: 1729791 : name = reader.getAttributeValue(false).convertFromUtf8();
542 [ - + # # ]: 1221 : } else if (attrNsId == ParseManager::NAMESPACE_XSI &&
[ - + ]
543 : 0 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("nil")))
544 : : {
545 [ # # ][ # # ]: 0 : nil = xmldata::parseBoolean(reader.getAttributeValue(true));
546 [ + - - + ]: 2442 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ - + ]
547 : 1221 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
548 : : {
549 : : Type type = xmldata::parseType(
550 [ # # ][ # # ]: 0 : reader, reader.getAttributeValue(true));
551 [ # # ][ # # ]: 0 : if (valueParser_.type_ != TYPE_ANY && type != valueParser_.type_) {
552 : : throw css::uno::RuntimeException(
553 : : (rtl::OUString(
554 : : RTL_CONSTASCII_USTRINGPARAM("invalid value type in ")) +
555 : : reader.getUrl()),
556 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
557 : : }
558 : 0 : valueParser_.type_ = type;
559 [ + - + - ]: 2442 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + - ]
560 : 1221 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("separator")))
561 : : {
562 [ + - ]: 1221 : xmlreader::Span s(reader.getAttributeValue(false));
563 [ - + ]: 1221 : if (s.length == 0) {
564 : : throw css::uno::RuntimeException(
565 : : (rtl::OUString(
566 : : RTL_CONSTASCII_USTRINGPARAM(
567 : : "bad oor:separator attribute in ")) +
568 : : reader.getUrl()),
569 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
570 : : }
571 : 1221 : separator = rtl::OString(s.begin, s.length);
572 [ # # # # ]: 0 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ # # ]
573 : 0 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
574 : : {
575 [ # # ][ # # ]: 0 : op = parseOperation(reader.getAttributeValue(true));
576 : : }
577 : : }
578 [ + + ]: 1810940 : if (trackPath_) {
579 [ + - ]: 84 : path_.push_back(name);
580 [ - + ][ # # ]: 84 : if (partial_ != 0 &&
[ - + ]
581 [ # # ]: 0 : partial_->contains(path_) != Partial::CONTAINS_NODE)
582 : : {
583 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
584 : : return;
585 : : }
586 : : }
587 [ + - ]: 1810940 : NodeMap & members = locprop->getMembers();
588 [ + - ]: 1810940 : NodeMap::iterator i(members.find(name));
589 [ + + ][ + - ]: 1810940 : if (i != members.end() && i->second->getLayer() > valueParser_.getLayer()) {
[ + - ][ - + ]
[ + - ]
[ - + # # ]
590 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
591 : : return;
592 : : }
593 [ - + ][ # # ]: 1810940 : if (nil && !locprop->isNillable()) {
[ # # ][ - + ]
594 : : throw css::uno::RuntimeException(
595 : : (rtl::OUString(
596 : : RTL_CONSTASCII_USTRINGPARAM(
597 : : "xsi:nil attribute for non-nillable prop in ")) +
598 : : reader.getUrl()),
599 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
600 : : }
601 [ + - - ]: 1810940 : switch (op) {
602 : : case OPERATION_FUSE:
603 : : {
604 : 1810940 : bool pop = false;
605 [ - + ]: 1810940 : if (nil) {
606 [ # # ]: 0 : if (i == members.end()) {
607 [ # # ]: 0 : members[name] = new LocalizedValueNode(
608 [ # # ][ # # ]: 0 : valueParser_.getLayer(), css::uno::Any());
[ # # ][ # # ]
609 : : } else {
610 : : dynamic_cast< LocalizedValueNode * >(
611 : 0 : i->second.get())->setValue(
612 [ # # # # ]: 0 : valueParser_.getLayer(), css::uno::Any());
[ # # ]
613 : : }
614 [ # # ][ # # ]: 0 : state_.push(State(true));
[ # # ]
615 : : } else {
616 : 1810940 : valueParser_.separator_ = separator;
617 [ + - ][ + - ]: 1810940 : valueParser_.start(locprop, name);
[ + - ]
618 : 1810940 : pop = true;
619 : : }
620 [ + + ]: 1810940 : if (trackPath_) {
621 [ + - ]: 84 : recordModification(false);
622 [ + - ]: 84 : if (pop) {
623 [ + - ]: 84 : path_.pop_back();
624 : : }
625 : : }
626 : : }
627 : 1810940 : break;
628 : : case OPERATION_REMOVE:
629 : : //TODO: only allow if parent.op == OPERATION_FUSE
630 : : //TODO: disallow removing when e.g. lang=""?
631 [ # # ]: 0 : if (i != members.end()) {
632 [ # # ]: 0 : members.erase(i);
633 : : }
634 [ # # ][ # # ]: 0 : state_.push(State(true));
[ # # ]
635 [ # # ]: 0 : recordModification(false);
636 : 0 : break;
637 : : default:
638 : : throw css::uno::RuntimeException(
639 : : (rtl::OUString(
640 : : RTL_CONSTASCII_USTRINGPARAM(
641 : : "bad op attribute for value element in ")) +
642 : : reader.getUrl()),
643 [ # # ][ # # ]: 1810940 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
644 [ - + ][ + - ]: 1810940 : }
645 : : }
646 : :
647 : 6426494 : void XcuParser::handleGroupProp(
648 : : xmlreader::XmlReader & reader, GroupNode * group)
649 : : {
650 : 6426494 : bool hasName = false;
651 : 6426494 : rtl::OUString name;
652 : 6426494 : Type type = TYPE_ERROR;
653 : 6426494 : Operation op = OPERATION_MODIFY;
654 : 6426494 : bool finalized = false;
655 : 8459570 : for (;;) {
656 : : int attrNsId;
657 : 14886064 : xmlreader::Span attrLn;
658 [ + + ][ + - ]: 14886064 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
659 : : break;
660 : : }
661 [ + - + + ]: 16919140 : if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
662 : 8459570 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
663 : : {
664 : 6426494 : hasName = true;
665 [ + - ][ + - ]: 6426494 : name = reader.getAttributeValue(false).convertFromUtf8();
666 [ + - + + ]: 4066152 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
667 : 2033076 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
668 : : {
669 [ + - ][ + - ]: 1907463 : type = xmldata::parseType(reader, reader.getAttributeValue(true));
670 [ + - + + ]: 251226 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
671 : 125613 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
672 : : {
673 [ + - ][ + - ]: 97866 : op = parseOperation(reader.getAttributeValue(true));
674 [ + - + - ]: 55494 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + - ]
675 : 27747 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
676 : : {
677 [ + - ][ + - ]: 27747 : finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
678 : : }
679 : : }
680 [ - + ]: 6426494 : if (!hasName) {
681 : : throw css::uno::RuntimeException(
682 : : (rtl::OUString(
683 : : RTL_CONSTASCII_USTRINGPARAM("no prop name attribute in ")) +
684 : : reader.getUrl()),
685 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
686 : : }
687 [ + + ]: 6426494 : if (trackPath_) {
688 [ + - ]: 13980 : path_.push_back(name);
689 : : //TODO: This ignores locprop values for which specific include paths
690 : : // exist (i.e., for which contains(locprop path) = CONTAINS_SUBNODES):
691 [ - + ][ # # ]: 13980 : if (partial_ != 0 &&
[ - + ]
692 [ # # ]: 0 : partial_->contains(path_) != Partial::CONTAINS_NODE)
693 : : {
694 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
695 : 6426494 : return;
696 : : }
697 : : }
698 [ + - ]: 6426494 : NodeMap & members = group->getMembers();
699 [ + - ]: 6426494 : NodeMap::iterator i(members.find(name));
700 [ + + ]: 6426494 : if (i == members.end()) {
701 [ + - ]: 92440 : handleUnknownGroupProp(reader, group, name, type, op, finalized);
702 : : } else {
703 [ + - ]: 6334054 : switch (i->second->kind()) {
[ + + - ]
704 : : case Node::KIND_PROPERTY:
705 [ + - ]: 4494582 : handlePlainGroupProp(reader, group, i, name, type, op, finalized);
706 : 4494582 : break;
707 : : case Node::KIND_LOCALIZED_PROPERTY:
708 : : handleLocalizedGroupProp(
709 : : reader,
710 : 1839472 : dynamic_cast< LocalizedPropertyNode * >(i->second.get()), name,
711 [ + - ][ - + ]: 1839472 : type, op, finalized);
712 : 1839472 : break;
713 : : default:
714 : : throw css::uno::RuntimeException(
715 : : (rtl::OUString(
716 : : RTL_CONSTASCII_USTRINGPARAM("inappropriate prop ")) +
717 : : name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
718 : : reader.getUrl()),
719 [ # # ][ # # ]: 6426494 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
720 : : }
721 [ + - ]: 6426494 : }
722 : : }
723 : :
724 : 92440 : void XcuParser::handleUnknownGroupProp(
725 : : xmlreader::XmlReader const & reader, GroupNode * group,
726 : : rtl::OUString const & name, Type type, Operation operation, bool finalized)
727 : : {
728 [ + - ]: 92440 : switch (operation) {
729 : : case OPERATION_REPLACE:
730 : : case OPERATION_FUSE:
731 [ + - ]: 92440 : if (group->isExtensible()) {
732 [ - + ]: 92440 : if (type == TYPE_ERROR) {
733 : : throw css::uno::RuntimeException(
734 : : (rtl::OUString(
735 : : RTL_CONSTASCII_USTRINGPARAM(
736 : : "missing type attribute for prop ")) +
737 : : name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
738 : : reader.getUrl()),
739 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
740 : : }
741 : 92440 : valueParser_.type_ = type;
742 : : rtl::Reference< Node > prop(
743 : : new PropertyNode(
744 : 92440 : valueParser_.getLayer(), TYPE_ANY, true, css::uno::Any(),
745 [ + - ][ + - ]: 92440 : true));
[ + - ][ + - ]
746 [ - + ]: 92440 : if (finalized) {
747 [ # # ][ # # ]: 0 : prop->setFinalized(valueParser_.getLayer());
748 : : }
749 [ + - ][ + - ]: 92440 : state_.push(State(prop, name, state_.top().locked));
[ + - ][ + - ]
750 [ + - ]: 92440 : recordModification(false);
751 [ + - ]: 92440 : break;
752 : : }
753 : : // fall through
754 : : default:
755 : : SAL_WARN(
756 : : "configmgr",
757 : : "unknown property \"" << name << "\" in \"" << reader.getUrl()
758 : : << '"');
759 [ # # ]: 0 : state_.push(State(true)); // ignored
760 : 0 : break;
761 : : }
762 : 92440 : }
763 : :
764 : 4494582 : void XcuParser::handlePlainGroupProp(
765 : : xmlreader::XmlReader const & reader, GroupNode * group,
766 : : NodeMap::iterator const & propertyIndex, rtl::OUString const & name,
767 : : Type type, Operation operation, bool finalized)
768 : : {
769 : : PropertyNode * property = dynamic_cast< PropertyNode * >(
770 [ - + ]: 4494582 : propertyIndex->second.get());
771 [ - + ]: 4494582 : if (property->getLayer() > valueParser_.getLayer()) {
772 [ # # ]: 0 : state_.push(State(true)); // ignored
773 : 4494582 : return;
774 : : }
775 : : int finalizedLayer = std::min(
776 : 27747 : finalized ? valueParser_.getLayer() : Data::NO_LAYER,
777 [ + + ][ + - ]: 4494582 : property->getFinalized());
[ + - ]
778 : 4494582 : property->setFinalized(finalizedLayer);
779 [ + + - + ]: 5366806 : if (type != TYPE_ERROR && property->getStaticType() != TYPE_ANY &&
[ - + ][ + + ]
780 : 872224 : type != property->getStaticType())
781 : : {
782 : : throw css::uno::RuntimeException(
783 : : (rtl::OUString(
784 : : RTL_CONSTASCII_USTRINGPARAM("invalid type for prop ")) +
785 : : name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
786 : : reader.getUrl()),
787 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
788 : : }
789 [ + + ]: 4494582 : valueParser_.type_ = type == TYPE_ERROR ? property->getStaticType() : type;
790 [ + - - ]: 4494582 : switch (operation) {
791 : : case OPERATION_MODIFY:
792 : : case OPERATION_REPLACE:
793 : : case OPERATION_FUSE:
794 : : state_.push(
795 : : State(
796 : : property,
797 : 4494582 : (state_.top().locked ||
798 [ - + ][ + - ]: 4494582 : finalizedLayer < valueParser_.getLayer())));
[ + - ][ + - ]
[ + - ]
799 : 4494582 : recordModification(false);
800 : 4494582 : break;
801 : : case OPERATION_REMOVE:
802 [ # # ]: 0 : if (!property->isExtension()) {
803 : : throw css::uno::RuntimeException(
804 : : (rtl::OUString(
805 : : RTL_CONSTASCII_USTRINGPARAM(
806 : : "invalid remove of non-extension prop ")) +
807 : : name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
808 : : reader.getUrl()),
809 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
810 : : }
811 : 0 : group->getMembers().erase(propertyIndex);
812 [ # # ]: 0 : state_.push(State(true)); // ignore children
813 : 0 : recordModification(false);
814 : 0 : break;
815 : : }
816 : : }
817 : :
818 : 1839472 : void XcuParser::handleLocalizedGroupProp(
819 : : xmlreader::XmlReader const & reader, LocalizedPropertyNode * property,
820 : : rtl::OUString const & name, Type type, Operation operation, bool finalized)
821 : : {
822 [ - + ]: 1839472 : if (property->getLayer() > valueParser_.getLayer()) {
823 [ # # ]: 0 : state_.push(State(true)); // ignored
824 : 1839472 : return;
825 : : }
826 : : int finalizedLayer = std::min(
827 : 0 : finalized ? valueParser_.getLayer() : Data::NO_LAYER,
828 [ - + ][ # # ]: 1839472 : property->getFinalized());
[ + - ]
829 : 1839472 : property->setFinalized(finalizedLayer);
830 [ + + - + ]: 2763813 : if (type != TYPE_ERROR && property->getStaticType() != TYPE_ANY &&
[ - + ][ + + ]
831 : 924341 : type != property->getStaticType())
832 : : {
833 : : throw css::uno::RuntimeException(
834 : : (rtl::OUString(
835 : : RTL_CONSTASCII_USTRINGPARAM("invalid type for prop ")) +
836 : : name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
837 : : reader.getUrl()),
838 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
839 : : }
840 [ + + ]: 1839472 : valueParser_.type_ = type == TYPE_ERROR ? property->getStaticType() : type;
841 [ + - - - ]: 1839472 : switch (operation) {
842 : : case OPERATION_MODIFY:
843 : : case OPERATION_FUSE:
844 : : state_.push(
845 : : State(
846 : : property,
847 : 1839472 : (state_.top().locked ||
848 [ - + ][ + - ]: 1839472 : finalizedLayer < valueParser_.getLayer())));
[ + - ][ + - ]
[ + - ]
849 : 1839472 : break;
850 : : case OPERATION_REPLACE:
851 : : {
852 : : rtl::Reference< Node > replacement(
853 : : new LocalizedPropertyNode(
854 : 0 : valueParser_.getLayer(), property->getStaticType(),
855 [ # # ][ # # ]: 0 : property->isNillable()));
[ # # ][ # # ]
[ # # ][ # # ]
856 [ # # ][ # # ]: 0 : replacement->setFinalized(property->getFinalized());
857 : : state_.push(
858 : : State(
859 : : replacement, name,
860 [ # # ]: 0 : (state_.top().locked ||
861 [ # # ][ # # ]: 0 : finalizedLayer < valueParser_.getLayer())));
[ # # ][ # # ]
[ # # ][ # # ]
862 [ # # ][ # # ]: 0 : recordModification(false);
863 : : }
864 : 0 : break;
865 : : case OPERATION_REMOVE:
866 : : throw css::uno::RuntimeException(
867 : : (rtl::OUString(
868 : : RTL_CONSTASCII_USTRINGPARAM(
869 : : "invalid remove of non-extension prop ")) +
870 : : name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
871 : : reader.getUrl()),
872 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
873 : : }
874 : : }
875 : :
876 : 179623 : void XcuParser::handleGroupNode(
877 : : xmlreader::XmlReader & reader, rtl::Reference< Node > const & group)
878 : : {
879 : 179623 : bool hasName = false;
880 : 179623 : rtl::OUString name;
881 : 179623 : Operation op = OPERATION_MODIFY;
882 : 179623 : bool finalized = false;
883 : 181341 : for (;;) {
884 : : int attrNsId;
885 : 360964 : xmlreader::Span attrLn;
886 [ + + ][ + - ]: 360964 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
887 : : break;
888 : : }
889 [ + - + + ]: 362682 : if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
890 : 181341 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
891 : : {
892 : 179623 : hasName = true;
893 [ + - ][ + - ]: 179623 : name = reader.getAttributeValue(false).convertFromUtf8();
894 [ + - - + ]: 3436 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ - + ]
895 : 1718 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
896 : : {
897 [ # # ][ # # ]: 0 : op = parseOperation(reader.getAttributeValue(true));
898 [ + - + + ]: 3436 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
899 : 1718 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
900 : : {
901 [ + - ][ + - ]: 1620 : finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
902 : : }
903 : : }
904 [ - + ]: 179623 : if (!hasName) {
905 : : throw css::uno::RuntimeException(
906 : : (rtl::OUString(
907 : : RTL_CONSTASCII_USTRINGPARAM("no node name attribute in ")) +
908 : : reader.getUrl()),
909 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
910 : : }
911 [ + + ]: 179623 : if (trackPath_) {
912 [ + - ]: 510 : path_.push_back(name);
913 [ - + ][ # # ]: 510 : if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
[ # # ][ - + ]
914 : : {
915 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
916 : : return;
917 : : }
918 : : }
919 : : rtl::Reference< Node > child(
920 [ + - ][ + - ]: 179623 : Data::findNode(valueParser_.getLayer(), group->getMembers(), name));
[ + - ]
921 [ - + ]: 179623 : if (!child.is()) {
922 : : SAL_WARN(
923 : : "configmgr",
924 : : "unknown node \"" << name << "\" in \"" << reader.getUrl() << '"');
925 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
926 : : return;
927 : : }
928 [ + - ]: 179623 : Node::Kind kind = child->kind();
929 [ + + ][ - + ]: 179623 : if (kind != Node::KIND_GROUP && kind != Node::KIND_SET) {
930 : : throw css::uno::RuntimeException(
931 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad <node> \"")) +
932 : : name +
933 : : rtl::OUString(
934 : : RTL_CONSTASCII_USTRINGPARAM("\" of non group/set kind in ")) +
935 : : reader.getUrl()),
936 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
937 : : }
938 [ - + ][ # # ]: 179623 : if (op != OPERATION_MODIFY && op != OPERATION_FUSE) {
939 : : throw css::uno::RuntimeException(
940 : : (rtl::OUString(
941 : : RTL_CONSTASCII_USTRINGPARAM(
942 : : "invalid operation on group node in ")) +
943 : : reader.getUrl()),
944 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
945 : : }
946 : : int finalizedLayer = std::min(
947 : 1620 : finalized ? valueParser_.getLayer() : Data::NO_LAYER,
948 [ + - ][ + + ]: 179623 : child->getFinalized());
[ + - ][ + - ]
949 [ + - ]: 179623 : child->setFinalized(finalizedLayer);
950 : : state_.push(
951 : : State(
952 : : child,
953 [ + - ][ + - ]: 179623 : state_.top().locked || finalizedLayer < valueParser_.getLayer()));
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
954 : : }
955 : :
956 : 2517837 : void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) {
957 : 2517837 : bool hasName = false;
958 : 2517837 : rtl::OUString name;
959 : 2517837 : rtl::OUString component(componentName_);
960 : 2517837 : bool hasNodeType = false;
961 : 2517837 : rtl::OUString nodeType;
962 : 2517837 : Operation op = OPERATION_MODIFY;
963 : 2517837 : bool finalized = false;
964 : 2517837 : bool mandatory = false;
965 : 5583916 : for (;;) {
966 : : int attrNsId;
967 : 8101753 : xmlreader::Span attrLn;
968 [ + + ][ + - ]: 8101753 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
969 : : break;
970 : : }
971 [ + - + + ]: 11167832 : if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
972 : 5583916 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
973 : : {
974 : 2517837 : hasName = true;
975 [ + - ][ + - ]: 2517837 : name = reader.getAttributeValue(false).convertFromUtf8();
976 [ + - - + ]: 6132158 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ - + ]
977 : 3066079 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
978 : : {
979 [ # # ][ # # ]: 0 : component = reader.getAttributeValue(false).convertFromUtf8();
980 [ + - - + ]: 6132158 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ - + ]
981 : 3066079 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
982 : : {
983 : 0 : hasNodeType = true;
984 [ # # ][ # # ]: 0 : nodeType = reader.getAttributeValue(false).convertFromUtf8();
985 [ + - + + ]: 6132158 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
986 : 3066079 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
987 : : {
988 [ + - ][ + - ]: 2494753 : op = parseOperation(reader.getAttributeValue(true));
989 [ + - + + ]: 1142652 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
990 : 571326 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
991 : : {
992 [ + - ][ + - ]: 560416 : finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
993 [ + - + + ]: 21820 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
[ + + ]
994 : 10910 : attrLn.equals(RTL_CONSTASCII_STRINGPARAM("mandatory")))
995 : : {
996 [ + - ][ + - ]: 10616 : mandatory = xmldata::parseBoolean(reader.getAttributeValue(true));
997 : : }
998 : : }
999 [ - + ]: 2517837 : if (!hasName) {
1000 : : throw css::uno::RuntimeException(
1001 : : (rtl::OUString(
1002 : : RTL_CONSTASCII_USTRINGPARAM("no node name attribute in ")) +
1003 : : reader.getUrl()),
1004 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
1005 : : }
1006 [ + + ]: 2517837 : if (trackPath_) {
1007 [ + - ]: 902 : path_.push_back(name);
1008 [ - + ][ # # ]: 902 : if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
[ # # ][ - + ]
1009 : : {
1010 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
1011 : : return;
1012 : : }
1013 : : }
1014 : : rtl::OUString templateName(
1015 : : xmldata::parseTemplateReference(
1016 [ + - ][ + - ]: 2517837 : component, hasNodeType, nodeType, &set->getDefaultTemplateName()));
1017 [ + - ][ - + ]: 2517837 : if (!set->isValidTemplate(templateName)) {
1018 : : throw css::uno::RuntimeException(
1019 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("set member node ")) +
1020 : : name +
1021 : : rtl::OUString(
1022 : : RTL_CONSTASCII_USTRINGPARAM(" references invalid template ")) +
1023 : : templateName + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
1024 : : reader.getUrl()),
1025 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
1026 : : }
1027 : : rtl::Reference< Node > tmpl(
1028 [ + - ][ + - ]: 2517837 : data_.getTemplate(valueParser_.getLayer(), templateName));
1029 [ - + ]: 2517837 : if (!tmpl.is()) {
1030 : : throw css::uno::RuntimeException(
1031 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("set member node ")) +
1032 : : name +
1033 : : rtl::OUString(
1034 : : RTL_CONSTASCII_USTRINGPARAM(
1035 : : " references undefined template ")) +
1036 : : templateName + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
1037 : : reader.getUrl()),
1038 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ][ # # ]
[ # # ]
1039 : : }
1040 [ + + ][ + - ]: 2517837 : int finalizedLayer = finalized ? valueParser_.getLayer() : Data::NO_LAYER;
1041 [ + + ][ + - ]: 2517837 : int mandatoryLayer = mandatory ? valueParser_.getLayer() : Data::NO_LAYER;
1042 [ + - ]: 2517837 : NodeMap & members = set->getMembers();
1043 [ + - ]: 2517837 : NodeMap::iterator i(members.find(name));
1044 [ + + ]: 2517837 : if (i != members.end()) {
1045 [ + - ][ + - ]: 40135 : finalizedLayer = std::min(finalizedLayer, i->second->getFinalized());
1046 [ + - ]: 40135 : i->second->setFinalized(finalizedLayer);
1047 [ + - ][ + - ]: 40135 : mandatoryLayer = std::min(mandatoryLayer, i->second->getMandatory());
1048 [ + - ]: 40135 : i->second->setMandatory(mandatoryLayer);
1049 [ + - ][ + - ]: 40135 : if (i->second->getLayer() > valueParser_.getLayer()) {
[ - + ]
1050 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
1051 : : return;
1052 : : }
1053 : : }
1054 [ + + + - : 2517837 : switch (op) {
- ]
1055 : : case OPERATION_MODIFY:
1056 [ - + ]: 23084 : if (i == members.end()) {
1057 : : SAL_WARN(
1058 : : "configmgr",
1059 : : "ignoring modify of unknown set member node \"" << name
1060 : : << "\" in \"" << reader.getUrl() << '"');
1061 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
1062 : : } else {
1063 : : state_.push(
1064 : : State(
1065 : 23084 : i->second,
1066 [ + - ]: 23084 : (state_.top().locked ||
1067 [ + - ][ + - ]: 46168 : finalizedLayer < valueParser_.getLayer())));
[ - + ][ + - ]
[ + - ][ + - ]
1068 : : }
1069 : 23084 : break;
1070 : : case OPERATION_REPLACE:
1071 [ + - ][ + - ]: 2477477 : if (state_.top().locked || finalizedLayer < valueParser_.getLayer()) {
[ + - ][ - + ]
[ - + ]
1072 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
1073 : : } else {
1074 [ + - ]: 2477477 : rtl::Reference< Node > member(tmpl->clone(true));
1075 [ + - ][ + - ]: 2477477 : member->setLayer(valueParser_.getLayer());
1076 [ + - ]: 2477477 : member->setFinalized(finalizedLayer);
1077 [ + - ]: 2477477 : member->setMandatory(mandatoryLayer);
1078 [ + - ][ + - ]: 2477477 : state_.push(State(member, name, false));
[ + - ]
1079 [ + - ][ + - ]: 2477477 : recordModification(i == members.end());
1080 : : }
1081 : 2477477 : break;
1082 : : case OPERATION_FUSE:
1083 [ + + ]: 17276 : if (i == members.end()) {
1084 [ + - ][ + - ]: 17178 : if (state_.top().locked || finalizedLayer < valueParser_.getLayer())
[ + - ][ - + ]
[ - + ]
1085 : : {
1086 [ # # ][ # # ]: 0 : state_.push(State(true)); // ignored
[ # # ]
1087 : : } else {
1088 [ + - ]: 17178 : rtl::Reference< Node > member(tmpl->clone(true));
1089 [ + - ][ + - ]: 17178 : member->setLayer(valueParser_.getLayer());
1090 [ + - ]: 17178 : member->setFinalized(finalizedLayer);
1091 [ + - ]: 17178 : member->setMandatory(mandatoryLayer);
1092 [ + - ][ + - ]: 17178 : state_.push(State(member, name, false));
[ + - ]
1093 [ + - ][ + - ]: 17178 : recordModification(true);
1094 : : }
1095 : : } else {
1096 : : state_.push(
1097 : : State(
1098 : 98 : i->second,
1099 [ + - ]: 98 : (state_.top().locked ||
1100 [ + - ][ + - ]: 196 : finalizedLayer < valueParser_.getLayer())));
[ - + ][ + - ]
[ + - ][ + - ]
1101 : : }
1102 : 17276 : break;
1103 : : case OPERATION_REMOVE:
1104 : : {
1105 : : // Ignore removal of unknown members, members finalized in a lower
1106 : : // layer, and members made mandatory in this or a lower layer;
1107 : : // forget about user-layer removals that no longer remove anything
1108 : : // (so that paired additions/removals in the user layer do not grow
1109 : : // registrymodifications.xcu unbounded):
1110 : 0 : bool known = i != members.end();
1111 [ # # ][ # # ]: 0 : if (known && !state_.top().locked &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1112 [ # # ]: 0 : finalizedLayer >= valueParser_.getLayer() &&
1113 : : (mandatoryLayer == Data::NO_LAYER ||
1114 [ # # ]: 0 : mandatoryLayer > valueParser_.getLayer()))
1115 : : {
1116 [ # # ]: 0 : members.erase(i);
1117 : : }
1118 [ # # ][ # # ]: 0 : state_.push(State(true));
[ # # ]
1119 [ # # ]: 0 : if (known) {
1120 [ # # ]: 0 : recordModification(false);
1121 : : }
1122 : 2517837 : break;
1123 : : }
1124 [ + - ][ - + ]: 2517837 : }
[ - + ][ - + ]
[ - + ][ + - ]
1125 : : }
1126 : :
1127 : 7081761 : void XcuParser::recordModification(bool addition) {
1128 [ - + ]: 7081761 : if (broadcastModifications_ != 0) {
1129 : 0 : broadcastModifications_->add(path_);
1130 : : }
1131 [ + + ][ - + ]: 7081761 : if (addition && additions_ != 0) {
1132 : 0 : additions_->push_back(path_);
1133 : : }
1134 [ + + ]: 7081761 : if (recordModifications_) {
1135 : 14966 : data_.modifications.add(path_);
1136 : : }
1137 : 7081761 : }
1138 : :
1139 : : }
1140 : :
1141 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|