LCOV - code coverage report
Current view: top level - embeddedobj/source/commonembedding - persistence.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 362 807 44.9 %
Date: 2014-11-03 Functions: 24 36 66.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 <commonembobj.hxx>
      21             : #include <com/sun/star/embed/Aspects.hpp>
      22             : #include <com/sun/star/document/XStorageBasedDocument.hpp>
      23             : #include <com/sun/star/embed/EmbedStates.hpp>
      24             : #include <com/sun/star/embed/EmbedVerbs.hpp>
      25             : #include <com/sun/star/embed/EntryInitModes.hpp>
      26             : #include <com/sun/star/embed/XStorage.hpp>
      27             : #include <com/sun/star/embed/XOptimizedStorage.hpp>
      28             : #include <com/sun/star/embed/ElementModes.hpp>
      29             : #include <com/sun/star/embed/EmbedUpdateModes.hpp>
      30             : #include <com/sun/star/embed/StorageFactory.hpp>
      31             : #include <com/sun/star/io/TempFile.hpp>
      32             : #include <com/sun/star/frame/XModel.hpp>
      33             : #include <com/sun/star/frame/XStorable.hpp>
      34             : #include <com/sun/star/frame/XLoadable.hpp>
      35             : #include <com/sun/star/frame/XComponentLoader.hpp>
      36             : #include <com/sun/star/frame/XModule.hpp>
      37             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      38             : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
      39             : #include <com/sun/star/lang/DisposedException.hpp>
      40             : #include <com/sun/star/util/XModifiable.hpp>
      41             : 
      42             : #include <com/sun/star/container/XNameAccess.hpp>
      43             : #include <com/sun/star/container/XChild.hpp>
      44             : #include <com/sun/star/util/XCloseable.hpp>
      45             : #include <com/sun/star/beans/XPropertySet.hpp>
      46             : #include <com/sun/star/beans/IllegalTypeException.hpp>
      47             : #include <com/sun/star/chart2/XChartDocument.hpp>
      48             : 
      49             : #include <comphelper/fileformat.h>
      50             : #include <comphelper/processfactory.hxx>
      51             : #include <comphelper/storagehelper.hxx>
      52             : #include <comphelper/mimeconfighelper.hxx>
      53             : #include <comphelper/namedvaluecollection.hxx>
      54             : 
      55             : #include <tools/diagnose_ex.h>
      56             : #include "persistence.hxx"
      57             : 
      58             : using namespace ::com::sun::star;
      59             : 
      60             : 
      61             : 
      62        2680 : uno::Sequence< beans::PropertyValue > GetValuableArgs_Impl( const uno::Sequence< beans::PropertyValue >& aMedDescr,
      63             :                                                             bool bCanUseDocumentBaseURL )
      64             : {
      65        2680 :     uno::Sequence< beans::PropertyValue > aResult;
      66        2680 :     sal_Int32 nResLen = 0;
      67             : 
      68        2882 :     for ( sal_Int32 nInd = 0; nInd < aMedDescr.getLength(); nInd++ )
      69             :     {
      70         606 :         if ( aMedDescr[nInd].Name == "ComponentData" || aMedDescr[nInd].Name == "DocumentTitle"
      71         202 :           || aMedDescr[nInd].Name == "InteractionHandler" || aMedDescr[nInd].Name == "JumpMark"
      72             :           // || aMedDescr[nInd].Name == "Password" // makes no sence for embedded objects
      73         202 :           || aMedDescr[nInd].Name == "Preview" || aMedDescr[nInd].Name == "ReadOnly"
      74         102 :           || aMedDescr[nInd].Name == "StartPresentation" || aMedDescr[nInd].Name == "RepairPackage"
      75         102 :           || aMedDescr[nInd].Name == "StatusIndicator" || aMedDescr[nInd].Name == "ViewData"
      76         102 :           || aMedDescr[nInd].Name == "ViewId" || aMedDescr[nInd].Name == "MacroExecutionMode"
      77         102 :           || aMedDescr[nInd].Name == "UpdateDocMode"
      78         304 :           || (aMedDescr[nInd].Name == "DocumentBaseURL" && bCanUseDocumentBaseURL) )
      79             :         {
      80         100 :             aResult.realloc( ++nResLen );
      81         100 :             aResult[nResLen-1] = aMedDescr[nInd];
      82             :         }
      83             :     }
      84             : 
      85        2680 :     return aResult;
      86             : }
      87             : 
      88             : 
      89          26 : uno::Sequence< beans::PropertyValue > addAsTemplate( const uno::Sequence< beans::PropertyValue >& aOrig )
      90             : {
      91          26 :     bool bAsTemplateSet = false;
      92          26 :     sal_Int32 nLength = aOrig.getLength();
      93          26 :     uno::Sequence< beans::PropertyValue > aResult( nLength );
      94             : 
      95         104 :     for ( sal_Int32 nInd = 0; nInd < nLength; nInd++ )
      96             :     {
      97          78 :         aResult[nInd].Name = aOrig[nInd].Name;
      98          78 :         if ( aResult[nInd].Name == "AsTemplate" )
      99             :         {
     100           0 :             aResult[nInd].Value <<= sal_True;
     101           0 :             bAsTemplateSet = true;
     102             :         }
     103             :         else
     104          78 :             aResult[nInd].Value = aOrig[nInd].Value;
     105             :     }
     106             : 
     107          26 :     if ( !bAsTemplateSet )
     108             :     {
     109          26 :         aResult.realloc( nLength + 1 );
     110          26 :         aResult[nLength].Name = "AsTemplate";
     111          26 :         aResult[nLength].Value <<= sal_True;
     112             :     }
     113             : 
     114          26 :     return aResult;
     115             : }
     116             : 
     117             : 
     118           0 : uno::Reference< io::XInputStream > createTempInpStreamFromStor(
     119             :                                                             const uno::Reference< embed::XStorage >& xStorage,
     120             :                                                             const uno::Reference< uno::XComponentContext >& xContext )
     121             : {
     122             :     SAL_WARN_IF( !xStorage.is(), "embeddedobj.common", "The storage can not be empty!" );
     123             : 
     124           0 :     uno::Reference< io::XInputStream > xResult;
     125             : 
     126           0 :     uno::Reference < io::XStream > xTempStream( io::TempFile::create(xContext), uno::UNO_QUERY_THROW );
     127             : 
     128           0 :     uno::Reference < lang::XSingleServiceFactory > xStorageFactory( embed::StorageFactory::create(xContext) );
     129             : 
     130           0 :     uno::Sequence< uno::Any > aArgs( 2 );
     131           0 :     aArgs[0] <<= xTempStream;
     132           0 :     aArgs[1] <<= embed::ElementModes::READWRITE;
     133           0 :     uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ),
     134           0 :                                                     uno::UNO_QUERY );
     135           0 :     if ( !xTempStorage.is() )
     136           0 :         throw uno::RuntimeException(); // TODO:
     137             : 
     138             :     try
     139             :     {
     140           0 :         xStorage->copyToStorage( xTempStorage );
     141           0 :     } catch( const uno::Exception& e )
     142             :     {
     143             :         throw embed::StorageWrappedTargetException(
     144             :                     "Can't copy storage!",
     145             :                     uno::Reference< uno::XInterface >(),
     146           0 :                     uno::makeAny( e ) );
     147             :     }
     148             : 
     149             :     try {
     150           0 :         uno::Reference< lang::XComponent > xComponent( xTempStorage, uno::UNO_QUERY );
     151             :         SAL_WARN_IF( !xComponent.is(), "embeddedobj.common", "Wrong storage implementation!" );
     152           0 :         if ( xComponent.is() )
     153           0 :             xComponent->dispose();
     154             :     }
     155           0 :     catch ( const uno::Exception& )
     156             :     {
     157             :     }
     158             : 
     159             :     try {
     160           0 :         uno::Reference< io::XOutputStream > xTempOut = xTempStream->getOutputStream();
     161           0 :         if ( xTempOut.is() )
     162           0 :             xTempOut->closeOutput();
     163             :     }
     164           0 :     catch ( const uno::Exception& )
     165             :     {
     166             :     }
     167             : 
     168           0 :     xResult = xTempStream->getInputStream();
     169             : 
     170           0 :     return xResult;
     171             : 
     172             : }
     173             : 
     174             : 
     175           0 : static void TransferMediaType( const uno::Reference< embed::XStorage >& i_rSource, const uno::Reference< embed::XStorage >& i_rTarget )
     176             : {
     177             :     try
     178             :     {
     179           0 :         const uno::Reference< beans::XPropertySet > xSourceProps( i_rSource, uno::UNO_QUERY_THROW );
     180           0 :         const uno::Reference< beans::XPropertySet > xTargetProps( i_rTarget, uno::UNO_QUERY_THROW );
     181           0 :         const OUString sMediaTypePropName( "MediaType" );
     182           0 :         xTargetProps->setPropertyValue( sMediaTypePropName, xSourceProps->getPropertyValue( sMediaTypePropName ) );
     183             :     }
     184           0 :     catch( const uno::Exception& )
     185             :     {
     186             :         DBG_UNHANDLED_EXCEPTION();
     187             :     }
     188           0 : }
     189             : 
     190             : 
     191        1164 : static uno::Reference< util::XCloseable > CreateDocument( const uno::Reference< uno::XComponentContext >& _rxContext,
     192             :     const OUString& _rDocumentServiceName, bool _bEmbeddedScriptSupport, const bool i_bDocumentRecoverySupport )
     193             : {
     194        1164 :     ::comphelper::NamedValueCollection aArguments;
     195        1164 :     aArguments.put( "EmbeddedObject", true );
     196        1164 :     aArguments.put( "EmbeddedScriptSupport", _bEmbeddedScriptSupport );
     197        1164 :     aArguments.put( "DocumentRecoverySupport", i_bDocumentRecoverySupport );
     198             : 
     199        2328 :     uno::Reference< uno::XInterface > xDocument;
     200             :     try
     201             :     {
     202        3492 :         xDocument = _rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
     203        2328 :                         _rDocumentServiceName, aArguments.getWrappedPropertyValues(), _rxContext );
     204             :     }
     205           0 :     catch( const uno::Exception& )
     206             :     {
     207             :         // if an embedded object implementation does not support XInitialization,
     208             :         // the default factory from cppuhelper will throw an
     209             :         // IllegalArgumentException when we try to create the instance with arguments.
     210             :         // Okay, so we fall back to creating the instance without any arguments.
     211             :         OSL_FAIL("Consider implementing interface XInitialization to avoid duplicate construction");
     212           0 :         xDocument = _rxContext->getServiceManager()->createInstanceWithContext( _rDocumentServiceName, _rxContext );
     213             :     }
     214             : 
     215             :     SAL_WARN_IF(!xDocument.is(), "embeddedobj.common", "Service " << _rDocumentServiceName << " is not available?");
     216        2328 :     return uno::Reference< util::XCloseable >( xDocument, uno::UNO_QUERY );
     217             : }
     218             : 
     219             : 
     220        1150 : static void SetDocToEmbedded( const uno::Reference< frame::XModel > xDocument, const OUString& aModuleName )
     221             : {
     222        1150 :     if ( xDocument.is() )
     223             :     {
     224        1150 :         uno::Sequence< beans::PropertyValue > aSeq( 1 );
     225        1150 :         aSeq[0].Name = "SetEmbedded";
     226        1150 :         aSeq[0].Value <<= sal_True;
     227        1150 :         xDocument->attachResource( OUString(), aSeq );
     228             : 
     229        1150 :         if ( !aModuleName.isEmpty() )
     230             :         {
     231             :             try
     232             :             {
     233           0 :                 uno::Reference< frame::XModule > xModule( xDocument, uno::UNO_QUERY_THROW );
     234           0 :                 xModule->setIdentifier( aModuleName );
     235             :             }
     236           0 :             catch( const uno::Exception& )
     237             :             {}
     238        1150 :         }
     239             :     }
     240        1150 : }
     241             : 
     242             : 
     243        2666 : void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
     244             :                                                   const uno::Reference< embed::XStorage >& xNewObjectStorage,
     245             :                                                   const OUString& aNewName )
     246             : {
     247        2666 :     if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
     248             :     {
     249             :         SAL_WARN_IF( xNewObjectStorage != m_xObjectStorage, "embeddedobj.common", "The storage must be the same!" );
     250           0 :         return;
     251             :     }
     252             : 
     253        2666 :     uno::Reference< lang::XComponent > xComponent( m_xObjectStorage, uno::UNO_QUERY );
     254             :     OSL_ENSURE( !m_xObjectStorage.is() || xComponent.is(), "Wrong storage implementation!" );
     255             : 
     256        2666 :     m_xObjectStorage = xNewObjectStorage;
     257        2666 :     m_xParentStorage = xNewParentStorage;
     258        2666 :     m_aEntryName = aNewName;
     259             : 
     260             :     // the linked document should not be switched
     261        2666 :     if ( !m_bIsLink )
     262             :     {
     263        2666 :         uno::Reference< document::XStorageBasedDocument > xDoc( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
     264        2666 :         if ( xDoc.is() )
     265        1636 :             SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
     266             :     }
     267             : 
     268             :     try {
     269        2666 :         if ( xComponent.is() )
     270        1644 :             xComponent->dispose();
     271             :     }
     272         556 :     catch ( const uno::Exception& )
     273             :     {
     274        2666 :     }
     275             : }
     276             : 
     277             : 
     278        1022 : void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
     279             :                                                   const OUString& aNewName )
     280             : {
     281        1022 :     if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
     282        1022 :         return;
     283             : 
     284        1022 :     sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
     285             : 
     286        1022 :     uno::Reference< embed::XStorage > xNewOwnStorage = xNewParentStorage->openStorageElement( aNewName, nStorageMode );
     287             :     SAL_WARN_IF( !xNewOwnStorage.is(), "embeddedobj.common", "The method can not return empty reference!" );
     288             : 
     289        1022 :     SwitchOwnPersistence( xNewParentStorage, xNewOwnStorage, aNewName );
     290             : }
     291             : 
     292             : 
     293        1150 : void OCommonEmbeddedObject::EmbedAndReparentDoc_Impl( const uno::Reference< util::XCloseable >& i_rxDocument ) const
     294             : {
     295        1150 :     SetDocToEmbedded( uno::Reference< frame::XModel >( i_rxDocument, uno::UNO_QUERY ), m_aModuleName );
     296             : 
     297             :     try
     298             :     {
     299        1150 :         uno::Reference < container::XChild > xChild( i_rxDocument, uno::UNO_QUERY );
     300        1150 :         if ( xChild.is() )
     301        1150 :             xChild->setParent( m_xParent );
     302             :     }
     303           0 :     catch( const lang::NoSupportException & )
     304             :     {
     305             :         SAL_WARN( "embeddedobj.common", "OCommonEmbeddedObject::EmbedAndReparentDoc: cannot set parent at document!" );
     306             :     }
     307        1150 : }
     308             : 
     309             : 
     310         888 : uno::Reference< util::XCloseable > OCommonEmbeddedObject::InitNewDocument_Impl()
     311             : {
     312             :     uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xContext, GetDocumentServiceName(),
     313         888 :                                                 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
     314             : 
     315        1776 :     uno::Reference< frame::XModel > xModel( xDocument, uno::UNO_QUERY );
     316        1776 :     uno::Reference< frame::XLoadable > xLoadable( xModel, uno::UNO_QUERY );
     317         888 :     if ( !xLoadable.is() )
     318           0 :         throw uno::RuntimeException();
     319             : 
     320             :     try
     321             :     {
     322             :         // set the document mode to embedded as the first action on document!!!
     323         888 :         EmbedAndReparentDoc_Impl( xDocument );
     324             : 
     325             :         // if we have a storage to recover the document from, do not use initNew, but instead load from that storage
     326         888 :         bool bInitNew = true;
     327         888 :         if ( m_xRecoveryStorage.is() )
     328             :         {
     329           0 :             uno::Reference< document::XStorageBasedDocument > xDoc( xLoadable, uno::UNO_QUERY );
     330             :             SAL_WARN_IF( !xDoc.is(), "embeddedobj.common", "OCommonEmbeddedObject::InitNewDocument_Impl: cannot recover from a storage when the document is not storage based!" );
     331           0 :             if ( xDoc.is() )
     332             :             {
     333           0 :                 ::comphelper::NamedValueCollection aLoadArgs;
     334           0 :                 FillDefaultLoadArgs_Impl( m_xRecoveryStorage, aLoadArgs );
     335             : 
     336           0 :                 xDoc->loadFromStorage( m_xRecoveryStorage, aLoadArgs.getPropertyValues() );
     337           0 :                 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
     338           0 :                 bInitNew = false;
     339           0 :             }
     340             :         }
     341             : 
     342         888 :         if ( bInitNew )
     343             :         {
     344             :             // init document as a new
     345         888 :             xLoadable->initNew();
     346             :         }
     347         888 :         xModel->attachResource( xModel->getURL(), m_aDocMediaDescriptor );
     348             :     }
     349           0 :     catch( const uno::Exception& )
     350             :     {
     351           0 :         uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
     352           0 :         if ( xCloseable.is() )
     353             :         {
     354             :             try
     355             :             {
     356           0 :                 xCloseable->close( sal_True );
     357             :             }
     358           0 :             catch( const uno::Exception& )
     359             :             {
     360             :             }
     361             :         }
     362             : 
     363           0 :         throw; // TODO
     364             :     }
     365             : 
     366        1776 :     return xDocument;
     367             : }
     368             : 
     369             : 
     370           0 : uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl()
     371             : {
     372             :     uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xContext, GetDocumentServiceName(),
     373           0 :                                                 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
     374             : 
     375           0 :     uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
     376           0 :     if ( !xLoadable.is() )
     377           0 :         throw uno::RuntimeException();
     378             : 
     379           0 :     sal_Int32 nLen = 2;
     380           0 :     uno::Sequence< beans::PropertyValue > aArgs( nLen );
     381           0 :     aArgs[0].Name = "URL";
     382           0 :     aArgs[0].Value <<= m_aLinkURL;
     383           0 :     aArgs[1].Name = "FilterName";
     384           0 :     aArgs[1].Value <<= m_aLinkFilterName;
     385           0 :     if ( m_bLinkHasPassword )
     386             :     {
     387           0 :         aArgs.realloc( ++nLen );
     388           0 :         aArgs[nLen-1].Name = "Password";
     389           0 :         aArgs[nLen-1].Value <<= m_aLinkPassword;
     390             :     }
     391             : 
     392           0 :     aArgs.realloc( m_aDocMediaDescriptor.getLength() + nLen );
     393           0 :     for ( sal_Int32 nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ )
     394             :     {
     395           0 :         aArgs[nInd+nLen].Name = m_aDocMediaDescriptor[nInd].Name;
     396           0 :         aArgs[nInd+nLen].Value = m_aDocMediaDescriptor[nInd].Value;
     397             :     }
     398             : 
     399             :     try
     400             :     {
     401             :         // the document is not really an embedded one, it is a link
     402           0 :         EmbedAndReparentDoc_Impl( xDocument );
     403             : 
     404             :         // load the document
     405           0 :         xLoadable->load( aArgs );
     406             : 
     407           0 :         if ( !m_bLinkHasPassword )
     408             :         {
     409             :             // check if there is a password to cache
     410           0 :             uno::Reference< frame::XModel > xModel( xLoadable, uno::UNO_QUERY_THROW );
     411           0 :             uno::Sequence< beans::PropertyValue > aProps = xModel->getArgs();
     412           0 :             for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ )
     413           0 :                 if ( aProps[nInd].Name == "Password" && ( aProps[nInd].Value >>= m_aLinkPassword ) )
     414             :                 {
     415           0 :                     m_bLinkHasPassword = true;
     416           0 :                     break;
     417           0 :                 }
     418             :         }
     419             :     }
     420           0 :     catch( const uno::Exception& )
     421             :     {
     422           0 :         uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
     423           0 :         if ( xCloseable.is() )
     424             :         {
     425             :             try
     426             :             {
     427           0 :                 xCloseable->close( sal_True );
     428             :             }
     429           0 :             catch( const uno::Exception& )
     430             :             {
     431             :             }
     432             :         }
     433             : 
     434           0 :         throw; // TODO
     435             :     }
     436             : 
     437           0 :     return xDocument;
     438             : 
     439             : }
     440             : 
     441             : 
     442        1918 : OUString OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion ) const
     443             : {
     444        1918 :     OUString aFilterName = GetPresetFilterName();
     445        1918 :     if ( aFilterName.isEmpty() )
     446             :     {
     447             :         try {
     448        1918 :             ::comphelper::MimeConfigurationHelper aHelper( m_xContext );
     449        1918 :             aFilterName = aHelper.GetDefaultFilterFromServiceName( GetDocumentServiceName(), nVersion );
     450           0 :         } catch( const uno::Exception& )
     451             :         {}
     452             :     }
     453             : 
     454        1918 :     return aFilterName;
     455             : }
     456             : 
     457             : 
     458         236 : void OCommonEmbeddedObject::FillDefaultLoadArgs_Impl( const uno::Reference< embed::XStorage >& i_rxStorage,
     459             :         ::comphelper::NamedValueCollection& o_rLoadArgs ) const
     460             : {
     461         236 :     o_rLoadArgs.put( "DocumentBaseURL", GetBaseURL_Impl() );
     462         236 :     o_rLoadArgs.put( "HierarchicalDocumentName", m_aEntryName );
     463         236 :     o_rLoadArgs.put( "ReadOnly", m_bReadOnly );
     464             : 
     465         236 :     OUString aFilterName = GetFilterName( ::comphelper::OStorageHelper::GetXStorageFormat( i_rxStorage ) );
     466             :     SAL_WARN_IF( aFilterName.isEmpty(), "embeddedobj.common", "OCommonEmbeddedObject::FillDefaultLoadArgs_Impl: Wrong document service name!" );
     467         236 :     if ( aFilterName.isEmpty() )
     468           0 :         throw io::IOException();    // TODO: error message/code
     469             : 
     470         236 :     o_rLoadArgs.put( "FilterName", aFilterName );
     471         236 : }
     472             : 
     473             : 
     474         242 : uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadDocumentFromStorage_Impl()
     475             : {
     476         242 :     ENSURE_OR_THROW( m_xObjectStorage.is(), "no object storage" );
     477             : 
     478         242 :     const uno::Reference< embed::XStorage > xSourceStorage( m_xRecoveryStorage.is() ? m_xRecoveryStorage : m_xObjectStorage );
     479             : 
     480             :     uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xContext, GetDocumentServiceName(),
     481         242 :                                                 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
     482             : 
     483             :     //#i103460# ODF: take the size given from the parent frame as default
     484         484 :     uno::Reference< chart2::XChartDocument > xChart( xDocument, uno::UNO_QUERY );
     485         242 :     if( xChart.is() )
     486             :     {
     487         232 :         uno::Reference< embed::XVisualObject > xChartVisualObject( xChart, uno::UNO_QUERY );
     488         232 :         if( xChartVisualObject.is() )
     489         232 :             xChartVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, m_aDefaultSizeForChart_In_100TH_MM );
     490             :     }
     491             : 
     492         484 :     uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
     493         484 :     uno::Reference< document::XStorageBasedDocument > xDoc( xDocument, uno::UNO_QUERY );
     494         242 :     if ( !xDoc.is() && !xLoadable.is() ) ///BUG: This should be || instead of && ?
     495           6 :         throw uno::RuntimeException();
     496             : 
     497         472 :     ::comphelper::NamedValueCollection aLoadArgs;
     498         236 :     FillDefaultLoadArgs_Impl( xSourceStorage, aLoadArgs );
     499             : 
     500         472 :     uno::Reference< io::XInputStream > xTempInpStream;
     501         236 :     if ( !xDoc.is() )
     502             :     {
     503           0 :         xTempInpStream = createTempInpStreamFromStor( xSourceStorage, m_xContext );
     504           0 :         if ( !xTempInpStream.is() )
     505           0 :             throw uno::RuntimeException();
     506             : 
     507           0 :         OUString aTempFileURL;
     508             :         try
     509             :         {
     510             :             // no need to let the file stay after the stream is removed since the embedded document
     511             :             // can not be stored directly
     512           0 :             uno::Reference< beans::XPropertySet > xTempStreamProps( xTempInpStream, uno::UNO_QUERY_THROW );
     513           0 :             xTempStreamProps->getPropertyValue("Uri") >>= aTempFileURL;
     514             :         }
     515           0 :         catch( const uno::Exception& )
     516             :         {
     517             :         }
     518             : 
     519             :         SAL_WARN_IF( aTempFileURL.isEmpty(), "embeddedobj.common", "Coudn't retrieve temporary file URL!" );
     520             : 
     521           0 :         aLoadArgs.put( "URL", aTempFileURL );
     522           0 :         aLoadArgs.put( "InputStream", xTempInpStream );
     523             :     }
     524             : 
     525             : 
     526         236 :     aLoadArgs.merge( m_aDocMediaDescriptor, true );
     527             : 
     528             :     try
     529             :     {
     530             :         // set the document mode to embedded as the first step!!!
     531         236 :         EmbedAndReparentDoc_Impl( xDocument );
     532             : 
     533         236 :         if ( xDoc.is() )
     534             :         {
     535         236 :             xDoc->loadFromStorage( xSourceStorage, aLoadArgs.getPropertyValues() );
     536         236 :             if ( xSourceStorage != m_xObjectStorage )
     537           0 :                 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
     538             :         }
     539             :         else
     540           0 :             xLoadable->load( aLoadArgs.getPropertyValues() );
     541             :     }
     542           0 :     catch( const uno::Exception& )
     543             :     {
     544           0 :         uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
     545           0 :         if ( xCloseable.is() )
     546             :         {
     547             :             try
     548             :             {
     549           0 :                 xCloseable->close( sal_True );
     550             :             }
     551           0 :             catch( const uno::Exception& )
     552             :             {
     553             :                 DBG_UNHANDLED_EXCEPTION();
     554             :             }
     555             :         }
     556             : 
     557           0 :         throw; // TODO
     558             :     }
     559             : 
     560         478 :     return xDocument;
     561             : }
     562             : 
     563             : 
     564           0 : uno::Reference< io::XInputStream > OCommonEmbeddedObject::StoreDocumentToTempStream_Impl(
     565             :                                                                             sal_Int32 nStorageFormat,
     566             :                                                                             const OUString& aBaseURL,
     567             :                                                                             const OUString& aHierarchName )
     568             : {
     569             :     uno::Reference < io::XOutputStream > xTempOut(
     570             :                 io::TempFile::create(m_xContext),
     571           0 :                 uno::UNO_QUERY_THROW );
     572           0 :     uno::Reference< io::XInputStream > aResult( xTempOut, uno::UNO_QUERY );
     573             : 
     574           0 :     if ( !aResult.is() )
     575           0 :         throw uno::RuntimeException(); // TODO:
     576             : 
     577           0 :     uno::Reference< frame::XStorable > xStorable;
     578             :     {
     579           0 :         osl::MutexGuard aGuard( m_aMutex );
     580           0 :         if ( m_pDocHolder )
     581           0 :             xStorable = uno::Reference< frame::XStorable > ( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
     582             :     }
     583             : 
     584           0 :     if( !xStorable.is() )
     585           0 :         throw uno::RuntimeException(); // TODO:
     586             : 
     587           0 :     OUString aFilterName = GetFilterName( nStorageFormat );
     588             : 
     589             :     SAL_WARN_IF( aFilterName.isEmpty(), "embeddedobj.common", "Wrong document service name!" );
     590           0 :     if ( aFilterName.isEmpty() )
     591           0 :         throw io::IOException(); // TODO:
     592             : 
     593           0 :     uno::Sequence< beans::PropertyValue > aArgs( 4 );
     594           0 :     aArgs[0].Name = "FilterName";
     595           0 :     aArgs[0].Value <<= aFilterName;
     596           0 :     aArgs[1].Name = "OutputStream";
     597           0 :     aArgs[1].Value <<= xTempOut;
     598           0 :     aArgs[2].Name = "DocumentBaseURL";
     599           0 :     aArgs[2].Value <<= aBaseURL;
     600           0 :     aArgs[3].Name = "HierarchicalDocumentName";
     601           0 :     aArgs[3].Value <<= aHierarchName;
     602             : 
     603           0 :     xStorable->storeToURL( OUString( "private:stream" ), aArgs );
     604             :     try
     605             :     {
     606           0 :         xTempOut->closeOutput();
     607             :     }
     608           0 :     catch( const uno::Exception& )
     609             :     {
     610             :         SAL_WARN( "embeddedobj.common", "Looks like stream was closed already" );
     611             :     }
     612             : 
     613           0 :     return aResult;
     614             : }
     615             : 
     616             : 
     617           0 : void OCommonEmbeddedObject::SaveObject_Impl()
     618             : {
     619           0 :     if ( m_xClientSite.is() )
     620             :     {
     621             :         try
     622             :         {
     623             :             // check whether the component is modified,
     624             :             // if not there is no need for storing
     625           0 :             uno::Reference< util::XModifiable > xModifiable( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
     626           0 :             if ( xModifiable.is() && !xModifiable->isModified() )
     627           0 :                 return;
     628             :         }
     629           0 :         catch( const uno::Exception& )
     630             :         {}
     631             : 
     632             :         try {
     633           0 :             m_xClientSite->saveObject();
     634             :         }
     635           0 :         catch( const uno::Exception& )
     636             :         {
     637             :             SAL_WARN( "embeddedobj.common", "The object was not stored!" );
     638             :         }
     639             :     }
     640             : }
     641             : 
     642             : 
     643         236 : OUString OCommonEmbeddedObject::GetBaseURL_Impl() const
     644             : {
     645         236 :     OUString aBaseURL;
     646         236 :     sal_Int32 nInd = 0;
     647             : 
     648         236 :     if ( m_xClientSite.is() )
     649             :     {
     650             :         try
     651             :         {
     652           0 :             uno::Reference< frame::XModel > xParentModel( m_xClientSite->getComponent(), uno::UNO_QUERY_THROW );
     653           0 :             uno::Sequence< beans::PropertyValue > aModelProps = xParentModel->getArgs();
     654           0 :             for ( nInd = 0; nInd < aModelProps.getLength(); nInd++ )
     655           0 :                 if ( aModelProps[nInd].Name.equals(
     656           0 :                                                 OUString( "DocumentBaseURL" ) ) )
     657             :                 {
     658           0 :                     aModelProps[nInd].Value >>= aBaseURL;
     659           0 :                     break;
     660           0 :                 }
     661             : 
     662             : 
     663             :         }
     664           0 :         catch( const uno::Exception& )
     665             :         {}
     666             :     }
     667             : 
     668         236 :     if ( aBaseURL.isEmpty() )
     669             :     {
     670         314 :         for ( nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ )
     671         234 :             if ( m_aDocMediaDescriptor[nInd].Name.equals(
     672         234 :                                                 OUString( "DocumentBaseURL" ) ) )
     673             :             {
     674           0 :                 m_aDocMediaDescriptor[nInd].Value >>= aBaseURL;
     675           0 :                 break;
     676             :             }
     677             :     }
     678             : 
     679         236 :     if ( aBaseURL.isEmpty() )
     680         236 :         aBaseURL = m_aDefaultParentBaseURL;
     681             : 
     682         236 :     return aBaseURL;
     683             : }
     684             : 
     685             : 
     686        1682 : OUString OCommonEmbeddedObject::GetBaseURLFrom_Impl(
     687             :                     const uno::Sequence< beans::PropertyValue >& lArguments,
     688             :                     const uno::Sequence< beans::PropertyValue >& lObjArgs )
     689             : {
     690        1682 :     OUString aBaseURL;
     691        1682 :     sal_Int32 nInd = 0;
     692             : 
     693        1682 :     for ( nInd = 0; nInd < lArguments.getLength(); nInd++ )
     694           0 :         if ( lArguments[nInd].Name == "DocumentBaseURL" )
     695             :         {
     696           0 :             lArguments[nInd].Value >>= aBaseURL;
     697           0 :             break;
     698             :         }
     699             : 
     700        1682 :     if ( aBaseURL.isEmpty() )
     701             :     {
     702        1722 :         for ( nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
     703          40 :             if ( lObjArgs[nInd].Name == "DefaultParentBaseURL" )
     704             :             {
     705           0 :                 lObjArgs[nInd].Value >>= aBaseURL;
     706           0 :                 break;
     707             :             }
     708             :     }
     709             : 
     710        1682 :     return aBaseURL;
     711             : }
     712             : 
     713             : 
     714             : 
     715        1662 : void OCommonEmbeddedObject::SwitchDocToStorage_Impl( const uno::Reference< document::XStorageBasedDocument >& xDoc, const uno::Reference< embed::XStorage >& xStorage )
     716             : {
     717        1662 :     xDoc->switchToStorage( xStorage );
     718             : 
     719        1662 :     uno::Reference< util::XModifiable > xModif( xDoc, uno::UNO_QUERY );
     720        1662 :     if ( xModif.is() )
     721        1662 :         xModif->setModified( sal_False );
     722             : 
     723        1662 :     if ( m_xRecoveryStorage.is() )
     724           0 :         m_xRecoveryStorage.clear();
     725        1662 : }
     726             : 
     727             : namespace {
     728             : 
     729        3364 : OUString getStringPropertyValue( const uno::Sequence<beans::PropertyValue>& rProps, const OUString& rName )
     730             : {
     731        3364 :     OUString aStr;
     732             : 
     733        3420 :     for (sal_Int32 i = 0; i < rProps.getLength(); ++i)
     734             :     {
     735          72 :         if (rProps[i].Name == rName)
     736             :         {
     737          16 :             rProps[i].Value >>= aStr;
     738          16 :             break;
     739             :         }
     740             :     }
     741             : 
     742        3364 :     return aStr;
     743             : }
     744             : 
     745             : }
     746             : 
     747        1682 : void OCommonEmbeddedObject::StoreDocToStorage_Impl(
     748             :     const uno::Reference<embed::XStorage>& xStorage,
     749             :     const uno::Sequence<beans::PropertyValue>& rMediaArgs,
     750             :     const uno::Sequence<beans::PropertyValue>& rObjArgs,
     751             :     sal_Int32 nStorageFormat,
     752             :     const OUString& aHierarchName,
     753             :     bool bAttachToTheStorage )
     754             : {
     755             :     SAL_WARN_IF( !xStorage.is(), "embeddedobj.common", "No storage is provided for storing!" );
     756             : 
     757        1682 :     if ( !xStorage.is() )
     758           0 :         throw uno::RuntimeException(); // TODO:
     759             : 
     760        1682 :     uno::Reference< document::XStorageBasedDocument > xDoc;
     761             :     {
     762        1682 :         osl::MutexGuard aGuard( m_aMutex );
     763        1682 :         if ( m_pDocHolder )
     764        1682 :             xDoc = uno::Reference< document::XStorageBasedDocument >( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
     765             :     }
     766             : 
     767        3364 :     OUString aBaseURL = GetBaseURLFrom_Impl(rMediaArgs, rObjArgs);
     768             : 
     769        1682 :     if ( xDoc.is() )
     770             :     {
     771        1682 :         OUString aFilterName = GetFilterName( nStorageFormat );
     772             : 
     773             :         SAL_WARN_IF( aFilterName.isEmpty(), "embeddedobj.common", "Wrong document service name!" );
     774        1682 :         if ( aFilterName.isEmpty() )
     775           0 :             throw io::IOException(); // TODO:
     776             : 
     777        3364 :         uno::Sequence<beans::PropertyValue> aArgs(5);
     778        1682 :         aArgs[0].Name = "FilterName";
     779        1682 :         aArgs[0].Value <<= aFilterName;
     780        1682 :         aArgs[1].Name = "HierarchicalDocumentName";
     781        1682 :         aArgs[1].Value <<= aHierarchName;
     782        1682 :         aArgs[2].Name = "DocumentBaseURL";
     783        1682 :         aArgs[2].Value <<= aBaseURL;
     784        1682 :         aArgs[3].Name = "SourceShellID";
     785        1682 :         aArgs[3].Value <<= getStringPropertyValue(rObjArgs, "SourceShellID");
     786        1682 :         aArgs[4].Name = "DestinationShellID";
     787        1682 :         aArgs[4].Value <<= getStringPropertyValue(rObjArgs, "DestinationShellID");
     788             : 
     789        1682 :         xDoc->storeToStorage( xStorage, aArgs );
     790        1682 :         if ( bAttachToTheStorage )
     791        1708 :             SwitchDocToStorage_Impl( xDoc, xStorage );
     792             :     }
     793             :     else
     794             :     {
     795             :         // store document to temporary stream based on temporary file
     796           0 :         uno::Reference < io::XInputStream > xTempIn = StoreDocumentToTempStream_Impl( nStorageFormat, aBaseURL, aHierarchName );
     797             : 
     798             :         SAL_WARN_IF( !xTempIn.is(), "embeddedobj.common", "The stream reference can not be empty!" );
     799             : 
     800             :         // open storage based on document temporary file for reading
     801           0 :         uno::Reference < lang::XSingleServiceFactory > xStorageFactory = embed::StorageFactory::create(m_xContext);
     802             : 
     803           0 :         uno::Sequence< uno::Any > aArgs(1);
     804           0 :         aArgs[0] <<= xTempIn;
     805           0 :         uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ),
     806           0 :                                                             uno::UNO_QUERY );
     807           0 :         if ( !xTempStorage.is() )
     808           0 :             throw uno::RuntimeException(); // TODO:
     809             : 
     810             :         // object storage must be commited automatically
     811           0 :         xTempStorage->copyToStorage( xStorage );
     812        1682 :     }
     813        1682 : }
     814             : 
     815             : 
     816          34 : uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateDocFromMediaDescr_Impl(
     817             :                                         const uno::Sequence< beans::PropertyValue >& aMedDescr )
     818             : {
     819             :     uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xContext, GetDocumentServiceName(),
     820          34 :                                                 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
     821             : 
     822          68 :     uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
     823          34 :     if ( !xLoadable.is() )
     824           8 :         throw uno::RuntimeException();
     825             : 
     826             :     try
     827             :     {
     828             :         // set the document mode to embedded as the first action on the document!!!
     829          26 :         EmbedAndReparentDoc_Impl( xDocument );
     830             : 
     831          26 :         xLoadable->load( addAsTemplate( aMedDescr ) );
     832             :     }
     833           0 :     catch( const uno::Exception& )
     834             :     {
     835           0 :         uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
     836           0 :         if ( xCloseable.is() )
     837             :         {
     838             :             try
     839             :             {
     840           0 :                 xCloseable->close( sal_True );
     841             :             }
     842           0 :             catch( const uno::Exception& )
     843             :             {
     844             :             }
     845             :         }
     846             : 
     847           0 :         throw; // TODO
     848             :     }
     849             : 
     850          52 :     return xDocument;
     851             : }
     852             : 
     853             : 
     854           0 : uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateTempDocFromLink_Impl()
     855             : {
     856           0 :     uno::Reference< util::XCloseable > xResult;
     857             : 
     858             :     SAL_WARN_IF( !m_bIsLink, "embeddedobj.common", "The object is not a linked one!" );
     859             : 
     860           0 :     uno::Sequence< beans::PropertyValue > aTempMediaDescr;
     861             : 
     862           0 :     sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
     863             :     try {
     864           0 :         nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
     865             :     }
     866           0 :     catch ( const beans::IllegalTypeException& )
     867             :     {
     868             :         // the container just has an unknown type, use current file format
     869             :     }
     870           0 :     catch ( const uno::Exception& )
     871             :     {
     872             :         SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
     873             :     }
     874             : 
     875           0 :     if ( m_pDocHolder->GetComponent().is() )
     876             :     {
     877           0 :         aTempMediaDescr.realloc( 4 );
     878             : 
     879             :         // TODO/LATER: may be private:stream should be used as target URL
     880           0 :         OUString aTempFileURL;
     881             :         uno::Reference< io::XInputStream > xTempStream = StoreDocumentToTempStream_Impl( SOFFICE_FILEFORMAT_CURRENT,
     882             :                                                                                          OUString(),
     883           0 :                                                                                          OUString() );
     884             :         try
     885             :         {
     886             :             // no need to let the file stay after the stream is removed since the embedded document
     887             :             // can not be stored directly
     888           0 :             uno::Reference< beans::XPropertySet > xTempStreamProps( xTempStream, uno::UNO_QUERY_THROW );
     889           0 :             xTempStreamProps->getPropertyValue("Uri") >>= aTempFileURL;
     890             :         }
     891           0 :         catch( const uno::Exception& )
     892             :         {
     893             :         }
     894             : 
     895             :         SAL_WARN_IF( aTempFileURL.isEmpty(), "embeddedobj.common", "Couldn't retrieve temporary file URL!" );
     896             : 
     897           0 :         aTempMediaDescr[0].Name = "URL";
     898           0 :         aTempMediaDescr[0].Value <<= aTempFileURL;
     899           0 :         aTempMediaDescr[1].Name = "InputStream";
     900           0 :         aTempMediaDescr[1].Value <<= xTempStream;
     901           0 :         aTempMediaDescr[2].Name = "FilterName";
     902           0 :         aTempMediaDescr[2].Value <<= GetFilterName( nStorageFormat );
     903           0 :         aTempMediaDescr[3].Name = "AsTemplate";
     904           0 :         aTempMediaDescr[3].Value <<= sal_True;
     905             :     }
     906             :     else
     907             :     {
     908           0 :         aTempMediaDescr.realloc( 2 );
     909           0 :         aTempMediaDescr[0].Name = "URL";
     910           0 :         aTempMediaDescr[0].Value <<= m_aLinkURL;
     911           0 :         aTempMediaDescr[1].Name = "FilterName";
     912           0 :         aTempMediaDescr[1].Value <<= m_aLinkFilterName;
     913             :     }
     914             : 
     915           0 :     xResult = CreateDocFromMediaDescr_Impl( aTempMediaDescr );
     916             : 
     917           0 :     return xResult;
     918             : }
     919             : 
     920             : 
     921        1022 : void SAL_CALL OCommonEmbeddedObject::setPersistentEntry(
     922             :                     const uno::Reference< embed::XStorage >& xStorage,
     923             :                     const OUString& sEntName,
     924             :                     sal_Int32 nEntryConnectionMode,
     925             :                     const uno::Sequence< beans::PropertyValue >& lArguments,
     926             :                     const uno::Sequence< beans::PropertyValue >& lObjArgs )
     927             :         throw ( lang::IllegalArgumentException,
     928             :                 embed::WrongStateException,
     929             :                 io::IOException,
     930             :                 uno::Exception,
     931             :                 uno::RuntimeException, std::exception )
     932             : {
     933             :     // the type of the object must be already set
     934             :     // a kind of typedetection should be done in the factory
     935             : 
     936        1022 :     ::osl::MutexGuard aGuard( m_aMutex );
     937        1022 :     if ( m_bDisposed )
     938           0 :         throw lang::DisposedException(); // TODO
     939             : 
     940        1022 :     if ( !xStorage.is() )
     941             :         throw lang::IllegalArgumentException( "No parent storage is provided!",
     942             :                                             static_cast< ::cppu::OWeakObject* >(this),
     943           0 :                                             1 );
     944             : 
     945        1022 :     if ( sEntName.isEmpty() )
     946             :         throw lang::IllegalArgumentException( "Empty element name is provided!",
     947             :                                             static_cast< ::cppu::OWeakObject* >(this),
     948           0 :                                             2 );
     949             : 
     950             :     // May be LOADED should be forbidden here ???
     951        1022 :     if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
     952           0 :       && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
     953             :     {
     954             :         // if the object is not loaded
     955             :         // it can not get persistent representation without initialization
     956             : 
     957             :         // if the object is loaded
     958             :         // it can switch persistent representation only without initialization
     959             : 
     960             :         throw embed::WrongStateException(
     961             :                     "Can't change persistent representation of activated object!",
     962           0 :                      static_cast< ::cppu::OWeakObject* >(this) );
     963             :     }
     964             : 
     965        1022 :     if ( m_bWaitSaveCompleted )
     966             :     {
     967           0 :         if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
     968             :         {
     969             :             // saveCompleted is expected, handle it accordingly
     970           0 :             if ( m_xNewParentStorage == xStorage && m_aNewEntryName.equals( sEntName ) )
     971             :             {
     972           0 :                 saveCompleted( sal_True );
     973           0 :                 return;
     974             :             }
     975             : 
     976             :             // if a completely different entry is provided, switch first back to the old persistence in saveCompleted
     977             :             // and then switch to the target persistence
     978           0 :             bool bSwitchFurther = ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) );
     979           0 :             saveCompleted( sal_False );
     980           0 :             if ( !bSwitchFurther )
     981           0 :                 return;
     982             :         }
     983             :         else
     984             :             throw embed::WrongStateException(
     985             :                         "The object waits for saveCompleted() call!",
     986           0 :                         static_cast< ::cppu::OWeakObject* >(this) );
     987             :     }
     988             : 
     989             :     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
     990             :     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
     991             :     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
     992        1022 :     if ( m_bIsLink )
     993             :     {
     994           0 :         m_aEntryName = sEntName;
     995           0 :         return;
     996             :     }
     997             : 
     998        2044 :     uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
     999        1022 :     if ( !xNameAccess.is() )
    1000           0 :         throw uno::RuntimeException(); //TODO
    1001             : 
    1002             :     // detect entry existence
    1003        1022 :     bool bElExists = xNameAccess->hasByName( sEntName );
    1004             : 
    1005        2044 :     m_aDocMediaDescriptor = GetValuableArgs_Impl( lArguments,
    1006        1022 :                                                   nEntryConnectionMode != embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT );
    1007             : 
    1008        1022 :     m_bReadOnly = false;
    1009        1224 :     for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
    1010         202 :         if ( lArguments[nInd].Name == "ReadOnly" )
    1011         100 :             lArguments[nInd].Value >>= m_bReadOnly;
    1012             : 
    1013             :     // TODO: use lObjArgs for StoreVisualReplacement
    1014        2042 :     for ( sal_Int32 nObjInd = 0; nObjInd < lObjArgs.getLength(); nObjInd++ )
    1015        1020 :         if ( lObjArgs[nObjInd].Name == "OutplaceDispatchInterceptor" )
    1016             :         {
    1017           0 :             uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor;
    1018           0 :             if ( lObjArgs[nObjInd].Value >>= xDispatchInterceptor )
    1019           0 :                 m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor );
    1020             :         }
    1021        1020 :         else if ( lObjArgs[nObjInd].Name == "DefaultParentBaseURL" )
    1022             :         {
    1023           0 :             lObjArgs[nObjInd].Value >>= m_aDefaultParentBaseURL;
    1024             :         }
    1025        1020 :         else if ( lObjArgs[nObjInd].Name == "Parent" )
    1026             :         {
    1027        1012 :             lObjArgs[nObjInd].Value >>= m_xParent;
    1028             :         }
    1029           8 :         else if ( lObjArgs[nObjInd].Name == "IndividualMiscStatus" )
    1030             :         {
    1031           0 :             sal_Int64 nMiscStatus=0;
    1032           0 :             lObjArgs[nObjInd].Value >>= nMiscStatus;
    1033           0 :             m_nMiscStatus |= nMiscStatus;
    1034             :         }
    1035           8 :         else if ( lObjArgs[nObjInd].Name == "CloneFrom" )
    1036             :         {
    1037           8 :             uno::Reference < embed::XEmbeddedObject > xObj;
    1038           8 :             lObjArgs[nObjInd].Value >>= xObj;
    1039           8 :             if ( xObj.is() )
    1040             :             {
    1041           8 :                 m_bHasClonedSize = true;
    1042           8 :                 m_aClonedSize = xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
    1043           8 :                 m_nClonedMapUnit = xObj->getMapUnit( embed::Aspects::MSOLE_CONTENT );
    1044           8 :             }
    1045             :         }
    1046           0 :         else if ( lObjArgs[nObjInd].Name == "OutplaceFrameProperties" )
    1047             :         {
    1048           0 :             uno::Sequence< uno::Any > aOutFrameProps;
    1049           0 :             uno::Sequence< beans::NamedValue > aOutFramePropsTyped;
    1050           0 :             if ( lObjArgs[nObjInd].Value >>= aOutFrameProps )
    1051             :             {
    1052           0 :                 m_pDocHolder->SetOutplaceFrameProperties( aOutFrameProps );
    1053             :             }
    1054           0 :             else if ( lObjArgs[nObjInd].Value >>= aOutFramePropsTyped )
    1055             :             {
    1056           0 :                 aOutFrameProps.realloc( aOutFramePropsTyped.getLength() );
    1057           0 :                 uno::Any* pProp = aOutFrameProps.getArray();
    1058           0 :                 for (   const beans::NamedValue* pTypedProp = aOutFramePropsTyped.getConstArray();
    1059           0 :                         pTypedProp != aOutFramePropsTyped.getConstArray() + aOutFramePropsTyped.getLength();
    1060             :                         ++pTypedProp, ++pProp
    1061             :                     )
    1062             :                 {
    1063           0 :                     *pProp <<= *pTypedProp;
    1064             :                 }
    1065           0 :                 m_pDocHolder->SetOutplaceFrameProperties( aOutFrameProps );
    1066             :             }
    1067             :             else
    1068           0 :                 SAL_WARN( "embeddedobj.common", "OCommonEmbeddedObject::setPersistentEntry: illegal type for argument 'OutplaceFrameProperties'!" );
    1069             :         }
    1070           0 :         else if ( lObjArgs[nObjInd].Name == "ModuleName" )
    1071             :         {
    1072           0 :             lObjArgs[nObjInd].Value >>= m_aModuleName;
    1073             :         }
    1074           0 :         else if ( lObjArgs[nObjInd].Name == "EmbeddedScriptSupport" )
    1075             :         {
    1076           0 :             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_bEmbeddedScriptSupport );
    1077             :         }
    1078           0 :         else if ( lObjArgs[nObjInd].Name == "DocumentRecoverySupport" )
    1079             :         {
    1080           0 :             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_bDocumentRecoverySupport );
    1081             :         }
    1082           0 :         else if ( lObjArgs[nObjInd].Name == "RecoveryStorage" )
    1083             :         {
    1084           0 :             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_xRecoveryStorage );
    1085             :         }
    1086             : 
    1087             : 
    1088        1022 :     sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
    1089             : 
    1090        1022 :     SwitchOwnPersistence( xStorage, sEntName );
    1091             : 
    1092        1022 :     if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT )
    1093             :     {
    1094         100 :         if ( bElExists )
    1095             :         {
    1096             :             // the initialization from existing storage allows to leave object in loaded state
    1097         100 :             m_nObjectState = embed::EmbedStates::LOADED;
    1098             :         }
    1099             :         else
    1100             :         {
    1101           0 :             m_pDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly );
    1102           0 :             if ( !m_pDocHolder->GetComponent().is() )
    1103           0 :                 throw io::IOException(); // TODO: can not create document
    1104             : 
    1105           0 :             m_nObjectState = embed::EmbedStates::RUNNING;
    1106             :         }
    1107             :     }
    1108             :     else
    1109             :     {
    1110         922 :         if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE )
    1111           0 :             throw io::IOException();
    1112             : 
    1113         922 :         if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
    1114             :         {
    1115             :             // the document just already changed its storage to store to
    1116             :             // the links to OOo documents for now ignore this call
    1117             :             // TODO: OOo links will have persistence so it will be switched here
    1118             :         }
    1119         922 :         else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT )
    1120             :         {
    1121         888 :             if ( m_xRecoveryStorage.is() )
    1122           0 :                 TransferMediaType( m_xRecoveryStorage, m_xObjectStorage );
    1123             : 
    1124             :             // TODO:
    1125         888 :             m_pDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly );
    1126             : 
    1127         888 :             if ( !m_pDocHolder->GetComponent().is() )
    1128           0 :                 throw io::IOException(); // TODO: can not create document
    1129             : 
    1130         888 :             m_nObjectState = embed::EmbedStates::RUNNING;
    1131             :         }
    1132          34 :         else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT )
    1133             :         {
    1134          34 :             m_pDocHolder->SetComponent( CreateDocFromMediaDescr_Impl( lArguments ), m_bReadOnly );
    1135          26 :             m_nObjectState = embed::EmbedStates::RUNNING;
    1136             :         }
    1137             :         //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
    1138             :         //{
    1139             :             //TODO:
    1140             :         //}
    1141             :         else
    1142             :             throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
    1143             :                                         static_cast< ::cppu::OWeakObject* >(this),
    1144           0 :                                         3 );
    1145        1022 :     }
    1146             : }
    1147             : 
    1148             : 
    1149           8 : void SAL_CALL OCommonEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage,
    1150             :                             const OUString& sEntName,
    1151             :                             const uno::Sequence< beans::PropertyValue >& lArguments,
    1152             :                             const uno::Sequence< beans::PropertyValue >& lObjArgs )
    1153             :         throw ( lang::IllegalArgumentException,
    1154             :                 embed::WrongStateException,
    1155             :                 io::IOException,
    1156             :                 uno::Exception,
    1157             :                 uno::RuntimeException, std::exception )
    1158             : {
    1159           8 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
    1160           8 :     if ( m_bDisposed )
    1161           0 :         throw lang::DisposedException(); // TODO
    1162             : 
    1163           8 :     if ( m_nObjectState == -1 )
    1164             :     {
    1165             :         // the object is still not loaded
    1166             :         throw embed::WrongStateException( "Can't store object without persistence!",
    1167           0 :                                         static_cast< ::cppu::OWeakObject* >(this) );
    1168             :     }
    1169             : 
    1170           8 :     if ( m_bWaitSaveCompleted )
    1171             :         throw embed::WrongStateException(
    1172             :                     "The object waits for saveCompleted() call!",
    1173           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1174             : 
    1175             :     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
    1176             :     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
    1177             :     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
    1178           8 :     if ( m_bIsLink )
    1179           8 :         return;
    1180             : 
    1181             :     OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
    1182             : 
    1183           8 :     sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
    1184           8 :     sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
    1185             :     try {
    1186           8 :         nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage );
    1187             :     }
    1188           0 :     catch ( const beans::IllegalTypeException& )
    1189             :     {
    1190             :         // the container just has an unknown type, use current file format
    1191             :     }
    1192           0 :     catch ( const uno::Exception& )
    1193             :     {
    1194             :         SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
    1195             :     }
    1196           8 :     if (nTargetStorageFormat == SOFFICE_FILEFORMAT_60)
    1197             :     {
    1198             :         SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
    1199           0 :         nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
    1200             :         // setting MediaType is done later anyway, no need to do it here
    1201             :     }
    1202             : 
    1203             :     try
    1204             :     {
    1205           8 :         nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
    1206             :     }
    1207           0 :     catch ( const beans::IllegalTypeException& )
    1208             :     {
    1209             :         // the container just has an unknown type, use current file format
    1210             :     }
    1211           0 :     catch ( const uno::Exception& )
    1212             :     {
    1213             :         SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
    1214             :     }
    1215             : 
    1216           8 :     bool bTryOptimization = false;
    1217          24 :     for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
    1218             :     {
    1219             :         // StoreVisualReplacement and VisualReplacement args have no sence here
    1220          16 :         if ( lObjArgs[nInd].Name == "CanTryOptimization" )
    1221           0 :             lObjArgs[nInd].Value >>= bTryOptimization;
    1222             :     }
    1223             : 
    1224           8 :     bool bSwitchBackToLoaded = false;
    1225             : 
    1226             :     // Storing to different format can be done only in running state.
    1227           8 :     if ( m_nObjectState == embed::EmbedStates::LOADED )
    1228             :     {
    1229             :         // TODO/LATER: copying is not legal for documents with relative links.
    1230           0 :         if ( nTargetStorageFormat == nOriginalStorageFormat )
    1231             :         {
    1232           0 :             bool bOptimizationWorks = false;
    1233           0 :             if ( bTryOptimization )
    1234             :             {
    1235             :                 try
    1236             :                 {
    1237             :                     // try to use optimized copying
    1238           0 :                     uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW );
    1239           0 :                     uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW );
    1240           0 :                     xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName );
    1241           0 :                     bOptimizationWorks = true;
    1242             :                 }
    1243           0 :                 catch( const uno::Exception& )
    1244             :                 {
    1245             :                 }
    1246             :             }
    1247             : 
    1248           0 :             if ( !bOptimizationWorks )
    1249           0 :                 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
    1250             :         }
    1251             :         else
    1252             :         {
    1253           0 :             changeState( embed::EmbedStates::RUNNING );
    1254           0 :             bSwitchBackToLoaded = true;
    1255             :         }
    1256             :     }
    1257             : 
    1258           8 :     if ( m_nObjectState != embed::EmbedStates::LOADED )
    1259             :     {
    1260             :         uno::Reference< embed::XStorage > xSubStorage =
    1261           8 :                     xStorage->openStorageElement( sEntName, embed::ElementModes::READWRITE );
    1262             : 
    1263           8 :         if ( !xSubStorage.is() )
    1264           0 :             throw uno::RuntimeException(); //TODO
    1265             : 
    1266           8 :         aGuard.clear();
    1267             :         // TODO/LATER: support hierarchical name for embedded objects in embedded objects
    1268             :         StoreDocToStorage_Impl(
    1269           8 :             xSubStorage, lArguments, lObjArgs, nTargetStorageFormat, sEntName, false );
    1270           8 :         aGuard.reset();
    1271             : 
    1272           8 :         if ( bSwitchBackToLoaded )
    1273           0 :             changeState( embed::EmbedStates::LOADED );
    1274           8 :     }
    1275             : 
    1276             :     // TODO: should the listener notification be done?
    1277             : }
    1278             : 
    1279             : 
    1280        1658 : void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage,
    1281             :                             const OUString& sEntName,
    1282             :                             const uno::Sequence< beans::PropertyValue >& lArguments,
    1283             :                             const uno::Sequence< beans::PropertyValue >& lObjArgs )
    1284             :         throw ( lang::IllegalArgumentException,
    1285             :                 embed::WrongStateException,
    1286             :                 io::IOException,
    1287             :                 uno::Exception,
    1288             :                 uno::RuntimeException, std::exception )
    1289             : {
    1290             :     // TODO: use lObjArgs
    1291             : 
    1292        1658 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
    1293        1658 :     if ( m_bDisposed )
    1294           0 :         throw lang::DisposedException(); // TODO
    1295             : 
    1296        1658 :     if ( m_nObjectState == -1 )
    1297             :     {
    1298             :         // the object is still not loaded
    1299             :         throw embed::WrongStateException( "Can't store object without persistence!",
    1300           0 :                                         static_cast< ::cppu::OWeakObject* >(this) );
    1301             :     }
    1302             : 
    1303        1658 :     if ( m_bWaitSaveCompleted )
    1304             :         throw embed::WrongStateException(
    1305             :                     "The object waits for saveCompleted() call!",
    1306           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1307             : 
    1308             :     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
    1309             :     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
    1310             :     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
    1311        1658 :     if ( m_bIsLink )
    1312             :     {
    1313           0 :         m_aNewEntryName = sEntName;
    1314        1658 :         return;
    1315             :     }
    1316             : 
    1317             :     OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
    1318             : 
    1319        1658 :     sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
    1320        1658 :     sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
    1321             :     try {
    1322        1658 :         nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage );
    1323             :     }
    1324           0 :     catch ( const beans::IllegalTypeException& )
    1325             :     {
    1326             :         // the container just has an unknown type, use current file format
    1327             :     }
    1328           0 :     catch ( const uno::Exception& )
    1329             :     {
    1330             :         SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
    1331             :     }
    1332        1658 :     if (nTargetStorageFormat == SOFFICE_FILEFORMAT_60)
    1333             :     {
    1334             :         SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
    1335           0 :         nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
    1336             :         // setting MediaType is done later anyway, no need to do it here
    1337             :     }
    1338             : 
    1339             :     try
    1340             :     {
    1341        1658 :         nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
    1342             :     }
    1343         556 :     catch ( const beans::IllegalTypeException& )
    1344             :     {
    1345             :         // the container just has an unknown type, use current file format
    1346             :     }
    1347           0 :     catch ( const uno::Exception& )
    1348             :     {
    1349             :         SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
    1350             :     }
    1351             : 
    1352        1658 :     PostEvent_Impl( OUString( "OnSaveAs" ) );
    1353             : 
    1354        1658 :     bool bTryOptimization = false;
    1355        1686 :     for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
    1356             :     {
    1357             :         // StoreVisualReplacement and VisualReplacement args have no sence here
    1358          28 :         if ( lObjArgs[nInd].Name == "CanTryOptimization" )
    1359          14 :             lObjArgs[nInd].Value >>= bTryOptimization;
    1360             :     }
    1361             : 
    1362        1658 :     bool bSwitchBackToLoaded = false;
    1363             : 
    1364             :     // Storing to different format can be done only in running state.
    1365        1658 :     if ( m_nObjectState == embed::EmbedStates::LOADED )
    1366             :     {
    1367             :         // TODO/LATER: copying is not legal for documents with relative links.
    1368          10 :         if ( nTargetStorageFormat == nOriginalStorageFormat )
    1369             :         {
    1370          10 :             bool bOptimizationWorks = false;
    1371          10 :             if ( bTryOptimization )
    1372             :             {
    1373             :                 try
    1374             :                 {
    1375             :                     // try to use optimized copying
    1376           2 :                     uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW );
    1377           4 :                     uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW );
    1378           2 :                     xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName );
    1379           4 :                     bOptimizationWorks = true;
    1380             :                 }
    1381           0 :                 catch( const uno::Exception& )
    1382             :                 {
    1383             :                 }
    1384             :             }
    1385             : 
    1386          10 :             if ( !bOptimizationWorks )
    1387           8 :                 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
    1388             :         }
    1389             :         else
    1390             :         {
    1391           0 :             changeState( embed::EmbedStates::RUNNING );
    1392           0 :             bSwitchBackToLoaded = true;
    1393             :         }
    1394             :     }
    1395             : 
    1396             :     uno::Reference< embed::XStorage > xSubStorage =
    1397        3316 :                 xStorage->openStorageElement( sEntName, embed::ElementModes::READWRITE );
    1398             : 
    1399        1658 :     if ( !xSubStorage.is() )
    1400           0 :         throw uno::RuntimeException(); //TODO
    1401             : 
    1402        1658 :     if ( m_nObjectState != embed::EmbedStates::LOADED )
    1403             :     {
    1404        1648 :         aGuard.clear();
    1405             :         // TODO/LATER: support hierarchical name for embedded objects in embedded objects
    1406             :         StoreDocToStorage_Impl(
    1407        1648 :             xSubStorage, lArguments, lObjArgs, nTargetStorageFormat, sEntName, false );
    1408        1648 :         aGuard.reset();
    1409             : 
    1410        1648 :         if ( bSwitchBackToLoaded )
    1411           0 :             changeState( embed::EmbedStates::LOADED );
    1412             :     }
    1413             : 
    1414        1658 :     m_bWaitSaveCompleted = true;
    1415        1658 :     m_xNewObjectStorage = xSubStorage;
    1416        1658 :     m_xNewParentStorage = xStorage;
    1417        1658 :     m_aNewEntryName = sEntName;
    1418        3316 :     m_aNewDocMediaDescriptor = GetValuableArgs_Impl( lArguments, true );
    1419             : 
    1420             :     // TODO: register listeners for storages above, in case thay are disposed
    1421             :     //       an exception will be thrown on saveCompleted( true )
    1422             : 
    1423             :     // TODO: should the listener notification be done here or in saveCompleted?
    1424             : }
    1425             : 
    1426             : 
    1427        2210 : void SAL_CALL OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew )
    1428             :         throw ( embed::WrongStateException,
    1429             :                 uno::Exception,
    1430             :                 uno::RuntimeException, std::exception )
    1431             : {
    1432        2210 :     ::osl::MutexGuard aGuard( m_aMutex );
    1433        2210 :     if ( m_bDisposed )
    1434           0 :         throw lang::DisposedException(); // TODO
    1435             : 
    1436        2210 :     if ( m_nObjectState == -1 )
    1437             :     {
    1438             :         // the object is still not loaded
    1439             :         throw embed::WrongStateException( "Can't store object without persistence!",
    1440           0 :                                         static_cast< ::cppu::OWeakObject* >(this) );
    1441             :     }
    1442             : 
    1443             :     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
    1444             :     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
    1445             :     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
    1446        2210 :     if ( m_bIsLink )
    1447             :     {
    1448           0 :         if ( bUseNew )
    1449           0 :             m_aEntryName = m_aNewEntryName;
    1450           0 :         m_aNewEntryName = OUString();
    1451           0 :         return;
    1452             :     }
    1453             : 
    1454             :     // it is allowed to call saveCompleted( false ) for nonstored objects
    1455        2210 :     if ( !m_bWaitSaveCompleted && !bUseNew )
    1456         552 :         return;
    1457             : 
    1458             :     SAL_WARN_IF( !m_bWaitSaveCompleted, "embeddedobj.common", "Unexpected saveCompleted() call!" );
    1459        1658 :     if ( !m_bWaitSaveCompleted )
    1460           0 :         throw io::IOException(); // TODO: illegal call
    1461             : 
    1462             :     OSL_ENSURE( m_xNewObjectStorage.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" );
    1463        1658 :     if ( !m_xNewObjectStorage.is() || !m_xNewParentStorage.is() )
    1464           0 :         throw uno::RuntimeException(); // TODO: broken internal information
    1465             : 
    1466        1658 :     if ( bUseNew )
    1467             :     {
    1468        1644 :         SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStorage, m_aNewEntryName );
    1469        1644 :         m_aDocMediaDescriptor = m_aNewDocMediaDescriptor;
    1470             : 
    1471        1644 :         uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
    1472        1644 :         if ( xModif.is() )
    1473        1636 :             xModif->setModified( sal_False );
    1474             : 
    1475        1644 :         PostEvent_Impl( OUString( "OnSaveAsDone" ));
    1476             :     }
    1477             :     else
    1478             :     {
    1479             :         try {
    1480          14 :             uno::Reference< lang::XComponent > xComponent( m_xNewObjectStorage, uno::UNO_QUERY );
    1481             :             SAL_WARN_IF( !xComponent.is(), "embeddedobj.common", "Wrong storage implementation!" );
    1482          14 :             if ( xComponent.is() )
    1483          14 :                 xComponent->dispose();
    1484             :         }
    1485           0 :         catch ( const uno::Exception& )
    1486             :         {
    1487             :         }
    1488             :     }
    1489             : 
    1490        1658 :     m_xNewObjectStorage = uno::Reference< embed::XStorage >();
    1491        1658 :     m_xNewParentStorage = uno::Reference< embed::XStorage >();
    1492        1658 :     m_aNewEntryName = OUString();
    1493        1658 :     m_aNewDocMediaDescriptor.realloc( 0 );
    1494        1658 :     m_bWaitSaveCompleted = false;
    1495             : 
    1496        1658 :     if ( bUseNew )
    1497             :     {
    1498             :         // TODO: notify listeners
    1499             : 
    1500        1644 :         if ( m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE )
    1501             :         {
    1502             :             // TODO: update visual representation
    1503             :         }
    1504        1658 :     }
    1505             : }
    1506             : 
    1507             : 
    1508           0 : sal_Bool SAL_CALL OCommonEmbeddedObject::hasEntry()
    1509             :         throw ( embed::WrongStateException,
    1510             :                 uno::RuntimeException, std::exception )
    1511             : {
    1512           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1513           0 :     if ( m_bDisposed )
    1514           0 :         throw lang::DisposedException(); // TODO
    1515             : 
    1516           0 :     if ( m_bWaitSaveCompleted )
    1517             :         throw embed::WrongStateException(
    1518             :                     "The object waits for saveCompleted() call!",
    1519           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1520             : 
    1521           0 :     if ( m_xObjectStorage.is() )
    1522           0 :         return sal_True;
    1523             : 
    1524           0 :     return sal_False;
    1525             : }
    1526             : 
    1527             : 
    1528         298 : OUString SAL_CALL OCommonEmbeddedObject::getEntryName()
    1529             :         throw ( embed::WrongStateException,
    1530             :                 uno::RuntimeException, std::exception )
    1531             : {
    1532         298 :     ::osl::MutexGuard aGuard( m_aMutex );
    1533         298 :     if ( m_bDisposed )
    1534           0 :         throw lang::DisposedException(); // TODO
    1535             : 
    1536         298 :     if ( m_nObjectState == -1 )
    1537             :     {
    1538             :         // the object is still not loaded
    1539             :         throw embed::WrongStateException( "The object persistence is not initialized!",
    1540           0 :                                         static_cast< ::cppu::OWeakObject* >(this) );
    1541             :     }
    1542             : 
    1543         298 :     if ( m_bWaitSaveCompleted )
    1544             :         throw embed::WrongStateException(
    1545             :                     "The object waits for saveCompleted() call!",
    1546           2 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1547             : 
    1548         298 :     return m_aEntryName;
    1549             : }
    1550             : 
    1551             : 
    1552          26 : void SAL_CALL OCommonEmbeddedObject::storeOwn()
    1553             :         throw ( embed::WrongStateException,
    1554             :                 io::IOException,
    1555             :                 uno::Exception,
    1556             :                 uno::RuntimeException, std::exception )
    1557             : {
    1558             :     // during switching from Activated to Running and from Running to Loaded states the object will
    1559             :     // ask container to store the object, the container has to make decision
    1560             :     // to do so or not
    1561             : 
    1562          26 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
    1563          26 :     if ( m_bDisposed )
    1564           0 :         throw lang::DisposedException(); // TODO
    1565             : 
    1566          26 :     if ( m_nObjectState == -1 )
    1567             :     {
    1568             :         // the object is still not loaded
    1569             :         throw embed::WrongStateException( "Can't store object without persistence!",
    1570           0 :                                     static_cast< ::cppu::OWeakObject* >(this) );
    1571             :     }
    1572             : 
    1573          26 :     if ( m_bWaitSaveCompleted )
    1574             :         throw embed::WrongStateException(
    1575             :                     "The object waits for saveCompleted() call!",
    1576           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1577             : 
    1578          26 :     if ( m_bReadOnly )
    1579           0 :         throw io::IOException(); // TODO: access denied
    1580             : 
    1581             :     // nothing to do, if the object is in loaded state
    1582          26 :     if ( m_nObjectState == embed::EmbedStates::LOADED )
    1583          26 :         return;
    1584             : 
    1585          26 :     PostEvent_Impl( OUString( "OnSave" ) );
    1586             : 
    1587             :     SAL_WARN_IF( !m_pDocHolder->GetComponent().is(), "embeddedobj.common", "If an object is activated or in running state it must have a document!" );
    1588          26 :     if ( !m_pDocHolder->GetComponent().is() )
    1589           0 :         throw uno::RuntimeException();
    1590             : 
    1591          26 :     if ( m_bIsLink )
    1592             :     {
    1593             :         // TODO: just store the document to it's location
    1594           0 :         uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
    1595           0 :         if ( !xStorable.is() )
    1596           0 :             throw uno::RuntimeException(); // TODO
    1597             : 
    1598             :         // free the main mutex for the storing time
    1599           0 :         aGuard.clear();
    1600             : 
    1601           0 :         xStorable->store();
    1602             : 
    1603           0 :         aGuard.reset();
    1604             :     }
    1605             :     else
    1606             :     {
    1607             :         OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
    1608             : 
    1609          26 :         if ( !m_xObjectStorage.is() )
    1610           0 :             throw io::IOException(); //TODO: access denied
    1611             : 
    1612          26 :         sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
    1613             :         try {
    1614          26 :             nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
    1615             :         }
    1616           0 :         catch ( const beans::IllegalTypeException& )
    1617             :         {
    1618             :             // the container just has an unknown type, use current file format
    1619             :         }
    1620           0 :         catch ( const uno::Exception& )
    1621             :         {
    1622             :             SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
    1623             :         }
    1624          26 :         if (nStorageFormat == SOFFICE_FILEFORMAT_60)
    1625             :         {
    1626             :             SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
    1627           0 :             nStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
    1628             :             // setting MediaType is done later anyway, no need to do it here
    1629             :         }
    1630             : 
    1631          26 :         aGuard.clear();
    1632          26 :         uno::Sequence<beans::PropertyValue> aEmpty;
    1633          26 :         StoreDocToStorage_Impl( m_xObjectStorage, aEmpty, aEmpty, nStorageFormat, m_aEntryName, true );
    1634          26 :         aGuard.reset();
    1635             :     }
    1636             : 
    1637          52 :     uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
    1638          26 :     if ( xModif.is() )
    1639          26 :         xModif->setModified( sal_False );
    1640             : 
    1641          52 :     PostEvent_Impl( OUString( "OnSaveDone" ) );
    1642             : }
    1643             : 
    1644             : 
    1645           0 : sal_Bool SAL_CALL OCommonEmbeddedObject::isReadonly()
    1646             :         throw ( embed::WrongStateException,
    1647             :                 uno::RuntimeException, std::exception )
    1648             : {
    1649           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1650           0 :     if ( m_bDisposed )
    1651           0 :         throw lang::DisposedException(); // TODO
    1652             : 
    1653           0 :     if ( m_nObjectState == -1 )
    1654             :     {
    1655             :         // the object is still not loaded
    1656             :         throw embed::WrongStateException( "The object persistence is not initialized!",
    1657           0 :                                         static_cast< ::cppu::OWeakObject* >(this) );
    1658             :     }
    1659             : 
    1660           0 :     if ( m_bWaitSaveCompleted )
    1661             :         throw embed::WrongStateException(
    1662             :                     "The object waits for saveCompleted() call!",
    1663           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1664             : 
    1665           0 :     return m_bReadOnly;
    1666             : }
    1667             : 
    1668             : 
    1669           0 : void SAL_CALL OCommonEmbeddedObject::reload(
    1670             :                 const uno::Sequence< beans::PropertyValue >& lArguments,
    1671             :                 const uno::Sequence< beans::PropertyValue >& lObjArgs )
    1672             :         throw ( lang::IllegalArgumentException,
    1673             :                 embed::WrongStateException,
    1674             :                 io::IOException,
    1675             :                 uno::Exception,
    1676             :                 uno::RuntimeException, std::exception )
    1677             : {
    1678             :     // TODO: use lObjArgs
    1679             :     // for now this method is used only to switch readonly state
    1680             : 
    1681           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1682           0 :     if ( m_bDisposed )
    1683           0 :         throw lang::DisposedException(); // TODO
    1684             : 
    1685           0 :     if ( m_nObjectState == -1 )
    1686             :     {
    1687             :         // the object is still not loaded
    1688             :         throw embed::WrongStateException( "The object persistence is not initialized!",
    1689           0 :                                         static_cast< ::cppu::OWeakObject* >(this) );
    1690             :     }
    1691             : 
    1692           0 :     if ( m_nObjectState != embed::EmbedStates::LOADED )
    1693             :     {
    1694             :         // the object is still not loaded
    1695             :         throw embed::WrongStateException(
    1696             :                                 "The object must be in loaded state to be reloaded!",
    1697           0 :                                 static_cast< ::cppu::OWeakObject* >(this) );
    1698             :     }
    1699             : 
    1700           0 :     if ( m_bWaitSaveCompleted )
    1701             :         throw embed::WrongStateException(
    1702             :                     "The object waits for saveCompleted() call!",
    1703           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1704             : 
    1705           0 :     if ( m_bIsLink )
    1706             :     {
    1707             :         // reload of the link
    1708           0 :         OUString aOldLinkFilter = m_aLinkFilterName;
    1709             : 
    1710           0 :         OUString aNewLinkFilter;
    1711           0 :         for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
    1712             :         {
    1713           0 :             if ( lArguments[nInd].Name == "URL" )
    1714             :             {
    1715             :                 // the new URL
    1716           0 :                 lArguments[nInd].Value >>= m_aLinkURL;
    1717           0 :                 m_aLinkFilterName = OUString();
    1718             :             }
    1719           0 :             else if ( lArguments[nInd].Name == "FilterName" )
    1720             :             {
    1721           0 :                 lArguments[nInd].Value >>= aNewLinkFilter;
    1722           0 :                 m_aLinkFilterName = OUString();
    1723             :             }
    1724             :         }
    1725             : 
    1726           0 :         ::comphelper::MimeConfigurationHelper aHelper( m_xContext );
    1727           0 :         if ( m_aLinkFilterName.isEmpty() )
    1728             :         {
    1729           0 :             if ( !aNewLinkFilter.isEmpty() )
    1730           0 :                 m_aLinkFilterName = aNewLinkFilter;
    1731             :             else
    1732             :             {
    1733           0 :                 uno::Sequence< beans::PropertyValue > aArgs( 1 );
    1734           0 :                 aArgs[0].Name = "URL";
    1735           0 :                 aArgs[0].Value <<= m_aLinkURL;
    1736           0 :                 m_aLinkFilterName = aHelper.UpdateMediaDescriptorWithFilterName( aArgs, false );
    1737             :             }
    1738             :         }
    1739             : 
    1740           0 :         if ( !aOldLinkFilter.equals( m_aLinkFilterName ) )
    1741             :         {
    1742           0 :             uno::Sequence< beans::NamedValue > aObject = aHelper.GetObjectPropsByFilter( m_aLinkFilterName );
    1743             : 
    1744             :             // TODO/LATER: probably the document holder could be cleaned explicitly as in the destructor
    1745           0 :             m_pDocHolder->release();
    1746           0 :             m_pDocHolder = NULL;
    1747             : 
    1748           0 :             LinkInit_Impl( aObject, lArguments, lObjArgs );
    1749           0 :         }
    1750             :     }
    1751             : 
    1752           0 :     m_aDocMediaDescriptor = GetValuableArgs_Impl( lArguments, true );
    1753             : 
    1754             :     // TODO: use lObjArgs for StoreVisualReplacement
    1755           0 :     for ( sal_Int32 nObjInd = 0; nObjInd < lObjArgs.getLength(); nObjInd++ )
    1756           0 :         if ( lObjArgs[nObjInd].Name == "OutplaceDispatchInterceptor" )
    1757             :         {
    1758           0 :             uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor;
    1759           0 :             if ( lObjArgs[nObjInd].Value >>= xDispatchInterceptor )
    1760           0 :                 m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor );
    1761             : 
    1762           0 :             break;
    1763             :         }
    1764             : 
    1765             :     // TODO:
    1766             :     // when document allows reloading through API the object can be reloaded not only in loaded state
    1767             : 
    1768           0 :     bool bOldReadOnlyValue = m_bReadOnly;
    1769             : 
    1770           0 :     m_bReadOnly = false;
    1771           0 :     for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
    1772           0 :         if ( lArguments[nInd].Name == "ReadOnly" )
    1773           0 :             lArguments[nInd].Value >>= m_bReadOnly;
    1774             : 
    1775           0 :     if ( bOldReadOnlyValue != m_bReadOnly && !m_bIsLink )
    1776             :     {
    1777             :         // close own storage
    1778             :         try {
    1779           0 :             uno::Reference< lang::XComponent > xComponent( m_xObjectStorage, uno::UNO_QUERY );
    1780             :             OSL_ENSURE( !m_xObjectStorage.is() || xComponent.is(), "Wrong storage implementation!" );
    1781           0 :             if ( xComponent.is() )
    1782           0 :                 xComponent->dispose();
    1783             :         }
    1784           0 :         catch ( const uno::Exception& )
    1785             :         {
    1786             :         }
    1787             : 
    1788           0 :         sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
    1789           0 :         m_xObjectStorage = m_xParentStorage->openStorageElement( m_aEntryName, nStorageMode );
    1790           0 :     }
    1791           0 : }
    1792             : 
    1793           0 : sal_Bool SAL_CALL OCommonEmbeddedObject::isStored() throw (css::uno::RuntimeException, std::exception)
    1794             : {
    1795           0 :     uno::Reference<container::XNameAccess> xNA(m_xObjectStorage, uno::UNO_QUERY);
    1796           0 :     if (!xNA.is())
    1797           0 :         return false;
    1798             : 
    1799           0 :     return xNA->getElementNames().getLength() > 0;
    1800             : }
    1801             : 
    1802             : 
    1803           0 : void SAL_CALL OCommonEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage,
    1804             :                                                 const OUString& sEntName )
    1805             :         throw ( lang::IllegalArgumentException,
    1806             :                 embed::WrongStateException,
    1807             :                 io::IOException,
    1808             :                 uno::Exception,
    1809             :                 uno::RuntimeException, std::exception )
    1810             : {
    1811           0 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
    1812           0 :     if ( m_bDisposed )
    1813           0 :         throw lang::DisposedException(); // TODO
    1814             : 
    1815           0 :     if ( !m_bIsLink )
    1816             :     {
    1817             :         // it must be a linked initialized object
    1818             :         throw embed::WrongStateException(
    1819             :                     "The object is not a valid linked object!",
    1820           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1821             :     }
    1822             :     else
    1823             :     {
    1824             :         // the current implementation of OOo links does not implement this method since it does not implement
    1825             :         // all the set of interfaces required for OOo embedded object ( XEmbedPersist is not supported ).
    1826             :     }
    1827             : 
    1828           0 :     if ( !xStorage.is() )
    1829             :         throw lang::IllegalArgumentException( "No parent storage is provided!",
    1830             :                                             static_cast< ::cppu::OWeakObject* >(this),
    1831           0 :                                             1 );
    1832             : 
    1833           0 :     if ( sEntName.isEmpty() )
    1834             :         throw lang::IllegalArgumentException( "Empty element name is provided!",
    1835             :                                             static_cast< ::cppu::OWeakObject* >(this),
    1836           0 :                                             2 );
    1837             : 
    1838           0 :     if ( !m_bIsLink || m_nObjectState == -1 )
    1839             :     {
    1840             :         // it must be a linked initialized object
    1841             :         throw embed::WrongStateException(
    1842             :                     "The object is not a valid linked object!",
    1843           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1844             :     }
    1845             : 
    1846           0 :     if ( m_bWaitSaveCompleted )
    1847             :         throw embed::WrongStateException(
    1848             :                     "The object waits for saveCompleted() call!",
    1849           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1850             : 
    1851           0 :     uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
    1852           0 :     if ( !xNameAccess.is() )
    1853           0 :         throw uno::RuntimeException(); //TODO
    1854             : 
    1855           0 :     m_bReadOnly = false;
    1856             : 
    1857           0 :     if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) )
    1858           0 :         SwitchOwnPersistence( xStorage, sEntName );
    1859             : 
    1860             :     // for linked object it means that it becomes embedded object
    1861             :     // the document must switch it's persistence also
    1862             : 
    1863             :     // TODO/LATER: handle the case when temp doc can not be created
    1864             :     // the document is a new embedded object so it must be marked as modified
    1865           0 :     uno::Reference< util::XCloseable > xDocument = CreateTempDocFromLink_Impl();
    1866           0 :     uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
    1867           0 :     if ( !xModif.is() )
    1868           0 :         throw uno::RuntimeException();
    1869             :     try
    1870             :     {
    1871           0 :         xModif->setModified( sal_True );
    1872             :     }
    1873           0 :     catch( const uno::Exception& )
    1874             :     {}
    1875             : 
    1876           0 :     m_pDocHolder->SetComponent( xDocument, m_bReadOnly );
    1877             :     SAL_WARN_IF( !m_pDocHolder->GetComponent().is(), "embeddedobj.common", "If document can't be created, an exception must be thrown!" );
    1878             : 
    1879           0 :     if ( m_nObjectState == embed::EmbedStates::LOADED )
    1880             :     {
    1881             :         // the state is changed and can not be switched to loaded state back without saving
    1882           0 :         m_nObjectState = embed::EmbedStates::RUNNING;
    1883           0 :         StateChangeNotification_Impl( false, embed::EmbedStates::LOADED, m_nObjectState, aGuard );
    1884             :     }
    1885           0 :     else if ( m_nObjectState == embed::EmbedStates::ACTIVE )
    1886           0 :         m_pDocHolder->Show();
    1887             : 
    1888           0 :     m_bIsLink = false;
    1889           0 :     m_aLinkFilterName = OUString();
    1890           0 :     m_aLinkURL = OUString();
    1891           0 : }
    1892             : 
    1893             : 
    1894        1200 : sal_Bool SAL_CALL  OCommonEmbeddedObject::isLink()
    1895             :         throw ( embed::WrongStateException,
    1896             :                 uno::RuntimeException, std::exception )
    1897             : {
    1898        1200 :     ::osl::MutexGuard aGuard( m_aMutex );
    1899        1200 :     if ( m_bDisposed )
    1900           0 :         throw lang::DisposedException(); // TODO
    1901             : 
    1902        1200 :     return m_bIsLink;
    1903             : }
    1904             : 
    1905             : 
    1906           0 : OUString SAL_CALL OCommonEmbeddedObject::getLinkURL()
    1907             :         throw ( embed::WrongStateException,
    1908             :                 uno::Exception,
    1909             :                 uno::RuntimeException, std::exception )
    1910             : {
    1911           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1912           0 :     if ( m_bDisposed )
    1913           0 :         throw lang::DisposedException(); // TODO
    1914             : 
    1915           0 :     if ( !m_bIsLink )
    1916             :         throw embed::WrongStateException(
    1917             :                     "The object is not a link object!",
    1918           0 :                     static_cast< ::cppu::OWeakObject* >(this) );
    1919             : 
    1920           0 :     return m_aLinkURL;
    1921             : }
    1922             : 
    1923             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10