merge the formfield patch from ooo-build
[ooovba.git] / framework / source / accelerators / presethandler.cxx
blob0937ee0888a9e17b7dc16e56545567ad62180a01
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: presethandler.cxx,v $
10 * $Revision: 1.17.82.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
33 #include <accelerators/presethandler.hxx>
35 //_______________________________________________
36 // own includes
37 #include <classes/fwkresid.hxx>
39 #include "classes/resource.hrc"
40 #include <threadhelp/readguard.hxx>
41 #include <threadhelp/writeguard.hxx>
42 #include <services.h>
44 //_______________________________________________
45 // interface includes
47 #ifndef __COM_SUN_STAR_CONFIGURATION_CORRUPTEDUICONFIGURATIONEXCEPTION_HPP_
48 #include <com/sun/star/configuration/CorruptedUIConfigurationException.hpp>
49 #endif
51 #ifndef __COM_SUN_STAR_CONTAINER_NOSUCHELEMENTEXCEPTION_HPP_
52 #include <com/sun/star/container/NoSuchElementException.hpp>
53 #endif
55 #ifndef __COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
56 #include <com/sun/star/container/XNameAccess.hpp>
57 #endif
59 #ifndef __COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
60 #include <com/sun/star/beans/XPropertySet.hpp>
61 #endif
63 #ifndef __COM_SUN_STAR_EMBED_ELEMENTMODES_HPP_
64 #include <com/sun/star/embed/ElementModes.hpp>
65 #endif
67 #ifndef __COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_
68 #include <com/sun/star/embed/XTransactedObject.hpp>
69 #endif
71 #ifndef __COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
72 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
73 #endif
75 //_______________________________________________
76 // other includes
77 #include <vcl/svapp.hxx>
79 #ifndef _RTL_USTRBUF_HXX
80 #include <rtl/ustrbuf.hxx>
81 #endif
83 //_______________________________________________
84 // const
86 #define SUBSTORAGE_GLOBAL DECLARE_ASCII("global" )
87 #define SUBSTORAGE_MODULES DECLARE_ASCII("modules")
89 #define BASEPATH_SHARE_LAYER DECLARE_ASCII("UIConfig" )
90 #define BASEPATH_USER_LAYER DECLARE_ASCII("UserConfig")
92 #define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg")
93 #define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg")
94 // #define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg/uiconfig.zip")
95 // #define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg/uiconfig.zip")
97 #define FILE_EXTENSION DECLARE_ASCII(".xml")
99 #define PATH_SEPERATOR DECLARE_ASCII("/")
101 static const ::sal_Int32 ID_CORRUPT_UICONFIG_SHARE = 1;
102 static const ::sal_Int32 ID_CORRUPT_UICONFIG_USER = 2;
103 static const ::sal_Int32 ID_CORRUPT_UICONFIG_GENERAL = 3;
105 //_______________________________________________
106 // namespace
108 namespace framework
111 //-----------------------------------------------
112 ::rtl::OUString PresetHandler::PRESET_DEFAULT()
114 static ::rtl::OUString RSTYPE = DECLARE_ASCII("default");
115 return RSTYPE;
118 //-----------------------------------------------
119 ::rtl::OUString PresetHandler::TARGET_CURRENT()
121 static ::rtl::OUString RSTYPE = DECLARE_ASCII("current");
122 return RSTYPE;
125 //-----------------------------------------------
126 ::rtl::OUString PresetHandler::RESOURCETYPE_MENUBAR()
128 static ::rtl::OUString RSTYPE = DECLARE_ASCII("menubar");
129 return RSTYPE;
132 //-----------------------------------------------
133 ::rtl::OUString PresetHandler::RESOURCETYPE_TOOLBAR()
135 static ::rtl::OUString RSTYPE = DECLARE_ASCII("toolbar");
136 return RSTYPE;
139 //-----------------------------------------------
140 ::rtl::OUString PresetHandler::RESOURCETYPE_ACCELERATOR()
142 static ::rtl::OUString RSTYPE = DECLARE_ASCII("accelerator");
143 return RSTYPE;
146 //-----------------------------------------------
147 ::rtl::OUString PresetHandler::RESOURCETYPE_STATUSBAR()
149 static ::rtl::OUString RSTYPE = DECLARE_ASCII("statusbar");
150 return RSTYPE;
153 //-----------------------------------------------
154 PresetHandler::PresetHandler(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
155 : ThreadHelpBase (&Application::GetSolarMutex() )
156 , m_xSMGR (xSMGR )
157 , m_aSharedStorages ( )
158 , m_lDocumentStorages(xSMGR )
159 , m_aLocale (::comphelper::Locale::X_NOTRANSLATE())
163 //-----------------------------------------------
164 PresetHandler::PresetHandler(const PresetHandler& rCopy)
165 : ThreadHelpBase (&Application::GetSolarMutex() )
167 m_xSMGR = rCopy.m_xSMGR;
168 m_eConfigType = rCopy.m_eConfigType;
169 m_sResourceType = rCopy.m_sResourceType;
170 m_sModule = rCopy.m_sModule;
171 m_aSharedStorages = rCopy.m_aSharedStorages;
172 m_xWorkingStorageShare = rCopy.m_xWorkingStorageShare;
173 m_xWorkingStorageNoLang = rCopy.m_xWorkingStorageNoLang;
174 m_xWorkingStorageUser = rCopy.m_xWorkingStorageUser;
175 m_lPresets = rCopy.m_lPresets;
176 m_lTargets = rCopy.m_lTargets;
177 m_aLocale = rCopy.m_aLocale;
178 m_lDocumentStorages = rCopy.m_lDocumentStorages;
179 m_sRelPathShare = rCopy.m_sRelPathShare;
180 m_sRelPathNoLang = rCopy.m_sRelPathNoLang;
181 m_sRelPathUser = rCopy.m_sRelPathUser;
184 //-----------------------------------------------
185 PresetHandler::~PresetHandler()
187 m_xWorkingStorageShare.clear();
188 m_xWorkingStorageNoLang.clear();
189 m_xWorkingStorageUser.clear();
191 /* #i46497#
192 Dont call forgetCachedStorages() here for shared storages.
193 Because we opened different sub storages by using openPath().
194 And every already open path was reused and referenced (means it's
195 ref count was increased!)
196 So now we have to release our ref counts to these shared storages
197 only ... and not to free all used storages.
198 Otherwise we will disconnect all other open configuration access
199 objects which base on these storages.
201 m_aSharedStorages->m_lStoragesShare.closePath(m_sRelPathShare);
202 m_aSharedStorages->m_lStoragesUser.closePath (m_sRelPathUser );
204 /* On the other side closePath() is not needed for our special handled
205 document storage. Because it's not shared with others ... so we can
206 free it.
208 m_lDocumentStorages.forgetCachedStorages();
211 //-----------------------------------------------
212 void PresetHandler::forgetCachedStorages()
214 // SAFE -> ----------------------------------
215 WriteGuard aWriteLock(m_aLock);
217 if (m_eConfigType == E_DOCUMENT)
219 m_xWorkingStorageShare.clear();
220 m_xWorkingStorageNoLang.clear();
221 m_xWorkingStorageUser.clear();
224 m_lDocumentStorages.forgetCachedStorages();
226 aWriteLock.unlock();
227 // <- SAFE ----------------------------------
230 //-----------------------------------------------
231 ::rtl::OUString lcl_getLocalizedMessage(::sal_Int32 nID)
233 ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("Unknown error.");
235 switch(nID)
237 case ID_CORRUPT_UICONFIG_SHARE :
238 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_SHARE )));
239 break;
241 case ID_CORRUPT_UICONFIG_USER :
242 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_USER )));
243 break;
245 case ID_CORRUPT_UICONFIG_GENERAL :
246 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_GENERAL )));
247 break;
250 return sMessage;
253 //-----------------------------------------------
254 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageShare()
256 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesShare.getRootStorage();
257 if (xRoot.is())
258 return xRoot;
260 // SAFE -> ----------------------------------
261 ReadGuard aReadLock(m_aLock);
262 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
263 aReadLock.unlock();
264 // <- SAFE ----------------------------------
266 css::uno::Reference< css::beans::XPropertySet > xPathSettings(
267 xSMGR->createInstance(SERVICENAME_PATHSETTINGS),
268 css::uno::UNO_QUERY_THROW);
270 ::rtl::OUString sShareLayer;
271 xPathSettings->getPropertyValue(BASEPATH_SHARE_LAYER) >>= sShareLayer;
273 // "UIConfig" is a "multi path" ... use first part only here!
274 sal_Int32 nPos = sShareLayer.indexOf(';');
275 if (nPos > 0)
276 sShareLayer = sShareLayer.copy(0, nPos);
278 // Note: May be an user uses URLs without a final slash! Check it ...
279 nPos = sShareLayer.lastIndexOf('/');
280 if (nPos != sShareLayer.getLength()-1)
281 sShareLayer += ::rtl::OUString::createFromAscii("/");
283 sShareLayer += RELPATH_SHARE_LAYER; // folder
285 // TODO remove me!
286 // Attention: This is temp. workaround ... We create a temp. storage file
287 // based of a sytem directory. This must be used so, till the storage implementation
288 // can work on directories too.
290 css::uno::Sequence< css::uno::Any > lArgs(2);
291 lArgs[0] <<= sShareLayer;
292 lArgs[1] <<= css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE;
294 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory(xSMGR->createInstance(SERVICENAME_FILESYSTEMSTORAGEFACTORY) , css::uno::UNO_QUERY_THROW);
295 css::uno::Reference< css::embed::XStorage > xStorage;
299 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
301 catch(const css::uno::Exception& ex)
303 throw css::configuration::CorruptedUIConfigurationException(
304 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_SHARE),
305 css::uno::Reference< css::uno::XInterface >(),
306 ex.Message);
309 m_aSharedStorages->m_lStoragesShare.setRootStorage(xStorage);
311 return xStorage;
314 //-----------------------------------------------
315 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageUser()
317 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesUser.getRootStorage();
318 if (xRoot.is())
319 return xRoot;
321 // SAFE -> ----------------------------------
322 ReadGuard aReadLock(m_aLock);
323 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
324 aReadLock.unlock();
325 // <- SAFE ----------------------------------
327 css::uno::Reference< css::beans::XPropertySet > xPathSettings(
328 xSMGR->createInstance(SERVICENAME_PATHSETTINGS),
329 css::uno::UNO_QUERY_THROW);
331 ::rtl::OUString sUserLayer;
332 xPathSettings->getPropertyValue(BASEPATH_USER_LAYER) >>= sUserLayer ;
334 // Note: May be an user uses URLs without a final slash! Check it ...
335 sal_Int32 nPos = sUserLayer.lastIndexOf('/');
336 if (nPos != sUserLayer.getLength()-1)
337 sUserLayer += ::rtl::OUString::createFromAscii("/");
339 sUserLayer += RELPATH_USER_LAYER; // storage file
341 css::uno::Sequence< css::uno::Any > lArgs(2);
342 lArgs[0] <<= sUserLayer;
343 lArgs[1] <<= css::embed::ElementModes::READWRITE;
345 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory(xSMGR->createInstance(SERVICENAME_FILESYSTEMSTORAGEFACTORY) , css::uno::UNO_QUERY_THROW);
346 css::uno::Reference< css::embed::XStorage > xStorage;
350 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
352 catch(const css::uno::Exception& ex)
354 throw css::configuration::CorruptedUIConfigurationException(
355 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_USER),
356 css::uno::Reference< css::uno::XInterface >(),
357 ex.Message);
360 m_aSharedStorages->m_lStoragesUser.setRootStorage(xStorage);
362 return xStorage;
365 //-----------------------------------------------
366 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageShare()
368 // SAFE -> ----------------------------------
369 ReadGuard aReadLock(m_aLock);
370 return m_xWorkingStorageShare;
371 // <- SAFE ----------------------------------
374 //-----------------------------------------------
375 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageUser()
377 // SAFE -> ----------------------------------
378 ReadGuard aReadLock(m_aLock);
379 return m_xWorkingStorageUser;
380 // <- SAFE ----------------------------------
383 //-----------------------------------------------
384 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageShare(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
386 // SAFE -> ----------------------------------
387 ReadGuard aReadLock(m_aLock);
388 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageShare;
389 aReadLock.unlock();
390 // <- SAFE ----------------------------------
392 return m_aSharedStorages->m_lStoragesShare.getParentStorage(xWorking);
395 //-----------------------------------------------
396 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageUser(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
398 // SAFE -> ----------------------------------
399 ReadGuard aReadLock(m_aLock);
400 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser;
401 aReadLock.unlock();
402 // <- SAFE ----------------------------------
404 return m_aSharedStorages->m_lStoragesUser.getParentStorage(xWorking);
407 //-----------------------------------------------
408 void PresetHandler::connectToResource( PresetHandler::EConfigType eConfigType ,
409 const ::rtl::OUString& sResource ,
410 const ::rtl::OUString& sModule ,
411 const css::uno::Reference< css::embed::XStorage >& xDocumentRoot,
412 const ::comphelper::Locale& aLocale )
414 // TODO free all current open storages!
416 // SAFE -> ----------------------------------
417 WriteGuard aWriteLock(m_aLock);
419 m_eConfigType = eConfigType ;
420 m_sResourceType = sResource ;
421 m_sModule = sModule ;
422 m_aLocale = aLocale ;
424 aWriteLock.unlock();
425 // <- SAFE ----------------------------------
427 css::uno::Reference< css::embed::XStorage > xShare;
428 css::uno::Reference< css::embed::XStorage > xNoLang;
429 css::uno::Reference< css::embed::XStorage > xUser;
431 // special case for documents
432 // use outside root storage, if we run in E_DOCUMENT mode!
433 if (eConfigType == E_DOCUMENT)
435 if (!xDocumentRoot.is())
436 throw css::uno::RuntimeException(
437 ::rtl::OUString::createFromAscii("There is valid root storage, where the UI configuration can work on."),
438 css::uno::Reference< css::uno::XInterface >());
439 m_lDocumentStorages.setRootStorage(xDocumentRoot);
440 xShare = xDocumentRoot;
441 xUser = xDocumentRoot;
443 else
445 xShare = getOrCreateRootStorageShare();
446 xUser = getOrCreateRootStorageUser();
449 // #...#
453 // a) inside share layer we should not create any new structures ... We jave to use
454 // existing ones only!
455 // b) inside user layer we can (SOFT mode!) but sometimes we shouldnt (HARD mode!)
456 // create new empty structures. We should preferr using of any existing structure.
457 sal_Int32 eShareMode = (css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE);
458 sal_Int32 eUserMode = (css::embed::ElementModes::READWRITE );
460 ::rtl::OUStringBuffer sRelPathBuf(1024);
461 ::rtl::OUString sRelPathShare;
462 ::rtl::OUString sRelPathNoLang;
463 ::rtl::OUString sRelPathUser;
464 switch(eConfigType)
466 case E_GLOBAL :
468 sRelPathBuf.append(SUBSTORAGE_GLOBAL);
469 sRelPathBuf.append(PATH_SEPERATOR );
470 sRelPathBuf.append(sResource );
471 sRelPathShare = sRelPathBuf.makeStringAndClear();
472 sRelPathUser = sRelPathShare;
474 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True );
475 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False);
477 break;
479 case E_MODULES :
481 sRelPathBuf.append(SUBSTORAGE_MODULES);
482 sRelPathBuf.append(PATH_SEPERATOR );
483 sRelPathBuf.append(sModule );
484 sRelPathBuf.append(PATH_SEPERATOR );
485 sRelPathBuf.append(sResource );
486 sRelPathShare = sRelPathBuf.makeStringAndClear();
487 sRelPathUser = sRelPathShare;
489 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True );
490 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False);
492 break;
494 case E_DOCUMENT :
496 // A document does not have a share layer in real.
497 // It has one layer only, and this one should be opened READ_WRITE.
498 // So we open the user layer here only and set the share layer equals to it .-)
500 sRelPathBuf.append(sResource);
501 sRelPathUser = sRelPathBuf.makeStringAndClear();
502 sRelPathShare = sRelPathUser;
506 xUser = m_lDocumentStorages.openPath(sRelPathUser , eUserMode );
507 xShare = xUser;
509 catch(const css::uno::RuntimeException& exRun)
510 { throw exRun; }
511 catch(const css::uno::Exception&)
512 { xShare.clear(); xUser.clear(); }
514 break;
517 // Non-localized global share
518 xNoLang = xShare;
519 sRelPathNoLang = sRelPathShare;
521 if (
522 (aLocale != ::comphelper::Locale::X_NOTRANSLATE()) && // localized level?
523 (eConfigType != E_DOCUMENT ) // no localization in document mode!
526 // First try to find the right localized set inside share layer.
527 // Fallbacks are allowed there.
528 ::comphelper::Locale aShareLocale = aLocale ;
529 ::rtl::OUString sLocalizedSharePath(sRelPathShare);
530 sal_Bool bAllowFallbacks = sal_True ;
531 xShare = impl_openLocalizedPathIgnoringErrors(sLocalizedSharePath, eShareMode, sal_True , aShareLocale, bAllowFallbacks);
533 // The try to locate the right sub dir inside user layer ... without using fallbacks!
534 // Normaly the corresponding sub dir should be created matching the specified locale.
535 // Because we allow creation of storages inside user layer by default.
536 ::comphelper::Locale aUserLocale = aLocale ;
537 ::rtl::OUString sLocalizedUserPath(sRelPathUser);
538 bAllowFallbacks = sal_False ;
539 xUser = impl_openLocalizedPathIgnoringErrors(sLocalizedUserPath, eUserMode , sal_False, aUserLocale, bAllowFallbacks);
541 sRelPathShare = sLocalizedSharePath;
542 sRelPathUser = sLocalizedUserPath ;
545 // read content of level 3 (presets, targets)
546 css::uno::Reference< css::container::XNameAccess > xAccess ;
547 css::uno::Sequence< ::rtl::OUString > lNames ;
548 const ::rtl::OUString* pNames ;
549 sal_Int32 c ;
550 sal_Int32 i ;
551 OUStringList lPresets;
552 OUStringList lTargets;
554 // read preset names of share layer
555 xAccess = css::uno::Reference< css::container::XNameAccess >(xShare, css::uno::UNO_QUERY);
556 if (xAccess.is())
558 lNames = xAccess->getElementNames();
559 pNames = lNames.getConstArray();
560 c = lNames.getLength();
562 for (i=0; i<c; ++i)
564 ::rtl::OUString sTemp = pNames[i];
565 sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION);
566 if (nPos > -1)
567 sTemp = sTemp.copy(0,nPos);
568 lPresets.push_back(sTemp);
572 // read preset names of user layer
573 xAccess = css::uno::Reference< css::container::XNameAccess >(xUser, css::uno::UNO_QUERY);
574 if (xAccess.is())
576 lNames = xAccess->getElementNames();
577 pNames = lNames.getConstArray();
578 c = lNames.getLength();
580 for (i=0; i<c; ++i)
582 ::rtl::OUString sTemp = pNames[i];
583 sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION);
584 if (nPos > -1)
585 sTemp = sTemp.copy(0,nPos);
586 lTargets.push_back(sTemp);
590 // SAFE -> ----------------------------------
591 aWriteLock.lock();
593 m_xWorkingStorageShare = xShare ;
594 m_xWorkingStorageNoLang= xNoLang;
595 m_xWorkingStorageUser = xUser ;
596 m_lPresets = lPresets;
597 m_lTargets = lTargets;
598 m_sRelPathShare = sRelPathShare;
599 m_sRelPathNoLang = sRelPathNoLang;
600 m_sRelPathUser = sRelPathUser;
602 aWriteLock.unlock();
603 // <- SAFE ----------------------------------
606 catch(const css::uno::Exception& ex)
608 throw css::configuration::CorruptedUIConfigurationException(
609 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_GENERAL),
610 css::uno::Reference< css::uno::XInterface >(),
611 ex.Message);
615 //-----------------------------------------------
616 void PresetHandler::copyPresetToTarget(const ::rtl::OUString& sPreset,
617 const ::rtl::OUString& sTarget)
619 // dont check our preset list, if element exists
620 // We try to open it and forward all errors to the user!
622 // SAFE -> ----------------------------------
623 ReadGuard aReadLock(m_aLock);
624 css::uno::Reference< css::embed::XStorage > xWorkingShare = m_xWorkingStorageShare;
625 css::uno::Reference< css::embed::XStorage > xWorkingNoLang= m_xWorkingStorageNoLang;
626 css::uno::Reference< css::embed::XStorage > xWorkingUser = m_xWorkingStorageUser ;
627 aReadLock.unlock();
628 // <- SAFE ----------------------------------
630 // e.g. module without any config data ?!
631 if (
632 (!xWorkingShare.is()) ||
633 (!xWorkingUser.is() )
636 return;
639 ::rtl::OUString sPresetFile(sPreset);
640 sPresetFile += FILE_EXTENSION;
642 ::rtl::OUString sTargetFile(sTarget);
643 sTargetFile += FILE_EXTENSION;
645 // remove existing elements before you try to copy the preset to that location ...
646 // Otherwise w will get an ElementExistException inside copyElementTo()!
647 css::uno::Reference< css::container::XNameAccess > xCheckingUser(xWorkingUser, css::uno::UNO_QUERY_THROW);
648 if (xCheckingUser->hasByName(sTargetFile))
649 xWorkingUser->removeElement(sTargetFile);
651 xWorkingShare->copyElementTo(sPresetFile, xWorkingUser, sTargetFile);
653 // If our storages work in transacted mode, we have
654 // to commit all changes from bottom to top!
655 commitUserChanges();
658 //-----------------------------------------------
659 css::uno::Reference< css::io::XStream > PresetHandler::openPreset(const ::rtl::OUString& sPreset,
660 sal_Bool bUseNoLangGlobal)
662 // SAFE -> ----------------------------------
663 ReadGuard aReadLock(m_aLock);
664 css::uno::Reference< css::embed::XStorage > xFolder = bUseNoLangGlobal? m_xWorkingStorageNoLang: m_xWorkingStorageShare;
665 aReadLock.unlock();
666 // <- SAFE ----------------------------------
668 // e.g. module without any config data ?!
669 if (!xFolder.is())
670 return css::uno::Reference< css::io::XStream >();
672 ::rtl::OUString sFile(sPreset);
673 sFile += FILE_EXTENSION;
675 // inform user about errors (use original exceptions!)
676 css::uno::Reference< css::io::XStream > xStream = xFolder->openStreamElement(sFile, css::embed::ElementModes::READ);
677 return xStream;
680 //-----------------------------------------------
681 css::uno::Reference< css::io::XStream > PresetHandler::openTarget(const ::rtl::OUString& sTarget ,
682 sal_Bool bCreateIfMissing)
684 // SAFE -> ----------------------------------
685 ReadGuard aReadLock(m_aLock);
686 css::uno::Reference< css::embed::XStorage > xFolder = m_xWorkingStorageUser;
687 aReadLock.unlock();
688 // <- SAFE ----------------------------------
690 // e.g. module without any config data ?!
691 if (!xFolder.is())
692 return css::uno::Reference< css::io::XStream >();
694 ::rtl::OUString sFile(sTarget);
695 sFile += FILE_EXTENSION;
697 sal_Int32 nOpenMode = css::embed::ElementModes::READWRITE;
698 if (!bCreateIfMissing)
699 nOpenMode |= css::embed::ElementModes::NOCREATE;
701 // try it in read/write mode first and ignore errors.
702 css::uno::Reference< css::io::XStream > xStream;
705 xStream = xFolder->openStreamElement(sFile, nOpenMode);
706 return xStream;
708 catch(const css::uno::RuntimeException&)
709 { throw; }
710 catch(const css::uno::Exception&)
711 { xStream.clear(); }
713 // try it readonly if it failed before.
714 // inform user about errors (use original exceptions!)
715 nOpenMode &= ~css::embed::ElementModes::WRITE;
716 xStream = xFolder->openStreamElement(sFile, nOpenMode);
718 return xStream;
721 //-----------------------------------------------
722 void PresetHandler::commitUserChanges()
724 // SAFE -> ----------------------------------
725 ReadGuard aReadLock(m_aLock);
726 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser;
727 EConfigType eCfgType = m_eConfigType;
728 aReadLock.unlock();
729 // <- SAFE ----------------------------------
731 // e.g. module without any config data ?!
732 if (!xWorking.is())
733 return;
735 ::rtl::OUString sPath;
737 switch(eCfgType)
739 case E_GLOBAL :
740 case E_MODULES :
742 sPath = m_aSharedStorages->m_lStoragesUser.getPathOfStorage(xWorking);
743 m_aSharedStorages->m_lStoragesUser.commitPath(sPath);
744 m_aSharedStorages->m_lStoragesUser.notifyPath(sPath);
746 break;
748 case E_DOCUMENT :
750 sPath = m_lDocumentStorages.getPathOfStorage(xWorking);
751 m_lDocumentStorages.commitPath(sPath);
752 m_lDocumentStorages.notifyPath(sPath);
754 break;
758 //-----------------------------------------------
759 void PresetHandler::addStorageListener(IStorageListener* pListener)
761 // SAFE -> ----------------------------------
762 ReadGuard aReadLock(m_aLock);
763 ::rtl::OUString sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer!
764 EConfigType eCfgType = m_eConfigType;
765 aReadLock.unlock();
766 // <- SAFE ----------------------------------
768 if (!sRelPath.getLength())
769 return;
771 switch(eCfgType)
773 case E_GLOBAL :
774 case E_MODULES :
776 m_aSharedStorages->m_lStoragesUser.addStorageListener(pListener, sRelPath);
778 break;
780 case E_DOCUMENT :
782 m_lDocumentStorages.addStorageListener(pListener, sRelPath);
784 break;
788 //-----------------------------------------------
789 void PresetHandler::removeStorageListener(IStorageListener* pListener)
791 // SAFE -> ----------------------------------
792 ReadGuard aReadLock(m_aLock);
793 ::rtl::OUString sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer!
794 EConfigType eCfgType = m_eConfigType;
795 aReadLock.unlock();
796 // <- SAFE ----------------------------------
798 if (!sRelPath.getLength())
799 return;
801 switch(eCfgType)
803 case E_GLOBAL :
804 case E_MODULES :
806 m_aSharedStorages->m_lStoragesUser.removeStorageListener(pListener, sRelPath);
808 break;
810 case E_DOCUMENT :
812 m_lDocumentStorages.removeStorageListener(pListener, sRelPath);
814 break;
818 //-----------------------------------------------
819 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openPathIgnoringErrors(const ::rtl::OUString& sPath ,
820 sal_Int32 eMode ,
821 sal_Bool bShare)
823 css::uno::Reference< css::embed::XStorage > xPath;
826 if (bShare)
827 xPath = m_aSharedStorages->m_lStoragesShare.openPath(sPath, eMode);
828 else
829 xPath = m_aSharedStorages->m_lStoragesUser.openPath(sPath, eMode);
831 catch(const css::uno::RuntimeException& exRun)
832 { throw exRun; }
833 catch(const css::uno::Exception&)
834 { xPath.clear(); }
835 return xPath;
838 //-----------------------------------------------
839 ::std::vector< ::rtl::OUString >::const_iterator PresetHandler::impl_findMatchingLocalizedValue(const ::std::vector< ::rtl::OUString >& lLocalizedValues,
840 ::comphelper::Locale& aLocale ,
841 sal_Bool bAllowFallbacks )
843 ::std::vector< ::rtl::OUString >::const_iterator pFound = lLocalizedValues.end();
844 if (bAllowFallbacks)
846 pFound = ::comphelper::Locale::getFallback(lLocalizedValues, aLocale.toISO());
848 else
850 for ( pFound = lLocalizedValues.begin();
851 pFound != lLocalizedValues.end() ;
852 ++pFound )
854 const ::rtl::OUString& sCheckISO = *pFound;
855 ::comphelper::Locale aCheckLocale(sCheckISO);
856 if (aCheckLocale.equals(aLocale))
857 break;
861 // if we found a valid locale ... take it over to our in/out parameter aLocale
862 if (pFound != lLocalizedValues.end())
864 const ::rtl::OUString& sISOLocale = *pFound;
865 aLocale.fromISO(sISOLocale);
868 return pFound;
871 //-----------------------------------------------
872 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openLocalizedPathIgnoringErrors(::rtl::OUString& sPath ,
873 sal_Int32 eMode ,
874 sal_Bool bShare ,
875 ::comphelper::Locale& aLocale ,
876 sal_Bool bAllowFallback)
878 css::uno::Reference< css::embed::XStorage > xPath = impl_openPathIgnoringErrors(sPath, eMode, bShare);
879 ::std::vector< ::rtl::OUString > lSubFolders = impl_getSubFolderNames(xPath);
880 ::std::vector< ::rtl::OUString >::const_iterator pLocaleFolder = impl_findMatchingLocalizedValue(lSubFolders, aLocale, bAllowFallback);
882 // no fallback ... creation not allowed => no storage
883 if (
884 (pLocaleFolder == lSubFolders.end() ) &&
885 ((eMode & css::embed::ElementModes::NOCREATE) == css::embed::ElementModes::NOCREATE)
887 return css::uno::Reference< css::embed::XStorage >();
889 // it doesnt matter, if there is a locale fallback or not
890 // If creation of storages is allowed, we do it anyway.
891 // Otherwhise we have no acc config at all, which can make other trouble.
892 ::rtl::OUString sLocalizedPath;
893 sLocalizedPath = sPath;
894 sLocalizedPath += PATH_SEPERATOR;
895 if (pLocaleFolder != lSubFolders.end())
896 sLocalizedPath += *pLocaleFolder;
897 else
898 sLocalizedPath += aLocale.toISO();
900 css::uno::Reference< css::embed::XStorage > xLocalePath = impl_openPathIgnoringErrors(sLocalizedPath, eMode, bShare);
902 if (xLocalePath.is())
903 sPath = sLocalizedPath;
904 else
905 sPath = ::rtl::OUString();
907 return xLocalePath;
910 //-----------------------------------------------
911 ::std::vector< ::rtl::OUString > PresetHandler::impl_getSubFolderNames(const css::uno::Reference< css::embed::XStorage >& xFolder)
913 css::uno::Reference< css::container::XNameAccess > xAccess(xFolder, css::uno::UNO_QUERY);
914 if (!xAccess.is())
915 return ::std::vector< ::rtl::OUString >();
917 ::std::vector< ::rtl::OUString > lSubFolders;
918 const css::uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames();
919 const ::rtl::OUString* pNames = lNames.getConstArray();
920 sal_Int32 c = lNames.getLength();
921 sal_Int32 i = 0;
923 for (i=0; i<c; ++i)
927 if (xFolder->isStorageElement(pNames[i]))
928 lSubFolders.push_back(pNames[i]);
930 catch(const css::uno::RuntimeException& exRun)
931 { throw exRun; }
932 catch(const css::uno::Exception&)
936 return lSubFolders;
939 //-----------------------------------------------
940 } // namespace framework