bump product version to 4.1.6.2
[LibreOffice.git] / framework / source / accelerators / presethandler.cxx
blob7735ea59d41d324dca9521b40ad29a93d67cdf73
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <accelerators/presethandler.hxx>
22 #include <classes/fwkresid.hxx>
24 #include "classes/resource.hrc"
25 #include <threadhelp/readguard.hxx>
26 #include <threadhelp/writeguard.hxx>
27 #include <services.h>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/configuration/CorruptedUIConfigurationException.hpp>
31 #include <com/sun/star/container/NoSuchElementException.hpp>
32 #include <com/sun/star/container/XNameAccess.hpp>
33 #include <com/sun/star/embed/ElementModes.hpp>
34 #include <com/sun/star/embed/XTransactedObject.hpp>
35 #include <com/sun/star/embed/FileSystemStorageFactory.hpp>
36 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
37 #include <com/sun/star/util/PathSettings.hpp>
39 #include <vcl/svapp.hxx>
40 #include <cppuhelper/exc_hlp.hxx>
41 #include <rtl/ustrbuf.hxx>
42 #include <i18nlangtag/languagetag.hxx>
45 #define SUBSTORAGE_GLOBAL DECLARE_ASCII("global" )
46 #define SUBSTORAGE_MODULES DECLARE_ASCII("modules")
48 #define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg")
49 #define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg")
51 #define FILE_EXTENSION DECLARE_ASCII(".xml")
53 #define PATH_SEPARATOR DECLARE_ASCII("/")
55 static const ::sal_Int32 ID_CORRUPT_UICONFIG_SHARE = 1;
56 static const ::sal_Int32 ID_CORRUPT_UICONFIG_USER = 2;
57 static const ::sal_Int32 ID_CORRUPT_UICONFIG_GENERAL = 3;
60 namespace framework
63 //-----------------------------------------------
64 OUString PresetHandler::PRESET_DEFAULT()
66 return OUString("default");
69 //-----------------------------------------------
70 OUString PresetHandler::TARGET_CURRENT()
72 return OUString("current");
75 //-----------------------------------------------
76 OUString PresetHandler::RESOURCETYPE_MENUBAR()
78 return OUString("menubar");
81 //-----------------------------------------------
82 OUString PresetHandler::RESOURCETYPE_TOOLBAR()
84 return OUString("toolbar");
87 //-----------------------------------------------
88 OUString PresetHandler::RESOURCETYPE_ACCELERATOR()
90 return OUString("accelerator");
93 //-----------------------------------------------
94 OUString PresetHandler::RESOURCETYPE_STATUSBAR()
96 return OUString("statusbar");
99 //-----------------------------------------------
100 PresetHandler::PresetHandler(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
101 : ThreadHelpBase (&Application::GetSolarMutex() )
102 , m_xSMGR (xSMGR )
103 , m_aSharedStorages ( )
104 , m_lDocumentStorages()
105 , m_aLanguageTag (LANGUAGE_USER_PRIV_NOTRANSLATE)
109 //-----------------------------------------------
110 PresetHandler::PresetHandler(const PresetHandler& rCopy)
111 : ThreadHelpBase (&Application::GetSolarMutex() )
112 , m_aLanguageTag( rCopy.m_aLanguageTag)
114 m_xSMGR = rCopy.m_xSMGR;
115 m_eConfigType = rCopy.m_eConfigType;
116 m_sResourceType = rCopy.m_sResourceType;
117 m_sModule = rCopy.m_sModule;
118 m_aSharedStorages = rCopy.m_aSharedStorages;
119 m_xWorkingStorageShare = rCopy.m_xWorkingStorageShare;
120 m_xWorkingStorageNoLang = rCopy.m_xWorkingStorageNoLang;
121 m_xWorkingStorageUser = rCopy.m_xWorkingStorageUser;
122 m_lPresets = rCopy.m_lPresets;
123 m_lTargets = rCopy.m_lTargets;
124 m_lDocumentStorages = rCopy.m_lDocumentStorages;
125 m_sRelPathShare = rCopy.m_sRelPathShare;
126 m_sRelPathNoLang = rCopy.m_sRelPathNoLang;
127 m_sRelPathUser = rCopy.m_sRelPathUser;
130 //-----------------------------------------------
131 PresetHandler::~PresetHandler()
133 m_xWorkingStorageShare.clear();
134 m_xWorkingStorageNoLang.clear();
135 m_xWorkingStorageUser.clear();
137 /* #i46497#
138 Dont call forgetCachedStorages() here for shared storages.
139 Because we opened different sub storages by using openPath().
140 And every already open path was reused and referenced (means it's
141 ref count was increased!)
142 So now we have to release our ref counts to these shared storages
143 only ... and not to free all used storages.
144 Otherwise we will disconnect all other open configuration access
145 objects which base on these storages.
147 m_aSharedStorages->m_lStoragesShare.closePath(m_sRelPathShare);
148 m_aSharedStorages->m_lStoragesUser.closePath (m_sRelPathUser );
150 /* On the other side closePath() is not needed for our special handled
151 document storage. Because it's not shared with others ... so we can
152 free it.
154 m_lDocumentStorages.forgetCachedStorages();
157 //-----------------------------------------------
158 void PresetHandler::forgetCachedStorages()
160 // SAFE -> ----------------------------------
161 WriteGuard aWriteLock(m_aLock);
163 if (m_eConfigType == E_DOCUMENT)
165 m_xWorkingStorageShare.clear();
166 m_xWorkingStorageNoLang.clear();
167 m_xWorkingStorageUser.clear();
170 m_lDocumentStorages.forgetCachedStorages();
172 aWriteLock.unlock();
173 // <- SAFE ----------------------------------
176 namespace {
178 OUString lcl_getLocalizedMessage(::sal_Int32 nID)
180 OUString sMessage("Unknown error.");
182 switch(nID)
184 case ID_CORRUPT_UICONFIG_SHARE :
185 sMessage = OUString( String( FwkResId( STR_CORRUPT_UICFG_SHARE )));
187 break;
189 case ID_CORRUPT_UICONFIG_USER :
190 sMessage = OUString( String( FwkResId( STR_CORRUPT_UICFG_USER )));
191 break;
193 case ID_CORRUPT_UICONFIG_GENERAL :
194 sMessage = OUString( String( FwkResId( STR_CORRUPT_UICFG_GENERAL )));
195 break;
198 return sMessage;
201 void lcl_throwCorruptedUIConfigurationException(
202 css::uno::Any const & exception, sal_Int32 id)
204 css::uno::Exception e;
205 bool ok = (exception >>= e);
206 OSL_ASSERT(ok); (void) ok; // avoid warnings
207 throw css::configuration::CorruptedUIConfigurationException(
208 lcl_getLocalizedMessage(id),
209 css::uno::Reference< css::uno::XInterface >(),
210 (exception.getValueTypeName() +
211 OUString(": \"") + e.Message +
212 OUString("\"")));
217 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageShare()
219 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesShare.getRootStorage();
220 if (xRoot.is())
221 return xRoot;
223 // SAFE -> ----------------------------------
224 ReadGuard aReadLock(m_aLock);
225 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
226 aReadLock.unlock();
227 // <- SAFE ----------------------------------
229 css::uno::Reference< css::util::XPathSettings > xPathSettings =
230 css::util::PathSettings::create( comphelper::getComponentContext(xSMGR) );
232 OUString sShareLayer = xPathSettings->getBasePathShareLayer();
234 // "UIConfig" is a "multi path" ... use first part only here!
235 sal_Int32 nPos = sShareLayer.indexOf(';');
236 if (nPos > 0)
237 sShareLayer = sShareLayer.copy(0, nPos);
239 // Note: May be an user uses URLs without a final slash! Check it ...
240 nPos = sShareLayer.lastIndexOf('/');
241 if (nPos != sShareLayer.getLength()-1)
242 sShareLayer += OUString("/");
244 sShareLayer += RELPATH_SHARE_LAYER; // folder
246 // TODO remove me!
247 // Attention: This is temp. workaround ... We create a temp. storage file
248 // based of a sytem directory. This must be used so, till the storage implementation
249 // can work on directories too.
251 css::uno::Sequence< css::uno::Any > lArgs(2);
252 lArgs[0] <<= sShareLayer;
253 lArgs[1] <<= css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE;
255 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory = css::embed::FileSystemStorageFactory::create( comphelper::getComponentContext(xSMGR) );
256 css::uno::Reference< css::embed::XStorage > xStorage;
260 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
262 catch(const css::uno::Exception&)
264 css::uno::Any ex(cppu::getCaughtException());
265 lcl_throwCorruptedUIConfigurationException(
266 ex, ID_CORRUPT_UICONFIG_SHARE);
269 m_aSharedStorages->m_lStoragesShare.setRootStorage(xStorage);
271 return xStorage;
274 //-----------------------------------------------
275 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageUser()
277 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesUser.getRootStorage();
278 if (xRoot.is())
279 return xRoot;
281 // SAFE -> ----------------------------------
282 ReadGuard aReadLock(m_aLock);
283 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
284 aReadLock.unlock();
285 // <- SAFE ----------------------------------
287 css::uno::Reference< css::util::XPathSettings > xPathSettings =
288 css::util::PathSettings::create( comphelper::getComponentContext(xSMGR) );
290 OUString sUserLayer = xPathSettings->getBasePathUserLayer();
292 // Note: May be an user uses URLs without a final slash! Check it ...
293 sal_Int32 nPos = sUserLayer.lastIndexOf('/');
294 if (nPos != sUserLayer.getLength()-1)
295 sUserLayer += OUString("/");
297 sUserLayer += RELPATH_USER_LAYER; // storage file
299 css::uno::Sequence< css::uno::Any > lArgs(2);
300 lArgs[0] <<= sUserLayer;
301 lArgs[1] <<= css::embed::ElementModes::READWRITE;
303 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory = css::embed::FileSystemStorageFactory::create( comphelper::getComponentContext(xSMGR) );
304 css::uno::Reference< css::embed::XStorage > xStorage;
308 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
310 catch(const css::uno::Exception&)
312 css::uno::Any ex(cppu::getCaughtException());
313 lcl_throwCorruptedUIConfigurationException(
314 ex, ID_CORRUPT_UICONFIG_USER);
317 m_aSharedStorages->m_lStoragesUser.setRootStorage(xStorage);
319 return xStorage;
322 //-----------------------------------------------
323 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageShare()
325 // SAFE -> ----------------------------------
326 ReadGuard aReadLock(m_aLock);
327 return m_xWorkingStorageShare;
328 // <- SAFE ----------------------------------
331 //-----------------------------------------------
332 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageUser()
334 // SAFE -> ----------------------------------
335 ReadGuard aReadLock(m_aLock);
336 return m_xWorkingStorageUser;
337 // <- SAFE ----------------------------------
340 //-----------------------------------------------
341 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageShare(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
343 // SAFE -> ----------------------------------
344 ReadGuard aReadLock(m_aLock);
345 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageShare;
346 aReadLock.unlock();
347 // <- SAFE ----------------------------------
349 return m_aSharedStorages->m_lStoragesShare.getParentStorage(xWorking);
352 //-----------------------------------------------
353 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageUser(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
355 // SAFE -> ----------------------------------
356 ReadGuard aReadLock(m_aLock);
357 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser;
358 aReadLock.unlock();
359 // <- SAFE ----------------------------------
361 return m_aSharedStorages->m_lStoragesUser.getParentStorage(xWorking);
364 //-----------------------------------------------
365 void PresetHandler::connectToResource( PresetHandler::EConfigType eConfigType ,
366 const OUString& sResource ,
367 const OUString& sModule ,
368 const css::uno::Reference< css::embed::XStorage >& xDocumentRoot,
369 const LanguageTag& rLanguageTag )
371 // TODO free all current open storages!
373 // SAFE -> ----------------------------------
374 WriteGuard aWriteLock(m_aLock);
376 m_eConfigType = eConfigType ;
377 m_sResourceType = sResource ;
378 m_sModule = sModule ;
379 m_aLanguageTag = rLanguageTag ;
381 aWriteLock.unlock();
382 // <- SAFE ----------------------------------
384 css::uno::Reference< css::embed::XStorage > xShare;
385 css::uno::Reference< css::embed::XStorage > xNoLang;
386 css::uno::Reference< css::embed::XStorage > xUser;
388 // special case for documents
389 // use outside root storage, if we run in E_DOCUMENT mode!
390 if (eConfigType == E_DOCUMENT)
392 if (!xDocumentRoot.is())
393 throw css::uno::RuntimeException(
394 OUString("There is valid root storage, where the UI configuration can work on."),
395 css::uno::Reference< css::uno::XInterface >());
396 m_lDocumentStorages.setRootStorage(xDocumentRoot);
397 xShare = xDocumentRoot;
398 xUser = xDocumentRoot;
400 else
402 xShare = getOrCreateRootStorageShare();
403 xUser = getOrCreateRootStorageUser();
406 // #...#
410 // a) inside share layer we should not create any new structures ... We jave to use
411 // existing ones only!
412 // b) inside user layer we can (SOFT mode!) but sometimes we shouldnt (HARD mode!)
413 // create new empty structures. We should preferr using of any existing structure.
414 sal_Int32 eShareMode = (css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE);
415 sal_Int32 eUserMode = (css::embed::ElementModes::READWRITE );
417 OUStringBuffer sRelPathBuf(1024);
418 OUString sRelPathShare;
419 OUString sRelPathNoLang;
420 OUString sRelPathUser;
421 switch(eConfigType)
423 case E_GLOBAL :
425 sRelPathBuf.append(SUBSTORAGE_GLOBAL);
426 sRelPathBuf.append(PATH_SEPARATOR );
427 sRelPathBuf.append(sResource );
428 sRelPathShare = sRelPathBuf.makeStringAndClear();
429 sRelPathUser = sRelPathShare;
431 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True );
432 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False);
434 break;
436 case E_MODULES :
438 sRelPathBuf.append(SUBSTORAGE_MODULES);
439 sRelPathBuf.append(PATH_SEPARATOR );
440 sRelPathBuf.append(sModule );
441 sRelPathBuf.append(PATH_SEPARATOR );
442 sRelPathBuf.append(sResource );
443 sRelPathShare = sRelPathBuf.makeStringAndClear();
444 sRelPathUser = sRelPathShare;
446 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True );
447 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False);
449 break;
451 case E_DOCUMENT :
453 // A document does not have a share layer in real.
454 // It has one layer only, and this one should be opened READ_WRITE.
455 // So we open the user layer here only and set the share layer equals to it .-)
457 sRelPathBuf.append(sResource);
458 sRelPathUser = sRelPathBuf.makeStringAndClear();
459 sRelPathShare = sRelPathUser;
463 xUser = m_lDocumentStorages.openPath(sRelPathUser , eUserMode );
464 xShare = xUser;
466 catch(const css::uno::RuntimeException&)
467 { throw; }
468 catch(const css::uno::Exception&)
469 { xShare.clear(); xUser.clear(); }
471 break;
474 // Non-localized global share
475 xNoLang = xShare;
476 sRelPathNoLang = sRelPathShare;
478 if (
479 (rLanguageTag != LanguageTag(LANGUAGE_USER_PRIV_NOTRANSLATE)) && // localized level?
480 (eConfigType != E_DOCUMENT ) // no localization in document mode!
483 // First try to find the right localized set inside share layer.
484 // Fallbacks are allowed there.
485 OUString aShareLocale( rLanguageTag.getBcp47());
486 OUString sLocalizedSharePath(sRelPathShare);
487 sal_Bool bAllowFallbacks = sal_True ;
488 xShare = impl_openLocalizedPathIgnoringErrors(sLocalizedSharePath, eShareMode, sal_True , aShareLocale, bAllowFallbacks);
490 // The try to locate the right sub dir inside user layer ... without using fallbacks!
491 // Normaly the corresponding sub dir should be created matching the specified locale.
492 // Because we allow creation of storages inside user layer by default.
493 OUString aUserLocale( rLanguageTag.getBcp47());
494 OUString sLocalizedUserPath(sRelPathUser);
495 bAllowFallbacks = sal_False ;
496 xUser = impl_openLocalizedPathIgnoringErrors(sLocalizedUserPath, eUserMode , sal_False, aUserLocale, bAllowFallbacks);
498 sRelPathShare = sLocalizedSharePath;
499 sRelPathUser = sLocalizedUserPath ;
502 // read content of level 3 (presets, targets)
503 css::uno::Reference< css::container::XNameAccess > xAccess ;
504 css::uno::Sequence< OUString > lNames ;
505 const OUString* pNames ;
506 sal_Int32 c ;
507 sal_Int32 i ;
508 OUStringList lPresets;
509 OUStringList lTargets;
511 // read preset names of share layer
512 xAccess = css::uno::Reference< css::container::XNameAccess >(xShare, css::uno::UNO_QUERY);
513 if (xAccess.is())
515 lNames = xAccess->getElementNames();
516 pNames = lNames.getConstArray();
517 c = lNames.getLength();
519 for (i=0; i<c; ++i)
521 OUString sTemp = pNames[i];
522 sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION);
523 if (nPos > -1)
524 sTemp = sTemp.copy(0,nPos);
525 lPresets.push_back(sTemp);
529 // read preset names of user layer
530 xAccess = css::uno::Reference< css::container::XNameAccess >(xUser, css::uno::UNO_QUERY);
531 if (xAccess.is())
533 lNames = xAccess->getElementNames();
534 pNames = lNames.getConstArray();
535 c = lNames.getLength();
537 for (i=0; i<c; ++i)
539 OUString sTemp = pNames[i];
540 sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION);
541 if (nPos > -1)
542 sTemp = sTemp.copy(0,nPos);
543 lTargets.push_back(sTemp);
547 // SAFE -> ----------------------------------
548 aWriteLock.lock();
550 m_xWorkingStorageShare = xShare ;
551 m_xWorkingStorageNoLang= xNoLang;
552 m_xWorkingStorageUser = xUser ;
553 m_lPresets = lPresets;
554 m_lTargets = lTargets;
555 m_sRelPathShare = sRelPathShare;
556 m_sRelPathNoLang = sRelPathNoLang;
557 m_sRelPathUser = sRelPathUser;
559 aWriteLock.unlock();
560 // <- SAFE ----------------------------------
563 catch(const css::uno::Exception&)
565 css::uno::Any ex(cppu::getCaughtException());
566 lcl_throwCorruptedUIConfigurationException(
567 ex, ID_CORRUPT_UICONFIG_GENERAL);
571 //-----------------------------------------------
572 void PresetHandler::copyPresetToTarget(const OUString& sPreset,
573 const OUString& sTarget)
575 // dont check our preset list, if element exists
576 // We try to open it and forward all errors to the user!
578 // SAFE -> ----------------------------------
579 ReadGuard aReadLock(m_aLock);
580 css::uno::Reference< css::embed::XStorage > xWorkingShare = m_xWorkingStorageShare;
581 css::uno::Reference< css::embed::XStorage > xWorkingNoLang= m_xWorkingStorageNoLang;
582 css::uno::Reference< css::embed::XStorage > xWorkingUser = m_xWorkingStorageUser ;
583 aReadLock.unlock();
584 // <- SAFE ----------------------------------
586 // e.g. module without any config data ?!
587 if (
588 (!xWorkingShare.is()) ||
589 (!xWorkingUser.is() )
592 return;
595 OUString sPresetFile(sPreset);
596 sPresetFile += FILE_EXTENSION;
598 OUString sTargetFile(sTarget);
599 sTargetFile += FILE_EXTENSION;
601 // remove existing elements before you try to copy the preset to that location ...
602 // Otherwise w will get an ElementExistException inside copyElementTo()!
603 css::uno::Reference< css::container::XNameAccess > xCheckingUser(xWorkingUser, css::uno::UNO_QUERY_THROW);
604 if (xCheckingUser->hasByName(sTargetFile))
605 xWorkingUser->removeElement(sTargetFile);
607 xWorkingShare->copyElementTo(sPresetFile, xWorkingUser, sTargetFile);
609 // If our storages work in transacted mode, we have
610 // to commit all changes from bottom to top!
611 commitUserChanges();
614 //-----------------------------------------------
615 css::uno::Reference< css::io::XStream > PresetHandler::openPreset(const OUString& sPreset,
616 sal_Bool bUseNoLangGlobal)
618 // SAFE -> ----------------------------------
619 ReadGuard aReadLock(m_aLock);
620 css::uno::Reference< css::embed::XStorage > xFolder = bUseNoLangGlobal? m_xWorkingStorageNoLang: m_xWorkingStorageShare;
621 aReadLock.unlock();
622 // <- SAFE ----------------------------------
624 // e.g. module without any config data ?!
625 if (!xFolder.is())
626 return css::uno::Reference< css::io::XStream >();
628 OUString sFile(sPreset);
629 sFile += FILE_EXTENSION;
631 // inform user about errors (use original exceptions!)
632 css::uno::Reference< css::io::XStream > xStream = xFolder->openStreamElement(sFile, css::embed::ElementModes::READ);
633 return xStream;
636 //-----------------------------------------------
637 css::uno::Reference< css::io::XStream > PresetHandler::openTarget(const OUString& sTarget ,
638 sal_Bool bCreateIfMissing)
640 // SAFE -> ----------------------------------
641 ReadGuard aReadLock(m_aLock);
642 css::uno::Reference< css::embed::XStorage > xFolder = m_xWorkingStorageUser;
643 aReadLock.unlock();
644 // <- SAFE ----------------------------------
646 // e.g. module without any config data ?!
647 if (!xFolder.is())
648 return css::uno::Reference< css::io::XStream >();
650 OUString sFile(sTarget);
651 sFile += FILE_EXTENSION;
653 sal_Int32 nOpenMode = css::embed::ElementModes::READWRITE;
654 if (!bCreateIfMissing)
655 nOpenMode |= css::embed::ElementModes::NOCREATE;
657 // try it in read/write mode first and ignore errors.
658 css::uno::Reference< css::io::XStream > xStream;
661 xStream = xFolder->openStreamElement(sFile, nOpenMode);
662 return xStream;
664 catch(const css::uno::RuntimeException&)
665 { throw; }
666 catch(const css::uno::Exception&)
667 { xStream.clear(); }
669 // try it readonly if it failed before.
670 // inform user about errors (use original exceptions!)
671 nOpenMode &= ~css::embed::ElementModes::WRITE;
672 xStream = xFolder->openStreamElement(sFile, nOpenMode);
674 return xStream;
677 //-----------------------------------------------
678 void PresetHandler::commitUserChanges()
680 // SAFE -> ----------------------------------
681 ReadGuard aReadLock(m_aLock);
682 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser;
683 EConfigType eCfgType = m_eConfigType;
684 aReadLock.unlock();
685 // <- SAFE ----------------------------------
687 // e.g. module without any config data ?!
688 if (!xWorking.is())
689 return;
691 OUString sPath;
693 switch(eCfgType)
695 case E_GLOBAL :
696 case E_MODULES :
698 sPath = m_aSharedStorages->m_lStoragesUser.getPathOfStorage(xWorking);
699 m_aSharedStorages->m_lStoragesUser.commitPath(sPath);
700 m_aSharedStorages->m_lStoragesUser.notifyPath(sPath);
702 break;
704 case E_DOCUMENT :
706 sPath = m_lDocumentStorages.getPathOfStorage(xWorking);
707 m_lDocumentStorages.commitPath(sPath);
708 m_lDocumentStorages.notifyPath(sPath);
710 break;
714 //-----------------------------------------------
715 void PresetHandler::addStorageListener(IStorageListener* pListener)
717 // SAFE -> ----------------------------------
718 ReadGuard aReadLock(m_aLock);
719 OUString sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer!
720 EConfigType eCfgType = m_eConfigType;
721 aReadLock.unlock();
722 // <- SAFE ----------------------------------
724 if (sRelPath.isEmpty())
725 return;
727 switch(eCfgType)
729 case E_GLOBAL :
730 case E_MODULES :
732 m_aSharedStorages->m_lStoragesUser.addStorageListener(pListener, sRelPath);
734 break;
736 case E_DOCUMENT :
738 m_lDocumentStorages.addStorageListener(pListener, sRelPath);
740 break;
744 //-----------------------------------------------
745 void PresetHandler::removeStorageListener(IStorageListener* pListener)
747 // SAFE -> ----------------------------------
748 ReadGuard aReadLock(m_aLock);
749 OUString sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer!
750 EConfigType eCfgType = m_eConfigType;
751 aReadLock.unlock();
752 // <- SAFE ----------------------------------
754 if (sRelPath.isEmpty())
755 return;
757 switch(eCfgType)
759 case E_GLOBAL :
760 case E_MODULES :
762 m_aSharedStorages->m_lStoragesUser.removeStorageListener(pListener, sRelPath);
764 break;
766 case E_DOCUMENT :
768 m_lDocumentStorages.removeStorageListener(pListener, sRelPath);
770 break;
774 //-----------------------------------------------
775 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openPathIgnoringErrors(const OUString& sPath ,
776 sal_Int32 eMode ,
777 sal_Bool bShare)
779 css::uno::Reference< css::embed::XStorage > xPath;
782 if (bShare)
783 xPath = m_aSharedStorages->m_lStoragesShare.openPath(sPath, eMode);
784 else
785 xPath = m_aSharedStorages->m_lStoragesUser.openPath(sPath, eMode);
787 catch(const css::uno::RuntimeException&)
788 { throw; }
789 catch(const css::uno::Exception&)
790 { xPath.clear(); }
791 return xPath;
794 //-----------------------------------------------
795 ::std::vector< OUString >::const_iterator PresetHandler::impl_findMatchingLocalizedValue(
796 const ::std::vector< OUString >& lLocalizedValues,
797 OUString& rLanguageTag,
798 sal_Bool bAllowFallbacks )
800 ::std::vector< OUString >::const_iterator pFound = lLocalizedValues.end();
801 if (bAllowFallbacks)
803 pFound = LanguageTag::getFallback(lLocalizedValues, rLanguageTag);
804 // if we found a valid locale ... take it over to our in/out parameter
805 // rLanguageTag
806 if (pFound != lLocalizedValues.end())
808 rLanguageTag = *pFound;
811 else
813 for ( pFound = lLocalizedValues.begin();
814 pFound != lLocalizedValues.end() ;
815 ++pFound )
817 if (*pFound == rLanguageTag)
818 break;
822 return pFound;
825 //-----------------------------------------------
826 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openLocalizedPathIgnoringErrors(
827 OUString& sPath ,
828 sal_Int32 eMode ,
829 sal_Bool bShare ,
830 OUString& rLanguageTag ,
831 sal_Bool bAllowFallback)
833 css::uno::Reference< css::embed::XStorage > xPath = impl_openPathIgnoringErrors(sPath, eMode, bShare);
834 ::std::vector< OUString > lSubFolders = impl_getSubFolderNames(xPath);
835 ::std::vector< OUString >::const_iterator pLocaleFolder = impl_findMatchingLocalizedValue(lSubFolders, rLanguageTag, bAllowFallback);
837 // no fallback ... creation not allowed => no storage
838 if (
839 (pLocaleFolder == lSubFolders.end() ) &&
840 ((eMode & css::embed::ElementModes::NOCREATE) == css::embed::ElementModes::NOCREATE)
842 return css::uno::Reference< css::embed::XStorage >();
844 // it doesnt matter, if there is a locale fallback or not
845 // If creation of storages is allowed, we do it anyway.
846 // Otherwhise we have no acc config at all, which can make other trouble.
847 OUString sLocalizedPath;
848 sLocalizedPath = sPath;
849 sLocalizedPath += PATH_SEPARATOR;
850 if (pLocaleFolder != lSubFolders.end())
851 sLocalizedPath += *pLocaleFolder;
852 else
853 sLocalizedPath += rLanguageTag;
855 css::uno::Reference< css::embed::XStorage > xLocalePath = impl_openPathIgnoringErrors(sLocalizedPath, eMode, bShare);
857 if (xLocalePath.is())
858 sPath = sLocalizedPath;
859 else
860 sPath = OUString();
862 return xLocalePath;
865 //-----------------------------------------------
866 ::std::vector< OUString > PresetHandler::impl_getSubFolderNames(const css::uno::Reference< css::embed::XStorage >& xFolder)
868 css::uno::Reference< css::container::XNameAccess > xAccess(xFolder, css::uno::UNO_QUERY);
869 if (!xAccess.is())
870 return ::std::vector< OUString >();
872 ::std::vector< OUString > lSubFolders;
873 const css::uno::Sequence< OUString > lNames = xAccess->getElementNames();
874 const OUString* pNames = lNames.getConstArray();
875 sal_Int32 c = lNames.getLength();
876 sal_Int32 i = 0;
878 for (i=0; i<c; ++i)
882 if (xFolder->isStorageElement(pNames[i]))
883 lSubFolders.push_back(pNames[i]);
885 catch(const css::uno::RuntimeException&)
886 { throw; }
887 catch(const css::uno::Exception&)
891 return lSubFolders;
894 //-----------------------------------------------
895 } // namespace framework
897 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */