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