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