1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "oox/helper/storagebase.hxx" 29 30 #include <com/sun/star/embed/XTransactedObject.hpp> 31 #include <com/sun/star/io/XStream.hpp> 32 #include <rtl/ustrbuf.hxx> 33 #include "oox/helper/binaryinputstream.hxx" 34 #include "oox/helper/binaryoutputstream.hxx" 35 36 namespace oox { 37 38 // ============================================================================ 39 40 using namespace ::com::sun::star::embed; 41 using namespace ::com::sun::star::io; 42 using namespace ::com::sun::star::uno; 43 44 using ::rtl::OUString; 45 using ::rtl::OUStringBuffer; 46 47 // ============================================================================ 48 49 namespace { 50 51 void lclSplitFirstElement( OUString& orElement, OUString& orRemainder, const OUString& rFullName ) 52 { 53 sal_Int32 nSlashPos = rFullName.indexOf( '/' ); 54 if( (0 <= nSlashPos) && (nSlashPos < rFullName.getLength()) ) 55 { 56 orElement = rFullName.copy( 0, nSlashPos ); 57 orRemainder = rFullName.copy( nSlashPos + 1 ); 58 } 59 else 60 { 61 orElement = rFullName; 62 } 63 } 64 65 } // namespace 66 67 // ---------------------------------------------------------------------------- 68 69 StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) : 70 mxInStream( rxInStream ), 71 mbBaseStreamAccess( bBaseStreamAccess ), 72 mbReadOnly( true ) 73 { 74 OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" ); 75 } 76 77 StorageBase::StorageBase( const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) : 78 mxOutStream( rxOutStream ), 79 mbBaseStreamAccess( bBaseStreamAccess ), 80 mbReadOnly( false ) 81 { 82 OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" ); 83 } 84 85 StorageBase::StorageBase( const StorageBase& rParentStorage, const OUString& rStorageName, bool bReadOnly ) : 86 maParentPath( rParentStorage.getPath() ), 87 maStorageName( rStorageName ), 88 mbBaseStreamAccess( false ), 89 mbReadOnly( bReadOnly ) 90 { 91 } 92 93 StorageBase::~StorageBase() 94 { 95 } 96 97 bool StorageBase::isStorage() const 98 { 99 return implIsStorage(); 100 } 101 102 bool StorageBase::isRootStorage() const 103 { 104 return implIsStorage() && (maStorageName.getLength() == 0); 105 } 106 107 bool StorageBase::isReadOnly() const 108 { 109 return mbReadOnly; 110 } 111 112 Reference< XStorage > StorageBase::getXStorage() const 113 { 114 return implGetXStorage(); 115 } 116 117 const OUString& StorageBase::getName() const 118 { 119 return maStorageName; 120 } 121 122 OUString StorageBase::getPath() const 123 { 124 OUStringBuffer aBuffer( maParentPath ); 125 if( aBuffer.getLength() > 0 ) 126 aBuffer.append( sal_Unicode( '/' ) ); 127 aBuffer.append( maStorageName ); 128 return aBuffer.makeStringAndClear(); 129 } 130 131 void StorageBase::getElementNames( ::std::vector< OUString >& orElementNames ) const 132 { 133 orElementNames.clear(); 134 implGetElementNames( orElementNames ); 135 } 136 137 StorageRef StorageBase::openSubStorage( const OUString& rStorageName, bool bCreateMissing ) 138 { 139 StorageRef xSubStorage; 140 OSL_ENSURE( !bCreateMissing || !mbReadOnly, "StorageBase::openSubStorage - cannot create substorage in read-only mode" ); 141 if( !bCreateMissing || !mbReadOnly ) 142 { 143 OUString aElement, aRemainder; 144 lclSplitFirstElement( aElement, aRemainder, rStorageName ); 145 if( aElement.getLength() > 0 ) 146 xSubStorage = getSubStorage( aElement, bCreateMissing ); 147 if( xSubStorage.get() && (aRemainder.getLength() > 0) ) 148 xSubStorage = xSubStorage->openSubStorage( aRemainder, bCreateMissing ); 149 } 150 return xSubStorage; 151 } 152 153 Reference< XInputStream > StorageBase::openInputStream( const OUString& rStreamName ) 154 { 155 Reference< XInputStream > xInStream; 156 OUString aElement, aRemainder; 157 lclSplitFirstElement( aElement, aRemainder, rStreamName ); 158 if( aElement.getLength() > 0 ) 159 { 160 if( aRemainder.getLength() > 0 ) 161 { 162 StorageRef xSubStorage = getSubStorage( aElement, false ); 163 if( xSubStorage.get() ) 164 xInStream = xSubStorage->openInputStream( aRemainder ); 165 } 166 else 167 { 168 xInStream = implOpenInputStream( aElement ); 169 } 170 } 171 else if( mbBaseStreamAccess ) 172 { 173 xInStream = mxInStream; 174 } 175 return xInStream; 176 } 177 178 Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStreamName ) 179 { 180 Reference< XOutputStream > xOutStream; 181 OSL_ENSURE( !mbReadOnly, "StorageBase::openOutputStream - cannot create output stream in read-only mode" ); 182 if( !mbReadOnly ) 183 { 184 OUString aElement, aRemainder; 185 lclSplitFirstElement( aElement, aRemainder, rStreamName ); 186 if( aElement.getLength() > 0 ) 187 { 188 if( aRemainder.getLength() > 0 ) 189 { 190 StorageRef xSubStorage = getSubStorage( aElement, true ); 191 if( xSubStorage.get() ) 192 xOutStream = xSubStorage->openOutputStream( aRemainder ); 193 } 194 else 195 { 196 xOutStream = implOpenOutputStream( aElement ); 197 } 198 } 199 else if( mbBaseStreamAccess ) 200 { 201 xOutStream = mxOutStream->getOutputStream(); 202 } 203 } 204 return xOutStream; 205 } 206 207 void StorageBase::copyToStorage( StorageBase& rDestStrg, const OUString& rElementName ) 208 { 209 OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" ); 210 OSL_ENSURE( rElementName.getLength() > 0, "StorageBase::copyToStorage - invalid element name" ); 211 if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() && (rElementName.getLength() > 0) ) 212 { 213 StorageRef xSubStrg = openSubStorage( rElementName, false ); 214 if( xSubStrg.get() ) 215 { 216 StorageRef xDestSubStrg = rDestStrg.openSubStorage( rElementName, true ); 217 if( xDestSubStrg.get() ) 218 xSubStrg->copyStorageToStorage( *xDestSubStrg ); 219 } 220 else 221 { 222 Reference< XInputStream > xInStrm = openInputStream( rElementName ); 223 if( xInStrm.is() ) 224 { 225 Reference< XOutputStream > xOutStrm = rDestStrg.openOutputStream( rElementName ); 226 if( xOutStrm.is() ) 227 { 228 BinaryXInputStream aInStrm( xInStrm, true ); 229 BinaryXOutputStream aOutStrm( xOutStrm, true ); 230 aInStrm.copyToStream( aOutStrm ); 231 } 232 } 233 } 234 } 235 } 236 237 void StorageBase::copyStorageToStorage( StorageBase& rDestStrg ) 238 { 239 OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" ); 240 if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() ) 241 { 242 ::std::vector< OUString > aElements; 243 getElementNames( aElements ); 244 for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt ) 245 copyToStorage( rDestStrg, *aIt ); 246 } 247 } 248 249 void StorageBase::commit() 250 { 251 OSL_ENSURE( !mbReadOnly, "StorageBase::commit - cannot commit in read-only mode" ); 252 if( !mbReadOnly ) 253 { 254 // commit all open substorages 255 maSubStorages.forEachMem( &StorageBase::commit ); 256 // commit this storage 257 implCommit(); 258 } 259 } 260 261 // private -------------------------------------------------------------------- 262 263 StorageRef StorageBase::getSubStorage( const OUString& rElementName, bool bCreateMissing ) 264 { 265 StorageRef& rxSubStrg = maSubStorages[ rElementName ]; 266 if( !rxSubStrg ) 267 rxSubStrg = implOpenSubStorage( rElementName, bCreateMissing ); 268 return rxSubStrg; 269 } 270 271 // ============================================================================ 272 273 } // namespace oox 274