xref: /AOO41X/main/framework/source/accelerators/storageholder.cxx (revision 6d739b60ff8f4ed2134ae1442e284f9da90334b4)
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