LCOV - code coverage report
Current view: top level - framework/source/accelerators - presethandler.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 215 377 57.0 %
Date: 2015-06-13 12:38:46 Functions: 16 24 66.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11