xref: /trunk/main/oox/source/helper/storagebase.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "oox/helper/storagebase.hxx"
29 
30 #include <com/sun/star/embed/XTransactedObject.hpp>
31 #include <com/sun/star/io/XStream.hpp>
32 #include <rtl/ustrbuf.hxx>
33 #include "oox/helper/binaryinputstream.hxx"
34 #include "oox/helper/binaryoutputstream.hxx"
35 
36 namespace oox {
37 
38 // ============================================================================
39 
40 using namespace ::com::sun::star::embed;
41 using namespace ::com::sun::star::io;
42 using namespace ::com::sun::star::uno;
43 
44 using ::rtl::OUString;
45 using ::rtl::OUStringBuffer;
46 
47 // ============================================================================
48 
49 namespace {
50 
51 void lclSplitFirstElement( OUString& orElement, OUString& orRemainder, const OUString& rFullName )
52 {
53     sal_Int32 nSlashPos = rFullName.indexOf( '/' );
54     if( (0 <= nSlashPos) && (nSlashPos < rFullName.getLength()) )
55     {
56         orElement = rFullName.copy( 0, nSlashPos );
57         orRemainder = rFullName.copy( nSlashPos + 1 );
58     }
59     else
60     {
61         orElement = rFullName;
62     }
63 }
64 
65 } // namespace
66 
67 // ----------------------------------------------------------------------------
68 
69 StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) :
70     mxInStream( rxInStream ),
71     mbBaseStreamAccess( bBaseStreamAccess ),
72     mbReadOnly( true )
73 {
74     OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" );
75 }
76 
77 StorageBase::StorageBase( const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) :
78     mxOutStream( rxOutStream ),
79     mbBaseStreamAccess( bBaseStreamAccess ),
80     mbReadOnly( false )
81 {
82     OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" );
83 }
84 
85 StorageBase::StorageBase( const StorageBase& rParentStorage, const OUString& rStorageName, bool bReadOnly ) :
86     maParentPath( rParentStorage.getPath() ),
87     maStorageName( rStorageName ),
88     mbBaseStreamAccess( false ),
89     mbReadOnly( bReadOnly )
90 {
91 }
92 
93 StorageBase::~StorageBase()
94 {
95 }
96 
97 bool StorageBase::isStorage() const
98 {
99     return implIsStorage();
100 }
101 
102 bool StorageBase::isRootStorage() const
103 {
104     return implIsStorage() && (maStorageName.getLength() == 0);
105 }
106 
107 bool StorageBase::isReadOnly() const
108 {
109     return mbReadOnly;
110 }
111 
112 Reference< XStorage > StorageBase::getXStorage() const
113 {
114     return implGetXStorage();
115 }
116 
117 const OUString& StorageBase::getName() const
118 {
119     return maStorageName;
120 }
121 
122 OUString StorageBase::getPath() const
123 {
124     OUStringBuffer aBuffer( maParentPath );
125     if( aBuffer.getLength() > 0 )
126         aBuffer.append( sal_Unicode( '/' ) );
127     aBuffer.append( maStorageName );
128     return aBuffer.makeStringAndClear();
129 }
130 
131 void StorageBase::getElementNames( ::std::vector< OUString >& orElementNames ) const
132 {
133     orElementNames.clear();
134     implGetElementNames( orElementNames );
135 }
136 
137 StorageRef StorageBase::openSubStorage( const OUString& rStorageName, bool bCreateMissing )
138 {
139     StorageRef xSubStorage;
140     OSL_ENSURE( !bCreateMissing || !mbReadOnly, "StorageBase::openSubStorage - cannot create substorage in read-only mode" );
141     if( !bCreateMissing || !mbReadOnly )
142     {
143         OUString aElement, aRemainder;
144         lclSplitFirstElement( aElement, aRemainder, rStorageName );
145         if( aElement.getLength() > 0 )
146             xSubStorage = getSubStorage( aElement, bCreateMissing );
147         if( xSubStorage.get() && (aRemainder.getLength() > 0) )
148             xSubStorage = xSubStorage->openSubStorage( aRemainder, bCreateMissing );
149     }
150     return xSubStorage;
151 }
152 
153 Reference< XInputStream > StorageBase::openInputStream( const OUString& rStreamName )
154 {
155     Reference< XInputStream > xInStream;
156     OUString aElement, aRemainder;
157     lclSplitFirstElement( aElement, aRemainder, rStreamName );
158     if( aElement.getLength() > 0 )
159     {
160         if( aRemainder.getLength() > 0 )
161         {
162             StorageRef xSubStorage = getSubStorage( aElement, false );
163             if( xSubStorage.get() )
164                 xInStream = xSubStorage->openInputStream( aRemainder );
165         }
166         else
167         {
168             xInStream = implOpenInputStream( aElement );
169         }
170     }
171     else if( mbBaseStreamAccess )
172     {
173         xInStream = mxInStream;
174     }
175     return xInStream;
176 }
177 
178 Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStreamName )
179 {
180     Reference< XOutputStream > xOutStream;
181     OSL_ENSURE( !mbReadOnly, "StorageBase::openOutputStream - cannot create output stream in read-only mode" );
182     if( !mbReadOnly )
183     {
184         OUString aElement, aRemainder;
185         lclSplitFirstElement( aElement, aRemainder, rStreamName );
186         if( aElement.getLength() > 0 )
187         {
188             if( aRemainder.getLength() > 0 )
189             {
190                 StorageRef xSubStorage = getSubStorage( aElement, true );
191                 if( xSubStorage.get() )
192                     xOutStream = xSubStorage->openOutputStream( aRemainder );
193             }
194             else
195             {
196                 xOutStream = implOpenOutputStream( aElement );
197             }
198         }
199         else if( mbBaseStreamAccess )
200         {
201             xOutStream = mxOutStream->getOutputStream();
202         }
203     }
204     return xOutStream;
205 }
206 
207 void StorageBase::copyToStorage( StorageBase& rDestStrg, const OUString& rElementName )
208 {
209     OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
210     OSL_ENSURE( rElementName.getLength() > 0, "StorageBase::copyToStorage - invalid element name" );
211     if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() && (rElementName.getLength() > 0) )
212     {
213         StorageRef xSubStrg = openSubStorage( rElementName, false );
214         if( xSubStrg.get() )
215         {
216             StorageRef xDestSubStrg = rDestStrg.openSubStorage( rElementName, true );
217             if( xDestSubStrg.get() )
218                 xSubStrg->copyStorageToStorage( *xDestSubStrg );
219         }
220         else
221         {
222             Reference< XInputStream > xInStrm = openInputStream( rElementName );
223             if( xInStrm.is() )
224             {
225                 Reference< XOutputStream > xOutStrm = rDestStrg.openOutputStream( rElementName );
226                 if( xOutStrm.is() )
227                 {
228                     BinaryXInputStream aInStrm( xInStrm, true );
229                     BinaryXOutputStream aOutStrm( xOutStrm, true );
230                     aInStrm.copyToStream( aOutStrm );
231                 }
232             }
233         }
234     }
235 }
236 
237 void StorageBase::copyStorageToStorage( StorageBase& rDestStrg )
238 {
239     OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
240     if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() )
241     {
242         ::std::vector< OUString > aElements;
243         getElementNames( aElements );
244         for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt )
245             copyToStorage( rDestStrg, *aIt );
246     }
247 }
248 
249 void StorageBase::commit()
250 {
251     OSL_ENSURE( !mbReadOnly, "StorageBase::commit - cannot commit in read-only mode" );
252     if( !mbReadOnly )
253     {
254         // commit all open substorages
255         maSubStorages.forEachMem( &StorageBase::commit );
256         // commit this storage
257         implCommit();
258     }
259 }
260 
261 // private --------------------------------------------------------------------
262 
263 StorageRef StorageBase::getSubStorage( const OUString& rElementName, bool bCreateMissing )
264 {
265     StorageRef& rxSubStrg = maSubStorages[ rElementName ];
266     if( !rxSubStrg )
267         rxSubStrg = implOpenSubStorage( rElementName, bCreateMissing );
268     return rxSubStrg;
269 }
270 
271 // ============================================================================
272 
273 } // namespace oox
274