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