LibreOffice Module oox (master) 1
storagebase.cxx
Go to the documentation of this file.
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
21
22#include <com/sun/star/io/XStream.hpp>
23#include <osl/diagnose.h>
24#include <rtl/ustrbuf.hxx>
27#include <utility>
28
29namespace oox {
30
31using namespace ::com::sun::star::embed;
32using namespace ::com::sun::star::io;
33using namespace ::com::sun::star::uno;
34
35namespace {
36
37void lclSplitFirstElement( OUString& orElement, OUString& orRemainder, const OUString& _aFullName )
38{
39 OUString aFullName = _aFullName;
40 sal_Int32 nSlashPos = aFullName.indexOf( '/' );
41
42 // strip leading slashes
43 while( nSlashPos == 0 )
44 {
45 aFullName = aFullName.copy(1);
46 nSlashPos = aFullName.indexOf( '/' );
47 }
48
49 if( (0 <= nSlashPos) && (nSlashPos < aFullName.getLength()) )
50 {
51 orElement = aFullName.copy( 0, nSlashPos );
52 orRemainder = aFullName.copy( nSlashPos + 1 );
53 }
54 else
55 {
56 orElement = aFullName;
57 }
58}
59
60} // namespace
61
62StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) :
63 mxInStream( rxInStream ),
64 mbBaseStreamAccess( bBaseStreamAccess ),
65 mbReadOnly( true )
66{
67 OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" );
68}
69
70StorageBase::StorageBase( const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) :
71 mxOutStream( rxOutStream ),
72 mbBaseStreamAccess( bBaseStreamAccess ),
73 mbReadOnly( false )
74{
75 OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" );
76}
77
78StorageBase::StorageBase( const StorageBase& rParentStorage, OUString aStorageName, bool bReadOnly ) :
79 maParentPath( rParentStorage.getPath() ),
80 maStorageName(std::move( aStorageName )),
81 mbBaseStreamAccess( false ),
82 mbReadOnly( bReadOnly )
83{
84}
85
87{
88}
89
91{
92 return implIsStorage();
93}
94
96{
97 return implIsStorage() && maStorageName.isEmpty();
98}
99
100Reference< XStorage > StorageBase::getXStorage() const
101{
102 return implGetXStorage();
103}
104
105OUString StorageBase::getPath() const
106{
107 OUStringBuffer aBuffer( maParentPath );
108 if( !aBuffer.isEmpty() )
109 aBuffer.append( '/' );
110 aBuffer.append( maStorageName );
111 return aBuffer.makeStringAndClear();
112}
113
114void StorageBase::getElementNames( ::std::vector< OUString >& orElementNames ) const
115{
116 orElementNames.clear();
117 implGetElementNames( orElementNames );
118}
119
120StorageRef StorageBase::openSubStorage( const OUString& rStorageName, bool bCreateMissing )
121{
122 StorageRef xSubStorage;
123 OSL_ENSURE( !bCreateMissing || !mbReadOnly, "StorageBase::openSubStorage - cannot create substorage in read-only mode" );
124 if( !bCreateMissing || !mbReadOnly )
125 {
126 OUString aElement, aRemainder;
127 lclSplitFirstElement( aElement, aRemainder, rStorageName );
128 if( !aElement.isEmpty() )
129 xSubStorage = getSubStorage( aElement, bCreateMissing );
130 if( xSubStorage && !aRemainder.isEmpty() )
131 xSubStorage = xSubStorage->openSubStorage( aRemainder, bCreateMissing );
132 }
133 return xSubStorage;
134}
135
136Reference< XInputStream > StorageBase::openInputStream( const OUString& rStreamName )
137{
138 Reference< XInputStream > xInStream;
139 OUString aElement, aRemainder;
140 lclSplitFirstElement( aElement, aRemainder, rStreamName );
141 if( !aElement.isEmpty() )
142 {
143 if( !aRemainder.isEmpty() )
144 {
145 StorageRef xSubStorage = getSubStorage( aElement, false );
146 if( xSubStorage )
147 xInStream = xSubStorage->openInputStream( aRemainder );
148 }
149 else
150 {
151 xInStream = implOpenInputStream( aElement );
152 }
153 }
154 else if( mbBaseStreamAccess )
155 {
156 xInStream = mxInStream;
157 }
158 return xInStream;
159}
160
161Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStreamName )
162{
163 Reference< XOutputStream > xOutStream;
164 OSL_ENSURE( !mbReadOnly, "StorageBase::openOutputStream - cannot create output stream in read-only mode" );
165 if( !mbReadOnly )
166 {
167 OUString aElement, aRemainder;
168 lclSplitFirstElement( aElement, aRemainder, rStreamName );
169 if( !aElement.isEmpty() )
170 {
171 if( !aRemainder.isEmpty() )
172 {
173 StorageRef xSubStorage = getSubStorage( aElement, true );
174 if( xSubStorage )
175 xOutStream = xSubStorage->openOutputStream( aRemainder );
176 }
177 else
178 {
179 xOutStream = implOpenOutputStream( aElement );
180 }
181 }
182 else if( mbBaseStreamAccess )
183 {
184 xOutStream = mxOutStream->getOutputStream();
185 }
186 }
187 return xOutStream;
188}
189
190void StorageBase::copyToStorage( StorageBase& rDestStrg, const OUString& rElementName )
191{
192 OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
193 OSL_ENSURE( !rElementName.isEmpty(), "StorageBase::copyToStorage - invalid element name" );
194 if( !rDestStrg.isStorage() || rDestStrg.isReadOnly() || rElementName.isEmpty() )
195 return;
196
197 StorageRef xSubStrg = openSubStorage( rElementName, false );
198 if( xSubStrg )
199 {
200 StorageRef xDestSubStrg = rDestStrg.openSubStorage( rElementName, true );
201 if( xDestSubStrg )
202 xSubStrg->copyStorageToStorage( *xDestSubStrg );
203 }
204 else
205 {
206 Reference< XInputStream > xInStrm = openInputStream( rElementName );
207 if( xInStrm.is() )
208 {
209 Reference< XOutputStream > xOutStrm = rDestStrg.openOutputStream( rElementName );
210 if( xOutStrm.is() )
211 {
212 BinaryXInputStream aInStrm( xInStrm, true );
213 BinaryXOutputStream aOutStrm( xOutStrm, true );
214 aInStrm.copyToStream( aOutStrm );
215 }
216 }
217 }
218}
219
221{
222 OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
223 if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() )
224 {
225 ::std::vector< OUString > aElements;
226 getElementNames( aElements );
227 for (auto const& elem : aElements)
228 copyToStorage(rDestStrg, elem);
229 }
230}
231
233{
234 OSL_ENSURE( !mbReadOnly, "StorageBase::commit - cannot commit in read-only mode" );
235 if( !mbReadOnly )
236 {
237 // commit all open substorages
238 maSubStorages.forEachMem( &StorageBase::commit );
239 // commit this storage
240 implCommit();
241 }
242}
243
244// private --------------------------------------------------------------------
245
246StorageRef StorageBase::getSubStorage( const OUString& rElementName, bool bCreateMissing )
247{
248 StorageRef& rxSubStrg = maSubStorages[ rElementName ];
249 if( !rxSubStrg )
250 rxSubStrg = implOpenSubStorage( rElementName, bCreateMissing );
251 return rxSubStrg;
252}
253
254} // namespace oox
255
256/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void copyToStream(BinaryOutputStream &rOutStrm)
Copies bytes from the current position to the passed output stream.
Wraps a UNO input stream and provides convenient access functions.
Wraps a UNO output stream and provides convenient access functions.
Base class for storage access implementations.
Definition: storagebase.hxx:52
virtual css::uno::Reference< css::embed::XStorage > implGetXStorage() const =0
Returns the com.sun.star.embed.XStorage interface of the current storage.
virtual bool implIsStorage() const =0
Returns true, if the object represents a valid storage.
css::uno::Reference< css::embed::XStorage > getXStorage() const
Returns the com.sun.star.embed.XStorage interface of the current storage.
StorageBase(const css::uno::Reference< css::io::XInputStream > &rxInStream, bool bBaseStreamAccess)
OUString getPath() const
Returns the full path of this storage.
bool mbReadOnly
True = storage opened read-only (based on input stream).
css::uno::Reference< css::io::XStream > mxOutStream
Cached base output stream (to keep it alive).
css::uno::Reference< css::io::XInputStream > mxInStream
Cached base input stream (to keep it alive).
bool mbBaseStreamAccess
True = access base streams with empty stream name.
StorageRef getSubStorage(const OUString &rElementName, bool bCreateMissing)
Helper that opens and caches the specified direct substorage.
void getElementNames(::std::vector< OUString > &orElementNames) const
Fills the passed vector with the names of all direct elements of this storage.
void copyToStorage(StorageBase &rDestStrg, const OUString &rElementName)
Copies the specified element from this storage to the passed destination storage.
OUString maStorageName
Name of this storage, if it is a substorage.
css::uno::Reference< css::io::XInputStream > openInputStream(const OUString &rStreamName)
Opens and returns the specified input stream from the storage.
virtual void implCommit() const =0
Commits the current storage.
RefMap< OUString, StorageBase > maSubStorages
Map of direct sub storages.
virtual css::uno::Reference< css::io::XInputStream > implOpenInputStream(const OUString &rElementName)=0
Implementation of opening an input stream element.
void commit()
Commits the changes to the storage and all substorages.
virtual css::uno::Reference< css::io::XOutputStream > implOpenOutputStream(const OUString &rElementName)=0
Implementation of opening an output stream element.
bool isReadOnly() const
Returns true, if the storage operates in read-only mode (based on an input stream).
Definition: storagebase.hxx:72
void copyStorageToStorage(StorageBase &rDestStrg)
Copies all streams of this storage and of all substorages to the passed destination.
virtual StorageRef implOpenSubStorage(const OUString &rElementName, bool bCreate)=0
Implementation of opening a storage element.
bool isStorage() const
Returns true, if the object represents a valid storage.
Definition: storagebase.cxx:90
StorageRef openSubStorage(const OUString &rStorageName, bool bCreateMissing)
Opens and returns the specified sub storage from the storage.
virtual void implGetElementNames(::std::vector< OUString > &orElementNames) const =0
Returns the names of all elements of this storage.
OUString maParentPath
Full path of parent storage.
virtual ~StorageBase()
Definition: storagebase.cxx:86
bool isRootStorage() const
Returns true, if the object represents the root storage.
Definition: storagebase.cxx:95
css::uno::Reference< css::io::XOutputStream > openOutputStream(const OUString &rStreamName)
Opens and returns the specified output stream from the storage.
Reference< XInputStream > mxInStream
Definition: fastparser.cxx:47
bool bReadOnly
std::shared_ptr< StorageBase > StorageRef
Definition: storagebase.hxx:42
std::unique_ptr< char[]> aBuffer