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 //-----------------------------------------------
StorageHolder()89cdf0e10cSrcweir StorageHolder::StorageHolder()
90cdf0e10cSrcweir : ThreadHelpBase( )
91cdf0e10cSrcweir , m_xSMGR (::comphelper::getProcessServiceFactory())
92cdf0e10cSrcweir {
93cdf0e10cSrcweir }
94cdf0e10cSrcweir
95cdf0e10cSrcweir //-----------------------------------------------
StorageHolder(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)96cdf0e10cSrcweir StorageHolder::StorageHolder(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
97cdf0e10cSrcweir : ThreadHelpBase( )
98cdf0e10cSrcweir , m_xSMGR (xSMGR)
99cdf0e10cSrcweir {
100cdf0e10cSrcweir }
101cdf0e10cSrcweir
102cdf0e10cSrcweir //-----------------------------------------------
~StorageHolder()103cdf0e10cSrcweir StorageHolder::~StorageHolder()
104cdf0e10cSrcweir {
105cdf0e10cSrcweir // TODO implement me
106cdf0e10cSrcweir // dispose/clear etcpp.
107cdf0e10cSrcweir }
108cdf0e10cSrcweir
109cdf0e10cSrcweir //-----------------------------------------------
forgetCachedStorages()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 //-----------------------------------------------
setRootStorage(const css::uno::Reference<css::embed::XStorage> & xRoot)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 //-----------------------------------------------
getRootStorage() const141cdf0e10cSrcweir 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 //-----------------------------------------------
openPath(const::rtl::OUString & sPath,sal_Int32 nOpenMode)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 //-----------------------------------------------
getAllPathStorages(const::rtl::OUString & sPath)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 //-----------------------------------------------
commitPath(const::rtl::OUString & sPath)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 //-----------------------------------------------
closePath(const::rtl::OUString & rPath)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 //-----------------------------------------------
notifyPath(const::rtl::OUString & sPath)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 //-----------------------------------------------
addStorageListener(IStorageListener * pListener,const::rtl::OUString & sPath)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 //-----------------------------------------------
removeStorageListener(IStorageListener * pListener,const::rtl::OUString & sPath)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 //-----------------------------------------------
getPathOfStorage(const css::uno::Reference<css::embed::XStorage> & xStorage)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 //-----------------------------------------------
getParentStorage(const css::uno::Reference<css::embed::XStorage> & xChild)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 //-----------------------------------------------
getParentStorage(const::rtl::OUString & sChildPath)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 //-----------------------------------------------
operator =(const StorageHolder & rCopy)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 //-----------------------------------------------
openSubStorageWithFallback(const css::uno::Reference<css::embed::XStorage> & xBaseStorage,const::rtl::OUString & sSubStorage,sal_Int32 eOpenMode,sal_Bool bAllowFallback)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 //-----------------------------------------------
openSubStreamWithFallback(const css::uno::Reference<css::embed::XStorage> & xBaseStorage,const::rtl::OUString & sSubStream,sal_Int32 eOpenMode,sal_Bool bAllowFallback)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 //-----------------------------------------------
impl_st_normPath(const::rtl::OUString & sPath)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 //-----------------------------------------------
impl_st_parsePath(const::rtl::OUString & sPath)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