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

Generated by: LCOV version 1.10