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