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