1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_framework.hxx" 30*cdf0e10cSrcweir #include <accelerators/storageholder.hxx> 31*cdf0e10cSrcweir 32*cdf0e10cSrcweir //=============================================== 33*cdf0e10cSrcweir // own includes 34*cdf0e10cSrcweir #include <threadhelp/readguard.hxx> 35*cdf0e10cSrcweir #include <threadhelp/writeguard.hxx> 36*cdf0e10cSrcweir #include <services.h> 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir //=============================================== 39*cdf0e10cSrcweir // interface includes 40*cdf0e10cSrcweir 41*cdf0e10cSrcweir #ifndef __COM_SUN_STAR_CONTAINER_NOSUCHELEMENTEXCEPTION_HPP_ 42*cdf0e10cSrcweir #include <com/sun/star/container/NoSuchElementException.hpp> 43*cdf0e10cSrcweir #endif 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir #ifndef __COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ 46*cdf0e10cSrcweir #include <com/sun/star/container/XNameAccess.hpp> 47*cdf0e10cSrcweir #endif 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir #ifndef __COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ 50*cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 51*cdf0e10cSrcweir #endif 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir #ifndef __COM_SUN_STAR_EMBED_ELEMENTMODES_HPP_ 54*cdf0e10cSrcweir #include <com/sun/star/embed/ElementModes.hpp> 55*cdf0e10cSrcweir #endif 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir #ifndef __COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_ 58*cdf0e10cSrcweir #include <com/sun/star/embed/XTransactedObject.hpp> 59*cdf0e10cSrcweir #endif 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir #ifndef __COM_SUN_STAR_EMBED_XPACKAGESTRUCTURECREATOR_HPP_ 62*cdf0e10cSrcweir #include <com/sun/star/embed/XPackageStructureCreator.hpp> 63*cdf0e10cSrcweir #endif 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir #ifndef __COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_ 66*cdf0e10cSrcweir #include <com/sun/star/lang/XSingleServiceFactory.hpp> 67*cdf0e10cSrcweir #endif 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir #ifndef __COM_SUN_STAR_IO_XSEEKABLE_HPP_ 70*cdf0e10cSrcweir #include <com/sun/star/io/XSeekable.hpp> 71*cdf0e10cSrcweir #endif 72*cdf0e10cSrcweir 73*cdf0e10cSrcweir //=============================================== 74*cdf0e10cSrcweir // other includes 75*cdf0e10cSrcweir #include <comphelper/processfactory.hxx> 76*cdf0e10cSrcweir 77*cdf0e10cSrcweir //=============================================== 78*cdf0e10cSrcweir // const 79*cdf0e10cSrcweir 80*cdf0e10cSrcweir #define PATH_SEPERATOR_ASCII "/" 81*cdf0e10cSrcweir #define PATH_SEPERATOR_UNICODE ((sal_Unicode)'/') 82*cdf0e10cSrcweir #define PATH_SEPERATOR ::rtl::OUString::createFromAscii(PATH_SEPERATOR_ASCII) 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir //=============================================== 85*cdf0e10cSrcweir // namespace 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir namespace framework 88*cdf0e10cSrcweir { 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir namespace css = ::com::sun::star; 91*cdf0e10cSrcweir 92*cdf0e10cSrcweir //----------------------------------------------- 93*cdf0e10cSrcweir StorageHolder::StorageHolder() 94*cdf0e10cSrcweir : ThreadHelpBase( ) 95*cdf0e10cSrcweir , m_xSMGR (::comphelper::getProcessServiceFactory()) 96*cdf0e10cSrcweir { 97*cdf0e10cSrcweir } 98*cdf0e10cSrcweir 99*cdf0e10cSrcweir //----------------------------------------------- 100*cdf0e10cSrcweir StorageHolder::StorageHolder(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 101*cdf0e10cSrcweir : ThreadHelpBase( ) 102*cdf0e10cSrcweir , m_xSMGR (xSMGR) 103*cdf0e10cSrcweir { 104*cdf0e10cSrcweir } 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir //----------------------------------------------- 107*cdf0e10cSrcweir StorageHolder::~StorageHolder() 108*cdf0e10cSrcweir { 109*cdf0e10cSrcweir // TODO implement me 110*cdf0e10cSrcweir // dispose/clear etcpp. 111*cdf0e10cSrcweir } 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir //----------------------------------------------- 114*cdf0e10cSrcweir void StorageHolder::forgetCachedStorages() 115*cdf0e10cSrcweir { 116*cdf0e10cSrcweir // SAFE -> ---------------------------------- 117*cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir TPath2StorageInfo::iterator pIt; 120*cdf0e10cSrcweir for ( pIt = m_lStorages.begin(); 121*cdf0e10cSrcweir pIt != m_lStorages.end() ; 122*cdf0e10cSrcweir ++pIt ) 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir TStorageInfo& rInfo = pIt->second; 125*cdf0e10cSrcweir // TODO think about listener ! 126*cdf0e10cSrcweir rInfo.Storage.clear(); 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir m_lStorages.clear(); 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir aWriteLock.unlock(); 131*cdf0e10cSrcweir // <- SAFE ---------------------------------- 132*cdf0e10cSrcweir } 133*cdf0e10cSrcweir 134*cdf0e10cSrcweir //----------------------------------------------- 135*cdf0e10cSrcweir void StorageHolder::setRootStorage(const css::uno::Reference< css::embed::XStorage >& xRoot) 136*cdf0e10cSrcweir { 137*cdf0e10cSrcweir // SAFE -> ---------------------------------- 138*cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 139*cdf0e10cSrcweir m_xRoot = xRoot; 140*cdf0e10cSrcweir aWriteLock.unlock(); 141*cdf0e10cSrcweir // <- SAFE ---------------------------------- 142*cdf0e10cSrcweir } 143*cdf0e10cSrcweir 144*cdf0e10cSrcweir //----------------------------------------------- 145*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > StorageHolder::getRootStorage() const 146*cdf0e10cSrcweir { 147*cdf0e10cSrcweir // SAFE -> ---------------------------------- 148*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 149*cdf0e10cSrcweir return m_xRoot; 150*cdf0e10cSrcweir // <- SAFE ---------------------------------- 151*cdf0e10cSrcweir } 152*cdf0e10cSrcweir 153*cdf0e10cSrcweir //----------------------------------------------- 154*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > StorageHolder::openPath(const ::rtl::OUString& sPath , 155*cdf0e10cSrcweir sal_Int32 nOpenMode) 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath); 158*cdf0e10cSrcweir OUStringList lFolders = StorageHolder::impl_st_parsePath(sNormedPath); 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir // SAFE -> ---------------------------------- 161*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 162*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > xParent = m_xRoot; 163*cdf0e10cSrcweir aReadLock.unlock(); 164*cdf0e10cSrcweir // <- SAFE ---------------------------------- 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > xChild ; 167*cdf0e10cSrcweir ::rtl::OUString sRelPath; 168*cdf0e10cSrcweir OUStringList::const_iterator pIt ; 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir for ( pIt = lFolders.begin(); 171*cdf0e10cSrcweir pIt != lFolders.end() ; 172*cdf0e10cSrcweir ++pIt ) 173*cdf0e10cSrcweir { 174*cdf0e10cSrcweir const ::rtl::OUString& sChild = *pIt; 175*cdf0e10cSrcweir ::rtl::OUString sCheckPath (sRelPath); 176*cdf0e10cSrcweir sCheckPath += sChild; 177*cdf0e10cSrcweir sCheckPath += PATH_SEPERATOR; 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir // SAFE -> ------------------------------ 180*cdf0e10cSrcweir aReadLock.lock(); 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir // If we found an already open storage ... we must increase 183*cdf0e10cSrcweir // its use count. Otherwhise it will may be closed to early :-) 184*cdf0e10cSrcweir TPath2StorageInfo::iterator pCheck = m_lStorages.find(sCheckPath); 185*cdf0e10cSrcweir TStorageInfo* pInfo = 0; 186*cdf0e10cSrcweir if (pCheck != m_lStorages.end()) 187*cdf0e10cSrcweir { 188*cdf0e10cSrcweir pInfo = &(pCheck->second); 189*cdf0e10cSrcweir ++(pInfo->UseCount); 190*cdf0e10cSrcweir xChild = pInfo->Storage; 191*cdf0e10cSrcweir } 192*cdf0e10cSrcweir else 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir aReadLock.unlock(); 195*cdf0e10cSrcweir // <- SAFE ------------------------------ 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir try 198*cdf0e10cSrcweir { 199*cdf0e10cSrcweir xChild = StorageHolder::openSubStorageWithFallback(xParent, sChild, nOpenMode, sal_True); // TODO think about delegating fallback decision to our own calli! 200*cdf0e10cSrcweir } 201*cdf0e10cSrcweir catch(const css::uno::RuntimeException& exRun) 202*cdf0e10cSrcweir { throw exRun; } 203*cdf0e10cSrcweir catch(const css::uno::Exception& exAny) 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir /* TODO URGENT! 206*cdf0e10cSrcweir in case we found some "already existing storages" on the path before and increased its UseCount ... 207*cdf0e10cSrcweir and now we will get an exception on creating a new sub storage ... 208*cdf0e10cSrcweir we must decrease all UseCounts, which was touched before. Otherwise these storages cant be closed! 209*cdf0e10cSrcweir 210*cdf0e10cSrcweir Idea: Using of another structure member "PossibleUseCount" as vector of unique numbers. 211*cdf0e10cSrcweir Every thread use another unique number to identify all "owned candidates". 212*cdf0e10cSrcweir A flush method with the same unique number force increasing of the "UseCount" variable then 213*cdf0e10cSrcweir inside a synchronized block ... 214*cdf0e10cSrcweir */ 215*cdf0e10cSrcweir throw exAny; 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir // SAFE -> ------------------------------ 219*cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 220*cdf0e10cSrcweir pInfo = &(m_lStorages[sCheckPath]); 221*cdf0e10cSrcweir pInfo->Storage = xChild; 222*cdf0e10cSrcweir pInfo->UseCount = 1; 223*cdf0e10cSrcweir aWriteLock.unlock(); 224*cdf0e10cSrcweir // <- SAFE ------------------------------ 225*cdf0e10cSrcweir } 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir xParent = xChild; 228*cdf0e10cSrcweir sRelPath += sChild; 229*cdf0e10cSrcweir sRelPath += PATH_SEPERATOR; 230*cdf0e10cSrcweir } 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir // TODO think about return last storage as working storage ... but dont caching it inside this holder! 233*cdf0e10cSrcweir // => otherwhise the same storage is may be commit more then once. 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir return xChild; 236*cdf0e10cSrcweir } 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir //----------------------------------------------- 239*cdf0e10cSrcweir StorageHolder::TStorageList StorageHolder::getAllPathStorages(const ::rtl::OUString& sPath) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath); 242*cdf0e10cSrcweir OUStringList lFolders = StorageHolder::impl_st_parsePath(sNormedPath); 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir StorageHolder::TStorageList lStoragesOfPath; 245*cdf0e10cSrcweir ::rtl::OUString sRelPath ; 246*cdf0e10cSrcweir OUStringList::const_iterator pIt ; 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir // SAFE -> ---------------------------------- 249*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 250*cdf0e10cSrcweir 251*cdf0e10cSrcweir for ( pIt = lFolders.begin(); 252*cdf0e10cSrcweir pIt != lFolders.end() ; 253*cdf0e10cSrcweir ++pIt ) 254*cdf0e10cSrcweir { 255*cdf0e10cSrcweir const ::rtl::OUString& sChild = *pIt; 256*cdf0e10cSrcweir ::rtl::OUString sCheckPath (sRelPath); 257*cdf0e10cSrcweir sCheckPath += sChild; 258*cdf0e10cSrcweir sCheckPath += PATH_SEPERATOR; 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir TPath2StorageInfo::iterator pCheck = m_lStorages.find(sCheckPath); 261*cdf0e10cSrcweir if (pCheck == m_lStorages.end()) 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir // at least one path element was not found 264*cdf0e10cSrcweir // Seems that this path isnt open ... 265*cdf0e10cSrcweir lStoragesOfPath.clear(); 266*cdf0e10cSrcweir return lStoragesOfPath; 267*cdf0e10cSrcweir } 268*cdf0e10cSrcweir 269*cdf0e10cSrcweir TStorageInfo& rInfo = pCheck->second; 270*cdf0e10cSrcweir lStoragesOfPath.push_back(rInfo.Storage); 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir sRelPath += sChild; 273*cdf0e10cSrcweir sRelPath += PATH_SEPERATOR; 274*cdf0e10cSrcweir } 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir aReadLock.unlock(); 277*cdf0e10cSrcweir // <- SAFE ---------------------------------- 278*cdf0e10cSrcweir 279*cdf0e10cSrcweir return lStoragesOfPath; 280*cdf0e10cSrcweir } 281*cdf0e10cSrcweir 282*cdf0e10cSrcweir //----------------------------------------------- 283*cdf0e10cSrcweir void StorageHolder::commitPath(const ::rtl::OUString& sPath) 284*cdf0e10cSrcweir { 285*cdf0e10cSrcweir StorageHolder::TStorageList lStorages = getAllPathStorages(sPath); 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir css::uno::Reference< css::embed::XTransactedObject > xCommit; 288*cdf0e10cSrcweir StorageHolder::TStorageList::reverse_iterator pIt; 289*cdf0e10cSrcweir for ( pIt = lStorages.rbegin(); // order of commit is important ... otherwhise changes are not recognized! 290*cdf0e10cSrcweir pIt != lStorages.rend() ; 291*cdf0e10cSrcweir ++pIt ) 292*cdf0e10cSrcweir { 293*cdf0e10cSrcweir xCommit = css::uno::Reference< css::embed::XTransactedObject >(*pIt, css::uno::UNO_QUERY); 294*cdf0e10cSrcweir if (!xCommit.is()) 295*cdf0e10cSrcweir continue; 296*cdf0e10cSrcweir xCommit->commit(); 297*cdf0e10cSrcweir } 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir // SAFE -> ------------------------------ 300*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 301*cdf0e10cSrcweir xCommit = css::uno::Reference< css::embed::XTransactedObject >(m_xRoot, css::uno::UNO_QUERY); 302*cdf0e10cSrcweir aReadLock.unlock(); 303*cdf0e10cSrcweir // <- SAFE ------------------------------ 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir if (xCommit.is()) 306*cdf0e10cSrcweir xCommit->commit(); 307*cdf0e10cSrcweir } 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir //----------------------------------------------- 310*cdf0e10cSrcweir void StorageHolder::closePath(const ::rtl::OUString& rPath) 311*cdf0e10cSrcweir { 312*cdf0e10cSrcweir ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(rPath); 313*cdf0e10cSrcweir OUStringList lFolders = StorageHolder::impl_st_parsePath(sNormedPath); 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir /* convert list of pathes in the following way: 316*cdf0e10cSrcweir [0] = "path_1" => "path_1 317*cdf0e10cSrcweir [1] = "path_2" => "path_1/path_2" 318*cdf0e10cSrcweir [2] = "path_3" => "path_1/path_2/path_3" 319*cdf0e10cSrcweir */ 320*cdf0e10cSrcweir OUStringList::iterator pIt1 ; 321*cdf0e10cSrcweir ::rtl::OUString sParentPath; 322*cdf0e10cSrcweir for ( pIt1 = lFolders.begin(); 323*cdf0e10cSrcweir pIt1 != lFolders.end() ; 324*cdf0e10cSrcweir ++pIt1 ) 325*cdf0e10cSrcweir { 326*cdf0e10cSrcweir ::rtl::OUString sCurrentRelPath = sParentPath; 327*cdf0e10cSrcweir sCurrentRelPath += *pIt1; 328*cdf0e10cSrcweir sCurrentRelPath += PATH_SEPERATOR; 329*cdf0e10cSrcweir *pIt1 = sCurrentRelPath; 330*cdf0e10cSrcweir sParentPath = sCurrentRelPath; 331*cdf0e10cSrcweir } 332*cdf0e10cSrcweir 333*cdf0e10cSrcweir // SAFE -> ------------------------------ 334*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 335*cdf0e10cSrcweir 336*cdf0e10cSrcweir OUStringList::reverse_iterator pIt2; 337*cdf0e10cSrcweir for ( pIt2 = lFolders.rbegin(); 338*cdf0e10cSrcweir pIt2 != lFolders.rend() ; 339*cdf0e10cSrcweir ++pIt2 ) 340*cdf0e10cSrcweir { 341*cdf0e10cSrcweir ::rtl::OUString sPath = *pIt2; 342*cdf0e10cSrcweir TPath2StorageInfo::iterator pPath = m_lStorages.find(sPath); 343*cdf0e10cSrcweir if (pPath == m_lStorages.end()) 344*cdf0e10cSrcweir continue; // ??? 345*cdf0e10cSrcweir 346*cdf0e10cSrcweir TStorageInfo& rInfo = pPath->second; 347*cdf0e10cSrcweir --rInfo.UseCount; 348*cdf0e10cSrcweir if (rInfo.UseCount < 1) 349*cdf0e10cSrcweir { 350*cdf0e10cSrcweir rInfo.Storage.clear(); 351*cdf0e10cSrcweir m_lStorages.erase(pPath); 352*cdf0e10cSrcweir } 353*cdf0e10cSrcweir } 354*cdf0e10cSrcweir 355*cdf0e10cSrcweir aReadLock.unlock(); 356*cdf0e10cSrcweir // <- SAFE ------------------------------ 357*cdf0e10cSrcweir } 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir //----------------------------------------------- 360*cdf0e10cSrcweir void StorageHolder::notifyPath(const ::rtl::OUString& sPath) 361*cdf0e10cSrcweir { 362*cdf0e10cSrcweir ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath); 363*cdf0e10cSrcweir 364*cdf0e10cSrcweir // SAFE -> ------------------------------ 365*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 366*cdf0e10cSrcweir 367*cdf0e10cSrcweir TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath); 368*cdf0e10cSrcweir if (pIt1 == m_lStorages.end()) 369*cdf0e10cSrcweir return; 370*cdf0e10cSrcweir 371*cdf0e10cSrcweir TStorageInfo& rInfo = pIt1->second; 372*cdf0e10cSrcweir TStorageListenerList::iterator pIt2; 373*cdf0e10cSrcweir for ( pIt2 = rInfo.Listener.begin(); 374*cdf0e10cSrcweir pIt2 != rInfo.Listener.end() ; 375*cdf0e10cSrcweir ++pIt2 ) 376*cdf0e10cSrcweir { 377*cdf0e10cSrcweir IStorageListener* pListener = *pIt2; 378*cdf0e10cSrcweir if (pListener) 379*cdf0e10cSrcweir pListener->changesOccured(sNormedPath); 380*cdf0e10cSrcweir } 381*cdf0e10cSrcweir 382*cdf0e10cSrcweir aReadLock.unlock(); 383*cdf0e10cSrcweir // <- SAFE ------------------------------ 384*cdf0e10cSrcweir } 385*cdf0e10cSrcweir 386*cdf0e10cSrcweir //----------------------------------------------- 387*cdf0e10cSrcweir void StorageHolder::addStorageListener( IStorageListener* pListener, 388*cdf0e10cSrcweir const ::rtl::OUString& sPath ) 389*cdf0e10cSrcweir { 390*cdf0e10cSrcweir ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath); 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir // SAFE -> ------------------------------ 393*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 394*cdf0e10cSrcweir 395*cdf0e10cSrcweir TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath); 396*cdf0e10cSrcweir if (pIt1 == m_lStorages.end()) 397*cdf0e10cSrcweir return; 398*cdf0e10cSrcweir 399*cdf0e10cSrcweir TStorageInfo& rInfo = pIt1->second; 400*cdf0e10cSrcweir TStorageListenerList::iterator pIt2 = ::std::find(rInfo.Listener.begin(), rInfo.Listener.end(), pListener); 401*cdf0e10cSrcweir if (pIt2 == rInfo.Listener.end()) 402*cdf0e10cSrcweir rInfo.Listener.push_back(pListener); 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir aReadLock.unlock(); 405*cdf0e10cSrcweir // <- SAFE ------------------------------ 406*cdf0e10cSrcweir } 407*cdf0e10cSrcweir 408*cdf0e10cSrcweir //----------------------------------------------- 409*cdf0e10cSrcweir void StorageHolder::removeStorageListener( IStorageListener* pListener, 410*cdf0e10cSrcweir const ::rtl::OUString& sPath ) 411*cdf0e10cSrcweir { 412*cdf0e10cSrcweir ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sPath); 413*cdf0e10cSrcweir 414*cdf0e10cSrcweir // SAFE -> ------------------------------ 415*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir TPath2StorageInfo::iterator pIt1 = m_lStorages.find(sNormedPath); 418*cdf0e10cSrcweir if (pIt1 == m_lStorages.end()) 419*cdf0e10cSrcweir return; 420*cdf0e10cSrcweir 421*cdf0e10cSrcweir TStorageInfo& rInfo = pIt1->second; 422*cdf0e10cSrcweir TStorageListenerList::iterator pIt2 = ::std::find(rInfo.Listener.begin(), rInfo.Listener.end(), pListener); 423*cdf0e10cSrcweir if (pIt2 != rInfo.Listener.end()) 424*cdf0e10cSrcweir rInfo.Listener.erase(pIt2); 425*cdf0e10cSrcweir 426*cdf0e10cSrcweir aReadLock.unlock(); 427*cdf0e10cSrcweir // <- SAFE ------------------------------ 428*cdf0e10cSrcweir } 429*cdf0e10cSrcweir 430*cdf0e10cSrcweir //----------------------------------------------- 431*cdf0e10cSrcweir ::rtl::OUString StorageHolder::getPathOfStorage(const css::uno::Reference< css::embed::XStorage >& xStorage) 432*cdf0e10cSrcweir { 433*cdf0e10cSrcweir // SAFE -> ------------------------------ 434*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 435*cdf0e10cSrcweir 436*cdf0e10cSrcweir TPath2StorageInfo::const_iterator pIt; 437*cdf0e10cSrcweir for ( pIt = m_lStorages.begin(); 438*cdf0e10cSrcweir pIt != m_lStorages.end() ; 439*cdf0e10cSrcweir ++pIt ) 440*cdf0e10cSrcweir { 441*cdf0e10cSrcweir const TStorageInfo& rInfo = pIt->second; 442*cdf0e10cSrcweir if (rInfo.Storage == xStorage) 443*cdf0e10cSrcweir break; 444*cdf0e10cSrcweir } 445*cdf0e10cSrcweir 446*cdf0e10cSrcweir if (pIt == m_lStorages.end()) 447*cdf0e10cSrcweir return ::rtl::OUString(); 448*cdf0e10cSrcweir 449*cdf0e10cSrcweir return pIt->first; 450*cdf0e10cSrcweir 451*cdf0e10cSrcweir // <- SAFE ------------------------------ 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir //----------------------------------------------- 455*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > StorageHolder::getParentStorage(const css::uno::Reference< css::embed::XStorage >& xChild) 456*cdf0e10cSrcweir { 457*cdf0e10cSrcweir ::rtl::OUString sChildPath = getPathOfStorage(xChild); 458*cdf0e10cSrcweir return getParentStorage(sChildPath); 459*cdf0e10cSrcweir } 460*cdf0e10cSrcweir 461*cdf0e10cSrcweir //----------------------------------------------- 462*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > StorageHolder::getParentStorage(const ::rtl::OUString& sChildPath) 463*cdf0e10cSrcweir { 464*cdf0e10cSrcweir // normed path = "a/b/c/" ... we search for "a/b/" 465*cdf0e10cSrcweir ::rtl::OUString sNormedPath = StorageHolder::impl_st_normPath(sChildPath); 466*cdf0e10cSrcweir OUStringList lFolders = StorageHolder::impl_st_parsePath(sNormedPath); 467*cdf0e10cSrcweir sal_Int32 c = lFolders.size(); 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir // a) "" => - => no parent 470*cdf0e10cSrcweir // b) "a/b/c/" => "a/b/" => return storage "a/b/" 471*cdf0e10cSrcweir // c) "a/" => "" => return root ! 472*cdf0e10cSrcweir 473*cdf0e10cSrcweir // a) 474*cdf0e10cSrcweir if (c < 1) 475*cdf0e10cSrcweir return css::uno::Reference< css::embed::XStorage >(); 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir // SAFE -> ---------------------------------- 478*cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 479*cdf0e10cSrcweir 480*cdf0e10cSrcweir // b) 481*cdf0e10cSrcweir if (c < 2) 482*cdf0e10cSrcweir return m_xRoot; 483*cdf0e10cSrcweir 484*cdf0e10cSrcweir // c) 485*cdf0e10cSrcweir ::rtl::OUString sParentPath; 486*cdf0e10cSrcweir sal_Int32 i = 0; 487*cdf0e10cSrcweir for (i=0; i<c-1; ++i) 488*cdf0e10cSrcweir { 489*cdf0e10cSrcweir sParentPath += lFolders[i]; 490*cdf0e10cSrcweir sParentPath += PATH_SEPERATOR; 491*cdf0e10cSrcweir } 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir TPath2StorageInfo::const_iterator pParent = m_lStorages.find(sParentPath); 494*cdf0e10cSrcweir if (pParent != m_lStorages.end()) 495*cdf0e10cSrcweir return pParent->second.Storage; 496*cdf0e10cSrcweir 497*cdf0e10cSrcweir aReadLock.unlock(); 498*cdf0e10cSrcweir // <- SAFE ---------------------------------- 499*cdf0e10cSrcweir 500*cdf0e10cSrcweir // ? 501*cdf0e10cSrcweir LOG_WARNING("StorageHolder::getParentStorage()", "Unexpected situation. Cached storage item seems to be wrong.") 502*cdf0e10cSrcweir return css::uno::Reference< css::embed::XStorage >(); 503*cdf0e10cSrcweir } 504*cdf0e10cSrcweir 505*cdf0e10cSrcweir //----------------------------------------------- 506*cdf0e10cSrcweir void StorageHolder::operator=(const StorageHolder& rCopy) 507*cdf0e10cSrcweir { 508*cdf0e10cSrcweir // SAFE -> ---------------------------------- 509*cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 510*cdf0e10cSrcweir 511*cdf0e10cSrcweir m_xSMGR = rCopy.m_xSMGR; // ??? 512*cdf0e10cSrcweir m_xRoot = rCopy.m_xRoot; 513*cdf0e10cSrcweir m_lStorages = rCopy.m_lStorages; 514*cdf0e10cSrcweir 515*cdf0e10cSrcweir aWriteLock.unlock(); 516*cdf0e10cSrcweir // <- SAFE ---------------------------------- 517*cdf0e10cSrcweir } 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir //----------------------------------------------- 520*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > StorageHolder::openSubStorageWithFallback(const css::uno::Reference< css::embed::XStorage >& xBaseStorage , 521*cdf0e10cSrcweir const ::rtl::OUString& sSubStorage , 522*cdf0e10cSrcweir sal_Int32 eOpenMode , 523*cdf0e10cSrcweir sal_Bool bAllowFallback) 524*cdf0e10cSrcweir { 525*cdf0e10cSrcweir // a) try it first with user specified open mode 526*cdf0e10cSrcweir // ignore errors ... but save it for later use! 527*cdf0e10cSrcweir css::uno::Exception exResult; 528*cdf0e10cSrcweir try 529*cdf0e10cSrcweir { 530*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > xSubStorage = xBaseStorage->openStorageElement(sSubStorage, eOpenMode); 531*cdf0e10cSrcweir if (xSubStorage.is()) 532*cdf0e10cSrcweir return xSubStorage; 533*cdf0e10cSrcweir } 534*cdf0e10cSrcweir catch(const css::uno::RuntimeException&) 535*cdf0e10cSrcweir { throw; } 536*cdf0e10cSrcweir catch(const css::uno::Exception& ex) 537*cdf0e10cSrcweir { exResult = ex; } 538*cdf0e10cSrcweir 539*cdf0e10cSrcweir // b) readonly already tried? => forward last error! 540*cdf0e10cSrcweir if ( 541*cdf0e10cSrcweir (!bAllowFallback ) || // fallback allowed ? 542*cdf0e10cSrcweir ((eOpenMode & css::embed::ElementModes::WRITE) != css::embed::ElementModes::WRITE) // fallback possible ? 543*cdf0e10cSrcweir ) 544*cdf0e10cSrcweir throw exResult; 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir // c) try it readonly 547*cdf0e10cSrcweir // dont catch exception here! Outside code whish to know, if operation failed or not. 548*cdf0e10cSrcweir // Otherwhise they work on NULL references ... 549*cdf0e10cSrcweir sal_Int32 eNewMode = (eOpenMode & ~css::embed::ElementModes::WRITE); 550*cdf0e10cSrcweir css::uno::Reference< css::embed::XStorage > xSubStorage = xBaseStorage->openStorageElement(sSubStorage, eNewMode); 551*cdf0e10cSrcweir if (xSubStorage.is()) 552*cdf0e10cSrcweir return xSubStorage; 553*cdf0e10cSrcweir 554*cdf0e10cSrcweir // d) no chance! 555*cdf0e10cSrcweir LOG_WARNING("openSubStorageWithFallback()", "Unexpected situation! Got no exception for missing storage ...") 556*cdf0e10cSrcweir return css::uno::Reference< css::embed::XStorage >(); 557*cdf0e10cSrcweir } 558*cdf0e10cSrcweir 559*cdf0e10cSrcweir //----------------------------------------------- 560*cdf0e10cSrcweir css::uno::Reference< css::io::XStream > StorageHolder::openSubStreamWithFallback(const css::uno::Reference< css::embed::XStorage >& xBaseStorage , 561*cdf0e10cSrcweir const ::rtl::OUString& sSubStream , 562*cdf0e10cSrcweir sal_Int32 eOpenMode , 563*cdf0e10cSrcweir sal_Bool bAllowFallback) 564*cdf0e10cSrcweir { 565*cdf0e10cSrcweir // a) try it first with user specified open mode 566*cdf0e10cSrcweir // ignore errors ... but save it for later use! 567*cdf0e10cSrcweir css::uno::Exception exResult; 568*cdf0e10cSrcweir try 569*cdf0e10cSrcweir { 570*cdf0e10cSrcweir css::uno::Reference< css::io::XStream > xSubStream = xBaseStorage->openStreamElement(sSubStream, eOpenMode); 571*cdf0e10cSrcweir if (xSubStream.is()) 572*cdf0e10cSrcweir return xSubStream; 573*cdf0e10cSrcweir } 574*cdf0e10cSrcweir catch(const css::uno::RuntimeException&) 575*cdf0e10cSrcweir { throw; } 576*cdf0e10cSrcweir catch(const css::uno::Exception& ex) 577*cdf0e10cSrcweir { exResult = ex; } 578*cdf0e10cSrcweir 579*cdf0e10cSrcweir // b) readonly already tried? => forward last error! 580*cdf0e10cSrcweir if ( 581*cdf0e10cSrcweir (!bAllowFallback ) || // fallback allowed ? 582*cdf0e10cSrcweir ((eOpenMode & css::embed::ElementModes::WRITE) != css::embed::ElementModes::WRITE) // fallback possible ? 583*cdf0e10cSrcweir ) 584*cdf0e10cSrcweir throw exResult; 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir // c) try it readonly 587*cdf0e10cSrcweir // dont catch exception here! Outside code whish to know, if operation failed or not. 588*cdf0e10cSrcweir // Otherwhise they work on NULL references ... 589*cdf0e10cSrcweir sal_Int32 eNewMode = (eOpenMode & ~css::embed::ElementModes::WRITE); 590*cdf0e10cSrcweir css::uno::Reference< css::io::XStream > xSubStream = xBaseStorage->openStreamElement(sSubStream, eNewMode); 591*cdf0e10cSrcweir if (xSubStream.is()) 592*cdf0e10cSrcweir return xSubStream; 593*cdf0e10cSrcweir 594*cdf0e10cSrcweir // d) no chance! 595*cdf0e10cSrcweir LOG_WARNING("openSubStreamWithFallbacks()", "Unexpected situation! Got no exception for missing stream ...") 596*cdf0e10cSrcweir return css::uno::Reference< css::io::XStream >(); 597*cdf0e10cSrcweir } 598*cdf0e10cSrcweir 599*cdf0e10cSrcweir //----------------------------------------------- 600*cdf0e10cSrcweir ::rtl::OUString StorageHolder::impl_st_normPath(const ::rtl::OUString& sPath) 601*cdf0e10cSrcweir { 602*cdf0e10cSrcweir // path must start without "/" but end with "/"! 603*cdf0e10cSrcweir 604*cdf0e10cSrcweir ::rtl::OUString sNormedPath = sPath; 605*cdf0e10cSrcweir 606*cdf0e10cSrcweir // "/bla" => "bla" && "/" => "" (!) 607*cdf0e10cSrcweir if (sNormedPath.indexOf(PATH_SEPERATOR) == 0) 608*cdf0e10cSrcweir sNormedPath += sNormedPath.copy(1); 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir // "/" => "" || "" => "" ? 611*cdf0e10cSrcweir if (sNormedPath.getLength() < 1) 612*cdf0e10cSrcweir return ::rtl::OUString(); 613*cdf0e10cSrcweir 614*cdf0e10cSrcweir // "bla" => "bla/" 615*cdf0e10cSrcweir if (sNormedPath.lastIndexOf(PATH_SEPERATOR) != (sNormedPath.getLength()-1)) 616*cdf0e10cSrcweir sNormedPath += PATH_SEPERATOR; 617*cdf0e10cSrcweir 618*cdf0e10cSrcweir return sNormedPath; 619*cdf0e10cSrcweir } 620*cdf0e10cSrcweir 621*cdf0e10cSrcweir //----------------------------------------------- 622*cdf0e10cSrcweir OUStringList StorageHolder::impl_st_parsePath(const ::rtl::OUString& sPath) 623*cdf0e10cSrcweir { 624*cdf0e10cSrcweir OUStringList lToken; 625*cdf0e10cSrcweir sal_Int32 i = 0; 626*cdf0e10cSrcweir while (sal_True) 627*cdf0e10cSrcweir { 628*cdf0e10cSrcweir ::rtl::OUString sToken = sPath.getToken(0, PATH_SEPERATOR_UNICODE, i); 629*cdf0e10cSrcweir if (i < 0) 630*cdf0e10cSrcweir break; 631*cdf0e10cSrcweir lToken.push_back(sToken); 632*cdf0e10cSrcweir } 633*cdf0e10cSrcweir return lToken; 634*cdf0e10cSrcweir } 635*cdf0e10cSrcweir 636*cdf0e10cSrcweir //=============================================== 637*cdf0e10cSrcweir } // namespace framework 638