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

Generated by: LCOV version 1.11