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