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

Generated by: LCOV version 1.10