/* -*- 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 .
*/
//! models/documents should never be disposed (they may still be //! used for printing which is called asynchronously for example) //! instead call close
Reference< util::XCloseable > xClose( rxModel, UNO_QUERY ); if (xClose.is())
{ try
{ //! 'sal_True' -> transfer ownership to vetoing object if vetoed! //! I.e. now that object is responsible for closing the model and doc shell.
xClose->close( true );
} catch (const util::CloseVetoException&)
{ //! here we have the problem that the temporary file that is //! currently being printed will never be deleted. :-(
eResult = eVetoed;
} catch (const uno::RuntimeException&)
{
eResult = eFailed;
}
} return eResult;
}
// try to get the DocShell
SwDocShell *pTmpDocShell = nullptr; if (auto pTextDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(xTmpModel); pTextDoc)
pTmpDocShell = pTextDoc->GetDocShell();
bool bRes = false; if (xTmpModel.is() && pTmpDocShell) // everything available?
{ if (bClose)
CloseModelAndDocSh( rxModel, rxDocSh ); // set new stuff
rxModel = std::move(xTmpModel);
rxDocSh = pTmpDocShell;
bRes = true;
} else
{ // SfxObjectShellRef is ok here, since the document will be explicitly closed
SfxObjectShellRef xTmpDocSh = pTmpDocShell;
CloseModelAndDocSh( xTmpModel, xTmpDocSh );
}
bool bSuccess = false; try
{ bool bDeliverOwnership = ( 0 == m_nPendingDeleteAttempts ); // if this is our last attempt, then anybody which vetoes this has to take the consequences // (means take the ownership)
m_xDocument->close( bDeliverOwnership );
bSuccess = true;
} catch (const util::CloseVetoException&)
{ // somebody vetoed -> next try if ( m_nPendingDeleteAttempts )
{ // next attempt
--m_nPendingDeleteAttempts;
m_aDeleteTimer.Start();
} else
bSuccess = true; // can't do anything here ...
} catch (const Exception&)
{
TOOLS_WARN_EXCEPTION( "sw", "DelayedFileDeletion::OnTryDeleteFile: caught a strange exception!" );
bSuccess = true; // can't do anything here ...
}
if ( bSuccess )
{
SWUnoHelper::UCB_DeleteFile( m_sTemporaryFile );
aGuard.clear();
release(); // this should be our last reference, we should be dead after this
}
}
void DelayedFileDeletion::implTakeOwnership( )
{ // revoke ourself as listener try
{
m_xDocument->removeCloseListener( this );
} catch (const Exception&)
{
OSL_FAIL("DelayedFileDeletion::implTakeOwnership: could not revoke the listener!" );
}
m_aDeleteTimer.SetTimeout( 3000 ); // 3 seconds
m_aDeleteTimer.SetInvokeHandler( LINK( this, DelayedFileDeletion, OnTryDeleteFile ) );
m_nPendingDeleteAttempts = 3; // try 3 times at most
m_aDeleteTimer.Start( );
}
// always veto: We want to take the ownership ourself, as this is the only chance to delete // the temporary file which the model is based on throw util::CloseVetoException( );
}
void SAL_CALL DelayedFileDeletion::notifyClosing( const EventObject& )
{
OSL_FAIL("DelayedFileDeletion::notifyClosing: how this?" ); // this should not happen: // Either, a foreign instance closes the document, then we should veto this, and take the ownership // Or, we ourself close the document, then we should not be a listener anymore
}
void SAL_CALL DelayedFileDeletion::disposing( const EventObject& )
{
OSL_FAIL("DelayedFileDeletion::disposing: how this?" ); // this should not happen: // Either, a foreign instance closes the document, then we should veto this, and take the ownership // Or, we ourself close the document, then we should not be a listener anymore
}
staticbool DeleteTmpFile_Impl(
Reference< frame::XModel > &rxModel,
SfxObjectShellRef &rxDocSh, const OUString &rTmpFileURL )
{ bool bRes = false; if (!rTmpFileURL.isEmpty())
{ bool bDelete = true; if ( eVetoed == CloseModelAndDocSh( rxModel, rxDocSh ) )
{ // somebody vetoed the closing, and took the ownership of the document // -> ensure that the temporary file is deleted later on new DelayedFileDeletion( rxModel, rTmpFileURL ); // note: as soon as #106931# is fixed, the whole DelayedFileDeletion is to be superseded by // a better solution
bDelete = false;
}
if ( bDelete )
{ if ( !SWUnoHelper::UCB_DeleteFile( rTmpFileURL ) )
{ new DelayedFileDeletion( rxModel, rTmpFileURL ); // same not as above: as soon as #106931#, ...
}
} else
bRes = true; // file will be deleted delayed
} return bRes;
}
SwXMailMerge::~SwXMailMerge()
{ if (!m_aTmpFileName.isEmpty())
DeleteTmpFile_Impl( m_xModel, m_xDocSh, m_aTmpFileName ); else// there was no temporary file in use
{ //! we still need to close the model and doc shell manually //! because there is no automatism that will do that later. //! #120086# if ( eVetoed == CloseModelAndDocSh( m_xModel, m_xDocSh ) )
OSL_FAIL("ownership transferred to vetoing object!" );
SfxObjectShellRef xCurDocSh = m_xDocSh; // the document
for (const beans::NamedValue& rArgument : rArguments)
{ const OUString &rName = rArgument.Name; const Any &rValue = rArgument.Value;
bool bOK = true; if (rName == UNO_NAME_SELECTION)
bOK = rValue >>= aCurSelection; elseif (rName == UNO_NAME_RESULT_SET)
bOK = rValue >>= xCurResultSet; elseif (rName == UNO_NAME_CONNECTION)
bOK = rValue >>= xCurConnection; elseif (rName == UNO_NAME_MODEL) throw PropertyVetoException("Property is read-only: " + rName, getXWeak() ); elseif (rName == UNO_NAME_DATA_SOURCE_NAME)
bOK = rValue >>= aCurDataSourceName; elseif (rName == UNO_NAME_DAD_COMMAND)
bOK = rValue >>= aCurDataCommand; elseif (rName == UNO_NAME_FILTER)
bOK = rValue >>= aCurFilter; elseif (rName == UNO_NAME_DOCUMENT_URL)
{
bOK = rValue >>= aCurDocumentURL; if (!aCurDocumentURL.isEmpty()
&& !LoadFromURL_impl( xCurModel, xCurDocSh, aCurDocumentURL, false )) throw RuntimeException("Failed to create document from URL: " + aCurDocumentURL, getXWeak() );
} elseif (rName == UNO_NAME_OUTPUT_URL)
{
bOK = rValue >>= aCurOutputURL; if (!aCurOutputURL.isEmpty())
{ if (!UCB_IsDirectory(aCurOutputURL)) throw IllegalArgumentException("URL does not point to a directory: " + aCurOutputURL, getXWeak(), 0 ); if (UCB_IsReadOnlyFileName(aCurOutputURL)) throw IllegalArgumentException("URL is read-only: " + aCurOutputURL, getXWeak(), 0 );
}
} elseif (rName == UNO_NAME_FILE_NAME_PREFIX)
bOK = rValue >>= aCurFileNamePrefix; elseif (rName == UNO_NAME_DAD_COMMAND_TYPE)
bOK = rValue >>= nCurDataCommandType; elseif (rName == UNO_NAME_OUTPUT_TYPE)
bOK = rValue >>= nCurOutputType; elseif (rName == UNO_NAME_ESCAPE_PROCESSING)
bOK = rValue >>= bCurEscapeProcessing; elseif (rName == UNO_NAME_FILE_NAME_FROM_COLUMN)
bOK = rValue >>= bCurFileNameFromColumn; elseif (rName == UNO_NAME_SUBJECT)
bOK = rValue >>= m_sSubject; elseif (rName == UNO_NAME_ADDRESS_FROM_COLUMN)
bOK = rValue >>= m_sAddressFromColumn; elseif (rName == UNO_NAME_SEND_AS_HTML)
bOK = rValue >>= m_bSendAsHTML; elseif (rName == UNO_NAME_MAIL_BODY)
bOK = rValue >>= m_sMailBody; elseif (rName == UNO_NAME_ATTACHMENT_NAME)
bOK = rValue >>= m_sAttachmentName; elseif (rName == UNO_NAME_ATTACHMENT_FILTER)
bOK = rValue >>= m_sAttachmentFilter; elseif (rName == UNO_NAME_COPIES_TO)
bOK = rValue >>= m_aCopiesTo; elseif (rName == UNO_NAME_BLIND_COPIES_TO)
bOK = rValue >>= m_aBlindCopiesTo; elseif (rName == UNO_NAME_SEND_AS_ATTACHMENT)
bOK = rValue >>= m_bSendAsAttachment; elseif (rName == UNO_NAME_PRINT_OPTIONS)
bOK = rValue >>= m_aPrintSettings; elseif (rName == UNO_NAME_SAVE_AS_SINGLE_FILE)
bOK = rValue >>= m_bSaveAsSingleFile; elseif (rName == UNO_NAME_SAVE_FILTER)
bOK = rValue >>= m_sSaveFilter; elseif (rName == UNO_NAME_SAVE_FILTER_OPTIONS)
bOK = rValue >>= m_sSaveFilterOptions; elseif (rName == UNO_NAME_SAVE_FILTER_DATA)
bOK = rValue >>= m_aSaveFilterData; elseif (rName == UNO_NAME_IN_SERVER_PASSWORD)
bOK = rValue >>= m_sInServerPassword; elseif (rName == UNO_NAME_OUT_SERVER_PASSWORD)
bOK = rValue >>= m_sOutServerPassword; else throw UnknownPropertyException( "Property is unknown: " + rName, getXWeak() );
if (!bOK) throw IllegalArgumentException("Property type mismatch or property not set: " + rName, getXWeak(), 0 );
}
// need to translate the selection: the API here requires a sequence of bookmarks, but the Merge // method we will call below requires a sequence of indices. if ( aCurSelection.hasElements() )
{
Sequence< Any > aTranslated( aCurSelection.getLength() );
if ( !bValid )
{ throw IllegalArgumentException(
u"The current 'Selection' does not describe a valid array of bookmarks, relative to the current 'ResultSet'."_ustr,
getXWeak(),
0
);
}
// avoid assertion in 'Update' from Sfx by supplying a shell // and thus avoiding the SelectShell call in Writers GetState function // while still in Update of Sfx. // (GetSelection in Update is not allowed) if (!aCurDocumentURL.isEmpty())
pView->AttrChangedNotify(nullptr);//So that SelectShell is called.
SharedComponent aRowSetDisposeHelper; if (!xCurResultSet.is())
{ if (aCurDataSourceName.isEmpty() || aCurDataCommand.isEmpty() )
{
OSL_FAIL("PropertyValues missing or unset"); throw IllegalArgumentException(u"Either the ResultSet or DataSourceName and DataCommand must be set."_ustr, getXWeak(), 0 );
}
// build ResultSet from DataSourceName, DataCommand and DataCommandType
std::unique_ptr< SwMailMergeConfigItem > pMMConfigItem;
uno::Reference< mail::XMailService > xInService; switch (nCurOutputType)
{ case MailMergeType::PRINTER:
{ // #i25686# printing should not be done asynchronously to prevent dangling offices // when mail merge is called as command line macro
aMergeDesc.aPrintOptions = m_aPrintSettings;
aMergeDesc.bCreateSingleFile = true;
} break; case MailMergeType::SHELL:
aMergeDesc.bCreateSingleFile = true;
pMMConfigItem.reset(new SwMailMergeConfigItem);
aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get(); break; case MailMergeType::FILE:
{
INetURLObject aURLObj;
aURLObj.SetSmartProtocol( INetProtocol::File );
if (!aCurDocumentURL.isEmpty())
{ // if OutputURL or FileNamePrefix are missing get // them from DocumentURL
aURLObj.SetSmartURL( aCurDocumentURL ); if (aCurFileNamePrefix.isEmpty())
aCurFileNamePrefix = aURLObj.GetBase(); // filename without extension if (aCurOutputURL.isEmpty())
{
aURLObj.removeSegment();
aCurOutputURL = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
}
} else// default empty document without URL
{ if (aCurOutputURL.isEmpty()) throw RuntimeException(u"OutputURL is not set and can not be obtained."_ustr, getXWeak() );
}
if ( xCurModel.get() != m_xModel.get() )
{ // in case it was a temporary model -> close it, and delete the file
DeleteTmpFile_Impl( xCurModel, xCurDocSh, m_aTmpFileName );
m_aTmpFileName.clear();
} // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest)
if (!bSucc) throw Exception(u"Mail merge failed. Sorry, no further information available."_ustr, getXWeak() );
void SAL_CALL SwXMailMerge::cancel()
{ // Cancel may be called from a second thread, so this protects from m_pMgr /// cleanup in the execute function.
osl::MutexGuard aMgrGuard( GetMailMergeMutex() ); if (m_pMgr)
m_pMgr->MergeCancel();
}
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 und die Messung sind noch experimentell.