LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/framework/source/accelerators - storageholder.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 172 259 66.4 %
Date: 2013-07-09 Functions: 15 21 71.4 %
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/storageholder.hxx>
      21             : 
      22             : #include <threadhelp/readguard.hxx>
      23             : #include <threadhelp/writeguard.hxx>
      24             : #include <services.h>
      25             : 
      26             : #include <com/sun/star/container/NoSuchElementException.hpp>
      27             : 
      28             : #include <com/sun/star/container/XNameAccess.hpp>
      29             : 
      30             : #include <com/sun/star/beans/XPropertySet.hpp>
      31             : 
      32             : #include <com/sun/star/embed/ElementModes.hpp>
      33             : 
      34             : #include <com/sun/star/embed/XTransactedObject.hpp>
      35             : 
      36             : #include <com/sun/star/embed/XPackageStructureCreator.hpp>
      37             : 
      38             : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
      39             : 
      40             : #include <com/sun/star/io/XSeekable.hpp>
      41             : 
      42             : 
      43             : #define PATH_SEPARATOR_ASCII        "/"
      44             : #define PATH_SEPARATOR_UNICODE      ((sal_Unicode)'/')
      45             : #define PATH_SEPARATOR              OUString(PATH_SEPARATOR_ASCII)
      46             : 
      47             : 
      48             : namespace framework
      49             : {
      50             : 
      51             : //-----------------------------------------------
      52         963 : StorageHolder::StorageHolder()
      53         963 :     : ThreadHelpBase(                                        )
      54             : {
      55         963 : }
      56             : 
      57             : //-----------------------------------------------
      58         948 : StorageHolder::~StorageHolder()
      59             : {
      60             :     // TODO implement me
      61             :     // dispose/clear etcpp.
      62         948 : }
      63             : 
      64             : //-----------------------------------------------
      65         844 : void StorageHolder::forgetCachedStorages()
      66             : {
      67             :     // SAFE -> ----------------------------------
      68         844 :     WriteGuard aWriteLock(m_aLock);
      69             : 
      70         844 :     TPath2StorageInfo::iterator pIt;
      71        4398 :     for (  pIt  = m_lStorages.begin();
      72        2932 :            pIt != m_lStorages.end()  ;
      73             :          ++pIt                       )
      74             :     {
      75         622 :         TStorageInfo& rInfo = pIt->second;
      76             :         // TODO think about listener !
      77         622 :         rInfo.Storage.clear();
      78             :     }
      79         844 :     m_lStorages.clear();
      80             : 
      81         844 :     aWriteLock.unlock();
      82             :     // <- SAFE ----------------------------------
      83         844 : }
      84             : 
      85             : //-----------------------------------------------
      86         740 : void StorageHolder::setRootStorage(const css::uno::Reference< css::embed::XStorage >& xRoot)
      87             : {
      88             :     // SAFE -> ----------------------------------
      89         740 :     WriteGuard aWriteLock(m_aLock);
      90         740 :     m_xRoot = xRoot;
      91         740 :     aWriteLock.unlock();
      92             :     // <- SAFE ----------------------------------
      93         740 : }
      94             : 
      95             : //-----------------------------------------------
      96         539 : css::uno::Reference< css::embed::XStorage > StorageHolder::getRootStorage() const
      97             : {
      98             :     // SAFE -> ----------------------------------
      99         539 :     ReadGuard aReadLock(m_aLock);
     100         539 :     return m_xRoot;
     101             :     // <- SAFE ----------------------------------
     102             : }
     103             : 
     104             : //-----------------------------------------------
     105        1084 : css::uno::Reference< css::embed::XStorage > StorageHolder::openPath(const OUString& sPath    ,
     106             :                                                                           sal_Int32        nOpenMode)
     107             : {
     108        1084 :     OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
     109        2168 :     OUStringList    lFolders    = StorageHolder::impl_st_parsePath(sNormedPath);
     110             : 
     111             :     // SAFE -> ----------------------------------
     112        2168 :     ReadGuard aReadLock(m_aLock);
     113        2168 :     css::uno::Reference< css::embed::XStorage > xParent = m_xRoot;
     114        1084 :     aReadLock.unlock();
     115             :     // <- SAFE ----------------------------------
     116             : 
     117        1084 :     css::uno::Reference< css::embed::XStorage > xChild  ;
     118        2168 :     OUString                             sRelPath;
     119        1084 :     OUStringList::const_iterator                pIt     ;
     120             : 
     121        9222 :     for (  pIt  = lFolders.begin();
     122        6148 :            pIt != lFolders.end()  ;
     123             :          ++pIt                    )
     124             :     {
     125        2000 :         const OUString& sChild     = *pIt;
     126        2000 :               OUString  sCheckPath (sRelPath);
     127        2000 :                                sCheckPath += sChild;
     128        2000 :                                sCheckPath += PATH_SEPARATOR;
     129             : 
     130             :         // SAFE -> ------------------------------
     131        2000 :         aReadLock.lock();
     132             : 
     133             :         // If we found an already open storage ... we must increase
     134             :         // its use count. Otherwhise it will may be closed to early :-)
     135        2000 :         TPath2StorageInfo::iterator pCheck = m_lStorages.find(sCheckPath);
     136        2000 :         TStorageInfo*               pInfo  = 0;
     137        2000 :         if (pCheck != m_lStorages.end())
     138             :         {
     139         646 :             pInfo = &(pCheck->second);
     140         646 :             ++(pInfo->UseCount);
     141         646 :             xChild = pInfo->Storage;
     142             :         }
     143             :         else
     144             :         {
     145        1354 :             aReadLock.unlock();
     146             :             // <- SAFE ------------------------------
     147             : 
     148             :             try
     149             :             {
     150        1354 :                 xChild = StorageHolder::openSubStorageWithFallback(xParent, sChild, nOpenMode, sal_True); // TODO think about delegating fallback decision to our own calli!
     151             :             }
     152           0 :             catch(const css::uno::RuntimeException&)
     153           0 :                 { throw; }
     154          20 :             catch(const css::uno::Exception&)
     155             :                 {
     156             :                     /* TODO URGENT!
     157             :                         in case we found some "already existing storages" on the path before and increased its UseCount ...
     158             :                         and now we will get an exception on creating a new sub storage ...
     159             :                         we must decrease all UseCounts, which was touched before. Otherwise these storages cant be closed!
     160             : 
     161             :                         Idea: Using of another structure member "PossibleUseCount" as vector of unique numbers.
     162             :                         Every thread use another unique number to identify all "owned candidates".
     163             :                         A flush method with the same unique number force increasing of the "UseCount" variable then
     164             :                         inside a synchronized block ...
     165             :                     */
     166          10 :                     throw;
     167             :                 }
     168             : 
     169             :             // SAFE -> ------------------------------
     170        1344 :             WriteGuard aWriteLock(m_aLock);
     171        1344 :             pInfo = &(m_lStorages[sCheckPath]);
     172        1344 :             pInfo->Storage  = xChild;
     173        1344 :             pInfo->UseCount = 1;
     174        1344 :             aWriteLock.unlock();
     175             :             // <- SAFE ------------------------------
     176             :         }
     177             : 
     178        1990 :         xParent   = xChild;
     179        1990 :         sRelPath += sChild;
     180        1990 :         sRelPath += PATH_SEPARATOR;
     181        2000 :     }
     182             : 
     183             :     // TODO think about return last storage as working storage ... but dont caching it inside this holder!
     184             :     // => otherwise the same storage is may be commit more then once.
     185             : 
     186        2158 :     return xChild;
     187             : }
     188             : 
     189             : //-----------------------------------------------
     190           0 : StorageHolder::TStorageList StorageHolder::getAllPathStorages(const OUString& sPath)
     191             : {
     192           0 :     OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
     193           0 :     OUStringList    lFolders    = StorageHolder::impl_st_parsePath(sNormedPath);
     194             : 
     195           0 :     StorageHolder::TStorageList  lStoragesOfPath;
     196           0 :     OUString              sRelPath       ;
     197           0 :     OUStringList::const_iterator pIt            ;
     198             : 
     199             :     // SAFE -> ----------------------------------
     200           0 :     ReadGuard aReadLock(m_aLock);
     201             : 
     202           0 :     for (  pIt  = lFolders.begin();
     203           0 :            pIt != lFolders.end()  ;
     204             :          ++pIt                    )
     205             :     {
     206           0 :         const OUString& sChild     = *pIt;
     207           0 :               OUString  sCheckPath (sRelPath);
     208           0 :                                sCheckPath += sChild;
     209           0 :                                sCheckPath += PATH_SEPARATOR;
     210             : 
     211           0 :         TPath2StorageInfo::iterator pCheck = m_lStorages.find(sCheckPath);
     212           0 :         if (pCheck == m_lStorages.end())
     213             :         {
     214             :             // at least one path element was not found
     215             :             // Seems that this path isnt open ...
     216           0 :             lStoragesOfPath.clear();
     217           0 :             return lStoragesOfPath;
     218             :         }
     219             : 
     220           0 :         TStorageInfo& rInfo = pCheck->second;
     221           0 :         lStoragesOfPath.push_back(rInfo.Storage);
     222             : 
     223           0 :         sRelPath += sChild;
     224           0 :         sRelPath += PATH_SEPARATOR;
     225           0 :     }
     226             : 
     227           0 :     aReadLock.unlock();
     228             :     // <- SAFE ----------------------------------
     229             : 
     230           0 :     return lStoragesOfPath;
     231             : }
     232             : 
     233             : //-----------------------------------------------
     234           0 : void StorageHolder::commitPath(const OUString& sPath)
     235             : {
     236           0 :     StorageHolder::TStorageList lStorages = getAllPathStorages(sPath);
     237             : 
     238           0 :     css::uno::Reference< css::embed::XTransactedObject > xCommit;
     239           0 :     StorageHolder::TStorageList::reverse_iterator pIt;
     240           0 :     for (  pIt  = lStorages.rbegin(); // order of commit is important ... otherwise changes are not recognized!
     241           0 :            pIt != lStorages.rend()  ;
     242             :          ++pIt                      )
     243             :     {
     244           0 :         xCommit = css::uno::Reference< css::embed::XTransactedObject >(*pIt, css::uno::UNO_QUERY);
     245           0 :         if (!xCommit.is())
     246           0 :             continue;
     247           0 :         xCommit->commit();
     248             :     }
     249             : 
     250             :     // SAFE -> ------------------------------
     251           0 :     ReadGuard aReadLock(m_aLock);
     252           0 :     xCommit = css::uno::Reference< css::embed::XTransactedObject >(m_xRoot, css::uno::UNO_QUERY);
     253           0 :     aReadLock.unlock();
     254             :     // <- SAFE ------------------------------
     255             : 
     256           0 :     if (xCommit.is())
     257           0 :         xCommit->commit();
     258           0 : }
     259             : 
     260             : //-----------------------------------------------
     261        1672 : void StorageHolder::closePath(const OUString& rPath)
     262             : {
     263        1672 :     OUString sNormedPath = StorageHolder::impl_st_normPath(rPath);
     264        3344 :     OUStringList    lFolders    = StorageHolder::impl_st_parsePath(sNormedPath);
     265             : 
     266             :     /* convert list of paths in the following way:
     267             :         [0] = "path_1" => "path_1
     268             :         [1] = "path_2" => "path_1/path_2"
     269             :         [2] = "path_3" => "path_1/path_2/path_3"
     270             :     */
     271        1672 :     OUStringList::iterator pIt1       ;
     272        3344 :     OUString        sParentPath;
     273       12696 :     for (  pIt1  = lFolders.begin();
     274        8464 :            pIt1 != lFolders.end()  ;
     275             :          ++pIt1                    )
     276             :     {
     277        2560 :         OUString sCurrentRelPath  = sParentPath;
     278        2560 :                         sCurrentRelPath += *pIt1;
     279        2560 :                         sCurrentRelPath += PATH_SEPARATOR;
     280        2560 :         *pIt1       = sCurrentRelPath;
     281        2560 :         sParentPath = sCurrentRelPath;
     282        2560 :     }
     283             : 
     284             :     // SAFE -> ------------------------------
     285        3344 :     ReadGuard aReadLock(m_aLock);
     286             : 
     287        1672 :     OUStringList::reverse_iterator pIt2;
     288       12696 :     for (  pIt2  = lFolders.rbegin();
     289        8464 :            pIt2 != lFolders.rend()  ;
     290             :          ++pIt2                     )
     291             :     {
     292        2560 :         OUString             sPath = *pIt2;
     293        2560 :         TPath2StorageInfo::iterator pPath = m_lStorages.find(sPath);
     294        2560 :         if (pPath == m_lStorages.end())
     295        1237 :             continue; // ???
     296             : 
     297        1323 :         TStorageInfo& rInfo = pPath->second;
     298        1323 :         --rInfo.UseCount;
     299        1323 :         if (rInfo.UseCount < 1)
     300             :         {
     301         697 :             rInfo.Storage.clear();
     302         697 :             m_lStorages.erase(pPath);
     303             :         }
     304        1323 :     }
     305             : 
     306        3344 :     aReadLock.unlock();
     307             :     // <- SAFE ------------------------------
     308        1672 : }
     309             : 
     310             : //-----------------------------------------------
     311           0 : void StorageHolder::notifyPath(const OUString& sPath)
     312             : {
     313           0 :     OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
     314             : 
     315             :     // SAFE -> ------------------------------
     316           0 :     ReadGuard aReadLock(m_aLock);
     317             : 
     318           0 :     TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath);
     319           0 :     if (pIt1 == m_lStorages.end())
     320           0 :         return;
     321             : 
     322           0 :     TStorageInfo& rInfo = pIt1->second;
     323           0 :     TStorageListenerList::iterator pIt2;
     324           0 :     for (  pIt2  = rInfo.Listener.begin();
     325           0 :            pIt2 != rInfo.Listener.end()  ;
     326             :          ++pIt2                          )
     327             :     {
     328           0 :         IStorageListener* pListener = *pIt2;
     329           0 :         if (pListener)
     330           0 :             pListener->changesOccurred(sNormedPath);
     331             :     }
     332             : 
     333           0 :     aReadLock.unlock();
     334             :     // <- SAFE ------------------------------
     335             : }
     336             : 
     337             : //-----------------------------------------------
     338         622 : void StorageHolder::addStorageListener(      IStorageListener* pListener,
     339             :                                        const OUString&  sPath    )
     340             : {
     341         622 :     OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
     342             : 
     343             :     // SAFE -> ------------------------------
     344        1244 :     ReadGuard aReadLock(m_aLock);
     345             : 
     346         622 :     TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath);
     347         622 :     if (pIt1 == m_lStorages.end())
     348         622 :         return;
     349             : 
     350         622 :     TStorageInfo& rInfo = pIt1->second;
     351         622 :     TStorageListenerList::iterator pIt2 = ::std::find(rInfo.Listener.begin(), rInfo.Listener.end(), pListener);
     352         622 :     if (pIt2 == rInfo.Listener.end())
     353         622 :         rInfo.Listener.push_back(pListener);
     354             : 
     355        1244 :     aReadLock.unlock();
     356             :     // <- SAFE ------------------------------
     357             : }
     358             : 
     359             : //-----------------------------------------------
     360         614 : void StorageHolder::removeStorageListener(      IStorageListener* pListener,
     361             :                                           const OUString&  sPath    )
     362             : {
     363         614 :     OUString sNormedPath = StorageHolder::impl_st_normPath(sPath);
     364             : 
     365             :     // SAFE -> ------------------------------
     366        1228 :     ReadGuard aReadLock(m_aLock);
     367             : 
     368         614 :     TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath);
     369         614 :     if (pIt1 == m_lStorages.end())
     370         614 :         return;
     371             : 
     372         614 :     TStorageInfo& rInfo = pIt1->second;
     373         614 :     TStorageListenerList::iterator pIt2 = ::std::find(rInfo.Listener.begin(), rInfo.Listener.end(), pListener);
     374         614 :     if (pIt2 != rInfo.Listener.end())
     375         614 :         rInfo.Listener.erase(pIt2);
     376             : 
     377        1228 :     aReadLock.unlock();
     378             :     // <- SAFE ------------------------------
     379             : }
     380             : 
     381             : //-----------------------------------------------
     382         154 : OUString StorageHolder::getPathOfStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
     383             : {
     384             :     // SAFE -> ------------------------------
     385         154 :     ReadGuard aReadLock(m_aLock);
     386             : 
     387         154 :     TPath2StorageInfo::const_iterator pIt;
     388        1584 :     for (  pIt  = m_lStorages.begin();
     389        1056 :            pIt != m_lStorages.end()  ;
     390             :          ++pIt                       )
     391             :     {
     392         525 :         const TStorageInfo& rInfo = pIt->second;
     393         525 :         if (rInfo.Storage == xStorage)
     394         151 :             break;
     395             :     }
     396             : 
     397         154 :     if (pIt == m_lStorages.end())
     398           3 :         return OUString();
     399             : 
     400         151 :     return pIt->first;
     401             : 
     402             :     // <- SAFE ------------------------------
     403             : }
     404             : 
     405             : //-----------------------------------------------
     406         154 : css::uno::Reference< css::embed::XStorage > StorageHolder::getParentStorage(const css::uno::Reference< css::embed::XStorage >& xChild)
     407             : {
     408         154 :     OUString sChildPath = getPathOfStorage(xChild);
     409         154 :     return getParentStorage(sChildPath);
     410             : }
     411             : 
     412             : //-----------------------------------------------
     413         154 : css::uno::Reference< css::embed::XStorage > StorageHolder::getParentStorage(const OUString& sChildPath)
     414             : {
     415             :     // normed path = "a/b/c/" ... we search for "a/b/"
     416         154 :     OUString sNormedPath = StorageHolder::impl_st_normPath(sChildPath);
     417         308 :     OUStringList    lFolders    = StorageHolder::impl_st_parsePath(sNormedPath);
     418         154 :     sal_Int32       c           = lFolders.size();
     419             : 
     420             :     // a) ""       => -       => no parent
     421             :     // b) "a/b/c/" => "a/b/"  => return storage "a/b/"
     422             :     // c) "a/"     => ""      => return root !
     423             : 
     424             :     // a)
     425         154 :     if (c < 1)
     426           3 :         return css::uno::Reference< css::embed::XStorage >();
     427             : 
     428             :     // SAFE -> ----------------------------------
     429         302 :     ReadGuard aReadLock(m_aLock);
     430             : 
     431             :     // b)
     432         151 :     if (c < 2)
     433           0 :         return m_xRoot;
     434             : 
     435             :     // c)
     436         302 :     OUString sParentPath;
     437         151 :     sal_Int32       i = 0;
     438         453 :     for (i=0; i<c-1; ++i)
     439             :     {
     440         302 :         sParentPath += lFolders[i];
     441         302 :         sParentPath += PATH_SEPARATOR;
     442             :     }
     443             : 
     444         151 :     TPath2StorageInfo::const_iterator pParent = m_lStorages.find(sParentPath);
     445         151 :     if (pParent != m_lStorages.end())
     446         151 :         return pParent->second.Storage;
     447             : 
     448           0 :     aReadLock.unlock();
     449             :     // <- SAFE ----------------------------------
     450             : 
     451             :     // ?
     452             :     LOG_WARNING("StorageHolder::getParentStorage()", "Unexpected situation. Cached storage item seems to be wrong.")
     453         154 :     return css::uno::Reference< css::embed::XStorage >();
     454             : }
     455             : 
     456             : //-----------------------------------------------
     457           0 : void StorageHolder::operator=(const StorageHolder& rCopy)
     458             : {
     459             :     // SAFE -> ----------------------------------
     460           0 :     WriteGuard aWriteLock(m_aLock);
     461             : 
     462           0 :     m_xRoot     = rCopy.m_xRoot;
     463           0 :     m_lStorages = rCopy.m_lStorages;
     464             : 
     465           0 :     aWriteLock.unlock();
     466             :     // <- SAFE ----------------------------------
     467           0 : }
     468             : 
     469             : //-----------------------------------------------
     470        1354 : css::uno::Reference< css::embed::XStorage > StorageHolder::openSubStorageWithFallback(const css::uno::Reference< css::embed::XStorage >& xBaseStorage  ,
     471             :                                                                                       const OUString&                             sSubStorage   ,
     472             :                                                                                             sal_Int32                                    eOpenMode     ,
     473             :                                                                                             sal_Bool                                     bAllowFallback)
     474             : {
     475             :     // a) try it first with user specified open mode
     476             :     //    ignore errors ... but save it for later use!
     477        1354 :     css::uno::Exception exResult;
     478             :     try
     479             :     {
     480        1354 :         css::uno::Reference< css::embed::XStorage > xSubStorage = xBaseStorage->openStorageElement(sSubStorage, eOpenMode);
     481        1344 :         if (xSubStorage.is())
     482        1344 :             return xSubStorage;
     483             :     }
     484           0 :     catch(const css::uno::RuntimeException&)
     485           0 :         { throw; }
     486          20 :     catch(const css::uno::Exception& ex)
     487          10 :         { exResult = ex; }
     488             : 
     489             :     // b) readonly already tried? => forward last error!
     490          10 :     if (
     491          10 :         (!bAllowFallback                                                                 ) ||   // fallback allowed  ?
     492          10 :         ((eOpenMode & css::embed::ElementModes::WRITE) != css::embed::ElementModes::WRITE)      // fallback possible ?
     493             :        )
     494           7 :         throw exResult;
     495             : 
     496             :     // c) try it readonly
     497             :     //    dont catch exception here! Outside code whish to know, if operation failed or not.
     498             :     //    Otherwhise they work on NULL references ...
     499           3 :     sal_Int32 eNewMode = (eOpenMode & ~css::embed::ElementModes::WRITE);
     500           3 :     css::uno::Reference< css::embed::XStorage > xSubStorage = xBaseStorage->openStorageElement(sSubStorage, eNewMode);
     501           0 :     if (xSubStorage.is())
     502           0 :         return xSubStorage;
     503             : 
     504             :     // d) no chance!
     505             :     LOG_WARNING("openSubStorageWithFallback()", "Unexpected situation! Got no exception for missing storage ...")
     506        1354 :     return css::uno::Reference< css::embed::XStorage >();
     507             : }
     508             : 
     509             : //-----------------------------------------------
     510           0 : css::uno::Reference< css::io::XStream > StorageHolder::openSubStreamWithFallback(const css::uno::Reference< css::embed::XStorage >& xBaseStorage  ,
     511             :                                                                                  const OUString&                             sSubStream    ,
     512             :                                                                                        sal_Int32                                    eOpenMode     ,
     513             :                                                                                        sal_Bool                                     bAllowFallback)
     514             : {
     515             :     // a) try it first with user specified open mode
     516             :     //    ignore errors ... but save it for later use!
     517           0 :     css::uno::Exception exResult;
     518             :     try
     519             :     {
     520           0 :         css::uno::Reference< css::io::XStream > xSubStream = xBaseStorage->openStreamElement(sSubStream, eOpenMode);
     521           0 :         if (xSubStream.is())
     522           0 :             return xSubStream;
     523             :     }
     524           0 :     catch(const css::uno::RuntimeException&)
     525           0 :         { throw; }
     526           0 :     catch(const css::uno::Exception& ex)
     527           0 :         { exResult = ex; }
     528             : 
     529             :     // b) readonly already tried? => forward last error!
     530           0 :     if (
     531           0 :         (!bAllowFallback                                                                 ) ||   // fallback allowed  ?
     532           0 :         ((eOpenMode & css::embed::ElementModes::WRITE) != css::embed::ElementModes::WRITE)      // fallback possible ?
     533             :        )
     534           0 :         throw exResult;
     535             : 
     536             :     // c) try it readonly
     537             :     //    dont catch exception here! Outside code whish to know, if operation failed or not.
     538             :     //    Otherwhise they work on NULL references ...
     539           0 :     sal_Int32 eNewMode = (eOpenMode & ~css::embed::ElementModes::WRITE);
     540           0 :     css::uno::Reference< css::io::XStream > xSubStream = xBaseStorage->openStreamElement(sSubStream, eNewMode);
     541           0 :     if (xSubStream.is())
     542           0 :         return xSubStream;
     543             : 
     544             :     // d) no chance!
     545             :     LOG_WARNING("openSubStreamWithFallbacks()", "Unexpected situation! Got no exception for missing stream ...")
     546           0 :     return css::uno::Reference< css::io::XStream >();
     547             : }
     548             : 
     549             : //-----------------------------------------------
     550        4146 : OUString StorageHolder::impl_st_normPath(const OUString& sPath)
     551             : {
     552             :     // path must start without "/" but end with "/"!
     553             : 
     554        4146 :     OUString sNormedPath = sPath;
     555             : 
     556             :     // "/bla" => "bla" && "/" => "" (!)
     557        4146 :     if (sNormedPath.indexOf(PATH_SEPARATOR) == 0)
     558           0 :         sNormedPath += sNormedPath.copy(1);
     559             : 
     560             :     // "/" => "" || "" => "" ?
     561        4146 :     if (sNormedPath.isEmpty())
     562           3 :         return OUString();
     563             : 
     564             :     // "bla" => "bla/"
     565        4143 :     if (sNormedPath.lastIndexOf(PATH_SEPARATOR) != (sNormedPath.getLength()-1))
     566        3992 :         sNormedPath += PATH_SEPARATOR;
     567             : 
     568        4143 :     return sNormedPath;
     569             : }
     570             : 
     571             : //-----------------------------------------------
     572        2910 : OUStringList StorageHolder::impl_st_parsePath(const OUString& sPath)
     573             : {
     574        2910 :     OUStringList lToken;
     575        2910 :     sal_Int32    i  = 0;
     576             :     while (true)
     577             :     {
     578        7931 :         OUString sToken = sPath.getToken(0, PATH_SEPARATOR_UNICODE, i);
     579        7931 :         if (i < 0)
     580        2910 :             break;
     581        5021 :         lToken.push_back(sToken);
     582        5021 :     }
     583        2910 :     return lToken;
     584             : }
     585             : 
     586             : //===============================================
     587             : } // namespace framework
     588             : 
     589             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10