xref: /AOO41X/main/framework/source/accelerators/presethandler.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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