Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "oox/helper/storagebase.hxx"
21 :
22 : #include <com/sun/star/embed/XTransactedObject.hpp>
23 : #include <com/sun/star/io/XStream.hpp>
24 : #include <rtl/ustrbuf.hxx>
25 : #include "oox/helper/binaryinputstream.hxx"
26 : #include "oox/helper/binaryoutputstream.hxx"
27 :
28 : namespace oox {
29 :
30 : // ============================================================================
31 :
32 : using namespace ::com::sun::star::embed;
33 : using namespace ::com::sun::star::io;
34 : using namespace ::com::sun::star::uno;
35 :
36 : // ============================================================================
37 :
38 : namespace {
39 :
40 1498 : void lclSplitFirstElement( OUString& orElement, OUString& orRemainder, OUString aFullName )
41 : {
42 1498 : sal_Int32 nSlashPos = aFullName.indexOf( '/' );
43 :
44 : // strip leading slashes
45 2996 : while( nSlashPos == 0 )
46 : {
47 0 : aFullName = aFullName.copy(1);
48 0 : nSlashPos = aFullName.indexOf( '/' );
49 : }
50 :
51 1498 : if( (0 <= nSlashPos) && (nSlashPos < aFullName.getLength()) )
52 : {
53 716 : orElement = aFullName.copy( 0, nSlashPos );
54 716 : orRemainder = aFullName.copy( nSlashPos + 1 );
55 : }
56 : else
57 : {
58 782 : orElement = aFullName;
59 : }
60 1498 : }
61 :
62 : } // namespace
63 :
64 : // ----------------------------------------------------------------------------
65 :
66 535 : StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) :
67 : mxInStream( rxInStream ),
68 : mbBaseStreamAccess( bBaseStreamAccess ),
69 535 : mbReadOnly( true )
70 : {
71 : OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" );
72 535 : }
73 :
74 29 : StorageBase::StorageBase( const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) :
75 : mxOutStream( rxOutStream ),
76 : mbBaseStreamAccess( bBaseStreamAccess ),
77 29 : mbReadOnly( false )
78 : {
79 : OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" );
80 29 : }
81 :
82 313 : StorageBase::StorageBase( const StorageBase& rParentStorage, const OUString& rStorageName, bool bReadOnly ) :
83 : maParentPath( rParentStorage.getPath() ),
84 : maStorageName( rStorageName ),
85 : mbBaseStreamAccess( false ),
86 313 : mbReadOnly( bReadOnly )
87 : {
88 313 : }
89 :
90 877 : StorageBase::~StorageBase()
91 : {
92 877 : }
93 :
94 511 : bool StorageBase::isStorage() const
95 : {
96 511 : return implIsStorage();
97 : }
98 :
99 0 : bool StorageBase::isRootStorage() const
100 : {
101 0 : return implIsStorage() && maStorageName.isEmpty();
102 : }
103 :
104 438 : bool StorageBase::isReadOnly() const
105 : {
106 438 : return mbReadOnly;
107 : }
108 :
109 75 : Reference< XStorage > StorageBase::getXStorage() const
110 : {
111 75 : return implGetXStorage();
112 : }
113 :
114 6 : const OUString& StorageBase::getName() const
115 : {
116 6 : return maStorageName;
117 : }
118 :
119 313 : OUString StorageBase::getPath() const
120 : {
121 313 : OUStringBuffer aBuffer( maParentPath );
122 313 : if( aBuffer.getLength() > 0 )
123 19 : aBuffer.append( sal_Unicode( '/' ) );
124 313 : aBuffer.append( maStorageName );
125 313 : return aBuffer.makeStringAndClear();
126 : }
127 :
128 9 : void StorageBase::getElementNames( ::std::vector< OUString >& orElementNames ) const
129 : {
130 9 : orElementNames.clear();
131 9 : implGetElementNames( orElementNames );
132 9 : }
133 :
134 110 : StorageRef StorageBase::openSubStorage( const OUString& rStorageName, bool bCreateMissing )
135 : {
136 110 : StorageRef xSubStorage;
137 : OSL_ENSURE( !bCreateMissing || !mbReadOnly, "StorageBase::openSubStorage - cannot create substorage in read-only mode" );
138 110 : if( !bCreateMissing || !mbReadOnly )
139 : {
140 110 : OUString aElement, aRemainder;
141 110 : lclSplitFirstElement( aElement, aRemainder, rStorageName );
142 110 : if( !aElement.isEmpty() )
143 110 : xSubStorage = getSubStorage( aElement, bCreateMissing );
144 110 : if( xSubStorage.get() && !aRemainder.isEmpty() )
145 0 : xSubStorage = xSubStorage->openSubStorage( aRemainder, bCreateMissing );
146 : }
147 110 : return xSubStorage;
148 : }
149 :
150 1027 : Reference< XInputStream > StorageBase::openInputStream( const OUString& rStreamName )
151 : {
152 1027 : Reference< XInputStream > xInStream;
153 1027 : OUString aElement, aRemainder;
154 1027 : lclSplitFirstElement( aElement, aRemainder, rStreamName );
155 1027 : if( !aElement.isEmpty() )
156 : {
157 1027 : if( !aRemainder.isEmpty() )
158 : {
159 562 : StorageRef xSubStorage = getSubStorage( aElement, false );
160 562 : if( xSubStorage.get() )
161 529 : xInStream = xSubStorage->openInputStream( aRemainder );
162 : }
163 : else
164 : {
165 465 : xInStream = implOpenInputStream( aElement );
166 : }
167 : }
168 0 : else if( mbBaseStreamAccess )
169 : {
170 0 : xInStream = mxInStream;
171 : }
172 1027 : return xInStream;
173 : }
174 :
175 361 : Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStreamName )
176 : {
177 361 : Reference< XOutputStream > xOutStream;
178 : OSL_ENSURE( !mbReadOnly, "StorageBase::openOutputStream - cannot create output stream in read-only mode" );
179 361 : if( !mbReadOnly )
180 : {
181 361 : OUString aElement, aRemainder;
182 361 : lclSplitFirstElement( aElement, aRemainder, rStreamName );
183 361 : if( !aElement.isEmpty() )
184 : {
185 361 : if( !aRemainder.isEmpty() )
186 : {
187 154 : StorageRef xSubStorage = getSubStorage( aElement, true );
188 154 : if( xSubStorage.get() )
189 154 : xOutStream = xSubStorage->openOutputStream( aRemainder );
190 : }
191 : else
192 : {
193 207 : xOutStream = implOpenOutputStream( aElement );
194 : }
195 : }
196 0 : else if( mbBaseStreamAccess )
197 : {
198 0 : xOutStream = mxOutStream->getOutputStream();
199 361 : }
200 : }
201 361 : return xOutStream;
202 : }
203 :
204 58 : void StorageBase::copyToStorage( StorageBase& rDestStrg, const OUString& rElementName )
205 : {
206 : OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
207 : OSL_ENSURE( !rElementName.isEmpty(), "StorageBase::copyToStorage - invalid element name" );
208 58 : if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() && !rElementName.isEmpty() )
209 : {
210 58 : StorageRef xSubStrg = openSubStorage( rElementName, false );
211 58 : if( xSubStrg.get() )
212 : {
213 3 : StorageRef xDestSubStrg = rDestStrg.openSubStorage( rElementName, true );
214 3 : if( xDestSubStrg.get() )
215 3 : xSubStrg->copyStorageToStorage( *xDestSubStrg );
216 : }
217 : else
218 : {
219 55 : Reference< XInputStream > xInStrm = openInputStream( rElementName );
220 55 : if( xInStrm.is() )
221 : {
222 55 : Reference< XOutputStream > xOutStrm = rDestStrg.openOutputStream( rElementName );
223 55 : if( xOutStrm.is() )
224 : {
225 55 : BinaryXInputStream aInStrm( xInStrm, true );
226 55 : BinaryXOutputStream aOutStrm( xOutStrm, true );
227 55 : aInStrm.copyToStream( aOutStrm );
228 55 : }
229 55 : }
230 58 : }
231 : }
232 58 : }
233 :
234 6 : void StorageBase::copyStorageToStorage( StorageBase& rDestStrg )
235 : {
236 : OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
237 6 : if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() )
238 : {
239 6 : ::std::vector< OUString > aElements;
240 6 : getElementNames( aElements );
241 64 : for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt )
242 64 : copyToStorage( rDestStrg, *aIt );
243 : }
244 6 : }
245 :
246 83 : void StorageBase::commit()
247 : {
248 : OSL_ENSURE( !mbReadOnly, "StorageBase::commit - cannot commit in read-only mode" );
249 83 : if( !mbReadOnly )
250 : {
251 : // commit all open substorages
252 83 : maSubStorages.forEachMem( &StorageBase::commit );
253 : // commit this storage
254 83 : implCommit();
255 : }
256 83 : }
257 :
258 : // private --------------------------------------------------------------------
259 :
260 826 : StorageRef StorageBase::getSubStorage( const OUString& rElementName, bool bCreateMissing )
261 : {
262 826 : StorageRef& rxSubStrg = maSubStorages[ rElementName ];
263 826 : if( !rxSubStrg )
264 443 : rxSubStrg = implOpenSubStorage( rElementName, bCreateMissing );
265 826 : return rxSubStrg;
266 : }
267 :
268 : // ============================================================================
269 :
270 51 : } // namespace oox
271 :
272 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|