LCOV - code coverage report
Current view: top level - comphelper/source/container - embeddedobjectcontainer.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 416 695 59.9 %
Date: 2015-06-13 12:38:46 Functions: 41 49 83.7 %
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/container/XChild.hpp>
      21             : #include <com/sun/star/container/XNameAccess.hpp>
      22             : #include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
      23             : #include <com/sun/star/embed/XLinkCreator.hpp>
      24             : #include <com/sun/star/embed/XEmbedPersist.hpp>
      25             : #include <com/sun/star/embed/XLinkageSupport.hpp>
      26             : #include <com/sun/star/embed/XTransactedObject.hpp>
      27             : #include <com/sun/star/embed/XOptimizedStorage.hpp>
      28             : #include <com/sun/star/embed/EntryInitModes.hpp>
      29             : #include <com/sun/star/util/XCloseable.hpp>
      30             : #include <com/sun/star/util/XModifiable.hpp>
      31             : #include <com/sun/star/embed/EmbedStates.hpp>
      32             : #include <com/sun/star/datatransfer/XTransferable.hpp>
      33             : #include <com/sun/star/beans/XPropertySetInfo.hpp>
      34             : #include <com/sun/star/beans/XPropertySet.hpp>
      35             : #include <com/sun/star/embed/Aspects.hpp>
      36             : #include <com/sun/star/embed/EmbedMisc.hpp>
      37             : 
      38             : #include <comphelper/seqstream.hxx>
      39             : #include <comphelper/processfactory.hxx>
      40             : #include <comphelper/storagehelper.hxx>
      41             : #include <comphelper/embeddedobjectcontainer.hxx>
      42             : #include <comphelper/sequence.hxx>
      43             : #include <comphelper/propertysequence.hxx>
      44             : #include <cppuhelper/weakref.hxx>
      45             : #include <sal/log.hxx>
      46             : 
      47             : #include <algorithm>
      48             : #include <unordered_map>
      49             : 
      50             : 
      51             : using namespace ::com::sun::star;
      52             : 
      53             : namespace comphelper {
      54             : 
      55             : typedef std::unordered_map<OUString, uno::Reference <embed::XEmbeddedObject>, OUStringHash>
      56             : EmbeddedObjectContainerNameMap;
      57             : 
      58        5300 : struct EmbedImpl
      59             : {
      60             :     // TODO/LATER: remove objects from temp. Container storage when object is disposed
      61             :     EmbeddedObjectContainerNameMap maObjectContainer;
      62             :     uno::Reference < embed::XStorage > mxStorage;
      63             :     EmbeddedObjectContainer* mpTempObjectContainer;
      64             :     uno::Reference < embed::XStorage > mxImageStorage;
      65             :     uno::WeakReference < uno::XInterface > m_xModel;
      66             :     //EmbeddedObjectContainerNameMap maTempObjectContainer;
      67             :     //uno::Reference < embed::XStorage > mxTempStorage;
      68             : 
      69             :     /// bitfield
      70             :     bool mbOwnsStorage : 1;
      71             :     bool mbUserAllowsLinkUpdate : 1;
      72             : 
      73             :     const uno::Reference < embed::XStorage >& GetReplacements();
      74             : };
      75             : 
      76        2137 : const uno::Reference < embed::XStorage >& EmbedImpl::GetReplacements()
      77             : {
      78        2137 :     if ( !mxImageStorage.is() )
      79             :     {
      80             :         try
      81             :         {
      82        1104 :             mxImageStorage = mxStorage->openStorageElement(
      83         736 :                 OUString("ObjectReplacements"), embed::ElementModes::READWRITE );
      84             :         }
      85           0 :         catch (const uno::Exception&)
      86             :         {
      87           0 :             mxImageStorage = mxStorage->openStorageElement(
      88           0 :                 OUString("ObjectReplacements"), embed::ElementModes::READ );
      89             :         }
      90             :     }
      91             : 
      92        2137 :     if ( !mxImageStorage.is() )
      93           0 :         throw io::IOException();
      94             : 
      95        2137 :     return mxImageStorage;
      96             : }
      97             : 
      98         354 : EmbeddedObjectContainer::EmbeddedObjectContainer()
      99             : {
     100         354 :     pImpl = new EmbedImpl;
     101         354 :     pImpl->mxStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
     102         354 :     pImpl->mbOwnsStorage = true;
     103         354 :     pImpl->mbUserAllowsLinkUpdate = true;
     104         354 :     pImpl->mpTempObjectContainer = 0;
     105         354 : }
     106             : 
     107          45 : EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor )
     108             : {
     109          45 :     pImpl = new EmbedImpl;
     110          45 :     pImpl->mxStorage = rStor;
     111          45 :     pImpl->mbOwnsStorage = false;
     112          45 :     pImpl->mbUserAllowsLinkUpdate = true;
     113          45 :     pImpl->mpTempObjectContainer = 0;
     114          45 : }
     115             : 
     116        2255 : EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor, const uno::Reference < uno::XInterface >& xModel )
     117             : {
     118        2255 :     pImpl = new EmbedImpl;
     119        2255 :     pImpl->mxStorage = rStor;
     120        2255 :     pImpl->mbOwnsStorage = false;
     121        2255 :     pImpl->mbUserAllowsLinkUpdate = true;
     122        2255 :     pImpl->mpTempObjectContainer = 0;
     123        2255 :     pImpl->m_xModel = xModel;
     124        2255 : }
     125             : 
     126           0 : void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference < embed::XStorage >& rStor )
     127             : {
     128           0 :     ReleaseImageSubStorage();
     129             : 
     130           0 :     if ( pImpl->mbOwnsStorage )
     131           0 :         pImpl->mxStorage->dispose();
     132             : 
     133           0 :     pImpl->mxStorage = rStor;
     134           0 :     pImpl->mbOwnsStorage = false;
     135           0 : }
     136             : 
     137        2659 : bool EmbeddedObjectContainer::CommitImageSubStorage()
     138             : {
     139        2659 :     if ( pImpl->mxImageStorage.is() )
     140             :     {
     141             :         try
     142             :         {
     143         375 :             bool bReadOnlyMode = true;
     144         375 :             uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY);
     145         375 :             if ( xSet.is() )
     146             :             {
     147             :                 // get the open mode from the parent storage
     148         375 :                 sal_Int32 nMode = 0;
     149         375 :                 uno::Any aAny = xSet->getPropertyValue("OpenMode");
     150         375 :                 if ( aAny >>= nMode )
     151         375 :                     bReadOnlyMode = !(nMode & embed::ElementModes::WRITE );
     152             :             } // if ( xSet.is() )
     153         375 :             if ( !bReadOnlyMode )
     154             :             {
     155         375 :                 uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW );
     156         375 :                 xTransact->commit();
     157         375 :             }
     158             :         }
     159           0 :         catch (const uno::Exception&)
     160             :         {
     161           0 :             return false;
     162             :         }
     163             :     }
     164             : 
     165        2659 :     return true;
     166             : }
     167             : 
     168        2646 : void EmbeddedObjectContainer::ReleaseImageSubStorage()
     169             : {
     170        2646 :     CommitImageSubStorage();
     171             : 
     172        2646 :     if ( pImpl->mxImageStorage.is() )
     173             :     {
     174             :         try
     175             :         {
     176         368 :             pImpl->mxImageStorage->dispose();
     177         368 :             pImpl->mxImageStorage = uno::Reference< embed::XStorage >();
     178             :         }
     179           0 :         catch (const uno::Exception&)
     180             :         {
     181             :             SAL_WARN( "comphelper.container", "Problems releasing image substorage!\n" );
     182             :         }
     183             :     }
     184        2646 : }
     185             : 
     186        2646 : EmbeddedObjectContainer::~EmbeddedObjectContainer()
     187             : {
     188        2646 :     ReleaseImageSubStorage();
     189             : 
     190        2646 :     if ( pImpl->mbOwnsStorage )
     191         354 :         pImpl->mxStorage->dispose();
     192             : 
     193        2646 :     delete pImpl->mpTempObjectContainer;
     194        2646 :     delete pImpl;
     195        2646 : }
     196             : 
     197        2247 : void EmbeddedObjectContainer::CloseEmbeddedObjects()
     198             : {
     199        2247 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
     200        5299 :     while ( aIt != pImpl->maObjectContainer.end() )
     201             :     {
     202         805 :         uno::Reference < util::XCloseable > xClose( (*aIt).second, uno::UNO_QUERY );
     203         805 :         if ( xClose.is() )
     204             :         {
     205             :             try
     206             :             {
     207         805 :                 xClose->close( sal_True );
     208             :             }
     209         710 :             catch (const uno::Exception&)
     210             :             {
     211             :             }
     212             :         }
     213             : 
     214         805 :         ++aIt;
     215         805 :     }
     216        2247 : }
     217             : 
     218        1370 : OUString EmbeddedObjectContainer::CreateUniqueObjectName()
     219             : {
     220        1370 :     OUString aPersistName("Object ");
     221        1370 :     OUString aStr;
     222        1370 :     sal_Int32 i=1;
     223        5579 :     do
     224             :     {
     225        5579 :         aStr = aPersistName;
     226        5579 :         aStr += OUString::number( i++ );
     227             :     }
     228             :     while( HasEmbeddedObject( aStr ) );
     229             :     // TODO/LATER: should we consider deleted objects?
     230             : 
     231        1370 :     return aStr;
     232             : }
     233             : 
     234       13909 : uno::Sequence < OUString > EmbeddedObjectContainer::GetObjectNames()
     235             : {
     236       13909 :     uno::Sequence < OUString > aSeq( pImpl->maObjectContainer.size() );
     237       13909 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
     238       13909 :     sal_Int32 nIdx=0;
     239       33964 :     while ( aIt != pImpl->maObjectContainer.end() )
     240        6146 :         aSeq[nIdx++] = (*aIt++).first;
     241       13909 :     return aSeq;
     242             : }
     243             : 
     244           1 : bool EmbeddedObjectContainer::HasEmbeddedObjects()
     245             : {
     246           1 :     return pImpl->maObjectContainer.size() != 0;
     247             : }
     248             : 
     249        5918 : bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName )
     250             : {
     251        5918 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
     252        5918 :     if ( aIt == pImpl->maObjectContainer.end() )
     253             :     {
     254        1371 :         uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
     255        1371 :         return xAccess->hasByName(rName);
     256             :     }
     257             :     else
     258        4547 :         return true;
     259             : }
     260             : 
     261          58 : bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
     262             : {
     263          58 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
     264         189 :     while ( aIt != pImpl->maObjectContainer.end() )
     265             :     {
     266         131 :         if ( (*aIt).second == xObj )
     267          58 :             return true;
     268             :         else
     269          73 :             ++aIt;
     270             :     }
     271             : 
     272           0 :     return false;
     273             : }
     274             : 
     275         112 : bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rName )
     276             : {
     277             :     // allows to detect whether the object was already instantiated
     278             :     // currently the filter instantiate it on loading, so this method allows
     279             :     // to avoid objects pointing to the same persistence
     280         112 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
     281         112 :     return ( aIt != pImpl->maObjectContainer.end() );
     282             : }
     283             : 
     284         314 : OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj )
     285             : {
     286         314 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
     287         852 :     while ( aIt != pImpl->maObjectContainer.end() )
     288             :     {
     289         538 :         if ( (*aIt).second == xObj )
     290         314 :             return (*aIt).first;
     291             :         else
     292         224 :             ++aIt;
     293             :     }
     294             : 
     295             :     SAL_WARN( "comphelper.container", "Unknown object!" );
     296           0 :     return OUString();
     297             : }
     298             : 
     299        6504 : uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedObject( const OUString& rName )
     300             : {
     301             :     SAL_WARN_IF( rName.isEmpty(), "comphelper.container", "Empty object name!");
     302             : 
     303        6504 :     uno::Reference < embed::XEmbeddedObject > xObj;
     304        6504 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
     305             : 
     306             : #if OSL_DEBUG_LEVEL > 1
     307             :     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
     308             :     uno::Sequence< OUString> aSeq = xAccess->getElementNames();
     309             :     const OUString* pIter = aSeq.getConstArray();
     310             :     const OUString* pEnd   = pIter + aSeq.getLength();
     311             :     for(;pIter != pEnd;++pIter)
     312             :     {
     313             :         (void)*pIter;
     314             :     }
     315             :     OSL_ENSURE( aIt != pImpl->maObjectContainer.end() || xAccess->hasByName(rName), "Could not return object!" );
     316             : #endif
     317             : 
     318             :     // check if object was already created
     319        6504 :     if ( aIt != pImpl->maObjectContainer.end() )
     320        6375 :         xObj = (*aIt).second;
     321             :     else
     322         129 :         xObj = Get_Impl( rName, uno::Reference < embed::XEmbeddedObject >() );
     323             : 
     324        6504 :     return xObj;
     325             : }
     326             : 
     327         155 : uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::Get_Impl( const OUString& rName, const uno::Reference < embed::XEmbeddedObject >& xCopy )
     328             : {
     329         155 :     uno::Reference < embed::XEmbeddedObject > xObj;
     330             :     try
     331             :     {
     332             :         // create the object from the storage
     333         155 :         uno::Reference < beans::XPropertySet > xSet( pImpl->mxStorage, uno::UNO_QUERY );
     334         155 :         bool bReadOnlyMode = true;
     335         155 :         if ( xSet.is() )
     336             :         {
     337             :             // get the open mode from the parent storage
     338         155 :             sal_Int32 nMode = 0;
     339         155 :             uno::Any aAny = xSet->getPropertyValue("OpenMode");
     340         155 :             if ( aAny >>= nMode )
     341         155 :                 bReadOnlyMode = !(nMode & embed::ElementModes::WRITE );
     342             :         }
     343             : 
     344             :         // object was not added until now - should happen only by calling this method from "inside"
     345             :         //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call)
     346         310 :         uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
     347         310 :         uno::Sequence< beans::PropertyValue > aObjDescr( xCopy.is() ? 2 : 1 );
     348         155 :         aObjDescr[0].Name = "Parent";
     349         155 :         aObjDescr[0].Value <<= pImpl->m_xModel.get();
     350         155 :         if ( xCopy.is() )
     351             :         {
     352          26 :             aObjDescr[1].Name = "CloneFrom";
     353          26 :             aObjDescr[1].Value <<= xCopy;
     354             :         }
     355             : 
     356         310 :         uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
     357         155 :         aMediaDescr[0].Name = "ReadOnly";
     358         155 :         aMediaDescr[0].Value <<= bReadOnlyMode;
     359         450 :         xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromEntry(
     360             :                 pImpl->mxStorage, rName,
     361         295 :                 aMediaDescr, aObjDescr ), uno::UNO_QUERY );
     362             : 
     363             :         // insert object into my list
     364         295 :         AddEmbeddedObject( xObj, rName );
     365             :     }
     366          15 :     catch (uno::Exception const& e)
     367             :     {
     368             :         SAL_WARN("comphelper.container", "EmbeddedObjectContainer::Get_Impl: exception caught: " << e.Message);
     369             :     }
     370             : 
     371         155 :     return xObj;
     372             : }
     373             : 
     374         502 : uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId,
     375             :             const uno::Sequence < beans::PropertyValue >& rArgs, OUString& rNewName )
     376             : {
     377         502 :     if ( rNewName.isEmpty() )
     378         495 :         rNewName = CreateUniqueObjectName();
     379             : 
     380             :     SAL_WARN_IF( HasEmbeddedObject(rNewName), "comphelper.container", "Object to create already exists!");
     381             : 
     382             :     // create object from classid by inserting it into storage
     383         502 :     uno::Reference < embed::XEmbeddedObject > xObj;
     384             :     try
     385             :     {
     386         502 :         uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
     387             : 
     388        1004 :         uno::Sequence< beans::PropertyValue > aObjDescr( rArgs.getLength() + 1 );
     389         502 :         aObjDescr[0].Name = "Parent";
     390         502 :         aObjDescr[0].Value <<= pImpl->m_xModel.get();
     391         502 :         ::std::copy( rArgs.begin(), rArgs.end(), aObjDescr.getArray() + 1 );
     392        1506 :         xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitNew(
     393             :                     rClassId, OUString(), pImpl->mxStorage, rNewName,
     394        1004 :                     aObjDescr ), uno::UNO_QUERY );
     395             : 
     396         502 :         AddEmbeddedObject( xObj, rNewName );
     397             : 
     398             :         OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
     399         502 :                     "A freshly create object should be running always!\n" );
     400             :     }
     401           0 :     catch (uno::Exception const& e)
     402             :     {
     403             :         SAL_WARN("comphelper.container", "EmbeddedObjectContainer::CreateEmbeddedObject: exception caught: " << e.Message);
     404             :     }
     405             : 
     406         502 :     return xObj;
     407             : }
     408             : 
     409         502 : uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId, OUString& rNewName )
     410             : {
     411         502 :     return CreateEmbeddedObject( rClassId, uno::Sequence < beans::PropertyValue >(), rNewName );
     412             : }
     413             : 
     414        1498 : void EmbeddedObjectContainer::AddEmbeddedObject( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, const OUString& rName )
     415             : {
     416             : #if OSL_DEBUG_LEVEL > 1
     417             :     SAL_WARN_IF( rName.isEmpty(), "comphelper.container", "Added object doesn't have a name!");
     418             :     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
     419             :     uno::Reference < embed::XEmbedPersist > xEmb( xObj, uno::UNO_QUERY );
     420             :     uno::Reference < embed::XLinkageSupport > xLink( xEmb, uno::UNO_QUERY );
     421             :     // if the object has a persistence and the object is not a link than it must have persistence entry in the storage
     422             :     OSL_ENSURE( !( xEmb.is() && ( !xLink.is() || !xLink->isLink() ) ) || xAccess->hasByName(rName),
     423             :                     "Added element not in storage!" );
     424             : #endif
     425             : 
     426             :     // remember object - it needs to be in storage already
     427        1498 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
     428             :     OSL_ENSURE( aIt == pImpl->maObjectContainer.end(), "Element already inserted!" );
     429        1498 :     pImpl->maObjectContainer[ rName ] = xObj;
     430        1498 :     uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
     431        1498 :     if ( xChild.is() && xChild->getParent() != pImpl->m_xModel.get() )
     432          90 :         xChild->setParent( pImpl->m_xModel.get() );
     433             : 
     434             :     // look for object in temporary container
     435        1498 :     if ( pImpl->mpTempObjectContainer )
     436             :     {
     437          63 :         aIt = pImpl->mpTempObjectContainer->pImpl->maObjectContainer.begin();
     438         248 :         while ( aIt != pImpl->mpTempObjectContainer->pImpl->maObjectContainer.end() )
     439             :         {
     440         122 :             if ( (*aIt).second == xObj )
     441             :             {
     442             :                 // copy replacement image from temporary container (if there is any)
     443           0 :                 OUString aTempName = (*aIt).first;
     444           0 :                 OUString aMediaType;
     445           0 :                 uno::Reference < io::XInputStream > xStream = pImpl->mpTempObjectContainer->GetGraphicStream( xObj, &aMediaType );
     446           0 :                 if ( xStream.is() )
     447             :                 {
     448           0 :                     InsertGraphicStream( xStream, rName, aMediaType );
     449           0 :                     xStream = 0;
     450           0 :                     pImpl->mpTempObjectContainer->RemoveGraphicStream( aTempName );
     451             :                 }
     452             : 
     453             :                 // remove object from storage of temporary container
     454           0 :                 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
     455           0 :                 if ( xPersist.is() )
     456             :                 {
     457             :                     try
     458             :                     {
     459           0 :                         pImpl->mpTempObjectContainer->pImpl->mxStorage->removeElement( aTempName );
     460             :                     }
     461           0 :                     catch (const uno::Exception&)
     462             :                     {
     463             :                     }
     464             :                 }
     465             : 
     466             :                 // temp. container needs to forget the object
     467           0 :                 pImpl->mpTempObjectContainer->pImpl->maObjectContainer.erase( aIt );
     468           0 :                 break;
     469             :             }
     470             :             else
     471         122 :                 ++aIt;
     472             :         }
     473        1498 :     }
     474        1498 : }
     475             : 
     476         869 : bool EmbeddedObjectContainer::StoreEmbeddedObject(
     477             :     const uno::Reference < embed::XEmbeddedObject >& xObj, OUString& rName, bool bCopy,
     478             :     const OUString& rSrcShellID, const OUString& rDestShellID )
     479             : {
     480         869 :     uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
     481         869 :     if ( rName.isEmpty() )
     482         843 :         rName = CreateUniqueObjectName();
     483             : 
     484             : #if OSL_DEBUG_LEVEL > 1
     485             :     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
     486             :     OSL_ENSURE( !xPersist.is() || !xAccess->hasByName(rName), "Inserting element already present in storage!" );
     487             :     OSL_ENSURE( xPersist.is() || xObj->getCurrentState() == embed::EmbedStates::RUNNING, "Non persistent object inserted!");
     488             : #endif
     489             : 
     490             :     // insert objects' storage into the container storage (if object has one)
     491             :     try
     492             :     {
     493         869 :         if ( xPersist.is() )
     494             :         {
     495         864 :             uno::Sequence < beans::PropertyValue > aSeq;
     496         864 :             if ( bCopy )
     497             :             {
     498             :                 auto aObjArgs(::comphelper::InitPropertySequence({
     499             :                     { "SourceShellID", uno::makeAny(rSrcShellID) },
     500             :                     { "DestinationShellID", uno::makeAny(rDestShellID) }
     501          22 :                 }));
     502          22 :                 xPersist->storeToEntry(pImpl->mxStorage, rName, aSeq, aObjArgs);
     503             :             }
     504             :             else
     505             :             {
     506             :                 //TODO/LATER: possible optimization, don't store immediately
     507             :                 //xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq );
     508         842 :                 xPersist->storeAsEntry( pImpl->mxStorage, rName, aSeq, aSeq );
     509         842 :                 xPersist->saveCompleted( sal_True );
     510         864 :             }
     511             :         }
     512             :     }
     513           0 :     catch (uno::Exception const& e)
     514             :     {
     515             :         SAL_WARN("comphelper.container", "EmbeddedObjectContainer::StoreEmbeddedObject: exception caught: " << e.Message);
     516             :         // TODO/LATER: better error recovery should keep storage intact
     517           0 :         return false;
     518             :     }
     519             : 
     520         869 :     return true;
     521             : }
     522             : 
     523         843 : bool EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, OUString& rName )
     524             : {
     525             :     // store it into the container storage
     526         843 :     if (StoreEmbeddedObject(xObj, rName, false, OUString(), OUString()))
     527             :     {
     528             :         // remember object
     529         843 :         AddEmbeddedObject( xObj, rName );
     530         843 :         return true;
     531             :     }
     532             :     else
     533           0 :         return false;
     534             : }
     535             : 
     536           0 : uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < io::XInputStream >& xStm, OUString& rNewName )
     537             : {
     538           0 :     if ( rNewName.isEmpty() )
     539           0 :         rNewName = CreateUniqueObjectName();
     540             : 
     541             :     // store it into the container storage
     542           0 :     bool bIsStorage = false;
     543             :     try
     544             :     {
     545             :         // first try storage persistence
     546           0 :         uno::Reference < embed::XStorage > xStore = ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm );
     547             : 
     548             :         // storage was created from stream successfully
     549           0 :         bIsStorage = true;
     550             : 
     551           0 :         uno::Reference < embed::XStorage > xNewStore = pImpl->mxStorage->openStorageElement( rNewName, embed::ElementModes::READWRITE );
     552           0 :         xStore->copyToStorage( xNewStore );
     553             :     }
     554           0 :     catch (const uno::Exception&)
     555             :     {
     556           0 :         if ( bIsStorage )
     557             :             // it is storage persistence, but opening of new substorage or copying to it failed
     558           0 :             return uno::Reference < embed::XEmbeddedObject >();
     559             : 
     560             :         // stream didn't contain a storage, now try stream persistence
     561             :         try
     562             :         {
     563           0 :             uno::Reference < io::XStream > xNewStream = pImpl->mxStorage->openStreamElement( rNewName, embed::ElementModes::READWRITE );
     564           0 :             ::comphelper::OStorageHelper::CopyInputToOutput( xStm, xNewStream->getOutputStream() );
     565             : 
     566             :             // No mediatype is provided so the default for OLE objects value is used
     567             :             // it is correct so for now, but what if somebody introduces a new stream based embedded object?
     568             :             // Probably introducing of such an object must be restricted ( a storage must be used! ).
     569           0 :             uno::Reference< beans::XPropertySet > xProps( xNewStream, uno::UNO_QUERY_THROW );
     570           0 :             xProps->setPropertyValue("MediaType",
     571           0 :                     uno::makeAny( OUString( "application/vnd.sun.star.oleobject" ) ) );
     572             :         }
     573           0 :         catch (uno::Exception const& e)
     574             :         {
     575             :             // complete disaster!
     576             :             SAL_WARN("comphelper.container", "EmbeddedObjectContainer::InsertEmbeddedObject: exception caught: " << e.Message);
     577           0 :             return uno::Reference < embed::XEmbeddedObject >();
     578             :         }
     579           0 :     }
     580             : 
     581             :     // stream was copied into the container storage in either way, now try to open something form it
     582           0 :     uno::Reference < embed::XEmbeddedObject > xRet = GetEmbeddedObject( rNewName );
     583             :     try
     584             :     {
     585           0 :         if ( !xRet.is() )
     586             :             // no object could be created, so withdraw insertion
     587           0 :             pImpl->mxStorage->removeElement( rNewName );
     588             :     }
     589           0 :     catch (const uno::Exception&)
     590             :     {
     591             :     }
     592             : 
     593           0 :     return xRet;
     594             : }
     595             : 
     596          21 : uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, OUString& rNewName )
     597             : {
     598          21 :     if ( rNewName.isEmpty() )
     599           0 :         rNewName = CreateUniqueObjectName();
     600             : 
     601          21 :     uno::Reference < embed::XEmbeddedObject > xObj;
     602             :     try
     603             :     {
     604          21 :         uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
     605          42 :         uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
     606          21 :         aObjDescr[0].Name = "Parent";
     607          21 :         aObjDescr[0].Value <<= pImpl->m_xModel.get();
     608          55 :         xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromMediaDescriptor(
     609          34 :                 pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY );
     610          26 :         uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
     611             : 
     612             :            OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
     613             :                     "A freshly create object should be running always!\n" );
     614             : 
     615             :         // possible optimization: store later!
     616          13 :         if ( xPersist.is())
     617          13 :             xPersist->storeOwn();
     618             : 
     619          34 :         AddEmbeddedObject( xObj, rNewName );
     620             :     }
     621           8 :     catch (const uno::Exception&)
     622             :     {
     623             :     }
     624             : 
     625          21 :     return xObj;
     626             : }
     627             : 
     628           0 : uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, OUString& rNewName )
     629             : {
     630           0 :     if ( rNewName.isEmpty() )
     631           0 :         rNewName = CreateUniqueObjectName();
     632             : 
     633           0 :     uno::Reference < embed::XEmbeddedObject > xObj;
     634             :     try
     635             :     {
     636           0 :         uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create(::comphelper::getProcessComponentContext());
     637           0 :         uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
     638           0 :         aObjDescr[0].Name = "Parent";
     639           0 :         aObjDescr[0].Value <<= pImpl->m_xModel.get();
     640           0 :         xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceLink(
     641           0 :                 pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY );
     642             : 
     643           0 :         uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
     644             : 
     645             :            OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
     646             :                     "A freshly create object should be running always!\n" );
     647             : 
     648             :         // possible optimization: store later!
     649           0 :         if ( xPersist.is())
     650           0 :             xPersist->storeOwn();
     651             : 
     652           0 :         AddEmbeddedObject( xObj, rNewName );
     653             :     }
     654           0 :     catch (uno::Exception const& e)
     655             :     {
     656             :         SAL_WARN("comphelper", "EmbeddedObjectContainer::InsertEmbeddedLink: "
     657             :                 "exception caught: " << e.Message);
     658             :     }
     659             : 
     660           0 :     return xObj;
     661             : }
     662             : 
     663          22 : bool EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer& rSrc,
     664             :                                                             const OUString& aOrigName,
     665             :                                                             const OUString& aTargetName )
     666             : {
     667          22 :     bool bResult = false;
     668             : 
     669          22 :     if ( ( &rSrc != this || !aOrigName.equals( aTargetName ) ) && !aOrigName.isEmpty() && !aTargetName.isEmpty() )
     670             :     {
     671          22 :         OUString aMediaType;
     672          44 :         uno::Reference < io::XInputStream > xGrStream = rSrc.GetGraphicStream( aOrigName, &aMediaType );
     673          22 :         if ( xGrStream.is() )
     674          44 :             bResult = InsertGraphicStream( xGrStream, aTargetName, aMediaType );
     675             :     }
     676             : 
     677          22 :     return bResult;
     678             : }
     679             : 
     680          29 : uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmbeddedObject(
     681             :     EmbeddedObjectContainer& rSrc, const uno::Reference <embed::XEmbeddedObject>& xObj, OUString& rName,
     682             :     const OUString& rSrcShellID, const OUString& rDestShellID )
     683             : {
     684          29 :     uno::Reference< embed::XEmbeddedObject > xResult;
     685             : 
     686             :     // TODO/LATER: For now only objects that implement XEmbedPersist have a replacement image, it might change in future
     687             :     // do an incompatible change so that object name is provided in all the move and copy methods
     688          58 :     OUString aOrigName;
     689             :     try
     690             :     {
     691          29 :         uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY_THROW );
     692          22 :         aOrigName = xPersist->getEntryName();
     693             :     }
     694           7 :     catch (const uno::Exception&)
     695             :     {
     696             :     }
     697             : 
     698          29 :     if ( rName.isEmpty() )
     699          29 :         rName = CreateUniqueObjectName();
     700             : 
     701             :     // objects without persistence are not really stored by the method
     702          29 :     if (xObj.is() && StoreEmbeddedObject(xObj, rName, true, rSrcShellID, rDestShellID))
     703             :     {
     704          26 :         xResult = Get_Impl( rName, xObj);
     705          26 :         if ( !xResult.is() )
     706             :         {
     707             :             // this is a case when object has no real persistence
     708             :             // in such cases a new object should be explicitly created and initialized with the data of the old one
     709             :             try
     710             :             {
     711           4 :                 uno::Reference< embed::XLinkageSupport > xOrigLinkage( xObj, uno::UNO_QUERY );
     712           4 :                 if ( xOrigLinkage.is() && xOrigLinkage->isLink() )
     713             :                 {
     714             :                     // this is a OOo link, it has no persistence
     715           0 :                     OUString aURL = xOrigLinkage->getLinkURL();
     716           0 :                     if ( aURL.isEmpty() )
     717           0 :                         throw uno::RuntimeException();
     718             : 
     719             :                     // create new linked object from the URL the link is based on
     720             :                     uno::Reference < embed::XEmbeddedObjectCreator > xCreator =
     721           0 :                         embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
     722             : 
     723           0 :                     uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
     724           0 :                     aMediaDescr[0].Name = "URL";
     725           0 :                     aMediaDescr[0].Value <<= aURL;
     726           0 :                     uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
     727           0 :                     aObjDescr[0].Name = "Parent";
     728           0 :                     aObjDescr[0].Value <<= pImpl->m_xModel.get();
     729           0 :                     xResult = uno::Reference < embed::XEmbeddedObject >(
     730           0 :                                 xCreator->createInstanceLink(
     731             :                                     pImpl->mxStorage,
     732             :                                     rName,
     733             :                                     aMediaDescr,
     734           0 :                                     aObjDescr ),
     735           0 :                                 uno::UNO_QUERY_THROW );
     736             :                 }
     737             :                 else
     738             :                 {
     739             :                     // the component is required for copying of this object
     740           4 :                     if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
     741           4 :                         xObj->changeState( embed::EmbedStates::RUNNING );
     742             : 
     743             :                     // this must be an object based on properties, otherwise we can not copy it currently
     744           0 :                     uno::Reference< beans::XPropertySet > xOrigProps( xObj->getComponent(), uno::UNO_QUERY_THROW );
     745             : 
     746             :                     // use object class ID to create a new one and transfer all the properties
     747             :                     uno::Reference < embed::XEmbeddedObjectCreator > xCreator =
     748           0 :                         embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
     749             : 
     750           0 :                     uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
     751           0 :                     aObjDescr[0].Name = "Parent";
     752           0 :                     aObjDescr[0].Value <<= pImpl->m_xModel.get();
     753           0 :                     xResult = uno::Reference < embed::XEmbeddedObject >(
     754           0 :                                 xCreator->createInstanceInitNew(
     755           0 :                                     xObj->getClassID(),
     756           0 :                                     xObj->getClassName(),
     757             :                                     pImpl->mxStorage,
     758             :                                     rName,
     759           0 :                                     aObjDescr ),
     760           0 :                                 uno::UNO_QUERY_THROW );
     761             : 
     762           0 :                     if ( xResult->getCurrentState() == embed::EmbedStates::LOADED )
     763           0 :                         xResult->changeState( embed::EmbedStates::RUNNING );
     764             : 
     765           0 :                     uno::Reference< beans::XPropertySet > xTargetProps( xResult->getComponent(), uno::UNO_QUERY_THROW );
     766             : 
     767             :                     // copy all the properties from xOrigProps to xTargetProps
     768           0 :                     uno::Reference< beans::XPropertySetInfo > xOrigInfo = xOrigProps->getPropertySetInfo();
     769           0 :                     if ( !xOrigInfo.is() )
     770           0 :                         throw uno::RuntimeException();
     771             : 
     772           0 :                     uno::Sequence< beans::Property > aPropertiesList = xOrigInfo->getProperties();
     773           0 :                     for ( sal_Int32 nInd = 0; nInd < aPropertiesList.getLength(); nInd++ )
     774             :                     {
     775             :                         try
     776             :                         {
     777           0 :                             xTargetProps->setPropertyValue(
     778           0 :                                 aPropertiesList[nInd].Name,
     779           0 :                                 xOrigProps->getPropertyValue( aPropertiesList[nInd].Name ) );
     780             :                         }
     781           0 :                         catch (const beans::PropertyVetoException&)
     782             :                         {
     783             :                             // impossibility to copy readonly property is not treated as an error for now
     784             :                             // but the assertion is helpful to detect such scenarios and review them
     785             :                             SAL_WARN( "comphelper.container", "Could not copy readonly property!\n" );
     786             :                         }
     787           0 :                     }
     788             :                 }
     789             : 
     790           0 :                    if ( xResult.is() )
     791           4 :                     AddEmbeddedObject( xResult, rName );
     792             :             }
     793           4 :             catch (const uno::Exception&)
     794             :             {
     795           4 :                 if ( xResult.is() )
     796             :                 {
     797             :                     try
     798             :                     {
     799           0 :                         xResult->close( sal_True );
     800             :                     }
     801           0 :                     catch (const uno::Exception&)
     802             :                     {
     803             :                     }
     804           0 :                     xResult = uno::Reference< embed::XEmbeddedObject >();
     805             :                 }
     806             :             }
     807             :         }
     808             :     }
     809             : 
     810             :     SAL_WARN_IF( !xResult.is(), "comphelper.container", "Can not copy embedded object that has no persistence!\n" );
     811             : 
     812          29 :     if ( xResult.is() )
     813             :     {
     814             :         // the object is successfully copied, try to copy graphical replacement
     815          22 :         if ( !aOrigName.isEmpty() )
     816          22 :             TryToCopyGraphReplacement( rSrc, aOrigName, rName );
     817             : 
     818             :         // the object might need the size to be set
     819             :         try
     820             :         {
     821          22 :             if ( xResult->getStatus( embed::Aspects::MSOLE_CONTENT ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD )
     822           0 :                 xResult->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT,
     823           0 :                                             xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ) );
     824             :         }
     825           0 :         catch (const uno::Exception&)
     826             :         {
     827             :         }
     828             :     }
     829             : 
     830          58 :     return xResult;
     831             : }
     832             : 
     833           0 : bool EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, OUString& rName )
     834             : {
     835             :     // get the object name before(!) it is assigned to a new storage
     836           0 :     uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
     837           0 :     OUString aName;
     838           0 :     if ( xPersist.is() )
     839           0 :         aName = xPersist->getEntryName();
     840             : 
     841             :     // now move the object to the new container; the returned name is the new persist name in this container
     842             :     bool bRet;
     843             : 
     844             :     try
     845             :     {
     846           0 :         bRet = InsertEmbeddedObject( xObj, rName );
     847           0 :         if ( bRet )
     848           0 :             TryToCopyGraphReplacement( rSrc, aName, rName );
     849             :     }
     850           0 :     catch (const uno::Exception&)
     851             :     {
     852             :         SAL_WARN( "comphelper.container", "Failed to insert embedded object into storage!" );
     853           0 :         bRet = false;
     854             :     }
     855             : 
     856           0 :     if ( bRet )
     857             :     {
     858             :         // now remove the object from the former container
     859           0 :         bRet = false;
     860           0 :         EmbeddedObjectContainerNameMap::iterator aIt = rSrc.pImpl->maObjectContainer.begin();
     861           0 :         while ( aIt != rSrc.pImpl->maObjectContainer.end() )
     862             :         {
     863           0 :             if ( (*aIt).second == xObj )
     864             :             {
     865           0 :                 rSrc.pImpl->maObjectContainer.erase( aIt );
     866           0 :                 bRet = true;
     867           0 :                 break;
     868             :             }
     869             : 
     870           0 :             ++aIt;
     871             :         }
     872             : 
     873             :         SAL_WARN_IF( !bRet, "comphelper.container", "Object not found for removal!" );
     874           0 :         if ( xPersist.is() )
     875             :         {
     876             :             // now it's time to remove the storage from the container storage
     877             :             try
     878             :             {
     879           0 :                 if ( xPersist.is() )
     880           0 :                     rSrc.pImpl->mxStorage->removeElement( aName );
     881             :             }
     882           0 :             catch (const uno::Exception&)
     883             :             {
     884             :                 SAL_WARN( "comphelper.container", "Failed to remove object from storage!" );
     885           0 :                 bRet = false;
     886             :             }
     887             :         }
     888             : 
     889             :         // rSrc.RemoveGraphicStream( aName );
     890             :     }
     891             : 
     892           0 :     return bRet;
     893             : }
     894             : 
     895             : // #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+
     896          29 : bool EmbeddedObjectContainer::RemoveEmbeddedObject( const OUString& rName, bool bClose, bool bKeepToTempStorage )
     897             : {
     898          29 :     uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( rName );
     899          29 :     if ( xObj.is() )
     900             :         //return RemoveEmbeddedObject( xObj, bClose );
     901          29 :         return RemoveEmbeddedObject( xObj, bClose, bKeepToTempStorage );
     902             :     else
     903           0 :         return false;
     904             : }
     905             : 
     906           0 : bool EmbeddedObjectContainer::MoveEmbeddedObject( const OUString& rName, EmbeddedObjectContainer& rCnt )
     907             : {
     908             :     // find object entry
     909           0 :     EmbeddedObjectContainerNameMap::iterator aIt2 = rCnt.pImpl->maObjectContainer.find( rName );
     910             :     OSL_ENSURE( aIt2 == rCnt.pImpl->maObjectContainer.end(), "Object does already exist in target container!" );
     911             : 
     912           0 :     if ( aIt2 != rCnt.pImpl->maObjectContainer.end() )
     913           0 :         return false;
     914             : 
     915           0 :     uno::Reference < embed::XEmbeddedObject > xObj;
     916           0 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
     917           0 :     if ( aIt != pImpl->maObjectContainer.end() )
     918             :     {
     919           0 :         xObj = (*aIt).second;
     920             :         try
     921             :         {
     922           0 :             if ( xObj.is() )
     923             :             {
     924             :                 // move object
     925           0 :                 OUString aName( rName );
     926           0 :                 rCnt.InsertEmbeddedObject( xObj, aName );
     927           0 :                 pImpl->maObjectContainer.erase( aIt );
     928           0 :                 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
     929           0 :                 if ( xPersist.is() )
     930           0 :                     pImpl->mxStorage->removeElement( rName );
     931             :             }
     932             :             else
     933             :             {
     934             :                 // copy storages; object *must* have persistence!
     935           0 :                 uno::Reference < embed::XStorage > xOld = pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READ );
     936           0 :                 uno::Reference < embed::XStorage > xNew = rCnt.pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READWRITE );
     937           0 :                 xOld->copyToStorage( xNew );
     938             :             }
     939             : 
     940           0 :             rCnt.TryToCopyGraphReplacement( *this, rName, rName );
     941             :             // RemoveGraphicStream( rName );
     942             : 
     943           0 :             return true;
     944             :         }
     945           0 :         catch (const uno::Exception&)
     946             :         {
     947             :             SAL_WARN( "comphelper.container", "Could not move object!");
     948           0 :             return false;
     949             :         }
     950             : 
     951             :     }
     952             :     else
     953             :         SAL_WARN( "comphelper.container", "Unknown object!");
     954           0 :     return false;
     955             : }
     956             : 
     957             : //sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose )
     958             : // #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+
     959         116 : bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, bool bClose, bool bKeepToTempStorage )
     960             : {
     961         116 :     uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
     962         232 :     OUString aName;
     963         116 :     if ( xPersist.is() )
     964         109 :         aName = xPersist->getEntryName();
     965             : 
     966             : #if OSL_DEBUG_LEVEL > 1
     967             :     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
     968             :     uno::Reference < embed::XLinkageSupport > xLink( xPersist, uno::UNO_QUERY );
     969             :     sal_Bool bIsNotEmbedded = !xPersist.is() || ( xLink.is() && xLink->isLink() );
     970             : 
     971             :     // if the object has a persistence and the object is not a link than it must have persistence entry in the storage
     972             :     OSL_ENSURE( bIsNotEmbedded || xAccess->hasByName(aName), "Removing element not present in storage!" );
     973             : #endif
     974             : 
     975             :     // try to close it if permitted
     976         116 :     if ( bClose )
     977             :     {
     978           0 :         uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
     979             :         try
     980             :         {
     981           0 :             xClose->close( sal_True );
     982             :         }
     983           0 :         catch (const util::CloseVetoException&)
     984             :         {
     985           0 :             bClose = false;
     986           0 :         }
     987             :     }
     988             : 
     989         116 :     if ( !bClose )
     990             :     {
     991             :         // somebody still needs the object, so we must assign a temporary persistence
     992             :         try
     993             :         {
     994             :         //    if ( xPersist.is() )
     995         116 :              if ( xPersist.is() && bKeepToTempStorage ) // #i119941
     996             :             {
     997             :                 /*
     998             :                 //TODO/LATER: needs storage handling!  Why not letting the object do it?!
     999             :                 if ( !pImpl->mxTempStorage.is() )
    1000             :                     pImpl->mxTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
    1001             :                 uno::Sequence < beans::PropertyValue > aSeq;
    1002             : 
    1003             :                 OUString aTmpPersistName = "Object ";
    1004             :                 aTmpPersistName += OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() );
    1005             : 
    1006             :                 xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq );
    1007             :                 xPersist->saveCompleted( sal_True );
    1008             : 
    1009             :                 pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >();
    1010             :                 */
    1011             : 
    1012         109 :                 if ( !pImpl->mpTempObjectContainer )
    1013             :                 {
    1014          80 :                     pImpl->mpTempObjectContainer = new EmbeddedObjectContainer();
    1015             :                     try
    1016             :                     {
    1017             :                         // TODO/LATER: in future probably the temporary container will have two storages ( of two formats )
    1018             :                         //             the media type will be provided with object insertion
    1019          80 :                         OUString aOrigStorMediaType;
    1020         160 :                         uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW );
    1021          80 :                         static const OUString s_sMediaType("MediaType");
    1022          80 :                         xStorProps->getPropertyValue( s_sMediaType ) >>= aOrigStorMediaType;
    1023             : 
    1024             :                         SAL_WARN_IF( aOrigStorMediaType.isEmpty(), "comphelper.container", "No valuable media type in the storage!\n" );
    1025             : 
    1026             :                         uno::Reference< beans::XPropertySet > xTargetStorProps(
    1027             :                                                                     pImpl->mpTempObjectContainer->pImpl->mxStorage,
    1028         160 :                                                                     uno::UNO_QUERY_THROW );
    1029         160 :                         xTargetStorProps->setPropertyValue( s_sMediaType,uno::makeAny( aOrigStorMediaType ) );
    1030             :                     }
    1031           0 :                     catch (const uno::Exception&)
    1032             :                     {
    1033             :                         SAL_WARN( "comphelper.container", "Can not set the new media type to a storage!\n" );
    1034             :                     }
    1035             :                 }
    1036             : 
    1037         218 :                 OUString aTempName, aMediaType;
    1038         109 :                 pImpl->mpTempObjectContainer->InsertEmbeddedObject( xObj, aTempName );
    1039             : 
    1040         218 :                 uno::Reference < io::XInputStream > xStream = GetGraphicStream( xObj, &aMediaType );
    1041         109 :                 if ( xStream.is() )
    1042          22 :                     pImpl->mpTempObjectContainer->InsertGraphicStream( xStream, aTempName, aMediaType );
    1043             : 
    1044             :                 // object is stored, so at least it can be set to loaded state
    1045         218 :                 xObj->changeState( embed::EmbedStates::LOADED );
    1046             :             }
    1047             :             else
    1048             :                 // objects without persistence need to stay in running state if they shall not be closed
    1049           7 :                 xObj->changeState( embed::EmbedStates::RUNNING );
    1050             :         }
    1051          14 :         catch (const uno::Exception&)
    1052             :         {
    1053           7 :             return false;
    1054             :         }
    1055             :     }
    1056             : 
    1057         109 :     bool bFound = false;
    1058         109 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
    1059         230 :     while ( aIt != pImpl->maObjectContainer.end() )
    1060             :     {
    1061         121 :         if ( (*aIt).second == xObj )
    1062             :         {
    1063         109 :             pImpl->maObjectContainer.erase( aIt );
    1064         109 :             bFound = true;
    1065         109 :             uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
    1066         109 :             if ( xChild.is() )
    1067          91 :                 xChild->setParent( uno::Reference < uno::XInterface >() );
    1068         109 :             break;
    1069             :         }
    1070             : 
    1071          12 :         ++aIt;
    1072             :     }
    1073             : 
    1074             :     SAL_WARN_IF( !bFound,"comphelper.container", "Object not found for removal!" );
    1075             :     (void)bFound;
    1076         109 :     if ( xPersist.is() && bKeepToTempStorage )  // #i119941#
    1077             :     {
    1078             :         // remove replacement image (if there is one)
    1079         109 :         RemoveGraphicStream( aName );
    1080             : 
    1081             :         // now it's time to remove the storage from the container storage
    1082             :         try
    1083             :         {
    1084             : #if OSL_DEBUG_LEVEL > 1
    1085             :             // if the object has a persistence and the object is not a link than it must have persistence entry in storage
    1086             :             OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" );
    1087             : #endif
    1088         109 :             if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) )
    1089         109 :                 pImpl->mxStorage->removeElement( aName );
    1090             :         }
    1091           0 :         catch (const uno::Exception&)
    1092             :         {
    1093             :             SAL_WARN( "comphelper.container", "Failed to remove object from storage!" );
    1094           0 :             return false;
    1095             :         }
    1096             :     }
    1097             : 
    1098         225 :     return true;
    1099             : }
    1100             : 
    1101         185 : bool EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
    1102             : {
    1103             :     // disconnect the object from the container and close it if possible
    1104             : 
    1105         185 :     bool bFound = false;
    1106         185 :     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
    1107         557 :     while ( aIt != pImpl->maObjectContainer.end() )
    1108             :     {
    1109         372 :         if ( (*aIt).second == xObj )
    1110             :         {
    1111         185 :             pImpl->maObjectContainer.erase( aIt );
    1112         185 :             bFound = true;
    1113         185 :             break;
    1114             :         }
    1115             : 
    1116         187 :         ++aIt;
    1117             :     }
    1118             : 
    1119         185 :     if ( bFound )
    1120             :     {
    1121         185 :         uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
    1122             :         try
    1123             :         {
    1124         185 :             xClose->close( sal_True );
    1125             :         }
    1126         184 :         catch (const uno::Exception&)
    1127             :         {
    1128             :             // it is no problem if the object is already closed
    1129             :             // TODO/LATER: what if the object can not be closed?
    1130         185 :         }
    1131             :     }
    1132             : 
    1133         185 :     return bFound;
    1134             : }
    1135             : 
    1136         151 : uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const OUString& aName, OUString* pMediaType )
    1137             : {
    1138         151 :     uno::Reference < io::XInputStream > xStream;
    1139             : 
    1140             :     SAL_WARN_IF( aName.isEmpty(), "comphelper.container", "Retrieving graphic for unknown object!" );
    1141         151 :     if ( !aName.isEmpty() )
    1142             :     {
    1143             :         try
    1144             :         {
    1145         151 :             uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
    1146         211 :             uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( aName, embed::ElementModes::READ );
    1147          60 :             xStream = xGraphicStream->getInputStream();
    1148          60 :             if ( pMediaType )
    1149             :             {
    1150          60 :                 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
    1151          60 :                 if ( xSet.is() )
    1152             :                 {
    1153          60 :                     uno::Any aAny = xSet->getPropertyValue("MediaType");
    1154          60 :                     aAny >>= *pMediaType;
    1155          60 :                 }
    1156         151 :             }
    1157             :         }
    1158          91 :         catch (uno::Exception const& e)
    1159             :         {
    1160             :             SAL_INFO("comphelper.container",
    1161             :                 "EmbeddedObjectContainer::GetGraphicStream(): exception: " << e.Message);
    1162             :         }
    1163             :     }
    1164             : 
    1165         151 :     return xStream;
    1166             : }
    1167             : 
    1168         129 : uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, OUString* pMediaType )
    1169             : {
    1170             :     // try to load it from the container storage
    1171         129 :     return GetGraphicStream( GetEmbeddedObjectName( xObj ), pMediaType );
    1172             : }
    1173             : 
    1174          16 : uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetObjectStream( const OUString& aName, OUString* pMediaType )
    1175             : {
    1176          16 :     uno::Reference < io::XInputStream > xInputStream;
    1177             : 
    1178             :     SAL_WARN_IF( aName.isEmpty(), "comphelper.container", "Retrieving stream for unknown object!" );
    1179          16 :     if ( !aName.isEmpty() )
    1180             :     {
    1181             :         try
    1182             :         {
    1183          16 :             uno::Reference < io::XStream > xStream = pImpl->mxStorage->cloneStreamElement( aName );  //get a readonly clone
    1184          14 :             xInputStream = xStream->getInputStream();
    1185          14 :             if ( pMediaType )
    1186             :             {
    1187           0 :                 uno::Reference < beans::XPropertySet > xSet( xInputStream, uno::UNO_QUERY );
    1188           0 :                 if ( xSet.is() )
    1189             :                 {
    1190           0 :                     uno::Any aAny = xSet->getPropertyValue("MediaType");
    1191           0 :                     aAny >>= *pMediaType;
    1192           0 :                 }
    1193          14 :             }
    1194             :         }
    1195           2 :         catch (const uno::Exception&)
    1196             :         {
    1197             :         }
    1198             :     }
    1199             : 
    1200          16 :     return xInputStream;
    1201             : }
    1202             : 
    1203          16 : uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetObjectStream( const uno::Reference < embed::XEmbeddedObject >& xObj, OUString* pMediaType )
    1204             : {
    1205             :     // try to load it from the container storage
    1206          16 :     return GetObjectStream( GetEmbeddedObjectName( xObj ), pMediaType );
    1207             : }
    1208             : 
    1209        1193 : bool EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const OUString& rObjectName, const OUString& rMediaType )
    1210             : {
    1211             :     try
    1212             :     {
    1213        1193 :         uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
    1214             : 
    1215             :         // store it into the subfolder
    1216        2386 :         uno::Reference < io::XOutputStream > xOutStream;
    1217        1193 :         uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( rObjectName,
    1218        2386 :                 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
    1219        1193 :         xOutStream = xGraphicStream->getOutputStream();
    1220        1193 :         ::comphelper::OStorageHelper::CopyInputToOutput( rStream, xOutStream );
    1221        1193 :         xOutStream->flush();
    1222             : 
    1223        2386 :         uno::Reference< beans::XPropertySet > xPropSet( xGraphicStream, uno::UNO_QUERY );
    1224        1193 :         if ( !xPropSet.is() )
    1225           0 :             throw uno::RuntimeException();
    1226             : 
    1227        1193 :         xPropSet->setPropertyValue("UseCommonStoragePasswordEncryption",
    1228        1193 :                                     uno::makeAny( true ) );
    1229        2386 :         uno::Any aAny;
    1230        1193 :         aAny <<= rMediaType;
    1231        1193 :         xPropSet->setPropertyValue("MediaType", aAny );
    1232             : 
    1233        1193 :         xPropSet->setPropertyValue("Compressed",
    1234        2386 :                                     uno::makeAny( true ) );
    1235             :     }
    1236           0 :     catch (const uno::Exception&)
    1237             :     {
    1238           0 :         return false;
    1239             :     }
    1240             : 
    1241        1193 :     return true;
    1242             : }
    1243             : 
    1244          14 : bool EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const OUString& rObjectName, const OUString& rMediaType )
    1245             : {
    1246             :     try
    1247             :     {
    1248          14 :         uno::Reference < embed::XStorage > xReplacement = pImpl->GetReplacements();
    1249          28 :         uno::Reference < embed::XOptimizedStorage > xOptRepl( xReplacement, uno::UNO_QUERY_THROW );
    1250             : 
    1251             :         // store it into the subfolder
    1252          28 :         uno::Sequence< beans::PropertyValue > aProps( 3 );
    1253          14 :         aProps[0].Name = "MediaType";
    1254          14 :         aProps[0].Value <<= rMediaType;
    1255          14 :         aProps[1].Name = "UseCommonStoragePasswordEncryption";
    1256          14 :         aProps[1].Value <<= true;
    1257          14 :         aProps[2].Name = "Compressed";
    1258          14 :         aProps[2].Value <<= true;
    1259             : 
    1260          14 :         if ( xReplacement->hasByName( rObjectName ) )
    1261           0 :             xReplacement->removeElement( rObjectName );
    1262             : 
    1263          28 :         xOptRepl->insertStreamElementDirect( rObjectName, rStream, aProps );
    1264             :     }
    1265           0 :     catch (const uno::Exception&)
    1266             :     {
    1267           0 :         return false;
    1268             :     }
    1269             : 
    1270          14 :     return true;
    1271             : }
    1272             : 
    1273             : 
    1274         779 : bool EmbeddedObjectContainer::RemoveGraphicStream( const OUString& rObjectName )
    1275             : {
    1276             :     try
    1277             :     {
    1278         779 :         uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
    1279        1503 :         xReplacements->removeElement( rObjectName );
    1280             :     }
    1281        1448 :     catch (const uno::Exception&)
    1282             :     {
    1283         724 :         return false;
    1284             :     }
    1285             : 
    1286          55 :     return true;
    1287             : }
    1288             : namespace {
    1289           0 :     void InsertStreamIntoPicturesStorage_Impl( const uno::Reference< embed::XStorage >& xDocStor,
    1290             :                                             const uno::Reference< io::XInputStream >& xInStream,
    1291             :                                             const OUString& aStreamName )
    1292             :     {
    1293             :         OSL_ENSURE( !aStreamName.isEmpty() && xInStream.is() && xDocStor.is(), "Misuse of the method!\n" );
    1294             : 
    1295             :         try
    1296             :         {
    1297           0 :             uno::Reference< embed::XStorage > xPictures = xDocStor->openStorageElement(
    1298             :                                         OUString( "Pictures" ),
    1299           0 :                                         embed::ElementModes::READWRITE );
    1300           0 :             uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement(
    1301             :                                         aStreamName,
    1302           0 :                                         embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
    1303             :             uno::Reference< io::XOutputStream > xOutStream(
    1304           0 :                                         xObjReplStr->getInputStream(), uno::UNO_QUERY_THROW );
    1305             : 
    1306           0 :             ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xOutStream );
    1307           0 :             xOutStream->closeOutput();
    1308             : 
    1309           0 :             uno::Reference< embed::XTransactedObject > xTransact( xPictures, uno::UNO_QUERY );
    1310           0 :             if ( xTransact.is() )
    1311           0 :                 xTransact->commit();
    1312             :         }
    1313           0 :         catch (const uno::Exception&)
    1314             :         {
    1315             :             SAL_WARN( "comphelper.container", "The pictures storage is not available!\n" );
    1316             :         }
    1317           0 :     }
    1318             : 
    1319             : }
    1320             : 
    1321          12 : bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage)
    1322             : {
    1323          12 :     bool bResult = false;
    1324             :     try
    1325             :     {
    1326          12 :         comphelper::EmbeddedObjectContainer aCnt( _xStorage );
    1327          24 :         const uno::Sequence < OUString > aNames = GetObjectNames();
    1328          12 :         const OUString* pIter = aNames.getConstArray();
    1329          12 :         const OUString* pEnd   = pIter + aNames.getLength();
    1330          26 :         for(;pIter != pEnd;++pIter)
    1331             :         {
    1332          14 :             uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
    1333             :             SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
    1334          14 :             if ( xObj.is() )
    1335             :             {
    1336          14 :                 bool bSwitchBackToLoaded = false;
    1337          14 :                 uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
    1338             : 
    1339          28 :                 uno::Reference < io::XInputStream > xStream;
    1340          28 :                 OUString aMediaType;
    1341             : 
    1342          14 :                 sal_Int32 nCurState = xObj->getCurrentState();
    1343          14 :                 if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING )
    1344             :                 {
    1345             :                     // means that the object is not active
    1346             :                     // copy replacement image from old to new container
    1347          14 :                     xStream = GetGraphicStream( xObj, &aMediaType );
    1348             :                 }
    1349             : 
    1350          14 :                 if ( !xStream.is() && getUserAllowsLinkUpdate() )
    1351             :                 {
    1352             :                     // the image must be regenerated
    1353             :                     // TODO/LATER: another aspect could be used
    1354           4 :                     if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
    1355           0 :                             bSwitchBackToLoaded = true;
    1356             : 
    1357           8 :                     xStream = GetGraphicReplacementStream(
    1358             :                                                             embed::Aspects::MSOLE_CONTENT,
    1359             :                                                             xObj,
    1360           4 :                                                             &aMediaType );
    1361             :                 }
    1362             : 
    1363          14 :                 if ( _bOasisFormat || (xLink.is() && xLink->isLink()) )
    1364             :                 {
    1365          14 :                     if ( xStream.is() )
    1366             :                     {
    1367          14 :                         if ( _bOasisFormat )
    1368             :                         {
    1369             :                             // if it is an embedded object or the optimized inserting fails the normal inserting should be done
    1370          14 :                             if ( _bCreateEmbedded
    1371          14 :                                 || !aCnt.InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
    1372           0 :                                 aCnt.InsertGraphicStream( xStream, *pIter, aMediaType );
    1373             :                         }
    1374             :                         else
    1375             :                         {
    1376             :                             // it is a linked object exported into SO7 format
    1377           0 :                             InsertStreamIntoPicturesStorage_Impl( _xStorage, xStream, *pIter );
    1378             :                         }
    1379             :                     }
    1380             :                 }
    1381             : 
    1382          28 :                 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
    1383          14 :                 if ( xPersist.is() )
    1384             :                 {
    1385          14 :                     uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 );
    1386          14 :                     aArgs[0].Name = "StoreVisualReplacement";
    1387          14 :                     aArgs[0].Value <<= !_bOasisFormat;
    1388             : 
    1389             :                     // if it is an embedded object or the optimized inserting fails the normal inserting should be done
    1390          14 :                     aArgs[1].Name = "CanTryOptimization";
    1391          14 :                     aArgs[1].Value <<= !_bCreateEmbedded;
    1392          14 :                     if ( !_bOasisFormat )
    1393             :                     {
    1394             :                         // if object has no cached replacement it will use this one
    1395           0 :                         aArgs[2].Name = "VisualReplacement";
    1396           0 :                         aArgs[2].Value <<= xStream;
    1397             :                     }
    1398             : 
    1399             :                     try
    1400             :                     {
    1401          14 :                         xPersist->storeAsEntry( _xStorage, xPersist->getEntryName(), uno::Sequence< beans::PropertyValue >(), aArgs );
    1402             :                     }
    1403           1 :                     catch (const embed::WrongStateException&)
    1404             :                     {
    1405             :                         SAL_WARN("comphelper.container", "failed to store '" << *pIter << "'");
    1406          14 :                     }
    1407             :                 }
    1408             : 
    1409          14 :                 if ( bSwitchBackToLoaded )
    1410             :                     // switch back to loaded state; that way we have a minimum cache confusion
    1411          14 :                     xObj->changeState( embed::EmbedStates::LOADED );
    1412             :             }
    1413          14 :         }
    1414             : 
    1415          24 :         bResult = aCnt.CommitImageSubStorage();
    1416             : 
    1417             :     }
    1418           0 :     catch (const uno::Exception& e)
    1419             :     {
    1420             :         // TODO/LATER: error handling
    1421           0 :         bResult = false;
    1422             :         SAL_WARN("comphelper.container", "failed. Message: " << e.Message);
    1423             :     }
    1424             : 
    1425             :     // the old SO6 format does not store graphical replacements
    1426          12 :     if ( !_bOasisFormat && bResult )
    1427             :     {
    1428             :         try
    1429             :         {
    1430             :             // the substorage still can not be locked by the embedded object container
    1431           0 :             OUString aObjReplElement( "ObjectReplacements" );
    1432           0 :             if ( _xStorage->hasByName( aObjReplElement ) && _xStorage->isStorageElement( aObjReplElement ) )
    1433           0 :                 _xStorage->removeElement( aObjReplElement );
    1434             :         }
    1435           0 :         catch (const uno::Exception&)
    1436             :         {
    1437             :             // TODO/LATER: error handling;
    1438           0 :             bResult = false;
    1439             :         }
    1440             :     }
    1441          12 :     return bResult;
    1442             : }
    1443             : 
    1444           1 : bool EmbeddedObjectContainer::StoreChildren(bool _bOasisFormat,bool _bObjectsOnly)
    1445             : {
    1446           1 :     bool bResult = true;
    1447           1 :     const uno::Sequence < OUString > aNames = GetObjectNames();
    1448           1 :     const OUString* pIter = aNames.getConstArray();
    1449           1 :     const OUString* pEnd   = pIter + aNames.getLength();
    1450           1 :     for(;pIter != pEnd;++pIter)
    1451             :     {
    1452           0 :         uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
    1453             :         SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
    1454           0 :         if ( xObj.is() )
    1455             :         {
    1456           0 :             sal_Int32 nCurState = xObj->getCurrentState();
    1457           0 :             if ( _bOasisFormat && nCurState != embed::EmbedStates::LOADED && nCurState != embed::EmbedStates::RUNNING )
    1458             :             {
    1459             :                 // means that the object is active
    1460             :                 // the image must be regenerated
    1461           0 :                 OUString aMediaType;
    1462             : 
    1463             :                 // TODO/LATER: another aspect could be used
    1464             :                 uno::Reference < io::XInputStream > xStream =
    1465             :                             GetGraphicReplacementStream(
    1466             :                                                         embed::Aspects::MSOLE_CONTENT,
    1467             :                                                         xObj,
    1468           0 :                                                         &aMediaType );
    1469           0 :                 if ( xStream.is() )
    1470             :                 {
    1471           0 :                     if ( !InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
    1472           0 :                         InsertGraphicStream( xStream, *pIter, aMediaType );
    1473           0 :                 }
    1474             :             }
    1475             : 
    1476             :             // TODO/LATER: currently the object by default does not cache replacement image
    1477             :             // that means that if somebody loads SO7 document and store its objects using
    1478             :             // this method the images might be lost.
    1479             :             // Currently this method is only used on storing to alien formats, that means
    1480             :             // that SO7 documents storing does not use it, and all other filters are
    1481             :             // based on OASIS format. But if it changes the method must be fixed. The fix
    1482             :             // must be done only on demand since it can affect performance.
    1483             : 
    1484           0 :             uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
    1485           0 :             if ( xPersist.is() )
    1486             :             {
    1487             :                 try
    1488             :                 {
    1489             :                     //TODO/LATER: only storing if changed!
    1490             :                     //xPersist->storeOwn(); //commented, i120168
    1491             : 
    1492             :             // begin:all charts will be persited as xml format on disk when saving, which is time consuming.
    1493             :                     // '_bObjectsOnly' mean we are storing to alien formats.
    1494             :                     //  'isStorageElement' mean current object is NOT an MS OLE format. (may also include in future), i120168
    1495           0 :                     if (_bObjectsOnly && (nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING)
    1496           0 :                         && (pImpl->mxStorage->isStorageElement( *pIter ) ))
    1497             :                     {
    1498           0 :                         uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
    1499           0 :                         if ( xModifiable.is() && xModifiable->isModified())
    1500             :                         {
    1501           0 :                             xPersist->storeOwn();
    1502             :                         }
    1503             :                         else
    1504             :                         {
    1505             :                             //do nothing. Embedded model is not modified, no need to persist.
    1506           0 :                         }
    1507             :                     }
    1508             :                     else //the embedded object is in active status, always store back it.
    1509             :                     {
    1510           0 :                         xPersist->storeOwn();
    1511             :                     }
    1512             :                     //end i120168
    1513             :                 }
    1514           0 :                 catch (const uno::Exception&)
    1515             :                 {
    1516             :                     // TODO/LATER: error handling
    1517           0 :                     bResult = false;
    1518           0 :                     break;
    1519             :                 }
    1520             :             }
    1521             : 
    1522           0 :             if ( !_bOasisFormat && !_bObjectsOnly )
    1523             :             {
    1524             :                 // copy replacement images for linked objects
    1525             :                 try
    1526             :                 {
    1527           0 :                     uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
    1528           0 :                     if ( xLink.is() && xLink->isLink() )
    1529             :                     {
    1530           0 :                         OUString aMediaType;
    1531           0 :                         uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType );
    1532           0 :                         if ( xInStream.is() )
    1533           0 :                             InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, *pIter );
    1534           0 :                     }
    1535             :                 }
    1536           0 :                 catch (const uno::Exception&)
    1537             :                 {
    1538             :                 }
    1539           0 :             }
    1540             :         }
    1541           0 :     }
    1542             : 
    1543           1 :     if ( bResult && _bOasisFormat )
    1544           1 :         bResult = CommitImageSubStorage();
    1545             : 
    1546           1 :     if ( bResult && !_bObjectsOnly )
    1547             :     {
    1548             :         try
    1549             :         {
    1550           0 :             ReleaseImageSubStorage();
    1551           0 :             OUString aObjReplElement( "ObjectReplacements" );
    1552           0 :             if ( !_bOasisFormat && pImpl->mxStorage->hasByName( aObjReplElement ) && pImpl->mxStorage->isStorageElement( aObjReplElement ) )
    1553           0 :                 pImpl->mxStorage->removeElement( aObjReplElement );
    1554             :         }
    1555           0 :         catch (const uno::Exception&)
    1556             :         {
    1557             :             // TODO/LATER: error handling
    1558           0 :             bResult = false;
    1559             :         }
    1560             :     }
    1561           1 :     return bResult;
    1562             : }
    1563             : 
    1564        4909 : uno::Reference< io::XInputStream > EmbeddedObjectContainer::GetGraphicReplacementStream(
    1565             :                                                                 sal_Int64 nViewAspect,
    1566             :                                                                 const uno::Reference< embed::XEmbeddedObject >& xObj,
    1567             :                                                                 OUString* pMediaType )
    1568             : {
    1569        4909 :     uno::Reference< io::XInputStream > xInStream;
    1570        4909 :     if ( xObj.is() )
    1571             :     {
    1572             :         try
    1573             :         {
    1574             :             // retrieving of the visual representation can switch object to running state
    1575        4909 :             embed::VisualRepresentation aRep = xObj->getPreferredVisualRepresentation( nViewAspect );
    1576        4909 :             if ( pMediaType )
    1577        4909 :                 *pMediaType = aRep.Flavor.MimeType;
    1578             : 
    1579        9818 :             uno::Sequence < sal_Int8 > aSeq;
    1580        4909 :             aRep.Data >>= aSeq;
    1581        9818 :             xInStream = new ::comphelper::SequenceInputStream( aSeq );
    1582             :         }
    1583           0 :         catch (const uno::Exception&)
    1584             :         {
    1585             :         }
    1586             :     }
    1587             : 
    1588        4909 :     return xInStream;
    1589             : }
    1590             : 
    1591           0 : bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed::XStorage >& _xStorage,bool _bClearModifedFlag)
    1592             : {
    1593           0 :     bool bError = false;
    1594           0 :     const uno::Sequence < OUString > aNames = GetObjectNames();
    1595           0 :     const OUString* pIter = aNames.getConstArray();
    1596           0 :     const OUString* pEnd   = pIter + aNames.getLength();
    1597           0 :     for(;pIter != pEnd;++pIter)
    1598             :     {
    1599           0 :         uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
    1600             :         SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
    1601           0 :         if ( xObj.is() )
    1602             :         {
    1603           0 :             uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
    1604           0 :             if ( xPersist.is() )
    1605             :             {
    1606             :                 try
    1607             :                 {
    1608           0 :                     xPersist->setPersistentEntry( _xStorage,
    1609             :                                                 *pIter,
    1610             :                                                 embed::EntryInitModes::NO_INIT,
    1611             :                                                 uno::Sequence< beans::PropertyValue >(),
    1612           0 :                                                 uno::Sequence< beans::PropertyValue >() );
    1613             : 
    1614             :                 }
    1615           0 :                 catch (const uno::Exception&)
    1616             :                 {
    1617             :                     // TODO/LATER: error handling
    1618           0 :                     bError = true;
    1619           0 :                     break;
    1620             :                 }
    1621             :             }
    1622           0 :             if ( _bClearModifedFlag )
    1623             :             {
    1624             :                 // if this method is used as part of SaveCompleted the object must stay unmodified after execution
    1625             :                 try
    1626             :                 {
    1627           0 :                     uno::Reference< util::XModifiable > xModif( xObj->getComponent(), uno::UNO_QUERY_THROW );
    1628           0 :                     if ( xModif->isModified() )
    1629           0 :                         xModif->setModified( sal_False );
    1630             :                 }
    1631           0 :                 catch (const uno::Exception&)
    1632             :                 {
    1633             :                 }
    1634           0 :             }
    1635             :         }
    1636           0 :     }
    1637           0 :     return bError;
    1638             : }
    1639             : 
    1640           4 : bool EmbeddedObjectContainer::getUserAllowsLinkUpdate() const
    1641             : {
    1642           4 :     return pImpl->mbUserAllowsLinkUpdate;
    1643             : }
    1644             : 
    1645           0 : void EmbeddedObjectContainer::setUserAllowsLinkUpdate(bool bNew)
    1646             : {
    1647           0 :     if(pImpl->mbUserAllowsLinkUpdate != bNew)
    1648             :     {
    1649           0 :         pImpl->mbUserAllowsLinkUpdate = bNew;
    1650             :     }
    1651           0 : }
    1652             : 
    1653             : }
    1654             : 
    1655             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11