xref: /aoo42x/main/ucb/source/ucp/tdoc/tdoc_storage.cxx (revision 2f86921c)
1*2f86921cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*2f86921cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*2f86921cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*2f86921cSAndrew Rist  * distributed with this work for additional information
6*2f86921cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*2f86921cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*2f86921cSAndrew Rist  * "License"); you may not use this file except in compliance
9*2f86921cSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*2f86921cSAndrew Rist  *
11*2f86921cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*2f86921cSAndrew Rist  *
13*2f86921cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*2f86921cSAndrew Rist  * software distributed under the License is distributed on an
15*2f86921cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*2f86921cSAndrew Rist  * KIND, either express or implied.  See the License for the
17*2f86921cSAndrew Rist  * specific language governing permissions and limitations
18*2f86921cSAndrew Rist  * under the License.
19*2f86921cSAndrew Rist  *
20*2f86921cSAndrew Rist  *************************************************************/
21*2f86921cSAndrew Rist 
22*2f86921cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_ucb.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir /**************************************************************************
28cdf0e10cSrcweir 								TODO
29cdf0e10cSrcweir  **************************************************************************
30cdf0e10cSrcweir 
31cdf0e10cSrcweir  - remove root storage access workaround
32cdf0e10cSrcweir 
33cdf0e10cSrcweir  *************************************************************************/
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #define ROOTSTORAGE_ACCESS_WORKAROUND 1
36cdf0e10cSrcweir 
37cdf0e10cSrcweir #include <memory>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include "com/sun/star/beans/XPropertySet.hpp"
40cdf0e10cSrcweir #include "com/sun/star/embed/ElementModes.hpp"
41cdf0e10cSrcweir #include "com/sun/star/lang/XSingleServiceFactory.hpp"
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #include "tdoc_uri.hxx"
44cdf0e10cSrcweir #include "tdoc_docmgr.hxx"
45cdf0e10cSrcweir #include "tdoc_stgelems.hxx"
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include "tdoc_storage.hxx"
48cdf0e10cSrcweir 
49cdf0e10cSrcweir using namespace com::sun::star;
50cdf0e10cSrcweir using namespace tdoc_ucp;
51cdf0e10cSrcweir 
52cdf0e10cSrcweir 
53cdf0e10cSrcweir //=========================================================================
54cdf0e10cSrcweir //=========================================================================
55cdf0e10cSrcweir //
56cdf0e10cSrcweir // StorageElementFactory Implementation.
57cdf0e10cSrcweir //
58cdf0e10cSrcweir //=========================================================================
59cdf0e10cSrcweir //=========================================================================
60cdf0e10cSrcweir 
61cdf0e10cSrcweir StorageElementFactory::StorageElementFactory(
62cdf0e10cSrcweir     const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
63cdf0e10cSrcweir     const rtl::Reference< OfficeDocumentsManager > & xDocsMgr )
64cdf0e10cSrcweir : m_xDocsMgr( xDocsMgr ),
65cdf0e10cSrcweir   m_xSMgr( xSMgr )
66cdf0e10cSrcweir {
67cdf0e10cSrcweir }
68cdf0e10cSrcweir 
69cdf0e10cSrcweir //=========================================================================
70cdf0e10cSrcweir StorageElementFactory::~StorageElementFactory()
71cdf0e10cSrcweir {
72cdf0e10cSrcweir     OSL_ENSURE( m_aMap.size() == 0,
73cdf0e10cSrcweir         "StorageElementFactory::~StorageElementFactory - Dangling storages!" );
74cdf0e10cSrcweir }
75cdf0e10cSrcweir 
76cdf0e10cSrcweir //=========================================================================
77cdf0e10cSrcweir uno::Reference< embed::XStorage >
78cdf0e10cSrcweir StorageElementFactory::createTemporaryStorage()
79cdf0e10cSrcweir 	throw ( uno::Exception,
80cdf0e10cSrcweir 			uno::RuntimeException )
81cdf0e10cSrcweir {
82cdf0e10cSrcweir 	uno::Reference< embed::XStorage > xStorage;
83cdf0e10cSrcweir 	uno::Reference< lang::XSingleServiceFactory > xStorageFac;
84cdf0e10cSrcweir 	if ( m_xSMgr.is() )
85cdf0e10cSrcweir 	{
86cdf0e10cSrcweir 		xStorageFac = uno::Reference< lang::XSingleServiceFactory >(
87cdf0e10cSrcweir    			m_xSMgr->createInstance(
88cdf0e10cSrcweir    				rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
89cdf0e10cSrcweir    					"com.sun.star.embed.StorageFactory" ) ) ),
90cdf0e10cSrcweir    			uno::UNO_QUERY );
91cdf0e10cSrcweir 	}
92cdf0e10cSrcweir 
93cdf0e10cSrcweir 	OSL_ENSURE( xStorageFac.is(), "Can't create storage factory!" );
94cdf0e10cSrcweir 	if ( xStorageFac.is() )
95cdf0e10cSrcweir 		xStorage = uno::Reference< embed::XStorage >(
96cdf0e10cSrcweir 							xStorageFac->createInstance(),
97cdf0e10cSrcweir 							uno::UNO_QUERY );
98cdf0e10cSrcweir 
99cdf0e10cSrcweir 	if ( !xStorage.is() )
100cdf0e10cSrcweir 		throw uno::RuntimeException();
101cdf0e10cSrcweir 
102cdf0e10cSrcweir 	return xStorage;
103cdf0e10cSrcweir }
104cdf0e10cSrcweir 
105cdf0e10cSrcweir //=========================================================================
106cdf0e10cSrcweir uno::Reference< embed::XStorage >
107cdf0e10cSrcweir StorageElementFactory::createStorage( const rtl::OUString & rUri,
108cdf0e10cSrcweir                                       StorageAccessMode eMode )
109cdf0e10cSrcweir     throw ( embed::InvalidStorageException,
110cdf0e10cSrcweir             lang::IllegalArgumentException,
111cdf0e10cSrcweir             io::IOException,
112cdf0e10cSrcweir             embed::StorageWrappedTargetException,
113cdf0e10cSrcweir             uno::RuntimeException )
114cdf0e10cSrcweir {
115cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
116cdf0e10cSrcweir 
117cdf0e10cSrcweir     if ( ( eMode != READ ) &&
118cdf0e10cSrcweir          ( eMode != READ_WRITE_NOCREATE ) &&
119cdf0e10cSrcweir          ( eMode != READ_WRITE_CREATE ) )
120cdf0e10cSrcweir         throw lang::IllegalArgumentException(
121cdf0e10cSrcweir             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
122cdf0e10cSrcweir                 "Invalid open mode!" ) ),
123cdf0e10cSrcweir             uno::Reference< uno::XInterface >(),
124cdf0e10cSrcweir             sal_Int16( 2 ) );
125cdf0e10cSrcweir 
126cdf0e10cSrcweir     Uri aUri( rUri );
127cdf0e10cSrcweir     if ( aUri.isRoot() )
128cdf0e10cSrcweir     {
129cdf0e10cSrcweir         throw lang::IllegalArgumentException(
130cdf0e10cSrcweir             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
131cdf0e10cSrcweir                 "Root never has a storage!" ) ),
132cdf0e10cSrcweir             uno::Reference< uno::XInterface >(),
133cdf0e10cSrcweir             sal_Int16( 1 ) );
134cdf0e10cSrcweir     }
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     rtl::OUString aUriKey
137cdf0e10cSrcweir         ( ( rUri.getStr()[ rUri.getLength() - 1 ] == sal_Unicode( '/' ) )
138cdf0e10cSrcweir           ? rUri.copy( 0, rUri.getLength() - 1 )
139cdf0e10cSrcweir           : rUri );
140cdf0e10cSrcweir 
141cdf0e10cSrcweir     StorageMap::iterator aIt ( m_aMap.begin() );
142cdf0e10cSrcweir     StorageMap::iterator aEnd( m_aMap.end() );
143cdf0e10cSrcweir 
144cdf0e10cSrcweir     while ( aIt != aEnd )
145cdf0e10cSrcweir     {
146cdf0e10cSrcweir         if ( (*aIt).first.first == aUriKey )
147cdf0e10cSrcweir         {
148cdf0e10cSrcweir             // URI matches. Now, check open mode.
149cdf0e10cSrcweir             bool bMatch = true;
150cdf0e10cSrcweir             switch ( eMode )
151cdf0e10cSrcweir             {
152cdf0e10cSrcweir                 case READ:
153cdf0e10cSrcweir                     // No need to check; storage is at least readable.
154cdf0e10cSrcweir                     bMatch = true;
155cdf0e10cSrcweir                     break;
156cdf0e10cSrcweir 
157cdf0e10cSrcweir                 case READ_WRITE_NOCREATE:
158cdf0e10cSrcweir                 case READ_WRITE_CREATE:
159cdf0e10cSrcweir                     // If found storage is writable, it can be used.
160cdf0e10cSrcweir                     // If not, a new one must be created.
161cdf0e10cSrcweir                     bMatch = (*aIt).first.second;
162cdf0e10cSrcweir                     break;
163cdf0e10cSrcweir             }
164cdf0e10cSrcweir 
165cdf0e10cSrcweir             if ( bMatch )
166cdf0e10cSrcweir                 break;
167cdf0e10cSrcweir         }
168cdf0e10cSrcweir         ++aIt;
169cdf0e10cSrcweir     }
170cdf0e10cSrcweir 
171cdf0e10cSrcweir     if ( aIt == aEnd )
172cdf0e10cSrcweir     {
173cdf0e10cSrcweir         uno::Reference< embed::XStorage > xParentStorage;
174cdf0e10cSrcweir 
175cdf0e10cSrcweir         // documents never have a parent storage.
176cdf0e10cSrcweir         if ( !aUri.isDocument() )
177cdf0e10cSrcweir         {
178cdf0e10cSrcweir             xParentStorage = queryParentStorage( aUriKey, eMode );
179cdf0e10cSrcweir 
180cdf0e10cSrcweir             if ( !xParentStorage.is() )
181cdf0e10cSrcweir             {
182cdf0e10cSrcweir                 // requested to create new storage, but failed?
183cdf0e10cSrcweir                 OSL_ENSURE( eMode != READ_WRITE_CREATE,
184cdf0e10cSrcweir                             "Unable to create parent storage!" );
185cdf0e10cSrcweir                 return xParentStorage;
186cdf0e10cSrcweir             }
187cdf0e10cSrcweir         }
188cdf0e10cSrcweir 
189cdf0e10cSrcweir         uno::Reference< embed::XStorage > xStorage
190cdf0e10cSrcweir             = queryStorage( xParentStorage, aUriKey, eMode );
191cdf0e10cSrcweir 
192cdf0e10cSrcweir         if ( !xStorage.is() )
193cdf0e10cSrcweir         {
194cdf0e10cSrcweir             // requested to create new storage, but failed?
195cdf0e10cSrcweir             OSL_ENSURE( eMode != READ_WRITE_CREATE,
196cdf0e10cSrcweir                         "Unable to create storage!" );
197cdf0e10cSrcweir             return xStorage;
198cdf0e10cSrcweir         }
199cdf0e10cSrcweir 
200cdf0e10cSrcweir         bool bWritable = ( ( eMode == READ_WRITE_NOCREATE )
201cdf0e10cSrcweir                             || ( eMode == READ_WRITE_CREATE ) );
202cdf0e10cSrcweir 
203cdf0e10cSrcweir         std::auto_ptr< Storage > xElement(
204cdf0e10cSrcweir             new Storage( m_xSMgr, this, aUriKey, xParentStorage, xStorage ) );
205cdf0e10cSrcweir 
206cdf0e10cSrcweir         aIt = m_aMap.insert(
207cdf0e10cSrcweir             StorageMap::value_type(
208cdf0e10cSrcweir                 std::pair< rtl::OUString, bool >( aUriKey, bWritable ),
209cdf0e10cSrcweir                 xElement.get() ) ).first;
210cdf0e10cSrcweir 
211cdf0e10cSrcweir         aIt->second->m_aContainerIt = aIt;
212cdf0e10cSrcweir         xElement.release();
213cdf0e10cSrcweir         return aIt->second;
214cdf0e10cSrcweir     }
215cdf0e10cSrcweir     else if ( osl_incrementInterlockedCount( &aIt->second->m_refCount ) > 1 )
216cdf0e10cSrcweir     {
217cdf0e10cSrcweir         rtl::Reference< Storage > xElement( aIt->second );
218cdf0e10cSrcweir         osl_decrementInterlockedCount( &aIt->second->m_refCount );
219cdf0e10cSrcweir         return aIt->second;
220cdf0e10cSrcweir     }
221cdf0e10cSrcweir     else
222cdf0e10cSrcweir     {
223cdf0e10cSrcweir         osl_decrementInterlockedCount( &aIt->second->m_refCount );
224cdf0e10cSrcweir         aIt->second->m_aContainerIt = m_aMap.end();
225cdf0e10cSrcweir 
226cdf0e10cSrcweir         uno::Reference< embed::XStorage > xParentStorage;
227cdf0e10cSrcweir 
228cdf0e10cSrcweir         // documents never have a parent storage.
229cdf0e10cSrcweir         if ( !aUri.isDocument() )
230cdf0e10cSrcweir         {
231cdf0e10cSrcweir             xParentStorage = queryParentStorage( aUriKey, eMode );
232cdf0e10cSrcweir 
233cdf0e10cSrcweir             if ( !xParentStorage.is() )
234cdf0e10cSrcweir             {
235cdf0e10cSrcweir                 // requested to create new storage, but failed?
236cdf0e10cSrcweir                 OSL_ENSURE( eMode != READ_WRITE_CREATE,
237cdf0e10cSrcweir                             "Unable to create parent storage!" );
238cdf0e10cSrcweir                 return xParentStorage;
239cdf0e10cSrcweir             }
240cdf0e10cSrcweir         }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir         uno::Reference< embed::XStorage > xStorage
243cdf0e10cSrcweir             = queryStorage( xParentStorage, aUriKey, eMode );
244cdf0e10cSrcweir 
245cdf0e10cSrcweir         if ( !xStorage.is() )
246cdf0e10cSrcweir         {
247cdf0e10cSrcweir             // requested to create new storage, but failed?
248cdf0e10cSrcweir             OSL_ENSURE( eMode != READ_WRITE_CREATE,
249cdf0e10cSrcweir                         "Unable to create storage!" );
250cdf0e10cSrcweir             return xStorage;
251cdf0e10cSrcweir         }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir         aIt->second
254cdf0e10cSrcweir             = new Storage( m_xSMgr, this, aUriKey, xParentStorage, xStorage );
255cdf0e10cSrcweir         aIt->second->m_aContainerIt = aIt;
256cdf0e10cSrcweir         return aIt->second;
257cdf0e10cSrcweir     }
258cdf0e10cSrcweir }
259cdf0e10cSrcweir 
260cdf0e10cSrcweir //=========================================================================
261cdf0e10cSrcweir uno::Reference< io::XInputStream >
262cdf0e10cSrcweir StorageElementFactory::createInputStream( const rtl::OUString & rUri,
263cdf0e10cSrcweir                                           const rtl::OUString & rPassword )
264cdf0e10cSrcweir     throw ( embed::InvalidStorageException,
265cdf0e10cSrcweir             lang::IllegalArgumentException,
266cdf0e10cSrcweir             io::IOException,
267cdf0e10cSrcweir             embed::StorageWrappedTargetException,
268cdf0e10cSrcweir             packages::WrongPasswordException,
269cdf0e10cSrcweir             uno::RuntimeException )
270cdf0e10cSrcweir {
271cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
272cdf0e10cSrcweir 
273cdf0e10cSrcweir     uno::Reference< embed::XStorage > xParentStorage
274cdf0e10cSrcweir         = queryParentStorage( rUri, READ );
275cdf0e10cSrcweir 
276cdf0e10cSrcweir     // Each stream must have a parent storage.
277cdf0e10cSrcweir     if ( !xParentStorage.is() )
278cdf0e10cSrcweir         return uno::Reference< io::XInputStream >();
279cdf0e10cSrcweir 
280cdf0e10cSrcweir     uno::Reference< io::XStream > xStream
281cdf0e10cSrcweir         = queryStream( xParentStorage, rUri, rPassword, READ, false );
282cdf0e10cSrcweir 
283cdf0e10cSrcweir     if ( !xStream.is() )
284cdf0e10cSrcweir         return uno::Reference< io::XInputStream >();
285cdf0e10cSrcweir 
286cdf0e10cSrcweir     return xStream->getInputStream();
287cdf0e10cSrcweir }
288cdf0e10cSrcweir 
289cdf0e10cSrcweir //=========================================================================
290cdf0e10cSrcweir uno::Reference< io::XOutputStream >
291cdf0e10cSrcweir StorageElementFactory::createOutputStream( const rtl::OUString & rUri,
292cdf0e10cSrcweir                                            const rtl::OUString & rPassword,
293cdf0e10cSrcweir                                            bool bTruncate )
294cdf0e10cSrcweir     throw ( embed::InvalidStorageException,
295cdf0e10cSrcweir             lang::IllegalArgumentException,
296cdf0e10cSrcweir             io::IOException,
297cdf0e10cSrcweir             embed::StorageWrappedTargetException,
298cdf0e10cSrcweir             packages::WrongPasswordException,
299cdf0e10cSrcweir             uno::RuntimeException )
300cdf0e10cSrcweir {
301cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
302cdf0e10cSrcweir 
303cdf0e10cSrcweir     uno::Reference< embed::XStorage > xParentStorage
304cdf0e10cSrcweir         = queryParentStorage( rUri, READ_WRITE_CREATE );
305cdf0e10cSrcweir 
306cdf0e10cSrcweir     // Each stream must have a parent storage.
307cdf0e10cSrcweir     if ( !xParentStorage.is() )
308cdf0e10cSrcweir     {
309cdf0e10cSrcweir         OSL_ENSURE( false,
310cdf0e10cSrcweir                     "StorageElementFactory::createOutputStream - "
311cdf0e10cSrcweir                     "Unable to create parent storage!" );
312cdf0e10cSrcweir         return uno::Reference< io::XOutputStream >();
313cdf0e10cSrcweir     }
314cdf0e10cSrcweir 
315cdf0e10cSrcweir     uno::Reference< io::XStream > xStream
316cdf0e10cSrcweir         = queryStream(
317cdf0e10cSrcweir             xParentStorage, rUri, rPassword, READ_WRITE_CREATE, bTruncate );
318cdf0e10cSrcweir 
319cdf0e10cSrcweir     if ( !xStream.is() )
320cdf0e10cSrcweir     {
321cdf0e10cSrcweir         OSL_ENSURE( false,
322cdf0e10cSrcweir                     "StorageElementFactory::createOutputStream - "
323cdf0e10cSrcweir                     "Unable to create stream!" );
324cdf0e10cSrcweir         return uno::Reference< io::XOutputStream >();
325cdf0e10cSrcweir     }
326cdf0e10cSrcweir 
327cdf0e10cSrcweir     // Note: We need a wrapper to hold a reference to the parent storage to
328cdf0e10cSrcweir     //       ensure that nobody else owns it at the moment we want to commit
329cdf0e10cSrcweir     //       our changes. (There can be only one writable instance at a time
330cdf0e10cSrcweir     //       and even no writable instance if there is  already another
331cdf0e10cSrcweir     //       read-only instance!)
332cdf0e10cSrcweir     return uno::Reference< io::XOutputStream >(
333cdf0e10cSrcweir         new OutputStream(
334cdf0e10cSrcweir             m_xSMgr, rUri, xParentStorage, xStream->getOutputStream() ) );
335cdf0e10cSrcweir }
336cdf0e10cSrcweir 
337cdf0e10cSrcweir //=========================================================================
338cdf0e10cSrcweir uno::Reference< io::XStream >
339cdf0e10cSrcweir StorageElementFactory::createStream( const rtl::OUString & rUri,
340cdf0e10cSrcweir                                      const rtl::OUString & rPassword,
341cdf0e10cSrcweir                                      bool bTruncate )
342cdf0e10cSrcweir     throw ( embed::InvalidStorageException,
343cdf0e10cSrcweir             lang::IllegalArgumentException,
344cdf0e10cSrcweir             io::IOException,
345cdf0e10cSrcweir             embed::StorageWrappedTargetException,
346cdf0e10cSrcweir             packages::WrongPasswordException,
347cdf0e10cSrcweir             uno::RuntimeException )
348cdf0e10cSrcweir {
349cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
350cdf0e10cSrcweir 
351cdf0e10cSrcweir     uno::Reference< embed::XStorage > xParentStorage
352cdf0e10cSrcweir         = queryParentStorage( rUri, READ_WRITE_CREATE );
353cdf0e10cSrcweir 
354cdf0e10cSrcweir     // Each stream must have a parent storage.
355cdf0e10cSrcweir     if ( !xParentStorage.is() )
356cdf0e10cSrcweir     {
357cdf0e10cSrcweir         OSL_ENSURE( false,
358cdf0e10cSrcweir                     "StorageElementFactory::createStream - "
359cdf0e10cSrcweir                     "Unable to create parent storage!" );
360cdf0e10cSrcweir         return uno::Reference< io::XStream >();
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     uno::Reference< io::XStream > xStream
364cdf0e10cSrcweir         = queryStream(
365cdf0e10cSrcweir             xParentStorage, rUri, rPassword, READ_WRITE_NOCREATE, bTruncate );
366cdf0e10cSrcweir 
367cdf0e10cSrcweir     if ( !xStream.is() )
368cdf0e10cSrcweir     {
369cdf0e10cSrcweir         OSL_ENSURE( false,
370cdf0e10cSrcweir                     "StorageElementFactory::createStream - "
371cdf0e10cSrcweir                     "Unable to create stream!" );
372cdf0e10cSrcweir         return uno::Reference< io::XStream >();
373cdf0e10cSrcweir     }
374cdf0e10cSrcweir 
375cdf0e10cSrcweir     return uno::Reference< io::XStream >(
376cdf0e10cSrcweir         new Stream( m_xSMgr, rUri, xParentStorage, xStream ) );
377cdf0e10cSrcweir }
378cdf0e10cSrcweir 
379cdf0e10cSrcweir //=========================================================================
380cdf0e10cSrcweir void StorageElementFactory::releaseElement( Storage * pElement ) SAL_THROW( () )
381cdf0e10cSrcweir {
382cdf0e10cSrcweir     OSL_ASSERT( pElement );
383cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
384cdf0e10cSrcweir     if ( pElement->m_aContainerIt != m_aMap.end() )
385cdf0e10cSrcweir         m_aMap.erase( pElement->m_aContainerIt );
386cdf0e10cSrcweir }
387cdf0e10cSrcweir 
388cdf0e10cSrcweir //=========================================================================
389cdf0e10cSrcweir //
390cdf0e10cSrcweir // Non-UNO interface
391cdf0e10cSrcweir //
392cdf0e10cSrcweir //=========================================================================
393cdf0e10cSrcweir 
394cdf0e10cSrcweir uno::Reference< embed::XStorage > StorageElementFactory::queryParentStorage(
395cdf0e10cSrcweir         const rtl::OUString & rUri, StorageAccessMode eMode )
396cdf0e10cSrcweir     throw ( embed::InvalidStorageException,
397cdf0e10cSrcweir             lang::IllegalArgumentException,
398cdf0e10cSrcweir             io::IOException,
399cdf0e10cSrcweir             embed::StorageWrappedTargetException,
400cdf0e10cSrcweir             uno::RuntimeException )
401cdf0e10cSrcweir {
402cdf0e10cSrcweir     uno::Reference< embed::XStorage > xParentStorage;
403cdf0e10cSrcweir 
404cdf0e10cSrcweir     Uri aUri( rUri );
405cdf0e10cSrcweir     Uri aParentUri( aUri.getParentUri() );
406cdf0e10cSrcweir     if ( !aParentUri.isRoot() )
407cdf0e10cSrcweir     {
408cdf0e10cSrcweir         xParentStorage = createStorage( aUri.getParentUri(), eMode );
409cdf0e10cSrcweir         OSL_ENSURE( xParentStorage.is()
410cdf0e10cSrcweir                     // requested to create new storage, but failed?
411cdf0e10cSrcweir                     || ( eMode != READ_WRITE_CREATE ),
412cdf0e10cSrcweir                     "StorageElementFactory::queryParentStorage - No storage!" );
413cdf0e10cSrcweir     }
414cdf0e10cSrcweir     return xParentStorage;
415cdf0e10cSrcweir }
416cdf0e10cSrcweir 
417cdf0e10cSrcweir //=========================================================================
418cdf0e10cSrcweir uno::Reference< embed::XStorage > StorageElementFactory::queryStorage(
419cdf0e10cSrcweir         const uno::Reference< embed::XStorage > & xParentStorage,
420cdf0e10cSrcweir         const rtl::OUString & rUri,
421cdf0e10cSrcweir         StorageAccessMode eMode )
422cdf0e10cSrcweir     throw ( embed::InvalidStorageException,
423cdf0e10cSrcweir             lang::IllegalArgumentException,
424cdf0e10cSrcweir             io::IOException,
425cdf0e10cSrcweir             embed::StorageWrappedTargetException,
426cdf0e10cSrcweir             uno::RuntimeException )
427cdf0e10cSrcweir {
428cdf0e10cSrcweir     uno::Reference< embed::XStorage > xStorage;
429cdf0e10cSrcweir 
430cdf0e10cSrcweir     Uri aUri( rUri );
431cdf0e10cSrcweir 
432cdf0e10cSrcweir     if ( !xParentStorage.is() )
433cdf0e10cSrcweir     {
434cdf0e10cSrcweir         // document storage
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         xStorage = m_xDocsMgr->queryStorage( aUri.getDocumentId() );
437cdf0e10cSrcweir 
438cdf0e10cSrcweir         if ( !xStorage.is() )
439cdf0e10cSrcweir         {
440cdf0e10cSrcweir             if ( eMode == READ_WRITE_CREATE )
441cdf0e10cSrcweir                 throw lang::IllegalArgumentException(
442cdf0e10cSrcweir                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
443cdf0e10cSrcweir                         "Invalid open mode: document storages cannot be "
444cdf0e10cSrcweir                         "created!" ) ),
445cdf0e10cSrcweir                     uno::Reference< uno::XInterface >(),
446cdf0e10cSrcweir                     sal_Int16( 2 ) );
447cdf0e10cSrcweir             else
448cdf0e10cSrcweir                 throw embed::InvalidStorageException(
449cdf0e10cSrcweir                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
450cdf0e10cSrcweir                         "Invalid document id!" ) ),
451cdf0e10cSrcweir                     uno::Reference< uno::XInterface >() );
452cdf0e10cSrcweir         }
453cdf0e10cSrcweir 
454cdf0e10cSrcweir         // match xStorage's open mode against requested open mode
455cdf0e10cSrcweir 
456cdf0e10cSrcweir         uno::Reference< beans::XPropertySet > xPropSet(
457cdf0e10cSrcweir             xStorage, uno::UNO_QUERY );
458cdf0e10cSrcweir         OSL_ENSURE( xPropSet.is(),
459cdf0e10cSrcweir                     "StorageElementFactory::queryStorage - "
460cdf0e10cSrcweir                     "No XPropertySet interface!" );
461cdf0e10cSrcweir         try
462cdf0e10cSrcweir         {
463cdf0e10cSrcweir             uno::Any aPropValue = xPropSet->getPropertyValue(
464cdf0e10cSrcweir                 rtl::OUString(
465cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ) ) );
466cdf0e10cSrcweir 
467cdf0e10cSrcweir             sal_Int32 nOpenMode = 0;
468cdf0e10cSrcweir             if ( aPropValue >>= nOpenMode )
469cdf0e10cSrcweir             {
470cdf0e10cSrcweir                 switch ( eMode )
471cdf0e10cSrcweir                 {
472cdf0e10cSrcweir                     case READ:
473cdf0e10cSrcweir                         if ( !( nOpenMode & embed::ElementModes::READ ) )
474cdf0e10cSrcweir                         {
475cdf0e10cSrcweir                             // document opened, but not readable.
476cdf0e10cSrcweir                             throw embed::InvalidStorageException(
477cdf0e10cSrcweir                                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
478cdf0e10cSrcweir                                     "Storage is open, but not readable!" ) ),
479cdf0e10cSrcweir                                 uno::Reference< uno::XInterface >() );
480cdf0e10cSrcweir                         }
481cdf0e10cSrcweir                         // storage okay
482cdf0e10cSrcweir                         break;
483cdf0e10cSrcweir 
484cdf0e10cSrcweir                     case READ_WRITE_NOCREATE:
485cdf0e10cSrcweir                     case READ_WRITE_CREATE:
486cdf0e10cSrcweir                         if ( !( nOpenMode & embed::ElementModes::WRITE ) )
487cdf0e10cSrcweir                         {
488cdf0e10cSrcweir                             // document opened, but not writable.
489cdf0e10cSrcweir                             throw embed::InvalidStorageException(
490cdf0e10cSrcweir                                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
491cdf0e10cSrcweir                                     "Storage is open, but not writable!" ) ),
492cdf0e10cSrcweir                                 uno::Reference< uno::XInterface >() );
493cdf0e10cSrcweir                         }
494cdf0e10cSrcweir                         // storage okay
495cdf0e10cSrcweir                         break;
496cdf0e10cSrcweir                 }
497cdf0e10cSrcweir             }
498cdf0e10cSrcweir             else
499cdf0e10cSrcweir             {
500cdf0e10cSrcweir                 OSL_ENSURE(
501cdf0e10cSrcweir                     false, "Bug! Value of property OpenMode has wrong type!" );
502cdf0e10cSrcweir 
503cdf0e10cSrcweir                 throw uno::RuntimeException(
504cdf0e10cSrcweir                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
505cdf0e10cSrcweir                         "Bug! Value of property OpenMode has wrong type!" ) ),
506cdf0e10cSrcweir                     uno::Reference< uno::XInterface >() );
507cdf0e10cSrcweir             }
508cdf0e10cSrcweir         }
509cdf0e10cSrcweir         catch ( beans::UnknownPropertyException const & e )
510cdf0e10cSrcweir         {
511cdf0e10cSrcweir             OSL_ENSURE( false, "Property OpenMode not supported!" );
512cdf0e10cSrcweir 
513cdf0e10cSrcweir             throw embed::StorageWrappedTargetException(
514cdf0e10cSrcweir                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
515cdf0e10cSrcweir                         "Bug! Value of property OpenMode has wrong type!" ) ),
516cdf0e10cSrcweir                     uno::Reference< uno::XInterface >(),
517cdf0e10cSrcweir                     uno::makeAny( e ) );
518cdf0e10cSrcweir         }
519cdf0e10cSrcweir         catch ( lang::WrappedTargetException const & e )
520cdf0e10cSrcweir         {
521cdf0e10cSrcweir             OSL_ENSURE( false, "Caught WrappedTargetException!" );
522cdf0e10cSrcweir 
523cdf0e10cSrcweir             throw embed::StorageWrappedTargetException(
524cdf0e10cSrcweir                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
525cdf0e10cSrcweir                         "WrappedTargetException during getPropertyValue!" ) ),
526cdf0e10cSrcweir                     uno::Reference< uno::XInterface >(),
527cdf0e10cSrcweir                     uno::makeAny( e ) );
528cdf0e10cSrcweir         }
529cdf0e10cSrcweir     }
530cdf0e10cSrcweir     else
531cdf0e10cSrcweir     {
532cdf0e10cSrcweir         // sub storage
533cdf0e10cSrcweir 
534cdf0e10cSrcweir         const rtl::OUString & rName = aUri.getDecodedName();
535cdf0e10cSrcweir 
536cdf0e10cSrcweir         if ( eMode == READ )
537cdf0e10cSrcweir         {
538cdf0e10cSrcweir             try
539cdf0e10cSrcweir             {
540cdf0e10cSrcweir                 sal_Int32 nOpenMode = embed::ElementModes::READ
541cdf0e10cSrcweir                                       | embed::ElementModes::NOCREATE;
542cdf0e10cSrcweir                 xStorage
543cdf0e10cSrcweir                     = xParentStorage->openStorageElement( rName, nOpenMode );
544cdf0e10cSrcweir             }
545cdf0e10cSrcweir             catch ( io::IOException const & )
546cdf0e10cSrcweir             {
547cdf0e10cSrcweir                 // Another chance: Try to clone storage.
548cdf0e10cSrcweir                 xStorage = createTemporaryStorage();
549cdf0e10cSrcweir                 xParentStorage->copyStorageElementLastCommitTo( rName,
550cdf0e10cSrcweir                                                                 xStorage );
551cdf0e10cSrcweir             }
552cdf0e10cSrcweir         }
553cdf0e10cSrcweir         else
554cdf0e10cSrcweir         {
555cdf0e10cSrcweir             sal_Int32 nOpenMode = embed::ElementModes::READWRITE;
556cdf0e10cSrcweir             if ( eMode == READ_WRITE_NOCREATE )
557cdf0e10cSrcweir                 nOpenMode |= embed::ElementModes::NOCREATE;
558cdf0e10cSrcweir 
559cdf0e10cSrcweir             xStorage = xParentStorage->openStorageElement( rName, nOpenMode );
560cdf0e10cSrcweir         }
561cdf0e10cSrcweir     }
562cdf0e10cSrcweir 
563cdf0e10cSrcweir     OSL_ENSURE( xStorage.is() || ( eMode != READ_WRITE_CREATE ),
564cdf0e10cSrcweir                 "StorageElementFactory::queryStorage - No storage!" );
565cdf0e10cSrcweir     return xStorage;
566cdf0e10cSrcweir }
567cdf0e10cSrcweir 
568cdf0e10cSrcweir //=========================================================================
569cdf0e10cSrcweir uno::Reference< io::XStream >
570cdf0e10cSrcweir StorageElementFactory::queryStream(
571cdf0e10cSrcweir                 const uno::Reference< embed::XStorage > & xParentStorage,
572cdf0e10cSrcweir                 const rtl::OUString & rUri,
573cdf0e10cSrcweir                 const rtl::OUString & rPassword,
574cdf0e10cSrcweir                 StorageAccessMode eMode,
575cdf0e10cSrcweir                 bool bTruncate )
576cdf0e10cSrcweir     throw ( embed::InvalidStorageException,
577cdf0e10cSrcweir             lang::IllegalArgumentException,
578cdf0e10cSrcweir             io::IOException,
579cdf0e10cSrcweir             embed::StorageWrappedTargetException,
580cdf0e10cSrcweir             packages::WrongPasswordException,
581cdf0e10cSrcweir             uno::RuntimeException )
582cdf0e10cSrcweir {
583cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
584cdf0e10cSrcweir 
585cdf0e10cSrcweir     if ( !xParentStorage.is() )
586cdf0e10cSrcweir     {
587cdf0e10cSrcweir         throw lang::IllegalArgumentException(
588cdf0e10cSrcweir             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
589cdf0e10cSrcweir                 "No parent storage!" ) ),
590cdf0e10cSrcweir             uno::Reference< uno::XInterface >(),
591cdf0e10cSrcweir             sal_Int16( 2 ) );
592cdf0e10cSrcweir     }
593cdf0e10cSrcweir 
594cdf0e10cSrcweir     Uri aUri( rUri );
595cdf0e10cSrcweir     if ( aUri.isRoot() )
596cdf0e10cSrcweir     {
597cdf0e10cSrcweir         throw lang::IllegalArgumentException(
598cdf0e10cSrcweir             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
599cdf0e10cSrcweir                 "Root never is a stream!" ) ),
600cdf0e10cSrcweir             uno::Reference< uno::XInterface >(),
601cdf0e10cSrcweir             sal_Int16( 2 ) );
602cdf0e10cSrcweir     }
603cdf0e10cSrcweir     else if ( aUri.isDocument() )
604cdf0e10cSrcweir     {
605cdf0e10cSrcweir         throw lang::IllegalArgumentException(
606cdf0e10cSrcweir             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
607cdf0e10cSrcweir                 "A document never is a stream!" ) ),
608cdf0e10cSrcweir             uno::Reference< uno::XInterface >(),
609cdf0e10cSrcweir             sal_Int16( 2 ) );
610cdf0e10cSrcweir     }
611cdf0e10cSrcweir 
612cdf0e10cSrcweir     sal_Int32 nOpenMode;
613cdf0e10cSrcweir     switch ( eMode )
614cdf0e10cSrcweir     {
615cdf0e10cSrcweir         case READ:
616cdf0e10cSrcweir             nOpenMode = embed::ElementModes::READ
617cdf0e10cSrcweir                         | embed::ElementModes::NOCREATE
618cdf0e10cSrcweir                         | embed::ElementModes::SEEKABLE;
619cdf0e10cSrcweir             break;
620cdf0e10cSrcweir 
621cdf0e10cSrcweir         case READ_WRITE_NOCREATE:
622cdf0e10cSrcweir             nOpenMode = embed::ElementModes::READWRITE
623cdf0e10cSrcweir                         | embed::ElementModes::NOCREATE
624cdf0e10cSrcweir                         | embed::ElementModes::SEEKABLE;
625cdf0e10cSrcweir 
626cdf0e10cSrcweir             if ( bTruncate )
627cdf0e10cSrcweir                 nOpenMode |= embed::ElementModes::TRUNCATE;
628cdf0e10cSrcweir 
629cdf0e10cSrcweir             break;
630cdf0e10cSrcweir 
631cdf0e10cSrcweir         case READ_WRITE_CREATE:
632cdf0e10cSrcweir             nOpenMode = embed::ElementModes::READWRITE
633cdf0e10cSrcweir                         | embed::ElementModes::SEEKABLE;
634cdf0e10cSrcweir 
635cdf0e10cSrcweir             if ( bTruncate )
636cdf0e10cSrcweir                 nOpenMode |= embed::ElementModes::TRUNCATE;
637cdf0e10cSrcweir 
638cdf0e10cSrcweir             break;
639cdf0e10cSrcweir 
640cdf0e10cSrcweir         default:
641cdf0e10cSrcweir             OSL_ENSURE( false,
642cdf0e10cSrcweir                 "StorageElementFactory::queryStream : Unknown open mode!" );
643cdf0e10cSrcweir 
644cdf0e10cSrcweir             throw embed::InvalidStorageException(
645cdf0e10cSrcweir                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
646cdf0e10cSrcweir                     "Unknown open mode!" ) ),
647cdf0e10cSrcweir                 uno::Reference< uno::XInterface >() );
648cdf0e10cSrcweir     }
649cdf0e10cSrcweir 
650cdf0e10cSrcweir     // No object re-usage mechanism; streams are seekable => not stateless.
651cdf0e10cSrcweir 
652cdf0e10cSrcweir     uno::Reference< io::XStream > xStream;
653cdf0e10cSrcweir     if ( rPassword.getLength() > 0 )
654cdf0e10cSrcweir     {
655cdf0e10cSrcweir         if ( eMode == READ )
656cdf0e10cSrcweir         {
657cdf0e10cSrcweir             try
658cdf0e10cSrcweir             {
659cdf0e10cSrcweir                 xStream = xParentStorage->cloneEncryptedStreamElement(
660cdf0e10cSrcweir                                                          aUri.getDecodedName(),
661cdf0e10cSrcweir                                                          rPassword );
662cdf0e10cSrcweir             }
663cdf0e10cSrcweir             catch ( packages::NoEncryptionException const & )
664cdf0e10cSrcweir             {
665cdf0e10cSrcweir                 xStream
666cdf0e10cSrcweir                     = xParentStorage->cloneStreamElement( aUri.getDecodedName() );
667cdf0e10cSrcweir             }
668cdf0e10cSrcweir         }
669cdf0e10cSrcweir         else
670cdf0e10cSrcweir         {
671cdf0e10cSrcweir             try
672cdf0e10cSrcweir             {
673cdf0e10cSrcweir                 xStream = xParentStorage->openEncryptedStreamElement(
674cdf0e10cSrcweir                                                          aUri.getDecodedName(),
675cdf0e10cSrcweir                                                          nOpenMode,
676cdf0e10cSrcweir                                                          rPassword );
677cdf0e10cSrcweir             }
678cdf0e10cSrcweir             catch ( packages::NoEncryptionException const & )
679cdf0e10cSrcweir             {
680cdf0e10cSrcweir                 xStream
681cdf0e10cSrcweir                     = xParentStorage->openStreamElement( aUri.getDecodedName(),
682cdf0e10cSrcweir                                                          nOpenMode );
683cdf0e10cSrcweir             }
684cdf0e10cSrcweir         }
685cdf0e10cSrcweir     }
686cdf0e10cSrcweir     else
687cdf0e10cSrcweir     {
688cdf0e10cSrcweir         if ( eMode == READ )
689cdf0e10cSrcweir         {
690cdf0e10cSrcweir             xStream = xParentStorage->cloneStreamElement( aUri.getDecodedName() );
691cdf0e10cSrcweir         }
692cdf0e10cSrcweir         else
693cdf0e10cSrcweir         {
694cdf0e10cSrcweir             xStream = xParentStorage->openStreamElement( aUri.getDecodedName(),
695cdf0e10cSrcweir                                                          nOpenMode );
696cdf0e10cSrcweir         }
697cdf0e10cSrcweir     }
698cdf0e10cSrcweir 
699cdf0e10cSrcweir     if ( !xStream.is() )
700cdf0e10cSrcweir     {
701cdf0e10cSrcweir         throw embed::InvalidStorageException(
702cdf0e10cSrcweir             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
703cdf0e10cSrcweir                 "No stream!" ) ),
704cdf0e10cSrcweir             uno::Reference< uno::XInterface >() );
705cdf0e10cSrcweir     }
706cdf0e10cSrcweir 
707cdf0e10cSrcweir     return xStream;
708cdf0e10cSrcweir }
709