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