1*3a7cf181SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 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 10cdf0e10cSrcweir * 11*3a7cf181SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 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. 19cdf0e10cSrcweir * 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 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 90cdf0e10cSrcweir TempFile(): handle(0), closed(false) {} 91cdf0e10cSrcweir 92cdf0e10cSrcweir ~TempFile(); 93cdf0e10cSrcweir }; 94cdf0e10cSrcweir 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 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 124cdf0e10cSrcweir void writeData(oslFileHandle handle, rtl::OString const & text) { 125cdf0e10cSrcweir writeData(handle, text.getStr(), text.getLength()); 126cdf0e10cSrcweir } 127cdf0e10cSrcweir 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("	")); 139cdf0e10cSrcweir i = j + 1; 140cdf0e10cSrcweir break; 141cdf0e10cSrcweir case '\x0A': 142cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 143cdf0e10cSrcweir writeData(handle, RTL_CONSTASCII_STRINGPARAM("
")); 144cdf0e10cSrcweir i = j + 1; 145cdf0e10cSrcweir break; 146cdf0e10cSrcweir case '\x0D': 147cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 148cdf0e10cSrcweir writeData(handle, RTL_CONSTASCII_STRINGPARAM("
")); 149cdf0e10cSrcweir i = j + 1; 150cdf0e10cSrcweir break; 151cdf0e10cSrcweir case '"': 152cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 153cdf0e10cSrcweir writeData(handle, RTL_CONSTASCII_STRINGPARAM(""")); 154cdf0e10cSrcweir i = j + 1; 155cdf0e10cSrcweir break; 156cdf0e10cSrcweir case '&': 157cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 158cdf0e10cSrcweir writeData(handle, RTL_CONSTASCII_STRINGPARAM("&")); 159cdf0e10cSrcweir i = j + 1; 160cdf0e10cSrcweir break; 161cdf0e10cSrcweir case '<': 162cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 163cdf0e10cSrcweir writeData(handle, RTL_CONSTASCII_STRINGPARAM("<")); 164cdf0e10cSrcweir i = j + 1; 165cdf0e10cSrcweir break; 166cdf0e10cSrcweir default: 167cdf0e10cSrcweir break; 168cdf0e10cSrcweir } 169cdf0e10cSrcweir } 170cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 171cdf0e10cSrcweir } 172cdf0e10cSrcweir 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 181cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, sal_Int16 value) { 182cdf0e10cSrcweir writeData(handle, rtl::OString::valueOf(static_cast< sal_Int32 >(value))); 183cdf0e10cSrcweir } 184cdf0e10cSrcweir 185cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, sal_Int32 value) { 186cdf0e10cSrcweir writeData(handle, rtl::OString::valueOf(value)); 187cdf0e10cSrcweir } 188cdf0e10cSrcweir 189cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, sal_Int64 value) { 190cdf0e10cSrcweir writeData(handle, rtl::OString::valueOf(value)); 191cdf0e10cSrcweir } 192cdf0e10cSrcweir 193cdf0e10cSrcweir void writeValueContent(oslFileHandle handle, double value) { 194cdf0e10cSrcweir writeData(handle, rtl::OString::valueOf(value)); 195cdf0e10cSrcweir } 196cdf0e10cSrcweir 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("
")); 215cdf0e10cSrcweir i = j + 1; 216cdf0e10cSrcweir } else if (c == '&') { 217cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 218cdf0e10cSrcweir writeData(handle, RTL_CONSTASCII_STRINGPARAM("&")); 219cdf0e10cSrcweir i = j + 1; 220cdf0e10cSrcweir } else if (c == '<') { 221cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 222cdf0e10cSrcweir writeData(handle, RTL_CONSTASCII_STRINGPARAM("<")); 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(">")); 229cdf0e10cSrcweir i = j + 1; 230cdf0e10cSrcweir } 231cdf0e10cSrcweir } 232cdf0e10cSrcweir writeData(handle, convertToUtf8(value, i, j - i)); 233cdf0e10cSrcweir } 234cdf0e10cSrcweir 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 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 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 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 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 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 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 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