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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 #include <accelerators/presethandler.hxx>
27
28 //_______________________________________________
29 // own includes
30 #include <classes/fwkresid.hxx>
31
32 #include "classes/resource.hrc"
33 #include <threadhelp/readguard.hxx>
34 #include <threadhelp/writeguard.hxx>
35 #include <services.h>
36
37 //_______________________________________________
38 // interface includes
39
40 #ifndef __COM_SUN_STAR_CONFIGURATION_CORRUPTEDUICONFIGURATIONEXCEPTION_HPP_
41 #include <com/sun/star/configuration/CorruptedUIConfigurationException.hpp>
42 #endif
43
44 #ifndef __COM_SUN_STAR_CONTAINER_NOSUCHELEMENTEXCEPTION_HPP_
45 #include <com/sun/star/container/NoSuchElementException.hpp>
46 #endif
47
48 #ifndef __COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
49 #include <com/sun/star/container/XNameAccess.hpp>
50 #endif
51
52 #ifndef __COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 #endif
55
56 #ifndef __COM_SUN_STAR_EMBED_ELEMENTMODES_HPP_
57 #include <com/sun/star/embed/ElementModes.hpp>
58 #endif
59
60 #ifndef __COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_
61 #include <com/sun/star/embed/XTransactedObject.hpp>
62 #endif
63
64 #ifndef __COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
65 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
66 #endif
67
68 //_______________________________________________
69 // other includes
70 #include <vcl/svapp.hxx>
71
72 #ifndef _RTL_USTRBUF_HXX
73 #include <rtl/ustrbuf.hxx>
74 #endif
75
76 //_______________________________________________
77 // const
78
79 #define SUBSTORAGE_GLOBAL DECLARE_ASCII("global" )
80 #define SUBSTORAGE_MODULES DECLARE_ASCII("modules")
81
82 #define BASEPATH_SHARE_LAYER DECLARE_ASCII("UIConfig" )
83 #define BASEPATH_USER_LAYER DECLARE_ASCII("UserConfig")
84
85 #define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg")
86 #define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg")
87 // #define RELPATH_SHARE_LAYER DECLARE_ASCII("soffice.cfg/uiconfig.zip")
88 // #define RELPATH_USER_LAYER DECLARE_ASCII("soffice.cfg/uiconfig.zip")
89
90 #define FILE_EXTENSION DECLARE_ASCII(".xml")
91
92 #define PATH_SEPERATOR DECLARE_ASCII("/")
93
94 static const ::sal_Int32 ID_CORRUPT_UICONFIG_SHARE = 1;
95 static const ::sal_Int32 ID_CORRUPT_UICONFIG_USER = 2;
96 static const ::sal_Int32 ID_CORRUPT_UICONFIG_GENERAL = 3;
97
98 //_______________________________________________
99 // namespace
100
101 namespace framework
102 {
103
104 //-----------------------------------------------
PRESET_DEFAULT()105 ::rtl::OUString PresetHandler::PRESET_DEFAULT()
106 {
107 static ::rtl::OUString RSTYPE = DECLARE_ASCII("default");
108 return RSTYPE;
109 }
110
111 //-----------------------------------------------
TARGET_CURRENT()112 ::rtl::OUString PresetHandler::TARGET_CURRENT()
113 {
114 static ::rtl::OUString RSTYPE = DECLARE_ASCII("current");
115 return RSTYPE;
116 }
117
118 //-----------------------------------------------
RESOURCETYPE_MENUBAR()119 ::rtl::OUString PresetHandler::RESOURCETYPE_MENUBAR()
120 {
121 static ::rtl::OUString RSTYPE = DECLARE_ASCII("menubar");
122 return RSTYPE;
123 }
124
125 //-----------------------------------------------
RESOURCETYPE_TOOLBAR()126 ::rtl::OUString PresetHandler::RESOURCETYPE_TOOLBAR()
127 {
128 static ::rtl::OUString RSTYPE = DECLARE_ASCII("toolbar");
129 return RSTYPE;
130 }
131
132 //-----------------------------------------------
RESOURCETYPE_ACCELERATOR()133 ::rtl::OUString PresetHandler::RESOURCETYPE_ACCELERATOR()
134 {
135 static ::rtl::OUString RSTYPE = DECLARE_ASCII("accelerator");
136 return RSTYPE;
137 }
138
139 //-----------------------------------------------
RESOURCETYPE_STATUSBAR()140 ::rtl::OUString PresetHandler::RESOURCETYPE_STATUSBAR()
141 {
142 static ::rtl::OUString RSTYPE = DECLARE_ASCII("statusbar");
143 return RSTYPE;
144 }
145
146 //-----------------------------------------------
PresetHandler(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)147 PresetHandler::PresetHandler(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
148 : ThreadHelpBase (&Application::GetSolarMutex() )
149 , m_xSMGR (xSMGR )
150 , m_aSharedStorages ( )
151 , m_lDocumentStorages(xSMGR )
152 , m_aLocale (::comphelper::Locale::X_NOTRANSLATE())
153 {
154 }
155
156 //-----------------------------------------------
PresetHandler(const PresetHandler & rCopy)157 PresetHandler::PresetHandler(const PresetHandler& rCopy)
158 : ThreadHelpBase (&Application::GetSolarMutex() )
159 {
160 m_xSMGR = rCopy.m_xSMGR;
161 m_eConfigType = rCopy.m_eConfigType;
162 m_sResourceType = rCopy.m_sResourceType;
163 m_sModule = rCopy.m_sModule;
164 m_aSharedStorages = rCopy.m_aSharedStorages;
165 m_xWorkingStorageShare = rCopy.m_xWorkingStorageShare;
166 m_xWorkingStorageNoLang = rCopy.m_xWorkingStorageNoLang;
167 m_xWorkingStorageUser = rCopy.m_xWorkingStorageUser;
168 m_lPresets = rCopy.m_lPresets;
169 m_lTargets = rCopy.m_lTargets;
170 m_aLocale = rCopy.m_aLocale;
171 m_lDocumentStorages = rCopy.m_lDocumentStorages;
172 m_sRelPathShare = rCopy.m_sRelPathShare;
173 m_sRelPathNoLang = rCopy.m_sRelPathNoLang;
174 m_sRelPathUser = rCopy.m_sRelPathUser;
175 }
176
177 //-----------------------------------------------
~PresetHandler()178 PresetHandler::~PresetHandler()
179 {
180 m_xWorkingStorageShare.clear();
181 m_xWorkingStorageNoLang.clear();
182 m_xWorkingStorageUser.clear();
183
184 /* #i46497#
185 Don't call forgetCachedStorages() here for shared storages.
186 Because we opened different sub storages by using openPath().
187 And every already open path was reused and referenced (means it's
188 ref count was increased!)
189 So now we have to release our ref counts to these shared storages
190 only... and not to free all used storages.
191 Otherwise we will disconnect all other open configuration access
192 objects which base on these storages.
193 */
194 m_aSharedStorages->m_lStoragesShare.closePath(m_sRelPathShare);
195 m_aSharedStorages->m_lStoragesUser.closePath (m_sRelPathUser );
196
197 /* On the other side closePath() is not needed for our special handled
198 document storage. Because it's not shared with others... so we can
199 free it.
200 */
201 m_lDocumentStorages.forgetCachedStorages();
202 }
203
204 //-----------------------------------------------
forgetCachedStorages()205 void PresetHandler::forgetCachedStorages()
206 {
207 // SAFE -> ----------------------------------
208 WriteGuard aWriteLock(m_aLock);
209
210 if (m_eConfigType == E_DOCUMENT)
211 {
212 m_xWorkingStorageShare.clear();
213 m_xWorkingStorageNoLang.clear();
214 m_xWorkingStorageUser.clear();
215 }
216
217 m_lDocumentStorages.forgetCachedStorages();
218
219 aWriteLock.unlock();
220 // <- SAFE ----------------------------------
221 }
222
223 //-----------------------------------------------
lcl_getLocalizedMessage(::sal_Int32 nID)224 ::rtl::OUString lcl_getLocalizedMessage(::sal_Int32 nID)
225 {
226 ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("Unknown error.");
227
228 switch(nID)
229 {
230 case ID_CORRUPT_UICONFIG_SHARE :
231 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_SHARE )));
232 break;
233
234 case ID_CORRUPT_UICONFIG_USER :
235 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_USER )));
236 break;
237
238 case ID_CORRUPT_UICONFIG_GENERAL :
239 sMessage = ::rtl::OUString( String( FwkResId( STR_CORRUPT_UICFG_GENERAL )));
240 break;
241 }
242
243 return sMessage;
244 }
245
246 //-----------------------------------------------
getOrCreateRootStorageShare()247 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageShare()
248 {
249 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesShare.getRootStorage();
250 if (xRoot.is())
251 return xRoot;
252
253 // SAFE -> ----------------------------------
254 ReadGuard aReadLock(m_aLock);
255 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
256 aReadLock.unlock();
257 // <- SAFE ----------------------------------
258
259 css::uno::Reference< css::beans::XPropertySet > xPathSettings(
260 xSMGR->createInstance(SERVICENAME_PATHSETTINGS),
261 css::uno::UNO_QUERY_THROW);
262
263 ::rtl::OUString sShareLayer;
264 xPathSettings->getPropertyValue(BASEPATH_SHARE_LAYER) >>= sShareLayer;
265
266 // "UIConfig" is a "multi path" ... use first part only here!
267 sal_Int32 nPos = sShareLayer.indexOf(';');
268 if (nPos > 0)
269 sShareLayer = sShareLayer.copy(0, nPos);
270
271 // Note: Maybe a user uses URLs without a final slash! Check it ...
272 nPos = sShareLayer.lastIndexOf('/');
273 if (nPos != sShareLayer.getLength()-1)
274 sShareLayer += ::rtl::OUString::createFromAscii("/");
275
276 sShareLayer += RELPATH_SHARE_LAYER; // folder
277 /*
278 // TODO remove me!
279 // Attention: This is temp. workaround ... We create a temp. storage file
280 // based of a system directory. This must be used so, till the storage implementation
281 // can work on directories too.
282 */
283 css::uno::Sequence< css::uno::Any > lArgs(2);
284 lArgs[0] <<= sShareLayer;
285 lArgs[1] <<= css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE;
286
287 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory(xSMGR->createInstance(SERVICENAME_FILESYSTEMSTORAGEFACTORY) , css::uno::UNO_QUERY_THROW);
288 css::uno::Reference< css::embed::XStorage > xStorage;
289
290 try
291 {
292 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
293 }
294 catch(const css::uno::Exception& ex)
295 {
296 throw css::configuration::CorruptedUIConfigurationException(
297 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_SHARE),
298 css::uno::Reference< css::uno::XInterface >(),
299 ex.Message);
300 }
301
302 m_aSharedStorages->m_lStoragesShare.setRootStorage(xStorage);
303
304 return xStorage;
305 }
306
307 //-----------------------------------------------
getOrCreateRootStorageUser()308 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageUser()
309 {
310 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesUser.getRootStorage();
311 if (xRoot.is())
312 return xRoot;
313
314 // SAFE -> ----------------------------------
315 ReadGuard aReadLock(m_aLock);
316 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
317 aReadLock.unlock();
318 // <- SAFE ----------------------------------
319
320 css::uno::Reference< css::beans::XPropertySet > xPathSettings(
321 xSMGR->createInstance(SERVICENAME_PATHSETTINGS),
322 css::uno::UNO_QUERY_THROW);
323
324 ::rtl::OUString sUserLayer;
325 xPathSettings->getPropertyValue(BASEPATH_USER_LAYER) >>= sUserLayer ;
326
327 // Note: Maybe a user uses URLs without a final slash! Check it ...
328 sal_Int32 nPos = sUserLayer.lastIndexOf('/');
329 if (nPos != sUserLayer.getLength()-1)
330 sUserLayer += ::rtl::OUString::createFromAscii("/");
331
332 sUserLayer += RELPATH_USER_LAYER; // storage file
333
334 css::uno::Sequence< css::uno::Any > lArgs(2);
335 lArgs[0] <<= sUserLayer;
336 lArgs[1] <<= css::embed::ElementModes::READWRITE;
337
338 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory(xSMGR->createInstance(SERVICENAME_FILESYSTEMSTORAGEFACTORY) , css::uno::UNO_QUERY_THROW);
339 css::uno::Reference< css::embed::XStorage > xStorage;
340
341 try
342 {
343 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
344 }
345 catch(const css::uno::Exception& ex)
346 {
347 throw css::configuration::CorruptedUIConfigurationException(
348 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_USER),
349 css::uno::Reference< css::uno::XInterface >(),
350 ex.Message);
351 }
352
353 m_aSharedStorages->m_lStoragesUser.setRootStorage(xStorage);
354
355 return xStorage;
356 }
357
358 //-----------------------------------------------
getWorkingStorageShare()359 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageShare()
360 {
361 // SAFE -> ----------------------------------
362 ReadGuard aReadLock(m_aLock);
363 return m_xWorkingStorageShare;
364 // <- SAFE ----------------------------------
365 }
366
367 //-----------------------------------------------
getWorkingStorageUser()368 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageUser()
369 {
370 // SAFE -> ----------------------------------
371 ReadGuard aReadLock(m_aLock);
372 return m_xWorkingStorageUser;
373 // <- SAFE ----------------------------------
374 }
375
376 //-----------------------------------------------
getParentStorageShare(const css::uno::Reference<css::embed::XStorage> &)377 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageShare(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
378 {
379 // SAFE -> ----------------------------------
380 ReadGuard aReadLock(m_aLock);
381 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageShare;
382 aReadLock.unlock();
383 // <- SAFE ----------------------------------
384
385 return m_aSharedStorages->m_lStoragesShare.getParentStorage(xWorking);
386 }
387
388 //-----------------------------------------------
getParentStorageUser(const css::uno::Reference<css::embed::XStorage> &)389 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageUser(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
390 {
391 // SAFE -> ----------------------------------
392 ReadGuard aReadLock(m_aLock);
393 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser;
394 aReadLock.unlock();
395 // <- SAFE ----------------------------------
396
397 return m_aSharedStorages->m_lStoragesUser.getParentStorage(xWorking);
398 }
399
400 //-----------------------------------------------
connectToResource(PresetHandler::EConfigType eConfigType,const::rtl::OUString & sResource,const::rtl::OUString & sModule,const css::uno::Reference<css::embed::XStorage> & xDocumentRoot,const::comphelper::Locale & aLocale)401 void PresetHandler::connectToResource( PresetHandler::EConfigType eConfigType ,
402 const ::rtl::OUString& sResource ,
403 const ::rtl::OUString& sModule ,
404 const css::uno::Reference< css::embed::XStorage >& xDocumentRoot,
405 const ::comphelper::Locale& aLocale )
406 {
407 // TODO free all current open storages!
408
409 // SAFE -> ----------------------------------
410 WriteGuard aWriteLock(m_aLock);
411
412 m_eConfigType = eConfigType ;
413 m_sResourceType = sResource ;
414 m_sModule = sModule ;
415 m_aLocale = aLocale ;
416
417 aWriteLock.unlock();
418 // <- SAFE ----------------------------------
419
420 css::uno::Reference< css::embed::XStorage > xShare;
421 css::uno::Reference< css::embed::XStorage > xNoLang;
422 css::uno::Reference< css::embed::XStorage > xUser;
423
424 // special case for documents
425 // use outside root storage, if we run in E_DOCUMENT mode!
426 if (eConfigType == E_DOCUMENT)
427 {
428 if (!xDocumentRoot.is())
429 throw css::uno::RuntimeException(
430 ::rtl::OUString::createFromAscii("There is valid root storage, where the UI configuration can work on."),
431 css::uno::Reference< css::uno::XInterface >());
432 m_lDocumentStorages.setRootStorage(xDocumentRoot);
433 xShare = xDocumentRoot;
434 xUser = xDocumentRoot;
435 }
436 else
437 {
438 xShare = getOrCreateRootStorageShare();
439 xUser = getOrCreateRootStorageUser();
440 }
441
442 // #...#
443 try
444 {
445
446 // a) inside share layer we should not create any new structures ... We have to use
447 // existing ones only!
448 // b) inside user layer we can (SOFT mode!) but sometimes we shouldn't (HARD mode!)
449 // create new empty structures. We should prefer using of any existing structure.
450 sal_Int32 eShareMode = (css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE);
451 sal_Int32 eUserMode = (css::embed::ElementModes::READWRITE );
452
453 ::rtl::OUStringBuffer sRelPathBuf(1024);
454 ::rtl::OUString sRelPathShare;
455 ::rtl::OUString sRelPathNoLang;
456 ::rtl::OUString sRelPathUser;
457 switch(eConfigType)
458 {
459 case E_GLOBAL :
460 {
461 sRelPathBuf.append(SUBSTORAGE_GLOBAL);
462 sRelPathBuf.append(PATH_SEPERATOR );
463 sRelPathBuf.append(sResource );
464 sRelPathShare = sRelPathBuf.makeStringAndClear();
465 sRelPathUser = sRelPathShare;
466
467 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True );
468 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False);
469 }
470 break;
471
472 case E_MODULES :
473 {
474 sRelPathBuf.append(SUBSTORAGE_MODULES);
475 sRelPathBuf.append(PATH_SEPERATOR );
476 sRelPathBuf.append(sModule );
477 sRelPathBuf.append(PATH_SEPERATOR );
478 sRelPathBuf.append(sResource );
479 sRelPathShare = sRelPathBuf.makeStringAndClear();
480 sRelPathUser = sRelPathShare;
481
482 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, sal_True );
483 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , sal_False);
484 }
485 break;
486
487 case E_DOCUMENT :
488 {
489 // A document does not have a share layer in real.
490 // It has one layer only, and this one should be opened READ_WRITE.
491 // So we open the user layer here only and set the share layer equals to it .-)
492
493 sRelPathBuf.append(sResource);
494 sRelPathUser = sRelPathBuf.makeStringAndClear();
495 sRelPathShare = sRelPathUser;
496
497 try
498 {
499 xUser = m_lDocumentStorages.openPath(sRelPathUser , eUserMode );
500 xShare = xUser;
501 }
502 catch(const css::uno::RuntimeException& exRun)
503 { throw exRun; }
504 catch(const css::uno::Exception&)
505 { xShare.clear(); xUser.clear(); }
506 }
507 break;
508 }
509
510 // Non-localized global share
511 xNoLang = xShare;
512 sRelPathNoLang = sRelPathShare;
513
514 if (
515 (aLocale != ::comphelper::Locale::X_NOTRANSLATE()) && // localized level?
516 (eConfigType != E_DOCUMENT ) // no localization in document mode!
517 )
518 {
519 // First try to find the right localized set inside share layer.
520 // Fallbacks are allowed there.
521 ::comphelper::Locale aShareLocale = aLocale ;
522 ::rtl::OUString sLocalizedSharePath(sRelPathShare);
523 sal_Bool bAllowFallbacks = sal_True ;
524 xShare = impl_openLocalizedPathIgnoringErrors(sLocalizedSharePath, eShareMode, sal_True , aShareLocale, bAllowFallbacks);
525
526 // The try to locate the right sub dir inside user layer ... without using fallbacks!
527 // Normally the corresponding sub dir should be created matching the specified locale.
528 // Because we allow creation of storages inside user layer by default.
529 ::comphelper::Locale aUserLocale = aLocale ;
530 ::rtl::OUString sLocalizedUserPath(sRelPathUser);
531 bAllowFallbacks = sal_False ;
532 xUser = impl_openLocalizedPathIgnoringErrors(sLocalizedUserPath, eUserMode , sal_False, aUserLocale, bAllowFallbacks);
533
534 sRelPathShare = sLocalizedSharePath;
535 sRelPathUser = sLocalizedUserPath ;
536 }
537
538 // read content of level 3 (presets, targets)
539 css::uno::Reference< css::container::XNameAccess > xAccess ;
540 css::uno::Sequence< ::rtl::OUString > lNames ;
541 const ::rtl::OUString* pNames ;
542 sal_Int32 c ;
543 sal_Int32 i ;
544 OUStringList lPresets;
545 OUStringList lTargets;
546
547 // read preset names of share layer
548 xAccess = css::uno::Reference< css::container::XNameAccess >(xShare, css::uno::UNO_QUERY);
549 if (xAccess.is())
550 {
551 lNames = xAccess->getElementNames();
552 pNames = lNames.getConstArray();
553 c = lNames.getLength();
554
555 for (i=0; i<c; ++i)
556 {
557 ::rtl::OUString sTemp = pNames[i];
558 sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION);
559 if (nPos > -1)
560 sTemp = sTemp.copy(0,nPos);
561 lPresets.push_back(sTemp);
562 }
563 }
564
565 // read preset names of user layer
566 xAccess = css::uno::Reference< css::container::XNameAccess >(xUser, css::uno::UNO_QUERY);
567 if (xAccess.is())
568 {
569 lNames = xAccess->getElementNames();
570 pNames = lNames.getConstArray();
571 c = lNames.getLength();
572
573 for (i=0; i<c; ++i)
574 {
575 ::rtl::OUString sTemp = pNames[i];
576 sal_Int32 nPos = sTemp.indexOf(FILE_EXTENSION);
577 if (nPos > -1)
578 sTemp = sTemp.copy(0,nPos);
579 lTargets.push_back(sTemp);
580 }
581 }
582
583 // SAFE -> ----------------------------------
584 aWriteLock.lock();
585
586 m_xWorkingStorageShare = xShare ;
587 m_xWorkingStorageNoLang= xNoLang;
588 m_xWorkingStorageUser = xUser ;
589 m_lPresets = lPresets;
590 m_lTargets = lTargets;
591 m_sRelPathShare = sRelPathShare;
592 m_sRelPathNoLang = sRelPathNoLang;
593 m_sRelPathUser = sRelPathUser;
594
595 aWriteLock.unlock();
596 // <- SAFE ----------------------------------
597
598 }
599 catch(const css::uno::Exception& ex)
600 {
601 throw css::configuration::CorruptedUIConfigurationException(
602 lcl_getLocalizedMessage(ID_CORRUPT_UICONFIG_GENERAL),
603 css::uno::Reference< css::uno::XInterface >(),
604 ex.Message);
605 }
606 }
607
608 //-----------------------------------------------
copyPresetToTarget(const::rtl::OUString & sPreset,const::rtl::OUString & sTarget)609 void PresetHandler::copyPresetToTarget(const ::rtl::OUString& sPreset,
610 const ::rtl::OUString& sTarget)
611 {
612 // don't check our preset list, if element exists
613 // We try to open it and forward all errors to the user!
614
615 // SAFE -> ----------------------------------
616 ReadGuard aReadLock(m_aLock);
617 css::uno::Reference< css::embed::XStorage > xWorkingShare = m_xWorkingStorageShare;
618 css::uno::Reference< css::embed::XStorage > xWorkingNoLang= m_xWorkingStorageNoLang;
619 css::uno::Reference< css::embed::XStorage > xWorkingUser = m_xWorkingStorageUser ;
620 aReadLock.unlock();
621 // <- SAFE ----------------------------------
622
623 // e.g. module without any config data ?!
624 if (
625 (!xWorkingShare.is()) ||
626 (!xWorkingUser.is() )
627 )
628 {
629 return;
630 }
631
632 ::rtl::OUString sPresetFile(sPreset);
633 sPresetFile += FILE_EXTENSION;
634
635 ::rtl::OUString sTargetFile(sTarget);
636 sTargetFile += FILE_EXTENSION;
637
638 // remove existing elements before you try to copy the preset to that location ...
639 // Otherwise w will get an ElementExistException inside copyElementTo()!
640 css::uno::Reference< css::container::XNameAccess > xCheckingUser(xWorkingUser, css::uno::UNO_QUERY_THROW);
641 if (xCheckingUser->hasByName(sTargetFile))
642 xWorkingUser->removeElement(sTargetFile);
643
644 xWorkingShare->copyElementTo(sPresetFile, xWorkingUser, sTargetFile);
645
646 // If our storages work in transacted mode, we have
647 // to commit all changes from bottom to top!
648 commitUserChanges();
649 }
650
651 //-----------------------------------------------
openPreset(const::rtl::OUString & sPreset,sal_Bool bUseNoLangGlobal)652 css::uno::Reference< css::io::XStream > PresetHandler::openPreset(const ::rtl::OUString& sPreset,
653 sal_Bool bUseNoLangGlobal)
654 {
655 // SAFE -> ----------------------------------
656 ReadGuard aReadLock(m_aLock);
657 css::uno::Reference< css::embed::XStorage > xFolder = bUseNoLangGlobal? m_xWorkingStorageNoLang: m_xWorkingStorageShare;
658 aReadLock.unlock();
659 // <- SAFE ----------------------------------
660
661 // e.g. module without any config data ?!
662 if (!xFolder.is())
663 return css::uno::Reference< css::io::XStream >();
664
665 ::rtl::OUString sFile(sPreset);
666 sFile += FILE_EXTENSION;
667
668 // inform user about errors (use original exceptions!)
669 css::uno::Reference< css::io::XStream > xStream = xFolder->openStreamElement(sFile, css::embed::ElementModes::READ);
670 return xStream;
671 }
672
673 //-----------------------------------------------
openTarget(const::rtl::OUString & sTarget,sal_Bool bCreateIfMissing)674 css::uno::Reference< css::io::XStream > PresetHandler::openTarget(const ::rtl::OUString& sTarget ,
675 sal_Bool bCreateIfMissing)
676 {
677 // SAFE -> ----------------------------------
678 ReadGuard aReadLock(m_aLock);
679 css::uno::Reference< css::embed::XStorage > xFolder = m_xWorkingStorageUser;
680 aReadLock.unlock();
681 // <- SAFE ----------------------------------
682
683 // e.g. module without any config data ?!
684 if (!xFolder.is())
685 return css::uno::Reference< css::io::XStream >();
686
687 ::rtl::OUString sFile(sTarget);
688 sFile += FILE_EXTENSION;
689
690 sal_Int32 nOpenMode = css::embed::ElementModes::READWRITE;
691 if (!bCreateIfMissing)
692 nOpenMode |= css::embed::ElementModes::NOCREATE;
693
694 // try it in read/write mode first and ignore errors.
695 css::uno::Reference< css::io::XStream > xStream;
696 try
697 {
698 xStream = xFolder->openStreamElement(sFile, nOpenMode);
699 return xStream;
700 }
701 catch(const css::uno::RuntimeException&)
702 { throw; }
703 catch(const css::uno::Exception&)
704 { xStream.clear(); }
705
706 // try it readonly if it failed before.
707 // inform user about errors (use original exceptions!)
708 nOpenMode &= ~css::embed::ElementModes::WRITE;
709 xStream = xFolder->openStreamElement(sFile, nOpenMode);
710
711 return xStream;
712 }
713
714 //-----------------------------------------------
commitUserChanges()715 void PresetHandler::commitUserChanges()
716 {
717 // SAFE -> ----------------------------------
718 ReadGuard aReadLock(m_aLock);
719 css::uno::Reference< css::embed::XStorage > xWorking = m_xWorkingStorageUser;
720 EConfigType eCfgType = m_eConfigType;
721 aReadLock.unlock();
722 // <- SAFE ----------------------------------
723
724 // e.g. module without any config data ?!
725 if (!xWorking.is())
726 return;
727
728 ::rtl::OUString sPath;
729
730 switch(eCfgType)
731 {
732 case E_GLOBAL :
733 case E_MODULES :
734 {
735 sPath = m_aSharedStorages->m_lStoragesUser.getPathOfStorage(xWorking);
736 m_aSharedStorages->m_lStoragesUser.commitPath(sPath);
737 m_aSharedStorages->m_lStoragesUser.notifyPath(sPath);
738 }
739 break;
740
741 case E_DOCUMENT :
742 {
743 sPath = m_lDocumentStorages.getPathOfStorage(xWorking);
744 m_lDocumentStorages.commitPath(sPath);
745 m_lDocumentStorages.notifyPath(sPath);
746 }
747 break;
748 }
749 }
750
751 //-----------------------------------------------
addStorageListener(IStorageListener * pListener)752 void PresetHandler::addStorageListener(IStorageListener* pListener)
753 {
754 // SAFE -> ----------------------------------
755 ReadGuard aReadLock(m_aLock);
756 ::rtl::OUString sRelPath = m_sRelPathUser; // use user path ... because we don't work directly on the share layer!
757 EConfigType eCfgType = m_eConfigType;
758 aReadLock.unlock();
759 // <- SAFE ----------------------------------
760
761 if (!sRelPath.getLength())
762 return;
763
764 switch(eCfgType)
765 {
766 case E_GLOBAL :
767 case E_MODULES :
768 {
769 m_aSharedStorages->m_lStoragesUser.addStorageListener(pListener, sRelPath);
770 }
771 break;
772
773 case E_DOCUMENT :
774 {
775 m_lDocumentStorages.addStorageListener(pListener, sRelPath);
776 }
777 break;
778 }
779 }
780
781 //-----------------------------------------------
removeStorageListener(IStorageListener * pListener)782 void PresetHandler::removeStorageListener(IStorageListener* pListener)
783 {
784 // SAFE -> ----------------------------------
785 ReadGuard aReadLock(m_aLock);
786 ::rtl::OUString sRelPath = m_sRelPathUser; // use user path ... because we don't work directly on the share layer!
787 EConfigType eCfgType = m_eConfigType;
788 aReadLock.unlock();
789 // <- SAFE ----------------------------------
790
791 if (!sRelPath.getLength())
792 return;
793
794 switch(eCfgType)
795 {
796 case E_GLOBAL :
797 case E_MODULES :
798 {
799 m_aSharedStorages->m_lStoragesUser.removeStorageListener(pListener, sRelPath);
800 }
801 break;
802
803 case E_DOCUMENT :
804 {
805 m_lDocumentStorages.removeStorageListener(pListener, sRelPath);
806 }
807 break;
808 }
809 }
810
811 //-----------------------------------------------
impl_openPathIgnoringErrors(const::rtl::OUString & sPath,sal_Int32 eMode,sal_Bool bShare)812 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openPathIgnoringErrors(const ::rtl::OUString& sPath ,
813 sal_Int32 eMode ,
814 sal_Bool bShare)
815 {
816 css::uno::Reference< css::embed::XStorage > xPath;
817 try
818 {
819 if (bShare)
820 xPath = m_aSharedStorages->m_lStoragesShare.openPath(sPath, eMode);
821 else
822 xPath = m_aSharedStorages->m_lStoragesUser.openPath(sPath, eMode);
823 }
824 catch(const css::uno::RuntimeException& exRun)
825 { throw exRun; }
826 catch(const css::uno::Exception&)
827 { xPath.clear(); }
828 return xPath;
829 }
830
831 //-----------------------------------------------
impl_findMatchingLocalizedValue(const::std::vector<::rtl::OUString> & lLocalizedValues,::comphelper::Locale & aLocale,sal_Bool bAllowFallbacks)832 ::std::vector< ::rtl::OUString >::const_iterator PresetHandler::impl_findMatchingLocalizedValue(const ::std::vector< ::rtl::OUString >& lLocalizedValues,
833 ::comphelper::Locale& aLocale ,
834 sal_Bool bAllowFallbacks )
835 {
836 ::std::vector< ::rtl::OUString >::const_iterator pFound = lLocalizedValues.end();
837 if (bAllowFallbacks)
838 {
839 pFound = ::comphelper::Locale::getFallback(lLocalizedValues, aLocale.toISO());
840 }
841 else
842 {
843 for ( pFound = lLocalizedValues.begin();
844 pFound != lLocalizedValues.end() ;
845 ++pFound )
846 {
847 const ::rtl::OUString& sCheckISO = *pFound;
848 ::comphelper::Locale aCheckLocale(sCheckISO);
849 if (aCheckLocale.equals(aLocale))
850 break;
851 }
852 }
853
854 // if we found a valid locale ... take it over to our in/out parameter aLocale
855 if (pFound != lLocalizedValues.end())
856 {
857 const ::rtl::OUString& sISOLocale = *pFound;
858 aLocale.fromISO(sISOLocale);
859 }
860
861 return pFound;
862 }
863
864 //-----------------------------------------------
impl_openLocalizedPathIgnoringErrors(::rtl::OUString & sPath,sal_Int32 eMode,sal_Bool bShare,::comphelper::Locale & aLocale,sal_Bool bAllowFallback)865 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openLocalizedPathIgnoringErrors(::rtl::OUString& sPath ,
866 sal_Int32 eMode ,
867 sal_Bool bShare ,
868 ::comphelper::Locale& aLocale ,
869 sal_Bool bAllowFallback)
870 {
871 css::uno::Reference< css::embed::XStorage > xPath = impl_openPathIgnoringErrors(sPath, eMode, bShare);
872 ::std::vector< ::rtl::OUString > lSubFolders = impl_getSubFolderNames(xPath);
873 ::std::vector< ::rtl::OUString >::const_iterator pLocaleFolder = impl_findMatchingLocalizedValue(lSubFolders, aLocale, bAllowFallback);
874
875 // no fallback ... creation not allowed => no storage
876 if (
877 (pLocaleFolder == lSubFolders.end() ) &&
878 ((eMode & css::embed::ElementModes::NOCREATE) == css::embed::ElementModes::NOCREATE)
879 )
880 return css::uno::Reference< css::embed::XStorage >();
881
882 // it doesn't matter, if there is a locale fallback or not
883 // If creation of storages is allowed, we do it anyway.
884 // Otherwise we have no acc config at all, which can make other trouble.
885 ::rtl::OUString sLocalizedPath;
886 sLocalizedPath = sPath;
887 sLocalizedPath += PATH_SEPERATOR;
888 if (pLocaleFolder != lSubFolders.end())
889 sLocalizedPath += *pLocaleFolder;
890 else
891 sLocalizedPath += aLocale.toISO();
892
893 css::uno::Reference< css::embed::XStorage > xLocalePath = impl_openPathIgnoringErrors(sLocalizedPath, eMode, bShare);
894
895 if (xLocalePath.is())
896 sPath = sLocalizedPath;
897 else
898 sPath = ::rtl::OUString();
899
900 return xLocalePath;
901 }
902
903 //-----------------------------------------------
impl_getSubFolderNames(const css::uno::Reference<css::embed::XStorage> & xFolder)904 ::std::vector< ::rtl::OUString > PresetHandler::impl_getSubFolderNames(const css::uno::Reference< css::embed::XStorage >& xFolder)
905 {
906 css::uno::Reference< css::container::XNameAccess > xAccess(xFolder, css::uno::UNO_QUERY);
907 if (!xAccess.is())
908 return ::std::vector< ::rtl::OUString >();
909
910 ::std::vector< ::rtl::OUString > lSubFolders;
911 const css::uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames();
912 const ::rtl::OUString* pNames = lNames.getConstArray();
913 sal_Int32 c = lNames.getLength();
914 sal_Int32 i = 0;
915
916 for (i=0; i<c; ++i)
917 {
918 try
919 {
920 if (xFolder->isStorageElement(pNames[i]))
921 lSubFolders.push_back(pNames[i]);
922 }
923 catch(const css::uno::RuntimeException& exRun)
924 { throw exRun; }
925 catch(const css::uno::Exception&)
926 {}
927 }
928
929 return lSubFolders;
930 }
931
932 //-----------------------------------------------
933 } // namespace framework
934