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