1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef __FRAMEWORK_ACCELERATORS_PRESETHANDLER_HXX_
25 #define __FRAMEWORK_ACCELERATORS_PRESETHANDLER_HXX_
26 
27 //__________________________________________
28 // own includes
29 
30 #include <accelerators/storageholder.hxx>
31 #include <threadhelp/threadhelpbase.hxx>
32 #include <general.h>
33 #include <stdtypes.h>
34 
35 //__________________________________________
36 // interface includes
37 
38 #ifndef __COM_SUN_STAR_EMBED_XSTORAGE_HPP_
39 #include <com/sun/star/embed/XStorage.hpp>
40 #endif
41 
42 #ifndef __COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
43 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
44 #endif
45 
46 //__________________________________________
47 // other includes
48 #include <comphelper/processfactory.hxx>
49 #include <salhelper/singletonref.hxx>
50 #include <comphelper/locale.hxx>
51 
52 //__________________________________________
53 // definition
54 
55 namespace framework
56 {
57 
58 //__________________________________________
59 /**
60     TODO document me
61 
62         <layer>/global/<resourcetype>/<preset>.xml
63         <layer>/modules/<moduleid>/<resourcetype>/<preset>.xml
64 
65         RESOURCETYPE        PRESET        TARGET
66                             (share)       (user)
67         "accelerator"       "default"     "current"
68                             "word"
69                             "excel"
70 
71         "menubar"           "default"     "menubar"
72 
73  */
74 class PresetHandler : private ThreadHelpBase // attention! Must be the first base class to guarantee right initialize lock ...
75 {
76     //-------------------------------------------
77     // const
78 
79     public:
80 
81         static ::rtl::OUString PRESET_DEFAULT();
82         static ::rtl::OUString TARGET_CURRENT();
83 
84         static ::rtl::OUString RESOURCETYPE_MENUBAR();
85         static ::rtl::OUString RESOURCETYPE_TOOLBAR();
86         static ::rtl::OUString RESOURCETYPE_ACCELERATOR();
87         static ::rtl::OUString RESOURCETYPE_STATUSBAR();
88 
89     //-------------------------------------------
90     // types
91 
92     public:
93 
94         //---------------------------------------
95         /** @short  this handler can provide different
96                     types of configuration.
97 
98             @descr  Means: a global or a module dependent
99                     or ... configuration.
100          */
101         enum EConfigType
102         {
103             E_GLOBAL,
104             E_MODULES,
105             E_DOCUMENT
106         };
107 
108     private:
109 
110         //---------------------------------------
111         /** @short  because a concurrent access to the same storage from different implementations
112                     isn't supported, we have to share it with others.
113 
114             @descr  This struct makes it possible to use any shared storage
115                     in combination with a SingletonRef<> template ...
116 
117                     Attention: Because these struct is shared it must be
118                     used within a synchronized section. That's why this struct
119                     uses a base class ThreadHelpBase and can be locked
120                     from outside doing so!
121          */
122         struct TSharedStorages : public ThreadHelpBase
123         {
124             public:
125 
126                 StorageHolder m_lStoragesShare;
127                 StorageHolder m_lStoragesUser;
128 
TSharedStoragesframework::PresetHandler::TSharedStorages129                 TSharedStorages()
130                     : m_lStoragesShare(::comphelper::getProcessServiceFactory())
131                     , m_lStoragesUser (::comphelper::getProcessServiceFactory())
132                 {};
133 
~TSharedStoragesframework::PresetHandler::TSharedStorages134                 virtual ~TSharedStorages() {};
135         };
136 
137     //-------------------------------------------
138     // member
139 
140     private:
141 
142         //---------------------------------------
143         /** @short  can be used to create on needed uno resources. */
144         css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR;
145 
146         //---------------------------------------
147         /** @short  knows the type of provided configuration.
148 
149             @descr  e.g. global, modules, ...
150          */
151         EConfigType m_eConfigType;
152 
153         //---------------------------------------
154         /** @short  specify the type of resource, which configuration sets
155                     must be provided here.
156 
157             @descr  e.g. menubars, toolbars, accelerators
158          */
159         ::rtl::OUString m_sResourceType;
160 
161         //---------------------------------------
162         /** @short  specify the application module for a module
163                     dependent configuration.
164 
165             @descr  Will be used only, if m_sResourceType is set to
166                     "module". Further it must be a valid module identifier
167                     then ...
168          */
169         ::rtl::OUString m_sModule;
170 
171         //---------------------------------------
172         /** @short  provides access to the:
173                     a) shared root storages
174                     b) shared "inbetween" storages
175                     of the share and user layer. */
176         ::salhelper::SingletonRef< TSharedStorages > m_aSharedStorages;
177 
178         //---------------------------------------
179         /** @short  if we run in document mode, we can't use the global root storages!
180                     We have to use a special document storage explicitly. */
181         StorageHolder m_lDocumentStorages;
182 
183         //---------------------------------------
184         /** @short  holds the folder storage of the share layer alive,
185                     where the current configuration set exists.
186 
187             @descr  Note: If this preset handler works in document mode
188                     this member is meant relative to the document root ...
189                     not to the share layer root!
190 
191                     Further is defined, that m_xWorkingStorageUser
192                     is equals to m_xWorkingStorageShare then!
193          */
194         css::uno::Reference< css::embed::XStorage > m_xWorkingStorageShare;
195 
196         //---------------------------------------
197         /** @short  global language-independent storage
198          */
199         css::uno::Reference< css::embed::XStorage > m_xWorkingStorageNoLang;
200 
201         //---------------------------------------
202         /** @short  holds the folder storage of the user layer alive,
203                     where the current configuration set exists.
204 
205             @descr  Note: If this preset handler works in document mode
206                     this member is meaned relative to the document root ...
207                     not to the user layer root!
208 
209                     Further is defined, that m_xWorkingStorageUser
210                     is equals to m_xWorkingStorageShare then!
211          */
212         css::uno::Reference< css::embed::XStorage > m_xWorkingStorageUser;
213 
214         //---------------------------------------
215         /** @short  knows the names of all presets inside the current
216                     working storage of the share layer. */
217         OUStringList m_lPresets;
218 
219         //---------------------------------------
220         /** @short  knows the names of all targets inside the current
221                     working storage of the user layer. */
222         OUStringList m_lTargets;
223 
224         //---------------------------------------
225         /** @short  its the current office locale and will be used
226                     to handle localized presets.
227 
228             @descr  Default is "x-notranslate" which disable any
229                     localized handling inside this class! */
230         ::comphelper::Locale m_aLocale;
231 
232         //---------------------------------------
233         /** @short  knows the relative path from the root. */
234         ::rtl::OUString m_sRelPathShare;
235         ::rtl::OUString m_sRelPathNoLang;
236         ::rtl::OUString m_sRelPathUser;
237 
238     //-------------------------------------------
239     // native interface
240 
241     public:
242 
243         //---------------------------------------
244         /** @short  does nothing real.
245 
246             @descr  Because this class should be useable in combination
247                     with ::salhelper::SingletonRef template this ctor
248                     can't have any special parameters!
249 
250             @param  xSMGR
251                     points to an uno service manager, which is used internally
252                     to create own needed uno resources.
253          */
254         PresetHandler(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR);
255 
256         //---------------------------------------
257         /** @short  copy ctor */
258         PresetHandler(const PresetHandler& rCopy);
259 
260         //---------------------------------------
261         /** @short  closes all open storages ... if user forgot that .-) */
262         virtual ~PresetHandler();
263 
264         //---------------------------------------
265         /** @short  free all currently cache(!) storages. */
266         void forgetCachedStorages();
267 
268         //---------------------------------------
269         /** @short  return access to the internally used and cached root storage.
270 
271             @descr  These root storages are the base of all further opened
272                     presets and targets. They are provided here only, to support
273                     older implementations, which base on them ...
274 
275                     getOrCreate...() - What does it mean?
276                     Such root storage will be created one times only and
277                     cached then internally till the last instance of such PresetHandler
278                     dies.
279 
280             @return com::sun::star::embed::XStorage
281                     which represent a root storage.
282          */
283         css::uno::Reference< css::embed::XStorage > getOrCreateRootStorageShare();
284         css::uno::Reference< css::embed::XStorage > getOrCreateRootStorageUser();
285 
286         //---------------------------------------
287         /** @short  provides access to the current working storages.
288 
289             @descr  Working storages are the "lowest" storages, where the
290                     preset and target files exists.
291 
292             @return com::sun::star::embed::XStorage
293                     which the current working storage.
294          */
295         css::uno::Reference< css::embed::XStorage > getWorkingStorageShare();
296         css::uno::Reference< css::embed::XStorage > getWorkingStorageUser();
297 
298         //---------------------------------------
299         /** @short  check if there is a parent storage well known for
300                     the specified child storage and return it.
301 
302             @param  xChild
303                     the child storage where a paranet storage should be searched for.
304 
305             @return com::sun::star::embed::XStorage
306                     A valid storage if a paranet exists. NULL otherwise.
307          */
308         css::uno::Reference< css::embed::XStorage > getParentStorageShare(const css::uno::Reference< css::embed::XStorage >& xChild);
309         css::uno::Reference< css::embed::XStorage > getParentStorageUser (const css::uno::Reference< css::embed::XStorage >& xChild);
310 
311         //---------------------------------------
312         /** @short  free all internal structures and let this handler
313                     work on a new type of configuration sets.
314 
315             @param  eConfigType
316                     differ between global or module dependent configuration.
317 
318             @param  sResourceType
319                     differ between menubar/toolbar/accelerator/... configuration.
320 
321             @param  sModule
322                     if sResourceType is set to a module dependent configuration,
323                     it address the current application module.
324 
325             @param  xDocumentRoot
326                     if sResourceType is set to E_DOCUMENT, this value points to the
327                     root storage inside the document, where we can save our
328                     configuration files. Note: That's not the real root of the document ...
329                     it's only a sub storage. But we interpret it as our root storage.
330 
331             @param  aLocale
332                     in case this configuration supports localized entries,
333                     the current locale must be set.
334 
335                     Localization will be represented as directory structure
336                     of provided presets. Means: you call us with a preset name "default";
337                     and we use e.g. "/en-US/default.xml" internally.
338 
339                     If no localization exists for this preset set, this class
340                     will work in default mode - means "no locale" - automatically.
341                     e.g. "/default.xml"
342 
343             @throw  com::sun::star::uno::RuntimeException(!)
344                     if the specified resource couldn't be located.
345          */
346         void connectToResource(      EConfigType                                  eConfigType   ,
347                                const ::rtl::OUString&                             sResourceType ,
348                                const ::rtl::OUString&                             sModule       ,
349                                const css::uno::Reference< css::embed::XStorage >& xDocumentRoot ,
350                                const ::comphelper::Locale&                        aLocale       = ::comphelper::Locale(::comphelper::Locale::X_NOTRANSLATE()));
351 
352         //---------------------------------------
353         /** @short  try to copy the specified preset from the share
354                     layer to the user layer and establish it as the
355                     specified target.
356 
357             @descr  Means: copy share/.../<preset>.xml user/.../<target>.xml
358                     Note: The target will be overwritten completely or
359                     created as new by this operation!
360 
361             @param  sPreset
362                     the ALIAS name of an existing preset.
363 
364             @param  sTarget
365                     the ALIAS name of the target.
366 
367             @throw  com::sun::star::container::NoSuchElementException
368                     if the specified preset does not exists.
369 
370             @throw  com::sun::star::io::IOException
371                     if copying failed.
372          */
373         void copyPresetToTarget(const ::rtl::OUString& sPreset,
374                                 const ::rtl::OUString& sTarget);
375 
376         //---------------------------------------
377         /** @short  open the specified preset as stream object
378                     and return it.
379 
380             @descr  Note: Because presets resist inside the share
381                     layer, they will be opened readonly every time.
382 
383             @param  sPreset
384                     the ALIAS name of an existing preset.
385 
386             @param  bNoLangGlobal
387                     access the global language-independent storage instead of the preset storage
388 
389             @return The opened preset stream ... or NULL if the preset does not exists.
390          */
391         css::uno::Reference< css::io::XStream > openPreset(const ::rtl::OUString& sPreset,
392                                                            sal_Bool bUseNoLangGlobal = sal_False);
393 
394         //---------------------------------------
395         /** @short  open the specified target as stream object
396                     and return it.
397 
398             @descr  Note: Targets resist inside the user
399                     layer. Normally they are opened in read/write mode.
400                     But it will be opened readonly automatically if that isn't possible
401                     (maybe the file is write protected on the system ...).
402 
403             @param  sTarget
404                     the ALIAS name of the target.
405 
406             @param  bCreateIfMissing
407                     create target file, if it does not still exist.
408                     Note: That does not means resetting of an existing file!
409 
410             @return The opened target stream ... or NULL if the target does not exists
411                     or couldn't be created as new one.
412          */
413         css::uno::Reference< css::io::XStream > openTarget(const ::rtl::OUString& sTarget         ,
414                                                                  sal_Bool         bCreateIfMissing);
415 
416         //---------------------------------------
417         /** @short  do anything which is necessary to flush all changes
418                     back to disk.
419 
420             @descr  We have to call commit on all cached sub storages on the
421                     path from the root storage upside down to the working storage
422                     (which are not really used, but required to be held alive!).
423          */
424         void commitUserChanges();
425 
426         //---------------------------------------
427         /** TODO */
428         void addStorageListener(IStorageListener* pListener);
429         void removeStorageListener(IStorageListener* pListener);
430 
431     //-------------------------------------------
432     // helper
433 
434     private:
435 
436         //---------------------------------------
437         /** @short  open a config path ignoring errors (catching exceptions).
438 
439             @descr  We catch only normal exceptions here - no runtime exceptions.
440 
441             @param  sPath
442                     the configuration path, which should be opened.
443 
444             @param  eMode
445                     the open mode (READ/READWRITE)
446 
447             @param  bShare
448                     force using of the share layer instead of the user layer.
449 
450             @return An opened storage in case method was successfully - null otherwise.
451          */
452         css::uno::Reference< css::embed::XStorage > impl_openPathIgnoringErrors(const ::rtl::OUString& sPath ,
453                                                                                       sal_Int32        eMode ,
454                                                                                       sal_Bool         bShare);
455 
456         //---------------------------------------
457         /** @short  try to find the specified locale inside list of possible ones.
458 
459             @descr  The list of possible locale values was e.g. retrieved from the system
460                     (configuration, directory listing etcpp). The locale normally represent
461                     the current office locale. This method search for a suitable item by using
462                     different algorithm.
463                     a) exact search
464                     b) search with using fallbacks
465 
466             @param  lLocalizedValues
467                     list of ISO locale codes
468 
469             @param  aLocale
470                     [IN ] the current office locale, which should be searched inside lLocalizedValues.
471                     [OUT] in case fallbacks was allowed, it contains afterwards the fallback locale.
472 
473             @param  bAllowFallbacks
474                     enable/disable using of fallbacks
475 
476             @return An iterator, which points directly into lLocalizedValue list.
477                     As a negative result the special iterator lLocalizedValues.end() will be returned.
478          */
479         ::std::vector< ::rtl::OUString >::const_iterator impl_findMatchingLocalizedValue(const ::std::vector< ::rtl::OUString >& lLocalizedValues,
480                                                                                                ::comphelper::Locale&             aLocale         ,
481                                                                                                sal_Bool                          bAllowFallbacks );
482 
483         //---------------------------------------
484         /** @short  open a config path ignoring errors (catching exceptions).
485 
486             @descr  We catch only normal exceptions here - no runtime exceptions.
487                     Further the path itself is tries in different versions (using locale
488                     specific attributes).
489                     e.g. "path/e-US" => "path/en" => "path/de"
490 
491             @param  sPath
492                     the configuration path, which should be opened.
493                     Its further used as out parameter too, so we can return the localized
494                     path to the calli!
495 
496             @param  eMode
497                     the open mode (READ/READWRITE)
498 
499             @param  bShare
500                     force using of the share layer instead of the user layer.
501 
502             @param  aLocale
503                     [IN ] contains the start locale for searching localized sub dirs.
504                     [OUT] contains the locale of a found localized sub dir
505 
506             @param  bAllowFallback
507                     enable/disable fallback handling for locales
508 
509             @return An opened storage in case method was successfully - null otherwise.
510          */
511         css::uno::Reference< css::embed::XStorage > impl_openLocalizedPathIgnoringErrors(::rtl::OUString&      sPath         ,
512                                                                                          sal_Int32             eMode         ,
513                                                                                          sal_Bool              bShare        ,
514                                                                                          ::comphelper::Locale& aLocale       ,
515                                                                                          sal_Bool              bAllowFallback);
516 
517         //---------------------------------------
518         /** @short  returns the names of all sub storages of specified storage.
519 
520             @param  xFolder
521                     the base storage for this operation.
522 
523             @return [vector< string >]
524                     a list of folder names.
525          */
526         ::std::vector< ::rtl::OUString > impl_getSubFolderNames(const css::uno::Reference< css::embed::XStorage >& xFolder);
527 };
528 
529 } // namespace framework
530 
531 #endif // __FRAMEWORK_ACCELERATORS_PRESETHANDLER_HXX_
532