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

Generated by: LCOV version 1.10