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