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 <cassert>
23 : :
24 : : #include "boost/noncopyable.hpp"
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/Sequence.hxx"
29 : : #include "com/sun/star/uno/XInterface.hpp"
30 : : #include "osl/file.h"
31 : : #include "osl/file.hxx"
32 : : #include "rtl/oustringostreaminserter.hxx"
33 : : #include "rtl/string.h"
34 : : #include "rtl/string.hxx"
35 : : #include "rtl/textcvt.h"
36 : : #include "rtl/textenc.h"
37 : : #include "rtl/ustrbuf.hxx"
38 : : #include "rtl/ustring.h"
39 : : #include "rtl/ustring.hxx"
40 : : #include "sal/log.hxx"
41 : : #include "sal/types.h"
42 : : #include "xmlreader/span.hxx"
43 : :
44 : : #include "data.hxx"
45 : : #include "groupnode.hxx"
46 : : #include "localizedpropertynode.hxx"
47 : : #include "localizedvaluenode.hxx"
48 : : #include "modifications.hxx"
49 : : #include "node.hxx"
50 : : #include "nodemap.hxx"
51 : : #include "propertynode.hxx"
52 : : #include "type.hxx"
53 : : #include "writemodfile.hxx"
54 : :
55 : : namespace configmgr {
56 : :
57 : : class Components;
58 : :
59 : : namespace {
60 : :
61 : : namespace css = com::sun::star;
62 : :
63 : 2387486 : rtl::OString convertToUtf8(
64 : : rtl::OUString const & text, sal_Int32 offset, sal_Int32 length)
65 : : {
66 : : assert(offset <= text.getLength() && text.getLength() - offset >= length);
67 : 2387486 : rtl::OString s;
68 [ - + ]: 2387486 : if (!rtl_convertUStringToString(
69 : 2387486 : &s.pData, text.pData->buffer + offset, length,
70 : : RTL_TEXTENCODING_UTF8,
71 : : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
72 : 2387486 : RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
73 : : {
74 : : throw css::uno::RuntimeException(
75 : : rtl::OUString(
76 : : RTL_CONSTASCII_USTRINGPARAM("cannot convert to UTF-8")),
77 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
78 : : }
79 : 2387486 : return s;
80 : : }
81 : :
82 : : struct TempFile: public boost::noncopyable {
83 : : rtl::OUString url;
84 : : oslFileHandle handle;
85 : : bool closed;
86 : :
87 : 2576 : TempFile(): handle(0), closed(false) {}
88 : :
89 : : ~TempFile();
90 : : };
91 : :
92 : 2576 : TempFile::~TempFile() {
93 [ - + ]: 2576 : if (handle != 0) {
94 [ # # ]: 0 : if (!closed) {
95 [ # # ]: 0 : oslFileError e = osl_closeFile(handle);
96 : : if (e != osl_File_E_None) {
97 : : SAL_WARN("configmgr", "osl_closeFile failed with " << +e);
98 : : }
99 : : }
100 [ # # ]: 0 : osl::FileBase::RC e = osl::File::remove(url);
101 : : if (e != osl::FileBase::E_None) {
102 : : SAL_WARN(
103 : : "configmgr",
104 : : "osl::File::remove(" << url << ") failed with " << +e);
105 : : }
106 : : }
107 : 2576 : }
108 : :
109 : 13293771 : void writeData(oslFileHandle handle, char const * begin, sal_Int32 length) {
110 : : assert(length >= 0);
111 : : sal_uInt64 n;
112 [ + - ][ + - ]: 13293771 : if ((osl_writeFile(handle, begin, static_cast< sal_uInt32 >(length), &n) !=
[ - + ][ - + ]
113 : : osl_File_E_None) ||
114 : : n != static_cast< sal_uInt32 >(length))
115 : : {
116 : : throw css::uno::RuntimeException(
117 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("write failure")),
118 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
119 : : }
120 : 13293771 : }
121 : :
122 : 4096185 : void writeData(oslFileHandle handle, rtl::OString const & text) {
123 : 4096185 : writeData(handle, text.getStr(), text.getLength());
124 : 4096185 : }
125 : :
126 : 1683616 : void writeAttributeValue(oslFileHandle handle, rtl::OUString const & value) {
127 : 1683616 : sal_Int32 i = 0;
128 : 1683616 : sal_Int32 j = i;
129 [ + + ]: 66122072 : for (; j < value.getLength(); ++j) {
130 : : assert(
131 : : value[j] == 0x0009 || value[j] == 0x000A || value[j] == 0x000D ||
132 : : (value[j] >= 0x0020 && value[j] != 0xFFFE && value[j] != 0xFFFF));
133 [ - - - - : 64438456 : switch(value[j]) {
- - + ]
134 : : case '\x09':
135 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
136 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("	"));
137 : 0 : i = j + 1;
138 : 0 : break;
139 : : case '\x0A':
140 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
141 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("
"));
142 : 0 : i = j + 1;
143 : 0 : break;
144 : : case '\x0D':
145 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
146 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("
"));
147 : 0 : i = j + 1;
148 : 0 : break;
149 : : case '"':
150 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
151 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("""));
152 : 0 : i = j + 1;
153 : 0 : break;
154 : : case '&':
155 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
156 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("&"));
157 : 0 : i = j + 1;
158 : 0 : break;
159 : : case '<':
160 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
161 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<"));
162 : 0 : i = j + 1;
163 : 0 : break;
164 : : default:
165 : 64438456 : break;
166 : : }
167 : : }
168 [ + - ]: 1683616 : writeData(handle, convertToUtf8(value, i, j - i));
169 : 1683616 : }
170 : :
171 : 85357 : void writeValueContent(oslFileHandle handle, sal_Bool value) {
172 [ + + ]: 85357 : if (value) {
173 : 41446 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("true"));
174 : : } else {
175 : 43911 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("false"));
176 : : }
177 : 85357 : }
178 : :
179 : 5030 : void writeValueContent(oslFileHandle handle, sal_Int16 value) {
180 [ + - ]: 5030 : writeData(handle, rtl::OString::valueOf(static_cast< sal_Int32 >(value)));
181 : 5030 : }
182 : :
183 : 27685 : void writeValueContent(oslFileHandle handle, sal_Int32 value) {
184 [ + - ]: 27685 : writeData(handle, rtl::OString::valueOf(value));
185 : 27685 : }
186 : :
187 : 0 : void writeValueContent(oslFileHandle handle, sal_Int64 value) {
188 [ # # ]: 0 : writeData(handle, rtl::OString::valueOf(value));
189 : 0 : }
190 : :
191 : 0 : void writeValueContent(oslFileHandle handle, double value) {
192 [ # # ]: 0 : writeData(handle, rtl::OString::valueOf(value));
193 : 0 : }
194 : :
195 : 703870 : void writeValueContent(oslFileHandle handle, rtl::OUString const & value) {
196 : 703870 : sal_Int32 i = 0;
197 : 703870 : sal_Int32 j = i;
198 [ + + ]: 25447535 : for (; j < value.getLength(); ++j) {
199 : 24743665 : sal_Unicode c = value[j];
200 [ # # ][ # # ]: 24743665 : if ((c < 0x0020 && c != 0x0009 && c != 0x000A && c != 0x000D) ||
[ # # ][ + - ]
[ - + ][ - + ]
201 : : c == 0xFFFE || c == 0xFFFF)
202 : : {
203 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
204 : : writeData(
205 : 0 : handle, RTL_CONSTASCII_STRINGPARAM("<unicode oor:scalar=\""));
206 : : writeData(
207 [ # # ]: 0 : handle, rtl::OString::valueOf(static_cast< sal_Int32 >(c)));
208 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\"/>"));
209 : 0 : i = j + 1;
210 [ - + ]: 24743665 : } else if (c == '\x0D') {
211 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
212 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("
"));
213 : 0 : i = j + 1;
214 [ - + ]: 24743665 : } else if (c == '&') {
215 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
216 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("&"));
217 : 0 : i = j + 1;
218 [ - + ]: 24743665 : } else if (c == '<') {
219 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
220 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<"));
221 : 0 : i = j + 1;
222 [ - + ]: 24743665 : } else if (c == '>') {
223 : : // "MUST, for compatibility, be escaped [...] when it appears in the
224 : : // string ']]>'":
225 [ # # ]: 0 : writeData(handle, convertToUtf8(value, i, j - i));
226 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
227 : 0 : i = j + 1;
228 : : }
229 : : }
230 [ + - ]: 703870 : writeData(handle, convertToUtf8(value, i, j - i));
231 : 703870 : }
232 : :
233 : 0 : void writeValueContent(
234 : : oslFileHandle handle, css::uno::Sequence< sal_Int8 > const & value)
235 : : {
236 [ # # ]: 0 : for (sal_Int32 i = 0; i < value.getLength(); ++i) {
237 : : static char const hexDigit[16] = {
238 : : '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
239 : : 'D', 'E', 'F' };
240 : 0 : writeData(handle, hexDigit + ((value[i] >> 4) & 0xF), 1);
241 : 0 : writeData(handle, hexDigit + (value[i] & 0xF), 1);
242 : : }
243 : 0 : }
244 : :
245 : 189178 : template< typename T > void writeSingleValue(
246 : : oslFileHandle handle, css::uno::Any const & value)
247 : : {
248 [ # # ][ + - ]: 189178 : writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
[ # # ][ # # ]
[ + - ][ + - ]
[ + - ]
249 [ # # ]: 71116 : T val = T();
250 [ # # ]: 189178 : value >>= val;
251 [ # # + - : 189178 : writeValueContent(handle, val);
# # # # +
- + - +
- ]
252 [ # # ][ # # ]: 189178 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
[ + - ][ # # ]
[ # # ][ + - ]
[ + - ][ + - ]
253 : 189178 : }
254 : :
255 : 2 : template< typename T > void writeListValue(
256 : : oslFileHandle handle, css::uno::Any const & value)
257 : : {
258 [ # # ][ # # ]: 2 : writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
[ + - ][ # # ]
[ # # ]
259 [ # # ][ # # ]: 2 : css::uno::Sequence< T > val;
[ + - ][ # # ]
[ # # ]
260 [ # # ][ # # ]: 2 : value >>= val;
[ + - ][ # # ]
[ # # ]
261 [ # # ][ # # ]: 12 : for (sal_Int32 i = 0; i < val.getLength(); ++i) {
[ + + ][ # # ]
[ # # ]
262 [ # # ][ # # ]: 10 : if (i != 0) {
[ + + ][ # # ]
[ # # ]
263 [ # # ][ # # ]: 8 : writeData(handle, RTL_CONSTASCII_STRINGPARAM(" "));
[ + - ][ # # ]
[ # # ]
264 : : }
265 [ # # ][ # # ]: 10 : writeValueContent(handle, val[i]);
[ # # ][ # # ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
266 : : }
267 [ # # ][ # # ]: 2 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
[ # # ][ # # ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
268 : 2 : }
269 : :
270 : 632057 : template< typename T > void writeItemListValue(
271 : : oslFileHandle handle, css::uno::Any const & value)
272 : : {
273 [ # # ][ + - ]: 632057 : writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
274 [ # # ][ + - ]: 632057 : css::uno::Sequence< T > val;
275 [ # # ][ + - ]: 632057 : value >>= val;
276 [ # # ][ + + ]: 1264811 : for (sal_Int32 i = 0; i < val.getLength(); ++i) {
277 [ # # ][ + - ]: 632754 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<it>"));
278 [ # # ][ # # ]: 632754 : writeValueContent(handle, val[i]);
[ + - ][ + - ]
279 [ # # ][ + - ]: 632754 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("</it>"));
280 : : }
281 [ # # ][ # # ]: 632057 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
[ + - ][ + - ]
282 : 632057 : }
283 : :
284 : 821237 : void writeValue(oslFileHandle handle, Type type, css::uno::Any const & value) {
285 [ + + + - : 821237 : switch (type) {
- + - - -
+ - - + -
- ]
286 : : case TYPE_BOOLEAN:
287 : 85357 : writeSingleValue< sal_Bool >(handle, value);
288 : 85357 : break;
289 : : case TYPE_SHORT:
290 : 5030 : writeSingleValue< sal_Int16 >(handle, value);
291 : 5030 : break;
292 : : case TYPE_INT:
293 : 27675 : writeSingleValue< sal_Int32 >(handle, value);
294 : 27675 : break;
295 : : case TYPE_LONG:
296 : 0 : writeSingleValue< sal_Int64 >(handle, value);
297 : 0 : break;
298 : : case TYPE_DOUBLE:
299 : 0 : writeSingleValue< double >(handle, value);
300 : 0 : break;
301 : : case TYPE_STRING:
302 : 71116 : writeSingleValue< rtl::OUString >(handle, value);
303 : 71116 : break;
304 : : case TYPE_HEXBINARY:
305 : 0 : writeSingleValue< css::uno::Sequence< sal_Int8 > >(handle, value);
306 : 0 : break;
307 : : case TYPE_BOOLEAN_LIST:
308 : 0 : writeListValue< sal_Bool >(handle, value);
309 : 0 : break;
310 : : case TYPE_SHORT_LIST:
311 : 0 : writeListValue< sal_Int16 >(handle, value);
312 : 0 : break;
313 : : case TYPE_INT_LIST:
314 : 2 : writeListValue< sal_Int32 >(handle, value);
315 : 2 : break;
316 : : case TYPE_LONG_LIST:
317 : 0 : writeListValue< sal_Int64 >(handle, value);
318 : 0 : break;
319 : : case TYPE_DOUBLE_LIST:
320 : 0 : writeListValue< double >(handle, value);
321 : 0 : break;
322 : : case TYPE_STRING_LIST:
323 : 632057 : writeItemListValue< rtl::OUString >(handle, value);
324 : 632057 : break;
325 : : case TYPE_HEXBINARY_LIST:
326 : 0 : writeItemListValue< css::uno::Sequence< sal_Int8 > >(handle, value);
327 : 0 : break;
328 : : default: // TYPE_ERROR, TYPE_NIL, TYPE_ANY
329 : : assert(false); // this cannot happen
330 : : }
331 : 821237 : }
332 : :
333 : 888286 : void writeNode(
334 : : Components & components, oslFileHandle handle,
335 : : rtl::Reference< Node > const & parent, rtl::OUString const & name,
336 : : rtl::Reference< Node > const & node)
337 : : {
338 : : static xmlreader::Span const typeNames[] = {
339 : : xmlreader::Span(), xmlreader::Span(), xmlreader::Span(),
340 : : // TYPE_ERROR, TYPE_NIL, TYPE_ANY
341 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:boolean")),
342 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:short")),
343 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:int")),
344 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:long")),
345 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:double")),
346 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:string")),
347 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("xs:hexBinary")),
348 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:boolean-list")),
349 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:short-list")),
350 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:int-list")),
351 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:long-list")),
352 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:double-list")),
353 : : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:string-list")),
354 [ + + ][ + - ]: 888286 : xmlreader::Span(RTL_CONSTASCII_STRINGPARAM("oor:hexBinary-list")) };
355 [ + - + + : 888286 : switch (node->kind()) {
- - ]
356 : : case Node::KIND_PROPERTY:
357 : : {
358 [ - + ]: 837992 : PropertyNode * prop = dynamic_cast< PropertyNode * >(node.get());
359 : 837992 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
360 : 837992 : writeAttributeValue(handle, name);
361 : 837992 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\""));
362 : 837992 : Type type = prop->getStaticType();
363 [ + - ]: 837992 : Type dynType = getDynamicType(prop->getValue(components));
364 : : assert(dynType != TYPE_ERROR);
365 [ + + ]: 837992 : if (type == TYPE_ANY) {
366 : 645919 : type = dynType;
367 [ + - ]: 645919 : if (type != TYPE_NIL) {
368 : : writeData(
369 : 645919 : handle, RTL_CONSTASCII_STRINGPARAM(" oor:type=\""));
370 : : writeData(
371 : 645919 : handle, typeNames[type].begin, typeNames[type].length);
372 : 645919 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
373 : : }
374 : : }
375 [ + - ]: 837992 : writeData(handle, "><value");
376 [ + + ]: 837992 : if (dynType == TYPE_NIL) {
377 : : writeData(
378 : 22360 : handle, RTL_CONSTASCII_STRINGPARAM(" xsi:nil=\"true\"/>"));
379 : : } else {
380 [ + - ]: 815632 : writeValue(handle, type, prop->getValue(components));
381 : : }
382 [ + - ]: 837992 : writeData(handle, "</prop>");
383 : : }
384 : 837992 : break;
385 : : case Node::KIND_LOCALIZED_PROPERTY:
386 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
387 : 0 : writeAttributeValue(handle, name);
388 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\">"));
389 [ # # ][ # # ]: 0 : for (NodeMap::const_iterator i(node->getMembers().begin());
390 [ # # ]: 0 : i != node->getMembers().end(); ++i)
391 : : {
392 [ # # ]: 0 : writeNode(components, handle, node, i->first, i->second);
393 : : }
394 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("</prop>"));
395 : 0 : break;
396 : : case Node::KIND_LOCALIZED_VALUE:
397 : : {
398 [ + - ]: 5605 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
399 [ + - ]: 5605 : if (!name.isEmpty()) {
400 [ + - ]: 5605 : writeData(handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
401 [ + - ]: 5605 : writeAttributeValue(handle, name);
402 [ + - ]: 5605 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
403 : : }
404 : 5605 : Type type = dynamic_cast< LocalizedPropertyNode * >(parent.get())->
405 [ + - ][ - + ]: 5605 : getStaticType();
406 : : css::uno::Any value(
407 [ - + ][ + - ]: 5605 : dynamic_cast< LocalizedValueNode * >(node.get())->getValue());
408 [ + - ]: 5605 : Type dynType = getDynamicType(value);
409 : : assert(dynType != TYPE_ERROR);
410 [ - + ]: 5605 : if (type == TYPE_ANY) {
411 : 0 : type = dynType;
412 [ # # ]: 0 : if (type != TYPE_NIL) {
413 : : writeData(
414 [ # # ]: 0 : handle, RTL_CONSTASCII_STRINGPARAM(" oor:type=\""));
415 : : writeData(
416 [ # # ]: 0 : handle, typeNames[type].begin, typeNames[type].length);
417 [ # # ]: 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
418 : : }
419 : : }
420 [ - + ]: 5605 : if (dynType == TYPE_NIL) {
421 : : writeData(
422 [ # # ]: 0 : handle, RTL_CONSTASCII_STRINGPARAM(" xsi:nil=\"true\"/>"));
423 : : } else {
424 [ + - ]: 5605 : writeValue(handle, type, value);
425 : 5605 : }
426 : : }
427 : 5605 : break;
428 : : case Node::KIND_GROUP:
429 : : case Node::KIND_SET:
430 : 44689 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
431 : 44689 : writeAttributeValue(handle, name);
432 [ + + ]: 44689 : if (!node->getTemplateName().isEmpty()) { // set member
433 : : writeData(
434 : 26538 : handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"replace"));
435 : : }
436 : 44689 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
437 [ + + ][ + - ]: 276986 : for (NodeMap::const_iterator i(node->getMembers().begin());
438 [ + - ]: 138493 : i != node->getMembers().end(); ++i)
439 : : {
440 [ + - ]: 93804 : writeNode(components, handle, node, i->first, i->second);
441 : : }
442 : 44689 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("</node>"));
443 : 44689 : break;
444 : : case Node::KIND_ROOT:
445 : : assert(false); // this cannot happen
446 : 0 : break;
447 : : }
448 : 888286 : }
449 : :
450 : 879224 : void writeModifications(
451 : : Components & components, oslFileHandle handle,
452 : : rtl::OUString const & parentPathRepresentation,
453 : : rtl::Reference< Node > const & parent, rtl::OUString const & nodeName,
454 : : rtl::Reference< Node > const & node,
455 : : Modifications::Node const & modifications)
456 : : {
457 : : // It is never necessary to write oor:finalized or oor:mandatory attributes,
458 : : // as they cannot be set via the UNO API.
459 [ + + ]: 879224 : if (modifications.children.empty()) {
460 : : assert(parent.is());
461 : : // components themselves have no parent but must have children
462 : 794906 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\""));
463 : 794906 : writeAttributeValue(handle, parentPathRepresentation);
464 : 794906 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
465 [ + + ]: 794906 : if (node.is()) {
466 : 794482 : writeNode(components, handle, parent, nodeName, node);
467 : : } else {
468 [ - - + - ]: 424 : switch (parent->kind()) {
469 : : case Node::KIND_LOCALIZED_PROPERTY:
470 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
471 [ # # ]: 0 : if (!nodeName.isEmpty()) {
472 : : writeData(
473 : 0 : handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
474 : 0 : writeAttributeValue(handle, nodeName);
475 : 0 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
476 : : }
477 : : writeData(
478 : 0 : handle, RTL_CONSTASCII_STRINGPARAM(" oor:op=\"remove\"/>"));
479 : 0 : break;
480 : : case Node::KIND_GROUP:
481 : : assert(
482 : : dynamic_cast< GroupNode * >(parent.get())->isExtensible());
483 : : writeData(
484 : 0 : handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
485 : 0 : writeAttributeValue(handle, nodeName);
486 : : writeData(
487 : : handle,
488 : 0 : RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
489 : 0 : break;
490 : : case Node::KIND_SET:
491 : : writeData(
492 : 424 : handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
493 : 424 : writeAttributeValue(handle, nodeName);
494 : : writeData(
495 : : handle,
496 : 424 : RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
497 : 424 : break;
498 : : default:
499 : : assert(false); // this cannot happen
500 : 0 : break;
501 : : }
502 : : }
503 : 794906 : writeData(handle, RTL_CONSTASCII_STRINGPARAM("</item>\n"));
504 : : } else {
505 : : assert(node.is());
506 : : rtl::OUString pathRep(
507 : : parentPathRepresentation +
508 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
509 [ + - ][ + - ]: 84318 : Data::createSegment(node->getTemplateName(), nodeName));
[ + - ]
510 [ + + ]: 1894864 : for (Modifications::Node::Children::const_iterator i(
511 : 84318 : modifications.children.begin());
512 : 947432 : i != modifications.children.end(); ++i)
513 : : {
514 : : writeModifications(
515 : 863114 : components, handle, pathRep, node, i->first,
516 [ + - + - ]: 1726228 : node->getMember(i->first), i->second);
[ + - ]
517 : 84318 : }
518 : : }
519 : 879224 : }
520 : :
521 : : }
522 : :
523 : 2576 : void writeModFile(
524 : : Components & components, rtl::OUString const & url, Data const & data)
525 : : {
526 : 2576 : sal_Int32 i = url.lastIndexOf('/');
527 : : assert(i != -1);
528 : 2576 : rtl::OUString dir(url.copy(0, i));
529 [ + - - ]: 2576 : switch (osl::Directory::createPath(dir)) {
[ + - ]
530 : : case osl::FileBase::E_None:
531 : : case osl::FileBase::E_EXIST:
532 : 2576 : break;
533 : : case osl::FileBase::E_ACCES:
534 : : SAL_INFO(
535 : : "configmgr",
536 : : ("cannot create registrymodifications.xcu path (E_ACCES); changes"
537 : : " will be lost"));
538 : : return;
539 : : default:
540 : : throw css::uno::RuntimeException(
541 : : (rtl::OUString(
542 : : RTL_CONSTASCII_USTRINGPARAM("cannot create directory ")) +
543 : : dir),
544 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
545 : : }
546 : 2576 : TempFile tmp;
547 [ + - - ]: 2576 : switch (osl::FileBase::createTempFile(&dir, &tmp.handle, &tmp.url)) {
[ + - ]
548 : : case osl::FileBase::E_None:
549 : 2576 : break;
550 : : case osl::FileBase::E_ACCES:
551 : : SAL_INFO(
552 : : "configmgr",
553 : : ("cannot create temp registrymodifications.xcu (E_ACCES); changes"
554 : : " will be lost"));
555 : : return;
556 : : default:
557 : : throw css::uno::RuntimeException(
558 : : (rtl::OUString(
559 : : RTL_CONSTASCII_USTRINGPARAM(
560 : : "cannot create temporary file in ")) +
561 : : dir),
562 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
563 : : }
564 : : writeData(
565 : : tmp.handle,
566 : : RTL_CONSTASCII_STRINGPARAM(
567 : : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items"
568 : : " xmlns:oor=\"http://openoffice.org/2001/registry\""
569 : : " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
570 [ + - ]: 2576 : " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"));
571 : : //TODO: Do not write back information about those removed items that did not
572 : : // come from the .xcs/.xcu files, anyway (but had been added dynamically
573 : : // instead):
574 [ + + ]: 37372 : for (Modifications::Node::Children::const_iterator j(
575 [ + - ]: 2576 : data.modifications.getRoot().children.begin());
576 [ + - ]: 18686 : j != data.modifications.getRoot().children.end(); ++j)
577 : : {
578 : : writeModifications(
579 : : components, tmp.handle, rtl::OUString(), rtl::Reference< Node >(),
580 : 16110 : j->first,
581 [ + - ]: 16110 : Data::findNode(Data::NO_LAYER, data.getComponents(), j->first),
582 [ + - + - ]: 48330 : j->second);
[ + - ][ + - ]
583 : : }
584 [ + - ]: 2576 : writeData(tmp.handle, RTL_CONSTASCII_STRINGPARAM("</oor:items>\n"));
585 [ + - ]: 2576 : oslFileError e = osl_closeFile(tmp.handle);
586 : 2576 : tmp.closed = true;
587 [ - + ]: 2576 : if (e != osl_File_E_None) {
588 : : throw css::uno::RuntimeException(
589 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot close ")) +
590 : : tmp.url),
591 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
592 : : }
593 [ + - ][ - + ]: 2576 : if (osl::File::move(tmp.url, url) != osl::FileBase::E_None) {
594 : : throw css::uno::RuntimeException(
595 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot move ")) +
596 : : tmp.url),
597 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
598 : : }
599 [ + - ][ - + ]: 2576 : tmp.handle = 0;
[ + - ]
600 : : }
601 : :
602 : : }
603 : :
604 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|