LCOV - code coverage report
Current view: top level - package/source/xstor - ohierarchyholder.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 86 160 53.8 %
Date: 2015-06-13 12:38:46 Functions: 6 13 46.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11