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