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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_framework.hxx" 26 #include <accelerators/presethandler.hxx> 27 28 //_______________________________________________ 29 // own includes 30 #include <classes/fwkresid.hxx> 31 32 #include "classes/resource.hrc" 33 #include <threadhelp/readguard.hxx> 34 #include <threadhelp/writeguard.hxx> 35 #include <services.h> 36 37 //_______________________________________________ 38 // interface includes 39 40 #ifndef __COM_SUN_STAR_CONFIGURATION_CORRUPTEDUICONFIGURATIONEXCEPTION_HPP_ 41 #include <com/sun/star/configuration/CorruptedUIConfigurationException.hpp> 42 #endif 43 44 #ifndef __COM_SUN_STAR_CONTAINER_NOSUCHELEMENTEXCEPTION_HPP_ 45 #include <com/sun/star/container/NoSuchElementException.hpp> 46 #endif 47 48 #ifndef __COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ 49 #include <com/sun/star/container/XNameAccess.hpp> 50 #endif 51 52 #ifndef __COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ 53 #include <com/sun/star/beans/XPropertySet.hpp> 54 #endif 55 56 #ifndef __COM_SUN_STAR_EMBED_ELEMENTMODES_HPP_ 57 #include <com/sun/star/embed/ElementModes.hpp> 58 #endif 59 60 #ifndef __COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_ 61 #include <com/sun/star/embed/XTransactedObject.hpp> 62 #endif 63 64 #ifndef __COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_ 65 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 66 #endif 67 68 //_______________________________________________ 69 // other includes 70 #include <vcl/svapp.hxx> 71 72 #ifndef _RTL_USTRBUF_HXX 73 #include <rtl/ustrbuf.hxx> 74 #endif 75 76 //_______________________________________________ 77 // const 78 79 #define SUBSTORAGE_GLOBAL DECLARE_ASCII("global" ) 80 #define SUBSTORAGE_MODULES DECLARE_ASCII("modules") 81 82 #define BASEPATH_SHARE_LAYER DECLARE_ASCII("UIConfig" ) 83 #define BASEPATH_USER_LAYER DECLARE_ASCII("UserConfig") 84 85 #define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg") 86 #define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg") 87 // #define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg/uiconfig.zip") 88 // #define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg/uiconfig.zip") 89 90 #define FILE_EXTENSION DECLARE_ASCII(".xml") 91 92 #define PATH_SEPERATOR DECLARE_ASCII("/") 93 94 static const ::sal_Int32 ID_CORRUPT_UICONFIG_SHARE = 1; 95 static const ::sal_Int32 ID_CORRUPT_UICONFIG_USER = 2; 96 static const ::sal_Int32 ID_CORRUPT_UICONFIG_GENERAL = 3; 97 98 //_______________________________________________ 99 // namespace 100 101 namespace framework 102 { 103 104 //----------------------------------------------- 105 ::rtl::OUString PresetHandler::PRESET_DEFAULT() 106 { 107 static ::rtl::OUString RSTYPE = DECLARE_ASCII("default"); 108 return RSTYPE; 109 } 110 111 //----------------------------------------------- 112 ::rtl::OUString PresetHandler::TARGET_CURRENT() 113 { 114 static ::rtl::OUString RSTYPE = DECLARE_ASCII("current"); 115 return RSTYPE; 116 } 117 118 //----------------------------------------------- 119 ::rtl::OUString PresetHandler::RESOURCETYPE_MENUBAR() 120 { 121 static ::rtl::OUString RSTYPE = DECLARE_ASCII("menubar"); 122 return RSTYPE; 123 } 124 125 //----------------------------------------------- 126 ::rtl::OUString PresetHandler::RESOURCETYPE_TOOLBAR() 127 { 128 static ::rtl::OUString RSTYPE = DECLARE_ASCII("toolbar"); 129 return RSTYPE; 130 } 131 132 //----------------------------------------------- 133 ::rtl::OUString PresetHandler::RESOURCETYPE_ACCELERATOR() 134 { 135 static ::rtl::OUString RSTYPE = DECLARE_ASCII("accelerator"); 136 return RSTYPE; 137 } 138 139 //----------------------------------------------- 140 ::rtl::OUString PresetHandler::RESOURCETYPE_STATUSBAR() 141 { 142 static ::rtl::OUString RSTYPE = DECLARE_ASCII("statusbar"); 143 return RSTYPE; 144 } 145 146 //----------------------------------------------- 147 PresetHandler::PresetHandler(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 148 : ThreadHelpBase (&Application::GetSolarMutex() ) 149 , m_xSMGR (xSMGR ) 150 , m_aSharedStorages ( ) 151 , m_lDocumentStorages(xSMGR ) 152 , m_aLocale (::comphelper::Locale::X_NOTRANSLATE()) 153 { 154 } 155 156 //----------------------------------------------- 157 PresetHandler::PresetHandler(const PresetHandler& rCopy) 158 : ThreadHelpBase (&Application::GetSolarMutex() ) 159 { 160 m_xSMGR = rCopy.m_xSMGR; 161 m_eConfigType = rCopy.m_eConfigType; 162 m_sResourceType = rCopy.m_sResourceType; 163 m_sModule = rCopy.m_sModule; 164 m_aSharedStorages = rCopy.m_aSharedStorages; 165 m_xWorkingStorageShare = rCopy.m_xWorkingStorageShare; 166 m_xWorkingStorageNoLang = rCopy.m_xWorkingStorageNoLang; 167 m_xWorkingStorageUser = rCopy.m_xWorkingStorageUser; 168 m_lPresets = rCopy.m_lPresets; 169 m_lTargets = rCopy.m_lTargets; 170 m_aLocale = rCopy.m_aLocale; 171 m_lDocumentStorages = rCopy.m_lDocumentStorages; 172 m_sRelPathShare = rCopy.m_sRelPathShare; 173 m_sRelPathNoLang = rCopy.m_sRelPathNoLang; 174 m_sRelPathUser = rCopy.m_sRelPathUser; 175 } 176 177 //----------------------------------------------- 178 PresetHandler::~PresetHandler() 179 { 180 m_xWorkingStorageShare.clear(); 181 m_xWorkingStorageNoLang.clear(); 182 m_xWorkingStorageUser.clear(); 183 184 /* #i46497# 185 Dont call forgetCachedStorages() here for shared storages. 186 Because we opened different sub storages by using openPath(). 187 And every already open path was reused and referenced (means it's 188 ref count was increased!) 189 So now we have to release our ref counts to these shared storages 190 only ... and not to free all used storages. 191 Otherwise we will disconnect all other open configuration access 192 objects which base on these storages. 193 */ 194 m_aSharedStorages->m_lStoragesShare.closePath(m_sRelPathShare); 195 m_aSharedStorages->m_lStoragesUser.closePath (m_sRelPathUser ); 196 197 /* On the other side closePath() is not needed for our special handled 198 document storage. Because it's not shared with others ... so we can 199 free it. 200 */ 201 m_lDocumentStorages.forgetCachedStorages(); 202 } 203 204 //----------------------------------------------- 205 void PresetHandler::forgetCachedStorages() 206 { 207 // SAFE -> ---------------------------------- 208 WriteGuard aWriteLock(m_aLock); 209 210 if (m_eConfigType == E_DOCUMENT) 211 { 212 m_xWorkingStorageShare.clear(); 213 m_xWorkingStorageNoLang.clear(); 214 m_xWorkingStorageUser.clear(); 215 } 216 217 m_lDocumentStorages.forgetCachedStorages(); 218 219 aWriteLock.unlock(); 220 // <- SAFE ---------------------------------- 221 } 222 223 //----------------------------------------------- 224 ::rtl::OUString lcl_getLocalizedMessage(::sal_Int32 nID) 225 { 226 ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("Unknown error."); 227 228 switch(nID) 229 { 230 case ID_CORRUPT_UICONFIG_SHARE : 231 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_SHARE ))); 232 break; 233 234 case ID_CORRUPT_UICONFIG_USER : 235 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_USER ))); 236 break; 237 238 case ID_CORRUPT_UICONFIG_GENERAL : 239 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_GENERAL ))); 240 break; 241 } 242 243 return sMessage; 244 } 245 246 //----------------------------------------------- 247 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageShare() 248 { 249 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesShare.getRootStorage(); 250 if (xRoot.is()) 251 return xRoot; 252 253 // SAFE -> ---------------------------------- 254 ReadGuard aReadLock(m_aLock); 255 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 256 aReadLock.unlock(); 257 // <- SAFE ---------------------------------- 258 259 css::uno::Reference< css::beans::XPropertySet > xPathSettings( 260 xSMGR->createInstance(SERVICENAME_PATHSETTINGS), 261 css::uno::UNO_QUERY_THROW); 262 263 ::rtl::OUString sShareLayer; 264 xPathSettings->getPropertyValue(BASEPATH_SHARE_LAYER) >>= sShareLayer; 265 266 // "UIConfig" is a "multi path" ... use first part only here! 267 sal_Int32 nPos = sShareLayer.indexOf(';'); 268 if (nPos > 0) 269 sShareLayer = sShareLayer.copy(0, nPos); 270 271 // Note: May be an user uses URLs without a final slash! Check it ... 272 nPos = sShareLayer.lastIndexOf('/'); 273 if (nPos != sShareLayer.getLength()-1) 274 sShareLayer += ::rtl::OUString::createFromAscii("/"); 275 276 sShareLayer += RELPATH_SHARE_LAYER; // folder 277 /* 278 // TODO remove me! 279 // Attention: This is temp. workaround ... We create a temp. storage file 280 // based of a system directory. This must be used so, till the storage implementation 281 // can work on directories too. 282 */ 283 css::uno::Sequence< css::uno::Any > lArgs(2); 284 lArgs[0] <<= sShareLayer; 285 lArgs[1] <<= css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE; 286 287 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory(xSMGR->createInstance(SERVICENAME_FILESYSTEMSTORAGEFACTORY) , css::uno::UNO_QUERY_THROW); 288 css::uno::Reference< css::embed::XStorage > xStorage; 289 290 try 291 { 292 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW); 293 } 294 catch(const css::uno::Exception& ex) 295 { 296 throw css::configuration::CorruptedUIConfigurationException( 297 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_SHARE), 298 css::uno::Reference< css::uno::XInterface >(), 299 ex.Message); 300 } 301 302 m_aSharedStorages->m_lStoragesShare.setRootStorage(xStorage); 303 304 return xStorage; 305 } 306 307 //----------------------------------------------- 308 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageUser() 309 { 310 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesUser.getRootStorage(); 311 if (xRoot.is()) 312 return xRoot; 313 314 // SAFE -> ---------------------------------- 315 ReadGuard aReadLock(m_aLock); 316 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 317 aReadLock.unlock(); 318 // <- SAFE ---------------------------------- 319 320 css::uno::Reference< css::beans::XPropertySet > xPathSettings( 321 xSMGR->createInstance(SERVICENAME_PATHSETTINGS), 322 css::uno::UNO_QUERY_THROW); 323 324 ::rtl::OUString sUserLayer; 325 xPathSettings->getPropertyValue(BASEPATH_USER_LAYER) >>= sUserLayer ; 326 327 // Note: May be an user uses URLs without a final slash! Check it ... 328 sal_Int32 nPos = sUserLayer.lastIndexOf('/'); 329 if (nPos != sUserLayer.getLength()-1) 330 sUserLayer += ::rtl::OUString::createFromAscii("/"); 331 332 sUserLayer += RELPATH_USER_LAYER; // storage file 333 334 css::uno::Sequence< css::uno::Any > lArgs(2); 335 lArgs[0] <<= sUserLayer; 336 lArgs[1] <<= css::embed::ElementModes::READWRITE; 337 338 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory(xSMGR->createInstance(SERVICENAME_FILESYSTEMSTORAGEFACTORY) , css::uno::UNO_QUERY_THROW); 339 css::uno::Reference< css::embed::XStorage > xStorage; 340 341 try 342 { 343 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW); 344 } 345 catch(const css::uno::Exception& ex) 346 { 347 throw css::configuration::CorruptedUIConfigurationException( 348 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_USER), 349 css::uno::Reference< css::uno::XInterface >(), 350 ex.Message); 351 } 352 353 m_aSharedStorages->m_lStoragesUser.setRootStorage(xStorage); 354 355 return xStorage; 356 } 357 358 //----------------------------------------------- 359 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageShare() 360 { 361 // SAFE -> ---------------------------------- 362 ReadGuard aReadLock(m_aLock); 363 return m_xWorkingStorageShare; 364 // <- SAFE ---------------------------------- 365 } 366 367 //----------------------------------------------- 368 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageUser() 369 { 370 // SAFE -> ---------------------------------- 371 ReadGuard aReadLock(m_aLock); 372 return m_xWorkingStorageUser; 373 // <- SAFE ---------------------------------- 374 } 375 376 //----------------------------------------------- 377 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageShare(const css::uno::Reference< css::embed::XStorage >& /*xChild*/) 378 { 379 // SAFE -> ---------------------------------- 380 ReadGuard aReadLock(m_aLock); 381 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageShare; 382 aReadLock.unlock(); 383 // <- SAFE ---------------------------------- 384 385 return m_aSharedStorages->m_lStoragesShare.getParentStorage(xWorking); 386 } 387 388 //----------------------------------------------- 389 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageUser(const css::uno::Reference< css::embed::XStorage >& /*xChild*/) 390 { 391 // SAFE -> ---------------------------------- 392 ReadGuard aReadLock(m_aLock); 393 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser; 394 aReadLock.unlock(); 395 // <- SAFE ---------------------------------- 396 397 return m_aSharedStorages->m_lStoragesUser.getParentStorage(xWorking); 398 } 399 400 //----------------------------------------------- 401 void PresetHandler::connectToResource( PresetHandler::EConfigType eConfigType , 402 const ::rtl::OUString& sResource , 403 const ::rtl::OUString& sModule , 404 const css::uno::Reference< css::embed::XStorage >& xDocumentRoot, 405 const ::comphelper::Locale& aLocale ) 406 { 407 // TODO free all current open storages! 408 409 // SAFE -> ---------------------------------- 410 WriteGuard aWriteLock(m_aLock); 411 412 m_eConfigType = eConfigType ; 413 m_sResourceType = sResource ; 414 m_sModule = sModule ; 415 m_aLocale = aLocale ; 416 417 aWriteLock.unlock(); 418 // <- SAFE ---------------------------------- 419 420 css::uno::Reference< css::embed::XStorage > xShare; 421 css::uno::Reference< css::embed::XStorage > xNoLang; 422 css::uno::Reference< css::embed::XStorage > xUser; 423 424 // special case for documents 425 // use outside root storage, if we run in E_DOCUMENT mode! 426 if (eConfigType == E_DOCUMENT) 427 { 428 if (!xDocumentRoot.is()) 429 throw css::uno::RuntimeException( 430 ::rtl::OUString::createFromAscii("There is valid root storage, where the UI configuration can work on."), 431 css::uno::Reference< css::uno::XInterface >()); 432 m_lDocumentStorages.setRootStorage(xDocumentRoot); 433 xShare = xDocumentRoot; 434 xUser = xDocumentRoot; 435 } 436 else 437 { 438 xShare = getOrCreateRootStorageShare(); 439 xUser = getOrCreateRootStorageUser(); 440 } 441 442 // #...# 443 try 444 { 445 446 // a) inside share layer we should not create any new structures ... We jave to use 447 // existing ones only! 448 // b) inside user layer we can (SOFT mode!) but sometimes we shouldn't (HARD mode!) 449 // create new empty structures. We should preferr using of any existing structure. 450 sal_Int32 eShareMode = (css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE); 451 sal_Int32 eUserMode = (css::embed::ElementModes::READWRITE ); 452 453 ::rtl::OUStringBuffer sRelPathBuf(1024); 454 ::rtl::OUString sRelPathShare; 455 ::rtl::OUString sRelPathNoLang; 456 ::rtl::OUString sRelPathUser; 457 switch(eConfigType) 458 { 459 case E_GLOBAL : 460 { 461 sRelPathBuf.append(SUBSTORAGE_GLOBAL); 462 sRelPathBuf.append(PATH_SEPERATOR ); 463 sRelPathBuf.append(sResource ); 464 sRelPathShare = sRelPathBuf.makeStringAndClear(); 465 sRelPathUser = sRelPathShare; 466 467 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True ); 468 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False); 469 } 470 break; 471 472 case E_MODULES : 473 { 474 sRelPathBuf.append(SUBSTORAGE_MODULES); 475 sRelPathBuf.append(PATH_SEPERATOR ); 476 sRelPathBuf.append(sModule ); 477 sRelPathBuf.append(PATH_SEPERATOR ); 478 sRelPathBuf.append(sResource ); 479 sRelPathShare = sRelPathBuf.makeStringAndClear(); 480 sRelPathUser = sRelPathShare; 481 482 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True ); 483 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False); 484 } 485 break; 486 487 case E_DOCUMENT : 488 { 489 // A document does not have a share layer in real. 490 // It has one layer only, and this one should be opened READ_WRITE. 491 // So we open the user layer here only and set the share layer equals to it .-) 492 493 sRelPathBuf.append(sResource); 494 sRelPathUser = sRelPathBuf.makeStringAndClear(); 495 sRelPathShare = sRelPathUser; 496 497 try 498 { 499 xUser = m_lDocumentStorages.openPath(sRelPathUser , eUserMode ); 500 xShare = xUser; 501 } 502 catch(const css::uno::RuntimeException& exRun) 503 { throw exRun; } 504 catch(const css::uno::Exception&) 505 { xShare.clear(); xUser.clear(); } 506 } 507 break; 508 } 509 510 // Non-localized global share 511 xNoLang = xShare; 512 sRelPathNoLang = sRelPathShare; 513 514 if ( 515 (aLocale != ::comphelper::Locale::X_NOTRANSLATE()) && // localized level? 516 (eConfigType != E_DOCUMENT ) // no localization in document mode! 517 ) 518 { 519 // First try to find the right localized set inside share layer. 520 // Fallbacks are allowed there. 521 ::comphelper::Locale aShareLocale = aLocale ; 522 ::rtl::OUString sLocalizedSharePath(sRelPathShare); 523 sal_Bool bAllowFallbacks = sal_True ; 524 xShare = impl_openLocalizedPathIgnoringErrors(sLocalizedSharePath, eShareMode, sal_True , aShareLocale, bAllowFallbacks); 525 526 // The try to locate the right sub dir inside user layer ... without using fallbacks! 527 // Normally the corresponding sub dir should be created matching the specified locale. 528 // Because we allow creation of storages inside user layer by default. 529 ::comphelper::Locale aUserLocale = aLocale ; 530 ::rtl::OUString sLocalizedUserPath(sRelPathUser); 531 bAllowFallbacks = sal_False ; 532 xUser = impl_openLocalizedPathIgnoringErrors(sLocalizedUserPath, eUserMode , sal_False, aUserLocale, bAllowFallbacks); 533 534 sRelPathShare = sLocalizedSharePath; 535 sRelPathUser = sLocalizedUserPath ; 536 } 537 538 // read content of level 3 (presets, targets) 539 css::uno::Reference< css::container::XNameAccess > xAccess ; 540 css::uno::Sequence< ::rtl::OUString > lNames ; 541 const ::rtl::OUString* pNames ; 542 sal_Int32 c ; 543 sal_Int32 i ; 544 OUStringList lPresets; 545 OUStringList lTargets; 546 547 // read preset names of share layer 548 xAccess = css::uno::Reference< css::container::XNameAccess >(xShare, css::uno::UNO_QUERY); 549 if (xAccess.is()) 550 { 551 lNames = xAccess->getElementNames(); 552 pNames = lNames.getConstArray(); 553 c = lNames.getLength(); 554 555 for (i=0; i<c; ++i) 556 { 557 ::rtl::OUString sTemp = pNames[i]; 558 sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION); 559 if (nPos > -1) 560 sTemp = sTemp.copy(0,nPos); 561 lPresets.push_back(sTemp); 562 } 563 } 564 565 // read preset names of user layer 566 xAccess = css::uno::Reference< css::container::XNameAccess >(xUser, css::uno::UNO_QUERY); 567 if (xAccess.is()) 568 { 569 lNames = xAccess->getElementNames(); 570 pNames = lNames.getConstArray(); 571 c = lNames.getLength(); 572 573 for (i=0; i<c; ++i) 574 { 575 ::rtl::OUString sTemp = pNames[i]; 576 sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION); 577 if (nPos > -1) 578 sTemp = sTemp.copy(0,nPos); 579 lTargets.push_back(sTemp); 580 } 581 } 582 583 // SAFE -> ---------------------------------- 584 aWriteLock.lock(); 585 586 m_xWorkingStorageShare = xShare ; 587 m_xWorkingStorageNoLang= xNoLang; 588 m_xWorkingStorageUser = xUser ; 589 m_lPresets = lPresets; 590 m_lTargets = lTargets; 591 m_sRelPathShare = sRelPathShare; 592 m_sRelPathNoLang = sRelPathNoLang; 593 m_sRelPathUser = sRelPathUser; 594 595 aWriteLock.unlock(); 596 // <- SAFE ---------------------------------- 597 598 } 599 catch(const css::uno::Exception& ex) 600 { 601 throw css::configuration::CorruptedUIConfigurationException( 602 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_GENERAL), 603 css::uno::Reference< css::uno::XInterface >(), 604 ex.Message); 605 } 606 } 607 608 //----------------------------------------------- 609 void PresetHandler::copyPresetToTarget(const ::rtl::OUString& sPreset, 610 const ::rtl::OUString& sTarget) 611 { 612 // dont check our preset list, if element exists 613 // We try to open it and forward all errors to the user! 614 615 // SAFE -> ---------------------------------- 616 ReadGuard aReadLock(m_aLock); 617 css::uno::Reference< css::embed::XStorage > xWorkingShare = m_xWorkingStorageShare; 618 css::uno::Reference< css::embed::XStorage > xWorkingNoLang= m_xWorkingStorageNoLang; 619 css::uno::Reference< css::embed::XStorage > xWorkingUser = m_xWorkingStorageUser ; 620 aReadLock.unlock(); 621 // <- SAFE ---------------------------------- 622 623 // e.g. module without any config data ?! 624 if ( 625 (!xWorkingShare.is()) || 626 (!xWorkingUser.is() ) 627 ) 628 { 629 return; 630 } 631 632 ::rtl::OUString sPresetFile(sPreset); 633 sPresetFile += FILE_EXTENSION; 634 635 ::rtl::OUString sTargetFile(sTarget); 636 sTargetFile += FILE_EXTENSION; 637 638 // remove existing elements before you try to copy the preset to that location ... 639 // Otherwise w will get an ElementExistException inside copyElementTo()! 640 css::uno::Reference< css::container::XNameAccess > xCheckingUser(xWorkingUser, css::uno::UNO_QUERY_THROW); 641 if (xCheckingUser->hasByName(sTargetFile)) 642 xWorkingUser->removeElement(sTargetFile); 643 644 xWorkingShare->copyElementTo(sPresetFile, xWorkingUser, sTargetFile); 645 646 // If our storages work in transacted mode, we have 647 // to commit all changes from bottom to top! 648 commitUserChanges(); 649 } 650 651 //----------------------------------------------- 652 css::uno::Reference< css::io::XStream > PresetHandler::openPreset(const ::rtl::OUString& sPreset, 653 sal_Bool bUseNoLangGlobal) 654 { 655 // SAFE -> ---------------------------------- 656 ReadGuard aReadLock(m_aLock); 657 css::uno::Reference< css::embed::XStorage > xFolder = bUseNoLangGlobal? m_xWorkingStorageNoLang: m_xWorkingStorageShare; 658 aReadLock.unlock(); 659 // <- SAFE ---------------------------------- 660 661 // e.g. module without any config data ?! 662 if (!xFolder.is()) 663 return css::uno::Reference< css::io::XStream >(); 664 665 ::rtl::OUString sFile(sPreset); 666 sFile += FILE_EXTENSION; 667 668 // inform user about errors (use original exceptions!) 669 css::uno::Reference< css::io::XStream > xStream = xFolder->openStreamElement(sFile, css::embed::ElementModes::READ); 670 return xStream; 671 } 672 673 //----------------------------------------------- 674 css::uno::Reference< css::io::XStream > PresetHandler::openTarget(const ::rtl::OUString& sTarget , 675 sal_Bool bCreateIfMissing) 676 { 677 // SAFE -> ---------------------------------- 678 ReadGuard aReadLock(m_aLock); 679 css::uno::Reference< css::embed::XStorage > xFolder = m_xWorkingStorageUser; 680 aReadLock.unlock(); 681 // <- SAFE ---------------------------------- 682 683 // e.g. module without any config data ?! 684 if (!xFolder.is()) 685 return css::uno::Reference< css::io::XStream >(); 686 687 ::rtl::OUString sFile(sTarget); 688 sFile += FILE_EXTENSION; 689 690 sal_Int32 nOpenMode = css::embed::ElementModes::READWRITE; 691 if (!bCreateIfMissing) 692 nOpenMode |= css::embed::ElementModes::NOCREATE; 693 694 // try it in read/write mode first and ignore errors. 695 css::uno::Reference< css::io::XStream > xStream; 696 try 697 { 698 xStream = xFolder->openStreamElement(sFile, nOpenMode); 699 return xStream; 700 } 701 catch(const css::uno::RuntimeException&) 702 { throw; } 703 catch(const css::uno::Exception&) 704 { xStream.clear(); } 705 706 // try it readonly if it failed before. 707 // inform user about errors (use original exceptions!) 708 nOpenMode &= ~css::embed::ElementModes::WRITE; 709 xStream = xFolder->openStreamElement(sFile, nOpenMode); 710 711 return xStream; 712 } 713 714 //----------------------------------------------- 715 void PresetHandler::commitUserChanges() 716 { 717 // SAFE -> ---------------------------------- 718 ReadGuard aReadLock(m_aLock); 719 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser; 720 EConfigType eCfgType = m_eConfigType; 721 aReadLock.unlock(); 722 // <- SAFE ---------------------------------- 723 724 // e.g. module without any config data ?! 725 if (!xWorking.is()) 726 return; 727 728 ::rtl::OUString sPath; 729 730 switch(eCfgType) 731 { 732 case E_GLOBAL : 733 case E_MODULES : 734 { 735 sPath = m_aSharedStorages->m_lStoragesUser.getPathOfStorage(xWorking); 736 m_aSharedStorages->m_lStoragesUser.commitPath(sPath); 737 m_aSharedStorages->m_lStoragesUser.notifyPath(sPath); 738 } 739 break; 740 741 case E_DOCUMENT : 742 { 743 sPath = m_lDocumentStorages.getPathOfStorage(xWorking); 744 m_lDocumentStorages.commitPath(sPath); 745 m_lDocumentStorages.notifyPath(sPath); 746 } 747 break; 748 } 749 } 750 751 //----------------------------------------------- 752 void PresetHandler::addStorageListener(IStorageListener* pListener) 753 { 754 // SAFE -> ---------------------------------- 755 ReadGuard aReadLock(m_aLock); 756 ::rtl::OUString sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer! 757 EConfigType eCfgType = m_eConfigType; 758 aReadLock.unlock(); 759 // <- SAFE ---------------------------------- 760 761 if (!sRelPath.getLength()) 762 return; 763 764 switch(eCfgType) 765 { 766 case E_GLOBAL : 767 case E_MODULES : 768 { 769 m_aSharedStorages->m_lStoragesUser.addStorageListener(pListener, sRelPath); 770 } 771 break; 772 773 case E_DOCUMENT : 774 { 775 m_lDocumentStorages.addStorageListener(pListener, sRelPath); 776 } 777 break; 778 } 779 } 780 781 //----------------------------------------------- 782 void PresetHandler::removeStorageListener(IStorageListener* pListener) 783 { 784 // SAFE -> ---------------------------------- 785 ReadGuard aReadLock(m_aLock); 786 ::rtl::OUString sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer! 787 EConfigType eCfgType = m_eConfigType; 788 aReadLock.unlock(); 789 // <- SAFE ---------------------------------- 790 791 if (!sRelPath.getLength()) 792 return; 793 794 switch(eCfgType) 795 { 796 case E_GLOBAL : 797 case E_MODULES : 798 { 799 m_aSharedStorages->m_lStoragesUser.removeStorageListener(pListener, sRelPath); 800 } 801 break; 802 803 case E_DOCUMENT : 804 { 805 m_lDocumentStorages.removeStorageListener(pListener, sRelPath); 806 } 807 break; 808 } 809 } 810 811 //----------------------------------------------- 812 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openPathIgnoringErrors(const ::rtl::OUString& sPath , 813 sal_Int32 eMode , 814 sal_Bool bShare) 815 { 816 css::uno::Reference< css::embed::XStorage > xPath; 817 try 818 { 819 if (bShare) 820 xPath = m_aSharedStorages->m_lStoragesShare.openPath(sPath, eMode); 821 else 822 xPath = m_aSharedStorages->m_lStoragesUser.openPath(sPath, eMode); 823 } 824 catch(const css::uno::RuntimeException& exRun) 825 { throw exRun; } 826 catch(const css::uno::Exception&) 827 { xPath.clear(); } 828 return xPath; 829 } 830 831 //----------------------------------------------- 832 ::std::vector< ::rtl::OUString >::const_iterator PresetHandler::impl_findMatchingLocalizedValue(const ::std::vector< ::rtl::OUString >& lLocalizedValues, 833 ::comphelper::Locale& aLocale , 834 sal_Bool bAllowFallbacks ) 835 { 836 ::std::vector< ::rtl::OUString >::const_iterator pFound = lLocalizedValues.end(); 837 if (bAllowFallbacks) 838 { 839 pFound = ::comphelper::Locale::getFallback(lLocalizedValues, aLocale.toISO()); 840 } 841 else 842 { 843 for ( pFound = lLocalizedValues.begin(); 844 pFound != lLocalizedValues.end() ; 845 ++pFound ) 846 { 847 const ::rtl::OUString& sCheckISO = *pFound; 848 ::comphelper::Locale aCheckLocale(sCheckISO); 849 if (aCheckLocale.equals(aLocale)) 850 break; 851 } 852 } 853 854 // if we found a valid locale ... take it over to our in/out parameter aLocale 855 if (pFound != lLocalizedValues.end()) 856 { 857 const ::rtl::OUString& sISOLocale = *pFound; 858 aLocale.fromISO(sISOLocale); 859 } 860 861 return pFound; 862 } 863 864 //----------------------------------------------- 865 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openLocalizedPathIgnoringErrors(::rtl::OUString& sPath , 866 sal_Int32 eMode , 867 sal_Bool bShare , 868 ::comphelper::Locale& aLocale , 869 sal_Bool bAllowFallback) 870 { 871 css::uno::Reference< css::embed::XStorage > xPath = impl_openPathIgnoringErrors(sPath, eMode, bShare); 872 ::std::vector< ::rtl::OUString > lSubFolders = impl_getSubFolderNames(xPath); 873 ::std::vector< ::rtl::OUString >::const_iterator pLocaleFolder = impl_findMatchingLocalizedValue(lSubFolders, aLocale, bAllowFallback); 874 875 // no fallback ... creation not allowed => no storage 876 if ( 877 (pLocaleFolder == lSubFolders.end() ) && 878 ((eMode & css::embed::ElementModes::NOCREATE) == css::embed::ElementModes::NOCREATE) 879 ) 880 return css::uno::Reference< css::embed::XStorage >(); 881 882 // it doesn't matter, if there is a locale fallback or not 883 // If creation of storages is allowed, we do it anyway. 884 // Otherwise we have no acc config at all, which can make other trouble. 885 ::rtl::OUString sLocalizedPath; 886 sLocalizedPath = sPath; 887 sLocalizedPath += PATH_SEPERATOR; 888 if (pLocaleFolder != lSubFolders.end()) 889 sLocalizedPath += *pLocaleFolder; 890 else 891 sLocalizedPath += aLocale.toISO(); 892 893 css::uno::Reference< css::embed::XStorage > xLocalePath = impl_openPathIgnoringErrors(sLocalizedPath, eMode, bShare); 894 895 if (xLocalePath.is()) 896 sPath = sLocalizedPath; 897 else 898 sPath = ::rtl::OUString(); 899 900 return xLocalePath; 901 } 902 903 //----------------------------------------------- 904 ::std::vector< ::rtl::OUString > PresetHandler::impl_getSubFolderNames(const css::uno::Reference< css::embed::XStorage >& xFolder) 905 { 906 css::uno::Reference< css::container::XNameAccess > xAccess(xFolder, css::uno::UNO_QUERY); 907 if (!xAccess.is()) 908 return ::std::vector< ::rtl::OUString >(); 909 910 ::std::vector< ::rtl::OUString > lSubFolders; 911 const css::uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames(); 912 const ::rtl::OUString* pNames = lNames.getConstArray(); 913 sal_Int32 c = lNames.getLength(); 914 sal_Int32 i = 0; 915 916 for (i=0; i<c; ++i) 917 { 918 try 919 { 920 if (xFolder->isStorageElement(pNames[i])) 921 lSubFolders.push_back(pNames[i]); 922 } 923 catch(const css::uno::RuntimeException& exRun) 924 { throw exRun; } 925 catch(const css::uno::Exception&) 926 {} 927 } 928 929 return lSubFolders; 930 } 931 932 //----------------------------------------------- 933 } // namespace framework 934