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 4232 : void lclSplitFirstElement( OUString& orElement, OUString& orRemainder, OUString aFullName )
41 : {
42 4232 : sal_Int32 nSlashPos = aFullName.indexOf( '/' );
43 :
44 : // strip leading slashes
45 8464 : while( nSlashPos == 0 )
46 : {
47 0 : aFullName = aFullName.copy(1);
48 0 : nSlashPos = aFullName.indexOf( '/' );
49 : }
50 :
51 4232 : if( (0 <= nSlashPos) && (nSlashPos < aFullName.getLength()) )
52 : {
53 1436 : orElement = aFullName.copy( 0, nSlashPos );
54 1436 : orRemainder = aFullName.copy( nSlashPos + 1 );
55 : }
56 : else
57 : {
58 2796 : orElement = aFullName;
59 : }
60 4232 : }
61 :
62 : } // namespace
63 :
64 : // ----------------------------------------------------------------------------
65 :
66 1092 : StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) :
67 : mxInStream( rxInStream ),
68 : mbBaseStreamAccess( bBaseStreamAccess ),
69 1092 : mbReadOnly( true )
70 : {
71 : OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" );
72 1092 : }
73 :
74 88 : StorageBase::StorageBase( const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) :
75 : mxOutStream( rxOutStream ),
76 : mbBaseStreamAccess( bBaseStreamAccess ),
77 88 : mbReadOnly( false )
78 : {
79 : OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" );
80 88 : }
81 :
82 675 : StorageBase::StorageBase( const StorageBase& rParentStorage, const OUString& rStorageName, bool bReadOnly ) :
83 : maParentPath( rParentStorage.getPath() ),
84 : maStorageName( rStorageName ),
85 : mbBaseStreamAccess( false ),
86 675 : mbReadOnly( bReadOnly )
87 : {
88 675 : }
89 :
90 1855 : StorageBase::~StorageBase()
91 : {
92 1855 : }
93 :
94 1467 : bool StorageBase::isStorage() const
95 : {
96 1467 : return implIsStorage();
97 : }
98 :
99 0 : bool StorageBase::isRootStorage() const
100 : {
101 0 : return implIsStorage() && maStorageName.isEmpty();
102 : }
103 :
104 1687 : bool StorageBase::isReadOnly() const
105 : {
106 1687 : return mbReadOnly;
107 : }
108 :
109 162 : Reference< XStorage > StorageBase::getXStorage() const
110 : {
111 162 : return implGetXStorage();
112 : }
113 :
114 60 : const OUString& StorageBase::getName() const
115 : {
116 60 : return maStorageName;
117 : }
118 :
119 675 : OUString StorageBase::getPath() const
120 : {
121 675 : OUStringBuffer aBuffer( maParentPath );
122 675 : if( !aBuffer.isEmpty() )
123 37 : aBuffer.append( sal_Unicode( '/' ) );
124 675 : aBuffer.append( maStorageName );
125 675 : return aBuffer.makeStringAndClear();
126 : }
127 :
128 86 : void StorageBase::getElementNames( ::std::vector< OUString >& orElementNames ) const
129 : {
130 86 : orElementNames.clear();
131 86 : implGetElementNames( orElementNames );
132 86 : }
133 :
134 685 : StorageRef StorageBase::openSubStorage( const OUString& rStorageName, bool bCreateMissing )
135 : {
136 685 : StorageRef xSubStorage;
137 : OSL_ENSURE( !bCreateMissing || !mbReadOnly, "StorageBase::openSubStorage - cannot create substorage in read-only mode" );
138 685 : if( !bCreateMissing || !mbReadOnly )
139 : {
140 1370 : OUString aElement, aRemainder;
141 685 : lclSplitFirstElement( aElement, aRemainder, rStorageName );
142 685 : if( !aElement.isEmpty() )
143 685 : xSubStorage = getSubStorage( aElement, bCreateMissing );
144 685 : if( xSubStorage.get() && !aRemainder.isEmpty() )
145 685 : xSubStorage = xSubStorage->openSubStorage( aRemainder, bCreateMissing );
146 : }
147 685 : return xSubStorage;
148 : }
149 :
150 2408 : Reference< XInputStream > StorageBase::openInputStream( const OUString& rStreamName )
151 : {
152 2408 : Reference< XInputStream > xInStream;
153 4816 : OUString aElement, aRemainder;
154 2408 : lclSplitFirstElement( aElement, aRemainder, rStreamName );
155 2408 : if( !aElement.isEmpty() )
156 : {
157 2408 : if( !aRemainder.isEmpty() )
158 : {
159 1076 : StorageRef xSubStorage = getSubStorage( aElement, false );
160 1076 : if( xSubStorage.get() )
161 952 : xInStream = xSubStorage->openInputStream( aRemainder );
162 : }
163 : else
164 : {
165 1332 : xInStream = implOpenInputStream( aElement );
166 : }
167 : }
168 0 : else if( mbBaseStreamAccess )
169 : {
170 0 : xInStream = mxInStream;
171 : }
172 4816 : return xInStream;
173 : }
174 :
175 1139 : Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStreamName )
176 : {
177 1139 : Reference< XOutputStream > xOutStream;
178 : OSL_ENSURE( !mbReadOnly, "StorageBase::openOutputStream - cannot create output stream in read-only mode" );
179 1139 : if( !mbReadOnly )
180 : {
181 2278 : OUString aElement, aRemainder;
182 1139 : lclSplitFirstElement( aElement, aRemainder, rStreamName );
183 1139 : if( !aElement.isEmpty() )
184 : {
185 1139 : if( !aRemainder.isEmpty() )
186 : {
187 360 : StorageRef xSubStorage = getSubStorage( aElement, true );
188 360 : if( xSubStorage.get() )
189 360 : xOutStream = xSubStorage->openOutputStream( aRemainder );
190 : }
191 : else
192 : {
193 779 : xOutStream = implOpenOutputStream( aElement );
194 : }
195 : }
196 0 : else if( mbBaseStreamAccess )
197 : {
198 0 : xOutStream = mxOutStream->getOutputStream();
199 1139 : }
200 : }
201 1139 : return xOutStream;
202 : }
203 :
204 464 : 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 464 : if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() && !rElementName.isEmpty() )
209 : {
210 464 : StorageRef xSubStrg = openSubStorage( rElementName, false );
211 464 : if( xSubStrg.get() )
212 : {
213 30 : StorageRef xDestSubStrg = rDestStrg.openSubStorage( rElementName, true );
214 30 : if( xDestSubStrg.get() )
215 30 : xSubStrg->copyStorageToStorage( *xDestSubStrg );
216 : }
217 : else
218 : {
219 434 : Reference< XInputStream > xInStrm = openInputStream( rElementName );
220 434 : if( xInStrm.is() )
221 : {
222 434 : Reference< XOutputStream > xOutStrm = rDestStrg.openOutputStream( rElementName );
223 434 : if( xOutStrm.is() )
224 : {
225 434 : BinaryXInputStream aInStrm( xInStrm, true );
226 868 : BinaryXOutputStream aOutStrm( xOutStrm, true );
227 868 : aInStrm.copyToStream( aOutStrm );
228 434 : }
229 434 : }
230 464 : }
231 : }
232 464 : }
233 :
234 58 : void StorageBase::copyStorageToStorage( StorageBase& rDestStrg )
235 : {
236 : OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
237 58 : if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() )
238 : {
239 58 : ::std::vector< OUString > aElements;
240 58 : getElementNames( aElements );
241 522 : for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt )
242 522 : copyToStorage( rDestStrg, *aIt );
243 : }
244 58 : }
245 :
246 232 : void StorageBase::commit()
247 : {
248 : OSL_ENSURE( !mbReadOnly, "StorageBase::commit - cannot commit in read-only mode" );
249 232 : if( !mbReadOnly )
250 : {
251 : // commit all open substorages
252 232 : maSubStorages.forEachMem( &StorageBase::commit );
253 : // commit this storage
254 232 : implCommit();
255 : }
256 232 : }
257 :
258 : // private --------------------------------------------------------------------
259 :
260 2121 : StorageRef StorageBase::getSubStorage( const OUString& rElementName, bool bCreateMissing )
261 : {
262 2121 : StorageRef& rxSubStrg = maSubStorages[ rElementName ];
263 2121 : if( !rxSubStrg )
264 1338 : rxSubStrg = implOpenSubStorage( rElementName, bCreateMissing );
265 2121 : return rxSubStrg;
266 : }
267 :
268 : // ============================================================================
269 :
270 141 : } // namespace oox
271 :
272 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|