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