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

Generated by: LCOV version 1.10