/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
uno::Reference< uno::XInterface > xDocument; try
{
xDocument = _rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
_rDocumentServiceName, aArguments.getWrappedPropertyValues(), _rxContext );
} catch( const uno::Exception& )
{ // if an embedded object implementation does not support XInitialization, // the default factory from cppuhelper will throw an // IllegalArgumentException when we try to create the instance with arguments. // Okay, so we fall back to creating the instance without any arguments.
OSL_FAIL("Consider implementing interface XInitialization to avoid duplicate construction");
xDocument = _rxContext->getServiceManager()->createInstanceWithContext( _rDocumentServiceName, _rxContext );
}
SAL_WARN_IF(!xDocument.is(), "embeddedobj.common", "Service " << _rDocumentServiceName << " is not available?"); return uno::Reference< util::XCloseable >( xDocument, uno::UNO_QUERY );
}
// the linked document should not be switched if ( !m_bIsLinkURL )
{
uno::Reference< document::XStorageBasedDocument > xDoc( m_xDocHolder->GetComponent(), uno::UNO_QUERY ); if ( xDoc.is() )
SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
}
try
{ // set the document mode to embedded as the first action on document!!!
EmbedAndReparentDoc_Impl( xDocument );
// if we have a storage to recover the document from, do not use initNew, but instead load from that storage bool bInitNew = true; if ( m_xRecoveryStorage.is() )
{
uno::Reference< document::XStorageBasedDocument > xDoc( xLoadable, uno::UNO_QUERY );
SAL_WARN_IF( !xDoc.is(), "embeddedobj.common", "OCommonEmbeddedObject::InitNewDocument_Impl: cannot recover from a storage when the document is not storage based!" ); if ( xDoc.is() )
{
::comphelper::NamedValueCollection aLoadArgs;
FillDefaultLoadArgs_Impl( m_xRecoveryStorage, aLoadArgs );
for ( sal_Int32 nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ )
{ // return early if this document is not trusted to open links if (m_aDocMediaDescriptor[nInd].Name == utl::MediaDescriptor::PROP_REFERRER)
{
OUString referer;
m_aDocMediaDescriptor[nInd].Value >>= referer; if (SvtSecurityOptions::isUntrustedReferer(referer)) return nullptr;
}
pArgs[nInd+nLen].Name = m_aDocMediaDescriptor[nInd].Name;
pArgs[nInd+nLen].Value = m_aDocMediaDescriptor[nInd].Value;
}
// If no filter is found, fall back to the FileFormatVersion=6200 filter, Base only has that. if (aFilterName.isEmpty() && nVersion == SOFFICE_FILEFORMAT_CURRENT)
aFilterName = aHelper.GetDefaultFilterFromServiceName(GetDocumentServiceName(), SOFFICE_FILEFORMAT_60);
} catch( const uno::Exception& )
{}
}
OUString aTempFileURL; try
{ // no need to let the file stay after the stream is removed since the embedded document // can not be stored directly
uno::Reference< beans::XPropertySet > xTempStreamProps( xTempInpStream, uno::UNO_QUERY_THROW );
xTempStreamProps->getPropertyValue(u"Uri"_ustr) >>= aTempFileURL;
} catch( const uno::Exception& )
{
}
void OCommonEmbeddedObject::SaveObject_Impl()
{ if ( !m_xClientSite.is() ) return;
try
{ // check whether the component is modified, // if not there is no need for storing
uno::Reference< util::XModifiable > xModifiable( m_xDocHolder->GetComponent(), uno::UNO_QUERY ); if ( xModifiable.is() && !xModifiable->isModified() ) return;
} catch( const uno::Exception& )
{}
try {
m_xClientSite->saveObject();
} catch( const uno::Exception& )
{
SAL_WARN( "embeddedobj.common", "The object was not stored!" );
}
}
// No filter found? Try the older format, e.g. Base has only that. if (aFilterName.isEmpty() && nStorageFormat == SOFFICE_FILEFORMAT_CURRENT)
aFilterName = GetFilterName( SOFFICE_FILEFORMAT_60 );
SAL_WARN_IF( aFilterName.isEmpty(), "embeddedobj.common", "Wrong document service name!" ); if ( aFilterName.isEmpty() ) throw io::IOException(); // TODO:
xDoc->storeToStorage( xStorage, aArgs ); if ( bAttachToTheStorage )
SwitchDocToStorage_Impl( xDoc, xStorage );
} else
{ // store document to temporary stream based on temporary file
uno::Reference < io::XInputStream > xTempIn = StoreDocumentToTempStream_Impl( nStorageFormat, aBaseURL, aHierarchName );
SAL_WARN_IF( !xTempIn.is(), "embeddedobj.common", "The stream reference can not be empty!" );
// open storage based on document temporary file for reading
uno::Reference < lang::XSingleServiceFactory > xStorageFactory = embed::StorageFactory::create(m_xContext);
sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT; try {
nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
} catch ( const beans::IllegalTypeException& )
{ // the container just has an unknown type, use current file format
} catch ( const uno::Exception& )
{
SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
}
if ( m_xDocHolder->GetComponent().is() )
{
aTempMediaDescr.realloc( 4 );
// TODO/LATER: may be private:stream should be used as target URL
OUString aTempFileURL;
uno::Reference< io::XInputStream > xTempStream = StoreDocumentToTempStream_Impl( SOFFICE_FILEFORMAT_CURRENT,
OUString(),
OUString() ); try
{ // no need to let the file stay after the stream is removed since the embedded document // can not be stored directly
uno::Reference< beans::XPropertySet > xTempStreamProps( xTempStream, uno::UNO_QUERY_THROW );
xTempStreamProps->getPropertyValue(u"Uri"_ustr) >>= aTempFileURL;
} catch( const uno::Exception& )
{
}
void SAL_CALL OCommonEmbeddedObject::setPersistentEntry( const uno::Reference< embed::XStorage >& xStorage, const OUString& sEntName,
sal_Int32 nEntryConnectionMode, const uno::Sequence< beans::PropertyValue >& lArguments, const uno::Sequence< beans::PropertyValue >& lObjArgs )
{ // the type of the object must be already set // a kind of typedetection should be done in the factory
::osl::MutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO
if ( !xStorage.is() ) throw lang::IllegalArgumentException( u"No parent storage is provided!"_ustr, static_cast< ::cppu::OWeakObject* >(this),
1 );
if ( sEntName.isEmpty() ) throw lang::IllegalArgumentException( u"Empty element name is provided!"_ustr, static_cast< ::cppu::OWeakObject* >(this),
2 );
// May be LOADED should be forbidden here ??? if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
&& ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
{ // if the object is not loaded // it can not get persistent representation without initialization
// if the object is loaded // it can switch persistent representation only without initialization
if ( m_bWaitSaveCompleted )
{ if ( nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) throw embed::WrongStateException(
u"The object waits for saveCompleted() call!"_ustr, static_cast< ::cppu::OWeakObject* >(this) ); // saveCompleted is expected, handle it accordingly if ( m_xNewParentStorage == xStorage && m_aNewEntryName == sEntName )
{
saveCompleted( true ); return;
}
// if a completely different entry is provided, switch first back to the old persistence in saveCompleted // and then switch to the target persistence bool bSwitchFurther = ( m_xParentStorage != xStorage || m_aEntryName != sEntName );
saveCompleted( false ); if ( !bSwitchFurther ) return;
}
// for now support of this interface is required to allow breaking of links and converting them to normal embedded // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); if ( m_bIsLinkURL )
{
m_aEntryName = sEntName; return;
}
if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT )
{ if ( bElExists )
{ // the initialization from existing storage allows to leave object in loaded state
m_nObjectState = embed::EmbedStates::LOADED;
} else
{
m_xDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly ); if ( !m_xDocHolder->GetComponent().is() ) throw io::IOException(); // TODO: can not create document
if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
{ // the document just already changed its storage to store to // the links to OOo documents for now ignore this call // TODO: OOo links will have persistence so it will be switched here
} elseif ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT )
{ if ( m_xRecoveryStorage.is() )
TransferMediaType( m_xRecoveryStorage, m_xObjectStorage );
if ( m_nObjectState == -1 )
{ // the object is still not loaded throw embed::WrongStateException( u"Can't store object without persistence!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
}
if ( m_bWaitSaveCompleted ) throw embed::WrongStateException(
u"The object waits for saveCompleted() call!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
// for now support of this interface is required to allow breaking of links and converting them to normal embedded // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); if ( m_bIsLinkURL ) return;
OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!" );
sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT; try {
nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage );
} catch ( const beans::IllegalTypeException& )
{ // the container just has an unknown type, use current file format
} catch ( const uno::Exception& )
{
SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
} if (nTargetStorageFormat == SOFFICE_FILEFORMAT_60)
{
SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT; // setting MediaType is done later anyway, no need to do it here
}
try
{
nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
} catch ( const beans::IllegalTypeException& )
{ // the container just has an unknown type, use current file format
} catch ( const uno::Exception& )
{
SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
}
bool bTryOptimization = false; for ( beans::PropertyValue const & prop : lObjArgs )
{ // StoreVisualReplacement and VisualReplacement args have no sense here if ( prop.Name == "CanTryOptimization" )
prop.Value >>= bTryOptimization;
}
bool bSwitchBackToLoaded = false;
// Storing to different format can be done only in running state. if ( m_nObjectState == embed::EmbedStates::LOADED )
{ // TODO/LATER: copying is not legal for documents with relative links. if ( nTargetStorageFormat == nOriginalStorageFormat )
{ bool bOptimizationWorks = false; if ( bTryOptimization )
{ try
{ // try to use optimized copying
uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW );
uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW );
xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName );
bOptimizationWorks = true;
} catch( const uno::Exception& )
{
}
}
if ( m_nObjectState == -1 )
{ // the object is still not loaded throw embed::WrongStateException( u"Can't store object without persistence!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
}
if ( m_bWaitSaveCompleted ) throw embed::WrongStateException(
u"The object waits for saveCompleted() call!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
// for now support of this interface is required to allow breaking of links and converting them to normal embedded // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); if ( m_bIsLinkURL )
{
m_aNewEntryName = sEntName;
if ( !AutoSaveEvent )
handleLinkedOLE(CopyBackToOLELink::CopyTempToLink);
return;
}
OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!" );
sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT; try {
nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage );
} catch ( const beans::IllegalTypeException& )
{ // the container just has an unknown type, use current file format
} catch ( const uno::Exception& )
{
SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
} if (nTargetStorageFormat == SOFFICE_FILEFORMAT_60)
{
SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT; // setting MediaType is done later anyway, no need to do it here
}
try
{
nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
} catch ( const beans::IllegalTypeException& )
{ // the container just has an unknown type, use current file format
} catch ( const uno::Exception& )
{
SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
}
PostEvent_Impl( u"OnSaveAs"_ustr );
bool bTryOptimization = false; for ( beans::PropertyValue const & prop : lObjArgs )
{ // StoreVisualReplacement and VisualReplacement args have no sense here if ( prop.Name == "CanTryOptimization" )
prop.Value >>= bTryOptimization;
}
bool bSwitchBackToLoaded = false;
// Storing to different format can be done only in running state. if ( m_nObjectState == embed::EmbedStates::LOADED )
{ // TODO/LATER: copying is not legal for documents with relative links. if ( nTargetStorageFormat == nOriginalStorageFormat )
{ bool bOptimizationWorks = false; if ( bTryOptimization )
{ try
{ // try to use optimized copying
uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW );
uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW );
xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName );
bOptimizationWorks = true;
} catch( const uno::Exception& )
{
}
}
// TODO: register listeners for storages above, in case they are disposed // an exception will be thrown on saveCompleted( true )
// TODO: should the listener notification be done here or in saveCompleted?
}
void SAL_CALL OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew )
{
::osl::MutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO
if ( m_nObjectState == -1 )
{ // the object is still not loaded throw embed::WrongStateException( u"Can't store object without persistence!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
}
// for now support of this interface is required to allow breaking of links and converting them to normal embedded // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); if ( m_bIsLinkURL )
{ if ( bUseNew )
m_aEntryName = m_aNewEntryName;
m_aNewEntryName.clear(); return;
}
// it is allowed to call saveCompleted( false ) for nonstored objects if ( !m_bWaitSaveCompleted && !bUseNew ) return;
sal_Bool SAL_CALL OCommonEmbeddedObject::hasEntry()
{
::osl::MutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO
if ( m_bWaitSaveCompleted ) throw embed::WrongStateException(
u"The object waits for saveCompleted() call!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
if ( m_xObjectStorage.is() ) returntrue;
returnfalse;
}
OUString SAL_CALL OCommonEmbeddedObject::getEntryName()
{
::osl::MutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO
if ( m_nObjectState == -1 )
{ // the object is still not loaded throw embed::WrongStateException( u"The object persistence is not initialized!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
}
if ( m_bWaitSaveCompleted ) throw embed::WrongStateException(
u"The object waits for saveCompleted() call!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
return m_aEntryName;
}
void SAL_CALL OCommonEmbeddedObject::storeOwn()
{ // during switching from Activated to Running and from Running to Loaded states the object will // ask container to store the object, the container has to make decision // to do so or not
::osl::ResettableMutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO
if ( m_nObjectState == -1 )
{ // the object is still not loaded throw embed::WrongStateException( u"Can't store object without persistence!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
}
if ( m_bWaitSaveCompleted ) throw embed::WrongStateException(
u"The object waits for saveCompleted() call!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
if ( m_bReadOnly ) throw io::IOException(); // TODO: access denied
// nothing to do, if the object is in loaded state if ( m_nObjectState == embed::EmbedStates::LOADED ) return;
PostEvent_Impl( u"OnSave"_ustr );
SAL_WARN_IF( !m_xDocHolder->GetComponent().is(), "embeddedobj.common", "If an object is activated or in running state it must have a document!" ); if ( !m_xDocHolder->GetComponent().is() ) throw uno::RuntimeException();
if ( m_bIsLinkURL )
{ // TODO: just store the document to its location
uno::Reference< frame::XStorable > xStorable( m_xDocHolder->GetComponent(), uno::UNO_QUERY_THROW );
// free the main mutex for the storing time
aGuard.clear();
xStorable->store();
aGuard.reset();
} else
{
OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!" );
if ( !m_xObjectStorage.is() ) throw io::IOException(); //TODO: access denied
sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT; try {
nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
} catch ( const beans::IllegalTypeException& )
{ // the container just has an unknown type, use current file format
} catch ( const uno::Exception& )
{
SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
} if (nStorageFormat == SOFFICE_FILEFORMAT_60)
{
SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
nStorageFormat = SOFFICE_FILEFORMAT_CURRENT; // setting MediaType is done later anyway, no need to do it here
}
sal_Bool SAL_CALL OCommonEmbeddedObject::isReadonly()
{
::osl::MutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO
if ( m_nObjectState == -1 )
{ // the object is still not loaded throw embed::WrongStateException( u"The object persistence is not initialized!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
}
if ( m_bWaitSaveCompleted ) throw embed::WrongStateException(
u"The object waits for saveCompleted() call!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
return m_bReadOnly;
}
void SAL_CALL OCommonEmbeddedObject::reload( const uno::Sequence< beans::PropertyValue >& lArguments, const uno::Sequence< beans::PropertyValue >& lObjArgs )
{ // TODO: use lObjArgs // for now this method is used only to switch readonly state
::osl::MutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO
if ( m_nObjectState == -1 )
{ // the object is still not loaded throw embed::WrongStateException( u"The object persistence is not initialized!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
}
if ( m_nObjectState != embed::EmbedStates::LOADED )
{ // the object is still not loaded throw embed::WrongStateException(
u"The object must be in loaded state to be reloaded!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
}
if ( m_bWaitSaveCompleted ) throw embed::WrongStateException(
u"The object waits for saveCompleted() call!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
if ( m_bIsLinkURL )
{ // reload of the link
OUString aOldLinkFilter = m_aLinkFilterName;
if (!m_bIsLinkURL || m_nObjectState == -1)
{ // it must be a linked initialized object throw embed::WrongStateException(
u"The object is not a valid linked object!"_ustr, static_cast< ::cppu::OWeakObject* >(this) );
} // the current implementation of OOo links does not implement this method since it does not implement
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.32 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.