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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_package.hxx" 30 #include <com/sun/star/uno/Reference.hxx> 31 #include <com/sun/star/embed/ElementModes.hpp> 32 #include <com/sun/star/embed/XHierarchicalStorageAccess2.hpp> 33 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> 34 35 #include "ohierarchyholder.hxx" 36 37 using namespace ::com::sun::star; 38 39 //=============================================== 40 // OHierarchyHolder_Impl 41 //=============================================== 42 43 //----------------------------------------------- 44 uno::Reference< embed::XExtendedStorageStream > OHierarchyHolder_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData ) 45 { 46 uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW ); 47 48 if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) ) 49 throw io::IOException(); 50 51 uno::Reference< embed::XExtendedStorageStream > xResult = 52 m_xChild->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData ); 53 if ( !xResult.is() ) 54 throw uno::RuntimeException(); 55 56 return xResult; 57 } 58 59 //----------------------------------------------- 60 void OHierarchyHolder_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath ) 61 { 62 uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW ); 63 64 m_xChild->RemoveStreamHierarchically( aListPath ); 65 } 66 67 //----------------------------------------------- 68 // static 69 OStringList_Impl OHierarchyHolder_Impl::GetListPathFromString( const ::rtl::OUString& aPath ) 70 { 71 OStringList_Impl aResult; 72 sal_Int32 nIndex = 0; 73 do 74 { 75 ::rtl::OUString aName = aPath.getToken( 0, '/', nIndex ); 76 if ( !aName.getLength() ) 77 throw lang::IllegalArgumentException(); 78 79 aResult.push_back( aName ); 80 } 81 while ( nIndex >= 0 ); 82 83 return aResult; 84 } 85 86 //=============================================== 87 // OHierarchyElement_Impl 88 //=============================================== 89 90 //----------------------------------------------- 91 uno::Reference< embed::XExtendedStorageStream > OHierarchyElement_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData ) 92 { 93 ::osl::MutexGuard aGuard( m_aMutex ); 94 95 if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) ) 96 throw io::IOException(); 97 98 if ( !aListPath.size() ) 99 throw uno::RuntimeException(); 100 101 ::rtl::OUString aNextName = *(aListPath.begin()); 102 aListPath.erase( aListPath.begin() ); 103 104 uno::Reference< embed::XExtendedStorageStream > xResult; 105 106 uno::Reference< embed::XStorage > xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage 107 : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY ); 108 if ( !xOwnStor.is() ) 109 throw uno::RuntimeException(); 110 111 if ( !aListPath.size() ) 112 { 113 if ( !aEncryptionData.size() ) 114 { 115 uno::Reference< embed::XHierarchicalStorageAccess > xHStorage( xOwnStor, uno::UNO_QUERY_THROW ); 116 xResult = xHStorage->openStreamElementByHierarchicalName( aNextName, nStreamMode ); 117 } 118 else 119 { 120 uno::Reference< embed::XHierarchicalStorageAccess2 > xHStorage( xOwnStor, uno::UNO_QUERY_THROW ); 121 xResult = xHStorage->openEncryptedStreamByHierarchicalName( aNextName, nStreamMode, aEncryptionData.getAsConstNamedValueList() ); 122 } 123 124 uno::Reference< embed::XTransactedObject > xTransact( xResult, uno::UNO_QUERY ); 125 if ( xTransact.is() ) 126 { 127 // the existance of the transacted object means that the stream is opened for writing also 128 // so the whole chain must be commited 129 uno::Reference< embed::XTransactionBroadcaster > xTrBroadcast( xTransact, uno::UNO_QUERY_THROW ); 130 xTrBroadcast->addTransactionListener( static_cast< embed::XTransactionListener* >( this ) ); 131 } 132 else 133 { 134 uno::Reference< lang::XComponent > xStreamComp( xResult, uno::UNO_QUERY_THROW ); 135 xStreamComp->addEventListener( static_cast< lang::XEventListener* >( this ) ); 136 } 137 138 m_aOpenStreams.push_back( uno::WeakReference< embed::XExtendedStorageStream >( xResult ) ); 139 } 140 else 141 { 142 sal_Bool bNewElement = sal_False; 143 ::rtl::Reference< OHierarchyElement_Impl > aElement; 144 OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName ); 145 if ( aIter != m_aChildren.end() ) 146 aElement = aIter->second; 147 148 if ( !aElement.is() ) 149 { 150 bNewElement = sal_True; 151 uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName, nStorageMode ); 152 if ( !xChildStorage.is() ) 153 throw uno::RuntimeException(); 154 155 aElement = new OHierarchyElement_Impl( NULL, xChildStorage ); 156 } 157 158 xResult = aElement->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData ); 159 if ( !xResult.is() ) 160 throw uno::RuntimeException(); 161 162 if ( bNewElement ) 163 { 164 m_aChildren[aNextName] = aElement; 165 aElement->SetParent( this ); 166 } 167 } 168 169 // the subelement was opened successfuly, remember the storage to let it be locked 170 m_xOwnStorage = xOwnStor; 171 172 return xResult; 173 } 174 175 //----------------------------------------------- 176 void OHierarchyElement_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath ) 177 { 178 ::osl::MutexGuard aGuard( m_aMutex ); 179 180 if ( !aListPath.size() ) 181 throw uno::RuntimeException(); 182 183 ::rtl::OUString aNextName = *(aListPath.begin()); 184 aListPath.erase( aListPath.begin() ); 185 186 uno::Reference< embed::XExtendedStorageStream > xResult; 187 188 uno::Reference< embed::XStorage > xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage 189 : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY ); 190 if ( !xOwnStor.is() ) 191 throw uno::RuntimeException(); 192 193 if ( !aListPath.size() ) 194 { 195 xOwnStor->removeElement( aNextName ); 196 } 197 else 198 { 199 sal_Bool bNewElement = sal_False; 200 ::rtl::Reference< OHierarchyElement_Impl > aElement; 201 OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName ); 202 if ( aIter != m_aChildren.end() ) 203 aElement = aIter->second; 204 205 if ( !aElement.is() ) 206 { 207 bNewElement = sal_True; 208 uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName, 209 embed::ElementModes::READWRITE ); 210 if ( !xChildStorage.is() ) 211 throw uno::RuntimeException(); 212 213 aElement = new OHierarchyElement_Impl( NULL, xChildStorage ); 214 } 215 216 aElement->RemoveStreamHierarchically( aListPath ); 217 } 218 219 uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY ); 220 if ( xTransact.is() ) 221 xTransact->commit(); 222 223 TestForClosing(); 224 } 225 226 //----------------------------------------------- 227 void OHierarchyElement_Impl::Commit() 228 { 229 ::rtl::Reference< OHierarchyElement_Impl > aLocker( this ); 230 ::rtl::Reference< OHierarchyElement_Impl > aParent; 231 uno::Reference< embed::XStorage > xOwnStor; 232 233 { 234 ::osl::MutexGuard aGuard( m_aMutex ); 235 aParent = m_rParent; 236 xOwnStor = m_xOwnStorage; 237 } 238 239 if ( xOwnStor.is() ) 240 { 241 uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY_THROW ); 242 xTransact->commit(); 243 if ( aParent.is() ) 244 aParent->Commit(); 245 } 246 } 247 248 //----------------------------------------------- 249 void OHierarchyElement_Impl::TestForClosing() 250 { 251 ::rtl::Reference< OHierarchyElement_Impl > aLocker( this ); 252 { 253 ::osl::MutexGuard aGuard( m_aMutex ); 254 255 if ( !m_aOpenStreams.size() && !m_aChildren.size() ) 256 { 257 if ( m_rParent.is() ) 258 { 259 // only the root storage should not be disposed, other storages can be disposed 260 if ( m_xOwnStorage.is() ) 261 { 262 try 263 { 264 m_xOwnStorage->dispose(); 265 } 266 catch( uno::Exception& ) 267 {} 268 } 269 270 m_rParent->RemoveElement( this ); 271 } 272 273 m_xOwnStorage = uno::Reference< embed::XStorage >(); 274 } 275 } 276 } 277 278 //----------------------------------------------- 279 void SAL_CALL OHierarchyElement_Impl::disposing( const lang::EventObject& Source ) 280 throw ( uno::RuntimeException ) 281 { 282 uno::Sequence< embed::XStorage > aStoragesToCommit; 283 284 try 285 { 286 ::osl::ClearableMutexGuard aGuard( m_aMutex ); 287 uno::Reference< embed::XExtendedStorageStream > xStream( Source.Source, uno::UNO_QUERY ); 288 289 for ( OWeakStorRefList_Impl::iterator pStorageIter = m_aOpenStreams.begin(); 290 pStorageIter != m_aOpenStreams.end(); ) 291 { 292 OWeakStorRefList_Impl::iterator pTmp = pStorageIter++; 293 if ( !pTmp->get().is() || pTmp->get() == xStream ) 294 m_aOpenStreams.erase( pTmp ); 295 } 296 297 aGuard.clear(); 298 299 TestForClosing(); 300 } 301 catch( uno::Exception& ) 302 { 303 throw uno::RuntimeException(); // no exception must happen here, usually an exception means disaster 304 } 305 } 306 307 //----------------------------------------------- 308 void OHierarchyElement_Impl::RemoveElement( const ::rtl::Reference< OHierarchyElement_Impl >& aRef ) 309 { 310 { 311 ::osl::MutexGuard aGuard( m_aMutex ); 312 for ( OHierarchyElementList_Impl::iterator aIter = m_aChildren.begin(); 313 aIter != m_aChildren.end(); /* increment is done in body */) 314 { 315 OHierarchyElementList_Impl::iterator aTmpIter = aIter; 316 aIter++; 317 318 if ( aTmpIter->second == aRef ) 319 m_aChildren.erase( aTmpIter ); 320 } 321 } 322 323 TestForClosing(); 324 } 325 326 // XTransactionListener 327 //----------------------------------------------- 328 void SAL_CALL OHierarchyElement_Impl::preCommit( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) 329 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) 330 { 331 } 332 333 //----------------------------------------------- 334 void SAL_CALL OHierarchyElement_Impl::commited( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) 335 throw (::com::sun::star::uno::RuntimeException) 336 { 337 try 338 { 339 Commit(); 340 } 341 catch( uno::Exception& e ) 342 { 343 throw lang::WrappedTargetRuntimeException( 344 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can not commit storage sequence!" ) ), 345 uno::Reference< uno::XInterface >(), 346 uno::makeAny( e ) ); 347 } 348 } 349 350 //----------------------------------------------- 351 void SAL_CALL OHierarchyElement_Impl::preRevert( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) 352 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) 353 { 354 } 355 356 //----------------------------------------------- 357 void SAL_CALL OHierarchyElement_Impl::reverted( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) 358 throw (::com::sun::star::uno::RuntimeException) 359 { 360 } 361 362