LibreOffice Module sw (master)  1
unomailmerge.cxx
Go to the documentation of this file.
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 <vcl/svapp.hxx>
21 #include <osl/mutex.hxx>
22 #include <svl/itemprop.hxx>
23 #include <svl/urihelper.hxx>
25 #include <unotools/tempfile.hxx>
26 #include <sfx2/app.hxx>
27 #include <sfx2/docfile.hxx>
28 #include <sfx2/docfilt.hxx>
30 #include <comphelper/string.hxx>
32 #include <vcl/timer.hxx>
33 #include <com/sun/star/sdb/CommandType.hpp>
34 #include <com/sun/star/text/MailMergeType.hpp>
35 #include <com/sun/star/text/MailMergeEvent.hpp>
36 #include <com/sun/star/text/XMailMergeListener.hpp>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <com/sun/star/lang/XUnoTunnel.hpp>
39 #include <com/sun/star/sdbc/XResultSet.hpp>
40 #include <com/sun/star/sdbc/XConnection.hpp>
41 #include <com/sun/star/sdbc/XRowSet.hpp>
42 #include <com/sun/star/frame/Desktop.hpp>
43 #include <com/sun/star/util/XCloseable.hpp>
44 #include <com/sun/star/util/CloseVetoException.hpp>
45 #include <com/sun/star/sdbcx/XRowLocate.hpp>
46 #include <com/sun/star/frame/XStorable.hpp>
47 #include <com/sun/star/mail/XSmtpService.hpp>
48 #include <sfx2/viewfrm.hxx>
49 #include <sfx2/event.hxx>
50 #include <cppuhelper/implbase.hxx>
51 #include <swevent.hxx>
52 #include <unomailmerge.hxx>
53 #include <swdll.hxx>
54 #include <swmodule.hxx>
55 #include <unoprnms.hxx>
56 #include <unomap.hxx>
57 #include <swunohelper.hxx>
58 #include <docsh.hxx>
60 #include <view.hxx>
61 #include <dbmgr.hxx>
62 #include <unotxdoc.hxx>
63 #include <prtopt.hxx>
64 #include <wrtsh.hxx>
65 #include <shellio.hxx>
66 #include <mmconfigitem.hxx>
67 #include <mailmergehelper.hxx>
68 
69 #include <unomid.h>
70 #include <iodetect.hxx>
71 
72 #include <memory>
73 
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::frame;
76 using namespace ::com::sun::star::uno;
77 using namespace ::com::sun::star::lang;
78 using namespace ::com::sun::star::beans;
79 using namespace ::com::sun::star::text;
80 using namespace SWUnoHelper;
81 
82 typedef ::utl::SharedUNOComponent< XInterface > SharedComponent;
83 
84 static osl::Mutex & GetMailMergeMutex()
85 {
86  static osl::Mutex aMutex;
87  return aMutex;
88 }
89 
91 {
92  eSuccess, // successfully closed
93  eVetoed, // vetoed, ownership transferred to the vetoing instance
94  eFailed // failed for some unknown reason
95 };
97  Reference< frame::XModel > const &rxModel,
98  SfxObjectShellRef &rxDocSh )
99 {
100  CloseResult eResult = eSuccess;
101 
102  rxDocSh = nullptr;
103 
107  Reference< util::XCloseable > xClose( rxModel, UNO_QUERY );
108  if (xClose.is())
109  {
110  try
111  {
114  xClose->close( true );
115  }
116  catch (const util::CloseVetoException&)
117  {
120  eResult = eVetoed;
121  }
122  catch (const uno::RuntimeException&)
123  {
124  eResult = eFailed;
125  }
126  }
127  return eResult;
128 }
129 
131 static bool LoadFromURL_impl(
133  SfxObjectShellRef &rxDocSh,
134  const OUString &rURL,
135  bool bClose )
136 {
137  // try to open the document readonly and hidden
138  Reference< frame::XModel > xTmpModel;
139  Sequence < PropertyValue > aArgs( 1 );
140  aArgs[0].Name = "Hidden";
141  aArgs[0].Value <<= true;
142  try
143  {
144  Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
145  xTmpModel.set( xDesktop->loadComponentFromURL( rURL, "_blank", 0, aArgs ), UNO_QUERY );
146  }
147  catch (const Exception&)
148  {
149  return false;
150  }
151 
152  // try to get the DocShell
153  SwDocShell *pTmpDocShell = nullptr;
154  Reference < XUnoTunnel > xTunnel( xTmpModel, UNO_QUERY );
155  if (xTunnel.is())
156  {
157  SwXTextDocument* pTextDoc = reinterpret_cast<SwXTextDocument *>(
158  xTunnel->getSomething( SwXTextDocument::getUnoTunnelId() ));
159  pTmpDocShell = pTextDoc ? pTextDoc->GetDocShell() : nullptr;
160  }
161 
162  bool bRes = false;
163  if (xTmpModel.is() && pTmpDocShell) // everything available?
164  {
165  if (bClose)
166  CloseModelAndDocSh( rxModel, rxDocSh );
167  // set new stuff
168  rxModel = xTmpModel;
169  rxDocSh = pTmpDocShell;
170  bRes = true;
171  }
172  else
173  {
174  // SfxObjectShellRef is ok here, since the document will be explicitly closed
175  SfxObjectShellRef xTmpDocSh = pTmpDocShell;
176  CloseModelAndDocSh( xTmpModel, xTmpDocSh );
177  }
178 
179  return bRes;
180 }
181 
182 namespace
183 {
184  class DelayedFileDeletion : public ::cppu::WeakImplHelper<util::XCloseListener>
185  {
186  protected:
187  ::osl::Mutex m_aMutex;
188  Reference< util::XCloseable > m_xDocument;
189  Timer m_aDeleteTimer;
190  OUString const m_sTemporaryFile;
191  sal_Int32 m_nPendingDeleteAttempts;
192 
193  DelayedFileDeletion(DelayedFileDeletion const&) = delete;
194  DelayedFileDeletion& operator=(DelayedFileDeletion const&) = delete;
195 
196  public:
197  DelayedFileDeletion( const Reference< XModel >& _rxModel,
198  const OUString& _rTemporaryFile );
199 
200  protected:
201  virtual ~DelayedFileDeletion( ) override;
202 
203  // XCloseListener
204  virtual void SAL_CALL queryClosing( const EventObject& _rSource, sal_Bool _bGetsOwnership ) override;
205  virtual void SAL_CALL notifyClosing( const EventObject& _rSource ) override;
206 
207  // XEventListener
208  virtual void SAL_CALL disposing( const EventObject& Source ) override;
209 
210  private:
211  void implTakeOwnership( );
212  DECL_LINK( OnTryDeleteFile, Timer*, void );
213  };
214 
215  DelayedFileDeletion::DelayedFileDeletion( const Reference< XModel >& _rxModel, const OUString& _rTemporaryFile )
216  :
217  m_xDocument( _rxModel, UNO_QUERY )
218  ,m_sTemporaryFile( _rTemporaryFile )
219  ,m_nPendingDeleteAttempts( 0 )
220  {
221  osl_atomic_increment( &m_refCount );
222  try
223  {
224  if ( m_xDocument.is() )
225  {
226  m_xDocument->addCloseListener( this );
227  // successfully added -> keep ourself alive
228  acquire();
229  }
230  else {
231  OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: model is no component!" );
232  }
233  }
234  catch (const Exception&)
235  {
236  OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: could not register as event listener at the model!" );
237  }
238  osl_atomic_decrement( &m_refCount );
239  }
240 
241  IMPL_LINK_NOARG(DelayedFileDeletion, OnTryDeleteFile, Timer *, void)
242  {
243  ::osl::ClearableMutexGuard aGuard( m_aMutex );
244 
245  bool bSuccess = false;
246  try
247  {
248  bool bDeliverOwnership = ( 0 == m_nPendingDeleteAttempts );
249  // if this is our last attempt, then anybody which vetoes this has to take the consequences
250  // (means take the ownership)
251  m_xDocument->close( bDeliverOwnership );
252  bSuccess = true;
253  }
254  catch (const util::CloseVetoException&)
255  {
256  // somebody vetoed -> next try
257  if ( m_nPendingDeleteAttempts )
258  {
259  // next attempt
260  --m_nPendingDeleteAttempts;
261  m_aDeleteTimer.Start();
262  }
263  else
264  bSuccess = true; // can't do anything here ...
265  }
266  catch (const Exception&)
267  {
268  OSL_FAIL("DelayedFileDeletion::OnTryDeleteFile: caught a strange exception!" );
269  bSuccess = true;
270  // can't do anything here ...
271  }
272 
273  if ( bSuccess )
274  {
275  SWUnoHelper::UCB_DeleteFile( m_sTemporaryFile );
276  aGuard.clear();
277  release(); // this should be our last reference, we should be dead after this
278  }
279  }
280 
281  void DelayedFileDeletion::implTakeOwnership( )
282  {
283  // revoke ourself as listener
284  try
285  {
286  m_xDocument->removeCloseListener( this );
287  }
288  catch (const Exception&)
289  {
290  OSL_FAIL("DelayedFileDeletion::implTakeOwnership: could not revoke the listener!" );
291  }
292 
293  m_aDeleteTimer.SetTimeout( 3000 ); // 3 seconds
294  m_aDeleteTimer.SetInvokeHandler( LINK( this, DelayedFileDeletion, OnTryDeleteFile ) );
295  m_nPendingDeleteAttempts = 3; // try 3 times at most
296  m_aDeleteTimer.Start( );
297  }
298 
299  void SAL_CALL DelayedFileDeletion::queryClosing( const EventObject& , sal_Bool _bGetsOwnership )
300  {
301  ::osl::MutexGuard aGuard( m_aMutex );
302  if ( _bGetsOwnership )
303  implTakeOwnership( );
304 
305  // always veto: We want to take the ownership ourself, as this is the only chance to delete
306  // the temporary file which the model is based on
307  throw util::CloseVetoException( );
308  }
309 
310  void SAL_CALL DelayedFileDeletion::notifyClosing( const EventObject& )
311  {
312  OSL_FAIL("DelayedFileDeletion::notifyClosing: how this?" );
313  // this should not happen:
314  // Either, a foreign instance closes the document, then we should veto this, and take the ownership
315  // Or, we ourself close the document, then we should not be a listener anymore
316  }
317 
318  void SAL_CALL DelayedFileDeletion::disposing( const EventObject& )
319  {
320  OSL_FAIL("DelayedFileDeletion::disposing: how this?" );
321  // this should not happen:
322  // Either, a foreign instance closes the document, then we should veto this, and take the ownership
323  // Or, we ourself close the document, then we should not be a listener anymore
324  }
325 
326  DelayedFileDeletion::~DelayedFileDeletion( )
327  {
328  }
329 }
330 
331 static bool DeleteTmpFile_Impl(
333  SfxObjectShellRef &rxDocSh,
334  const OUString &rTmpFileURL )
335 {
336  bool bRes = false;
337  if (!rTmpFileURL.isEmpty())
338  {
339  bool bDelete = true;
340  if ( eVetoed == CloseModelAndDocSh( rxModel, rxDocSh ) )
341  {
342  // somebody vetoed the closing, and took the ownership of the document
343  // -> ensure that the temporary file is deleted later on
344  Reference< XEventListener > xEnsureDelete( new DelayedFileDeletion( rxModel, rTmpFileURL ) );
345  // note: as soon as #106931# is fixed, the whole DelayedFileDeletion is to be superseded by
346  // a better solution
347  bDelete = false;
348  }
349 
350  rxModel = nullptr;
351  rxDocSh = nullptr; // destroy doc shell
352 
353  if ( bDelete )
354  {
355  if ( !SWUnoHelper::UCB_DeleteFile( rTmpFileURL ) )
356  {
357  Reference< XEventListener > xEnsureDelete( new DelayedFileDeletion( rxModel, rTmpFileURL ) );
358  // same not as above: as soon as #106931#, ...
359  }
360  }
361  else
362  bRes = true; // file will be deleted delayed
363  }
364  return bRes;
365 }
366 
368  m_aEvtListeners ( GetMailMergeMutex() ),
369  m_aMergeListeners ( GetMailMergeMutex() ),
370  m_aPropListeners ( GetMailMergeMutex() ),
371  m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_MAILMERGE ) ),
372  m_nDataCommandType(sdb::CommandType::TABLE),
373  m_nOutputType(MailMergeType::PRINTER),
374  m_bEscapeProcessing(true),
375  m_bSinglePrintJobs(false),
376  m_bFileNameFromColumn(false),
377  m_bSendAsHTML(false),
378  m_bSendAsAttachment(false),
379  m_bSaveAsSingleFile(false),
380  m_bDisposing(false),
381  m_pMgr(nullptr)
382 {
383  // create empty document
384  // like in: SwModule::InsertEnv (appenv.cxx)
385  m_xDocSh = new SwDocShell( SfxObjectCreateMode::STANDARD );
386  m_xDocSh->DoInitNew();
388  SwView *pView = static_cast<SwView*>( pFrame->GetViewShell() );
389  pView->AttrChangedNotify( &pView->GetWrtShell() ); //So that SelectShell is called.
391 }
392 
394 {
395  if (!m_aTmpFileName.isEmpty())
397  else // there was no temporary file in use
398  {
403  OSL_FAIL("ownership transferred to vetoing object!" );
404 
405  m_xModel = nullptr;
406  m_xDocSh = nullptr; // destroy doc shell
407  }
408 }
409 
410 // Guarantee object consistence in case of an exception
412 {
413 public:
415  : m_pMailMerge(mailmerge)
416  {
417  assert(m_pMailMerge); //mailmerge object missing
418  }
420  {
421  osl::MutexGuard aMgrGuard( GetMailMergeMutex() );
422  m_pMailMerge->m_pMgr = nullptr;
423  }
424 
425 private:
428 
430 };
431 
433  const uno::Sequence< beans::NamedValue >& rArguments )
434 {
435  SolarMutexGuard aGuard;
436  MailMergeExecuteFinalizer aFinalizer(this);
437 
438  // get property values to be used
439  // (use values from the service as default and override them with
440  // the values that are provided as arguments)
441 
442  uno::Sequence< uno::Any > aCurSelection = m_aSelection;
443  uno::Reference< sdbc::XResultSet > xCurResultSet = m_xResultSet;
444  uno::Reference< sdbc::XConnection > xCurConnection = m_xConnection;
445  uno::Reference< frame::XModel > xCurModel = m_xModel;
446  OUString aCurDataSourceName = m_aDataSourceName;
447  OUString aCurDataCommand = m_aDataCommand;
448  OUString aCurFilter = m_aFilter;
449  OUString aCurDocumentURL = m_aDocumentURL;
450  OUString aCurOutputURL = m_aOutputURL;
451  OUString aCurFileNamePrefix = m_aFileNamePrefix;
452  sal_Int32 nCurDataCommandType = m_nDataCommandType;
453  sal_Int16 nCurOutputType = m_nOutputType;
454  bool bCurEscapeProcessing = m_bEscapeProcessing;
455  bool bCurSinglePrintJobs = m_bSinglePrintJobs;
456  bool bCurFileNameFromColumn = m_bFileNameFromColumn;
457 
458  SfxObjectShellRef xCurDocSh = m_xDocSh; // the document
459 
460  const beans::NamedValue *pArguments = rArguments.getConstArray();
461  sal_Int32 nArgs = rArguments.getLength();
462  for (sal_Int32 i = 0; i < nArgs; ++i)
463  {
464  const OUString &rName = pArguments[i].Name;
465  const Any &rValue = pArguments[i].Value;
466 
467  bool bOK = true;
468  if (rName == UNO_NAME_SELECTION)
469  bOK = rValue >>= aCurSelection;
470  else if (rName == UNO_NAME_RESULT_SET)
471  bOK = rValue >>= xCurResultSet;
472  else if (rName == UNO_NAME_CONNECTION)
473  bOK = rValue >>= xCurConnection;
474  else if (rName == UNO_NAME_MODEL)
475  throw PropertyVetoException("Property is read-only: " + rName, static_cast < cppu::OWeakObject * > ( this ) );
476  else if (rName == UNO_NAME_DATA_SOURCE_NAME)
477  bOK = rValue >>= aCurDataSourceName;
478  else if (rName == UNO_NAME_DAD_COMMAND)
479  bOK = rValue >>= aCurDataCommand;
480  else if (rName == UNO_NAME_FILTER)
481  bOK = rValue >>= aCurFilter;
482  else if (rName == UNO_NAME_DOCUMENT_URL)
483  {
484  bOK = rValue >>= aCurDocumentURL;
485  if (!aCurDocumentURL.isEmpty()
486  && !LoadFromURL_impl( xCurModel, xCurDocSh, aCurDocumentURL, false ))
487  throw RuntimeException("Failed to create document from URL: " + aCurDocumentURL, static_cast < cppu::OWeakObject * > ( this ) );
488  }
489  else if (rName == UNO_NAME_OUTPUT_URL)
490  {
491  bOK = rValue >>= aCurOutputURL;
492  if (!aCurOutputURL.isEmpty())
493  {
494  if (!UCB_IsDirectory(aCurOutputURL))
495  throw IllegalArgumentException("URL does not point to a directory: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 0 );
496  if (UCB_IsReadOnlyFileName(aCurOutputURL))
497  throw IllegalArgumentException("URL is read-only: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 0 );
498  }
499  }
500  else if (rName == UNO_NAME_FILE_NAME_PREFIX)
501  bOK = rValue >>= aCurFileNamePrefix;
502  else if (rName == UNO_NAME_DAD_COMMAND_TYPE)
503  bOK = rValue >>= nCurDataCommandType;
504  else if (rName == UNO_NAME_OUTPUT_TYPE)
505  bOK = rValue >>= nCurOutputType;
506  else if (rName == UNO_NAME_ESCAPE_PROCESSING)
507  bOK = rValue >>= bCurEscapeProcessing;
508  else if (rName == UNO_NAME_SINGLE_PRINT_JOBS)
509  bOK = rValue >>= bCurSinglePrintJobs;
510  else if (rName == UNO_NAME_FILE_NAME_FROM_COLUMN)
511  bOK = rValue >>= bCurFileNameFromColumn;
512  else if (rName == UNO_NAME_SUBJECT)
513  bOK = rValue >>= m_sSubject;
514  else if (rName == UNO_NAME_ADDRESS_FROM_COLUMN)
515  bOK = rValue >>= m_sAddressFromColumn;
516  else if (rName == UNO_NAME_SEND_AS_HTML)
517  bOK = rValue >>= m_bSendAsHTML;
518  else if (rName == UNO_NAME_MAIL_BODY)
519  bOK = rValue >>= m_sMailBody;
520  else if (rName == UNO_NAME_ATTACHMENT_NAME)
521  bOK = rValue >>= m_sAttachmentName;
522  else if (rName == UNO_NAME_ATTACHMENT_FILTER)
523  bOK = rValue >>= m_sAttachmentFilter;
524  else if (rName == UNO_NAME_COPIES_TO)
525  bOK = rValue >>= m_aCopiesTo;
526  else if (rName == UNO_NAME_BLIND_COPIES_TO)
527  bOK = rValue >>= m_aBlindCopiesTo;
528  else if (rName == UNO_NAME_SEND_AS_ATTACHMENT)
529  bOK = rValue >>= m_bSendAsAttachment;
530  else if (rName == UNO_NAME_PRINT_OPTIONS)
531  bOK = rValue >>= m_aPrintSettings;
532  else if (rName == UNO_NAME_SAVE_AS_SINGLE_FILE)
533  bOK = rValue >>= m_bSaveAsSingleFile;
534  else if (rName == UNO_NAME_SAVE_FILTER)
535  bOK = rValue >>= m_sSaveFilter;
536  else if (rName == UNO_NAME_SAVE_FILTER_OPTIONS)
537  bOK = rValue >>= m_sSaveFilterOptions;
538  else if (rName == UNO_NAME_SAVE_FILTER_DATA)
539  bOK = rValue >>= m_aSaveFilterData;
540  else if (rName == UNO_NAME_IN_SERVER_PASSWORD)
541  bOK = rValue >>= m_sInServerPassword;
542  else if (rName == UNO_NAME_OUT_SERVER_PASSWORD)
543  bOK = rValue >>= m_sOutServerPassword;
544  else
545  throw UnknownPropertyException( "Property is unknown: " + rName, static_cast < cppu::OWeakObject * > ( this ) );
546 
547  if (!bOK)
548  throw IllegalArgumentException("Property type mismatch or property not set: " + rName, static_cast < cppu::OWeakObject * > ( this ), 0 );
549  }
550 
551  // need to translate the selection: the API here requires a sequence of bookmarks, but the Merge
552  // method we will call below requires a sequence of indices.
553  if ( aCurSelection.hasElements() )
554  {
555  Sequence< Any > aTranslated( aCurSelection.getLength() );
556 
557  bool bValid = false;
558  Reference< sdbcx::XRowLocate > xRowLocate( xCurResultSet, UNO_QUERY );
559  if ( xRowLocate.is() )
560  {
561 
562  const Any* pBookmarks = aCurSelection.getConstArray();
563  const Any* pBookmarksEnd = pBookmarks + aCurSelection.getLength();
564  Any* pTranslated = aTranslated.getArray();
565 
566  try
567  {
568  bool bEverythingsFine = true;
569  for ( ; ( pBookmarks != pBookmarksEnd ) && bEverythingsFine; ++pBookmarks )
570  {
571  if ( xRowLocate->moveToBookmark( *pBookmarks ) )
572  *pTranslated <<= xCurResultSet->getRow();
573  else
574  bEverythingsFine = false;
575  ++pTranslated;
576  }
577  if ( bEverythingsFine )
578  bValid = true;
579  }
580  catch (const Exception&)
581  {
582  bValid = false;
583  }
584  }
585 
586  if ( !bValid )
587  {
588  throw IllegalArgumentException(
589  "The current 'Selection' does not describe a valid array of bookmarks, relative to the current 'ResultSet'.",
590  static_cast < cppu::OWeakObject * > ( this ),
591  0
592  );
593  }
594 
595  aCurSelection = aTranslated;
596  }
597 
598  SfxViewFrame* pFrame = SfxViewFrame::GetFirst( xCurDocSh.get(), false);
599  SwView *pView = pFrame ? dynamic_cast<SwView*>( pFrame->GetViewShell() ) : nullptr;
600  if (!pView)
601  throw RuntimeException();
602  SwWrtShell &rSh = *pView->GetWrtShellPtr();
603 
604  // avoid assertion in 'Update' from Sfx by supplying a shell
605  // and thus avoiding the SelectShell call in Writers GetState function
606  // while still in Update of Sfx.
607  // (GetSelection in Update is not allowed)
608  if (!aCurDocumentURL.isEmpty())
609  pView->AttrChangedNotify( &pView->GetWrtShell() );//So that SelectShell is called.
610 
611  SharedComponent aRowSetDisposeHelper;
612  if (!xCurResultSet.is())
613  {
614  if (aCurDataSourceName.isEmpty() || aCurDataCommand.isEmpty() )
615  {
616  OSL_FAIL("PropertyValues missing or unset");
617  throw IllegalArgumentException("Either the ResultSet or DataSourceName and DataCommand must be set.", static_cast < cppu::OWeakObject * > ( this ), 0 );
618  }
619 
620  // build ResultSet from DataSourceName, DataCommand and DataCommandType
621 
623  if (xMgr.is())
624  {
625  Reference< XInterface > xInstance = xMgr->createInstance( "com.sun.star.sdb.RowSet" );
626  aRowSetDisposeHelper.reset( xInstance, SharedComponent::TakeOwnership );
627  Reference< XPropertySet > xRowSetPropSet( xInstance, UNO_QUERY );
628  OSL_ENSURE( xRowSetPropSet.is(), "failed to get XPropertySet interface from RowSet" );
629  if (xRowSetPropSet.is())
630  {
631  if (xCurConnection.is())
632  xRowSetPropSet->setPropertyValue( "ActiveConnection", makeAny( xCurConnection ) );
633  xRowSetPropSet->setPropertyValue( "DataSourceName", makeAny( aCurDataSourceName ) );
634  xRowSetPropSet->setPropertyValue( "Command", makeAny( aCurDataCommand ) );
635  xRowSetPropSet->setPropertyValue( "CommandType", makeAny( nCurDataCommandType ) );
636  xRowSetPropSet->setPropertyValue( "EscapeProcessing", makeAny( bCurEscapeProcessing ) );
637  xRowSetPropSet->setPropertyValue( "ApplyFilter", makeAny( true ) );
638  xRowSetPropSet->setPropertyValue( "Filter", makeAny( aCurFilter ) );
639 
640  Reference< sdbc::XRowSet > xRowSet( xInstance, UNO_QUERY );
641  if (xRowSet.is())
642  xRowSet->execute(); // build ResultSet from properties
643  if( !xCurConnection.is() )
644  xCurConnection.set( xRowSetPropSet->getPropertyValue( "ActiveConnection" ), UNO_QUERY );
645  xCurResultSet.set( xRowSet, UNO_QUERY );
646  OSL_ENSURE( xCurResultSet.is(), "failed to build ResultSet" );
647  }
648  }
649  }
650 
651  svx::ODataAccessDescriptor aDescriptor;
652  aDescriptor.setDataSource(aCurDataSourceName);
653  aDescriptor[ svx::DataAccessDescriptorProperty::Connection ] <<= xCurConnection;
654  aDescriptor[ svx::DataAccessDescriptorProperty::Command ] <<= aCurDataCommand;
655  aDescriptor[ svx::DataAccessDescriptorProperty::CommandType ] <<= nCurDataCommandType;
656  aDescriptor[ svx::DataAccessDescriptorProperty::EscapeProcessing ] <<= bCurEscapeProcessing;
657  aDescriptor[ svx::DataAccessDescriptorProperty::Cursor ] <<= xCurResultSet;
658  // aDescriptor[ svx::DataAccessDescriptorProperty::ColumnName ] not used
659  // aDescriptor[ svx::DataAccessDescriptorProperty::ColumnObject ] not used
660  aDescriptor[ svx::DataAccessDescriptorProperty::Selection ] <<= aCurSelection;
661 
662  DBManagerOptions nMergeType;
663  switch (nCurOutputType)
664  {
665  case MailMergeType::PRINTER : nMergeType = DBMGR_MERGE_PRINTER; break;
666  case MailMergeType::FILE : nMergeType = DBMGR_MERGE_FILE; break;
667  case MailMergeType::MAIL : nMergeType = DBMGR_MERGE_EMAIL; break;
668  case MailMergeType::SHELL : nMergeType = DBMGR_MERGE_SHELL; break;
669  default:
670  throw IllegalArgumentException("Invalid value of property: OutputType", static_cast < cppu::OWeakObject * > ( this ), 0 );
671  }
672 
673  SwDBManager* pMgr = rSh.GetDBManager();
674  //force layout creation
675  rSh.CalcLayout();
676  OSL_ENSURE( pMgr, "database manager missing" );
677  m_pMgr = pMgr;
678 
679  SwMergeDescriptor aMergeDesc( nMergeType, rSh, aDescriptor );
680 
681  std::unique_ptr< SwMailMergeConfigItem > pMMConfigItem;
682  uno::Reference< mail::XMailService > xInService;
683  switch (nCurOutputType)
684  {
685  case MailMergeType::PRINTER:
686  {
688  SwPrintData aPrtData( rIDDA.getPrintData() );
689  aPrtData.SetPrintSingleJobs( bCurSinglePrintJobs );
690  rIDDA.setPrintData( aPrtData );
691  // #i25686# printing should not be done asynchronously to prevent dangling offices
692  // when mail merge is called as command line macro
693  aMergeDesc.aPrintOptions = m_aPrintSettings;
694  aMergeDesc.bCreateSingleFile = true;
695  }
696  break;
697  case MailMergeType::SHELL:
698  aMergeDesc.bCreateSingleFile = true;
699  pMMConfigItem.reset(new SwMailMergeConfigItem);
700  aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
701  break;
702  case MailMergeType::FILE:
703  {
704  INetURLObject aURLObj;
705  aURLObj.SetSmartProtocol( INetProtocol::File );
706 
707  if (!aCurDocumentURL.isEmpty())
708  {
709  // if OutputURL or FileNamePrefix are missing get
710  // them from DocumentURL
711  aURLObj.SetSmartURL( aCurDocumentURL );
712  if (aCurFileNamePrefix.isEmpty())
713  aCurFileNamePrefix = aURLObj.GetBase(); // filename without extension
714  if (aCurOutputURL.isEmpty())
715  {
716  aURLObj.removeSegment();
717  aCurOutputURL = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
718  }
719  }
720  else // default empty document without URL
721  {
722  if (aCurOutputURL.isEmpty())
723  throw RuntimeException("OutputURL is not set and can not be obtained.", static_cast < cppu::OWeakObject * > ( this ) );
724  }
725 
726  aURLObj.SetSmartURL( aCurOutputURL );
727  OUString aPath = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
728 
729  const OUString aDelim( "/" );
730  if (!aPath.isEmpty() && !aPath.endsWith(aDelim))
731  aPath += aDelim;
732  if (bCurFileNameFromColumn)
733  aMergeDesc.sDBcolumn = aCurFileNamePrefix;
734  else
735  {
736  aPath += aCurFileNamePrefix;
737  }
738 
739  aMergeDesc.sPrefix = aPath;
740  aMergeDesc.sSaveToFilter = m_sSaveFilter;
744  }
745  break;
746  case MailMergeType::MAIL:
747  {
748  aMergeDesc.sDBcolumn = m_sAddressFromColumn;
749  if(m_sAddressFromColumn.isEmpty())
750  throw RuntimeException("Mail address column not set.", static_cast < cppu::OWeakObject * > ( this ) );
751  aMergeDesc.sSaveToFilter = m_sAttachmentFilter;
752  aMergeDesc.sSubject = m_sSubject;
753  aMergeDesc.sMailBody = m_sMailBody;
754  aMergeDesc.sAttachmentName = m_sAttachmentName;
755  aMergeDesc.aCopiesTo = m_aCopiesTo;
756  aMergeDesc.aBlindCopiesTo = m_aBlindCopiesTo;
757  aMergeDesc.bSendAsHTML = m_bSendAsHTML;
759 
760  aMergeDesc.bCreateSingleFile = false;
761  pMMConfigItem.reset(new SwMailMergeConfigItem);
762  aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
764  *pMMConfigItem,
765  xInService,
767  if( !aMergeDesc.xSmtpServer.is() || !aMergeDesc.xSmtpServer->isConnected())
768  throw RuntimeException("Failed to connect to mail server.", static_cast < cppu::OWeakObject * > ( this ) );
769  }
770  break;
771  }
772 
773  // save document with temporary filename
774  std::shared_ptr<const SfxFilter> pSfxFlt = SwIoSystem::GetFilterOfFormat(
775  FILTER_XML,
776  SwDocShell::Factory().GetFilterContainer() );
777  OUString aExtension(comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(), '*'));
778  utl::TempFile aTempFile( "SwMM", true, &aExtension );
779  m_aTmpFileName = aTempFile.GetURL();
780 
781  Reference< XStorable > xStorable( xCurModel, UNO_QUERY );
782  bool bStoredAsTemporary = false;
783  if ( xStorable.is() )
784  {
785  try
786  {
787  xStorable->storeAsURL( m_aTmpFileName, Sequence< PropertyValue >() );
788  bStoredAsTemporary = true;
789  }
790  catch (const Exception&)
791  {
792  }
793  }
794  if ( !bStoredAsTemporary )
795  throw RuntimeException("Failed to save temporary file.", static_cast < cppu::OWeakObject * > ( this ) );
796 
797  pMgr->SetMergeSilent( true ); // suppress dialogs, message boxes, etc.
798  const SwXMailMerge *pOldSrc = pMgr->GetMailMergeEvtSrc();
799  OSL_ENSURE( !pOldSrc || pOldSrc == this, "Ooops... different event source already set." );
800  pMgr->SetMailMergeEvtSrc( this ); // launch events for listeners
801 
802  SfxGetpApp()->NotifyEvent(SfxEventHint(SfxEventHintId::SwMailMerge, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xCurDocSh.get()));
803  bool bSucc = pMgr->Merge( aMergeDesc );
804  SfxGetpApp()->NotifyEvent(SfxEventHint(SfxEventHintId::SwMailMergeEnd, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), xCurDocSh.get()));
805 
806  pMgr->SetMailMergeEvtSrc( pOldSrc );
807 
808  if ( xCurModel.get() != m_xModel.get() )
809  { // in case it was a temporary model -> close it, and delete the file
810  DeleteTmpFile_Impl( xCurModel, xCurDocSh, m_aTmpFileName );
811  m_aTmpFileName.clear();
812  }
813  // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest)
814 
815  if (!bSucc)
816  throw Exception("Mail merge failed. Sorry, no further information available.", static_cast < cppu::OWeakObject * > ( this ) );
817 
818  //de-initialize services
819  if(xInService.is() && xInService->isConnected())
820  xInService->disconnect();
821  if(aMergeDesc.xSmtpServer.is() && aMergeDesc.xSmtpServer->isConnected())
822  aMergeDesc.xSmtpServer->disconnect();
823 
824  if (DBMGR_MERGE_SHELL == nMergeType)
825  {
826  return makeAny( aMergeDesc.pMailMergeConfigItem->GetTargetView()->GetDocShell()->GetBaseModel() );
827  }
828  else
829  return makeAny( true );
830 }
831 
832 void SAL_CALL SwXMailMerge::cancel()
833 {
834  // Cancel may be called from a second thread, so this protects from m_pMgr
836  osl::MutexGuard aMgrGuard( GetMailMergeMutex() );
837  if (m_pMgr)
838  m_pMgr->MergeCancel();
839 }
840 
841 void SwXMailMerge::LaunchMailMergeEvent( const MailMergeEvent &rEvt ) const
842 {
843  comphelper::OInterfaceIteratorHelper2 aIt( const_cast<SwXMailMerge *>(this)->m_aMergeListeners );
844  while (aIt.hasMoreElements())
845  {
846  Reference< XMailMergeListener > xRef( aIt.next(), UNO_QUERY );
847  if (xRef.is())
848  xRef->notifyMailMergeEvent( rEvt );
849  }
850 }
851 
852 void SwXMailMerge::launchEvent( const PropertyChangeEvent &rEvt ) const
853 {
854  cppu::OInterfaceContainerHelper *pContainer =
855  m_aPropListeners.getContainer( rEvt.PropertyHandle );
856  if (pContainer)
857  {
858  cppu::OInterfaceIteratorHelper aIt( *pContainer );
859  while (aIt.hasMoreElements())
860  {
861  Reference< XPropertyChangeListener > xRef( aIt.next(), UNO_QUERY );
862  if (xRef.is())
863  xRef->propertyChange( rEvt );
864  }
865  }
866 }
867 
868 uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXMailMerge::getPropertySetInfo( )
869 {
870  SolarMutexGuard aGuard;
871  static Reference< XPropertySetInfo > aRef = m_pPropSet->getPropertySetInfo();
872  return aRef;
873 }
874 
876  const OUString& rPropertyName, const uno::Any& rValue )
877 {
878  SolarMutexGuard aGuard;
879 
880  const SfxItemPropertySimpleEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName );
881  if (!pCur)
882  throw UnknownPropertyException();
883  else if (pCur->nFlags & PropertyAttribute::READONLY)
884  throw PropertyVetoException();
885  else
886  {
887  void *pData = nullptr;
888  switch (pCur->nWID)
889  {
890  case WID_SELECTION : pData = &m_aSelection; break;
891  case WID_RESULT_SET : pData = &m_xResultSet; break;
892  case WID_CONNECTION : pData = &m_xConnection; break;
893  case WID_MODEL : pData = &m_xModel; break;
894  case WID_DATA_SOURCE_NAME : pData = &m_aDataSourceName; break;
895  case WID_DATA_COMMAND : pData = &m_aDataCommand; break;
896  case WID_FILTER : pData = &m_aFilter; break;
897  case WID_DOCUMENT_URL : pData = &m_aDocumentURL; break;
898  case WID_OUTPUT_URL : pData = &m_aOutputURL; break;
899  case WID_DATA_COMMAND_TYPE : pData = &m_nDataCommandType; break;
900  case WID_OUTPUT_TYPE : pData = &m_nOutputType; break;
901  case WID_ESCAPE_PROCESSING : pData = &m_bEscapeProcessing; break;
902  case WID_SINGLE_PRINT_JOBS : pData = &m_bSinglePrintJobs; break;
903  case WID_FILE_NAME_FROM_COLUMN : pData = &m_bFileNameFromColumn; break;
904  case WID_FILE_NAME_PREFIX : pData = &m_aFileNamePrefix; break;
905  case WID_MAIL_SUBJECT: pData = &m_sSubject; break;
906  case WID_ADDRESS_FROM_COLUMN: pData = &m_sAddressFromColumn; break;
907  case WID_SEND_AS_HTML: pData = &m_bSendAsHTML; break;
908  case WID_SEND_AS_ATTACHMENT: pData = &m_bSendAsAttachment; break;
909  case WID_MAIL_BODY: pData = &m_sMailBody; break;
910  case WID_ATTACHMENT_NAME: pData = &m_sAttachmentName; break;
911  case WID_ATTACHMENT_FILTER: pData = &m_sAttachmentFilter;break;
912  case WID_PRINT_OPTIONS: pData = &m_aPrintSettings; break;
913  case WID_SAVE_AS_SINGLE_FILE: pData = &m_bSaveAsSingleFile; break;
914  case WID_SAVE_FILTER: pData = &m_sSaveFilter; break;
915  case WID_SAVE_FILTER_OPTIONS: pData = &m_sSaveFilterOptions; break;
916  case WID_SAVE_FILTER_DATA: pData = &m_aSaveFilterData; break;
917  case WID_COPIES_TO: pData = &m_aCopiesTo; break;
918  case WID_BLIND_COPIES_TO: pData = &m_aBlindCopiesTo;break;
919  case WID_IN_SERVER_PASSWORD: pData = &m_sInServerPassword; break;
920  case WID_OUT_SERVER_PASSWORD: pData = &m_sOutServerPassword; break;
921  default :
922  OSL_FAIL("unknown WID");
923  }
924  Any aOld( pData, pCur->aType );
925 
926  bool bChanged = false;
927  bool bOK = true;
928  if (aOld != rValue)
929  {
930  if (pData == &m_aSelection)
931  bOK = rValue >>= m_aSelection;
932  else if (pData == &m_xResultSet)
933  bOK = rValue >>= m_xResultSet;
934  else if (pData == &m_xConnection)
935  bOK = rValue >>= m_xConnection;
936  else if (pData == &m_xModel)
937  bOK = rValue >>= m_xModel;
938  else if (pData == &m_aDataSourceName)
939  bOK = rValue >>= m_aDataSourceName;
940  else if (pData == &m_aDataCommand)
941  bOK = rValue >>= m_aDataCommand;
942  else if (pData == &m_aFilter)
943  bOK = rValue >>= m_aFilter;
944  else if (pData == &m_aDocumentURL)
945  {
946  OUString aText;
947  bOK = rValue >>= aText;
948  if (!aText.isEmpty()
949  && !LoadFromURL_impl( m_xModel, m_xDocSh, aText, true ))
950  throw RuntimeException("Failed to create document from URL: " + aText, static_cast < cppu::OWeakObject * > ( this ) );
951  m_aDocumentURL = aText;
952  }
953  else if (pData == &m_aOutputURL)
954  {
955  OUString aText;
956  bOK = rValue >>= aText;
957  if (!aText.isEmpty())
958  {
959  if (!UCB_IsDirectory(aText))
960  throw IllegalArgumentException("URL does not point to a directory: " + aText, static_cast < cppu::OWeakObject * > ( this ), 0 );
961  if (UCB_IsReadOnlyFileName(aText))
962  throw IllegalArgumentException("URL is read-only: " + aText, static_cast < cppu::OWeakObject * > ( this ), 0 );
963  }
964  m_aOutputURL = aText;
965  }
966  else if (pData == &m_nDataCommandType)
967  bOK = rValue >>= m_nDataCommandType;
968  else if (pData == &m_nOutputType)
969  bOK = rValue >>= m_nOutputType;
970  else if (pData == &m_bEscapeProcessing)
971  bOK = rValue >>= m_bEscapeProcessing;
972  else if (pData == &m_bSinglePrintJobs)
973  bOK = rValue >>= m_bSinglePrintJobs;
974  else if (pData == &m_bFileNameFromColumn)
975  bOK = rValue >>= m_bFileNameFromColumn;
976  else if (pData == &m_aFileNamePrefix)
977  bOK = rValue >>= m_aFileNamePrefix;
978  else if (pData == &m_sSubject)
979  bOK = rValue >>= m_sSubject;
980  else if (pData == &m_sAddressFromColumn)
981  bOK = rValue >>= m_sAddressFromColumn;
982  else if (pData == &m_bSendAsHTML)
983  bOK = rValue >>= m_bSendAsHTML;
984  else if (pData == &m_bSendAsAttachment)
985  bOK = rValue >>= m_bSendAsAttachment;
986  else if (pData == &m_sMailBody)
987  bOK = rValue >>= m_sMailBody;
988  else if (pData == &m_sAttachmentName)
989  bOK = rValue >>= m_sAttachmentName;
990  else if (pData == &m_sAttachmentFilter)
991  bOK = rValue >>= m_sAttachmentFilter;
992  else if (pData == &m_aPrintSettings)
993  bOK = rValue >>= m_aPrintSettings;
994  else if (pData == &m_bSaveAsSingleFile)
995  bOK = rValue >>= m_bSaveAsSingleFile;
996  else if (pData == &m_sSaveFilter)
997  bOK = rValue >>= m_sSaveFilter;
998  else if (pData == &m_sSaveFilterOptions)
999  bOK = rValue >>= m_sSaveFilterOptions;
1000  else if (pData == &m_aSaveFilterData)
1001  bOK = rValue >>= m_aSaveFilterData;
1002  else if (pData == &m_aCopiesTo)
1003  bOK = rValue >>= m_aCopiesTo;
1004  else if (pData == &m_aBlindCopiesTo)
1005  bOK = rValue >>= m_aBlindCopiesTo;
1006  else if(pData == &m_sInServerPassword)
1007  bOK = rValue >>= m_sInServerPassword;
1008  else if(pData == &m_sOutServerPassword)
1009  bOK = rValue >>= m_sOutServerPassword;
1010  else {
1011  OSL_FAIL("invalid pointer" );
1012  }
1013  OSL_ENSURE( bOK, "set value failed" );
1014  bChanged = true;
1015  }
1016  if (!bOK)
1017  throw IllegalArgumentException("Property type mismatch or property not set: " + rPropertyName, static_cast < cppu::OWeakObject * > ( this ), 0 );
1018 
1019  if (bChanged)
1020  {
1021  PropertyChangeEvent aChgEvt( static_cast<XPropertySet *>(this), rPropertyName,
1022  false, pCur->nWID, aOld, rValue );
1023  launchEvent( aChgEvt );
1024  }
1025  }
1026 }
1027 
1029  const OUString& rPropertyName )
1030 {
1031  SolarMutexGuard aGuard;
1032 
1033  Any aRet;
1034 
1035  const SfxItemPropertySimpleEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1036  if (!pCur)
1037  throw UnknownPropertyException();
1038 
1039  switch (pCur->nWID)
1040  {
1041  case WID_SELECTION : aRet <<= m_aSelection; break;
1042  case WID_RESULT_SET : aRet <<= m_xResultSet; break;
1043  case WID_CONNECTION : aRet <<= m_xConnection; break;
1044  case WID_MODEL : aRet <<= m_xModel; break;
1045  case WID_DATA_SOURCE_NAME : aRet <<= m_aDataSourceName; break;
1046  case WID_DATA_COMMAND : aRet <<= m_aDataCommand; break;
1047  case WID_FILTER : aRet <<= m_aFilter; break;
1048  case WID_DOCUMENT_URL : aRet <<= m_aDocumentURL; break;
1049  case WID_OUTPUT_URL : aRet <<= m_aOutputURL; break;
1050  case WID_DATA_COMMAND_TYPE : aRet <<= m_nDataCommandType; break;
1051  case WID_OUTPUT_TYPE : aRet <<= m_nOutputType; break;
1052  case WID_ESCAPE_PROCESSING : aRet <<= m_bEscapeProcessing; break;
1053  case WID_SINGLE_PRINT_JOBS : aRet <<= m_bSinglePrintJobs; break;
1054  case WID_FILE_NAME_FROM_COLUMN : aRet <<= m_bFileNameFromColumn; break;
1055  case WID_FILE_NAME_PREFIX : aRet <<= m_aFileNamePrefix; break;
1056  case WID_MAIL_SUBJECT: aRet <<= m_sSubject; break;
1057  case WID_ADDRESS_FROM_COLUMN: aRet <<= m_sAddressFromColumn; break;
1058  case WID_SEND_AS_HTML: aRet <<= m_bSendAsHTML; break;
1059  case WID_SEND_AS_ATTACHMENT: aRet <<= m_bSendAsAttachment; break;
1060  case WID_MAIL_BODY: aRet <<= m_sMailBody; break;
1061  case WID_ATTACHMENT_NAME: aRet <<= m_sAttachmentName; break;
1062  case WID_ATTACHMENT_FILTER: aRet <<= m_sAttachmentFilter;break;
1063  case WID_PRINT_OPTIONS: aRet <<= m_aPrintSettings; break;
1064  case WID_SAVE_AS_SINGLE_FILE: aRet <<= m_bSaveAsSingleFile; break;
1065  case WID_SAVE_FILTER: aRet <<= m_sSaveFilter; break;
1066  case WID_SAVE_FILTER_OPTIONS: aRet <<= m_sSaveFilterOptions; break;
1067  case WID_SAVE_FILTER_DATA: aRet <<= m_aSaveFilterData; break;
1068  case WID_COPIES_TO: aRet <<= m_aCopiesTo; break;
1069  case WID_BLIND_COPIES_TO: aRet <<= m_aBlindCopiesTo;break;
1070  case WID_IN_SERVER_PASSWORD: aRet <<= m_sInServerPassword; break;
1071  case WID_OUT_SERVER_PASSWORD: aRet <<= m_sOutServerPassword; break;
1072  default :
1073  OSL_FAIL("unknown WID");
1074  }
1075 
1076  return aRet;
1077 }
1078 
1080  const OUString& rPropertyName,
1081  const uno::Reference< beans::XPropertyChangeListener >& rListener )
1082 {
1083  SolarMutexGuard aGuard;
1084  if (!m_bDisposing && rListener.is())
1085  {
1086  const SfxItemPropertySimpleEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1087  if (!pCur)
1088  throw UnknownPropertyException();
1089  m_aPropListeners.addInterface( pCur->nWID, rListener );
1090  }
1091 }
1092 
1094  const OUString& rPropertyName,
1095  const uno::Reference< beans::XPropertyChangeListener >& rListener )
1096 {
1097  SolarMutexGuard aGuard;
1098  if (!m_bDisposing && rListener.is())
1099  {
1100  const SfxItemPropertySimpleEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName );
1101  if (!pCur)
1102  throw UnknownPropertyException();
1103  m_aPropListeners.removeInterface( pCur->nWID, rListener );
1104  }
1105 }
1106 
1108  const OUString& /*rPropertyName*/,
1109  const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ )
1110 {
1111  // no vetoable property, thus no support for vetoable change listeners
1112  OSL_FAIL("not implemented");
1113 }
1114 
1116  const OUString& /*rPropertyName*/,
1117  const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ )
1118 {
1119  // no vetoable property, thus no support for vetoable change listeners
1120  OSL_FAIL("not implemented");
1121 }
1122 
1123 void SAL_CALL SwXMailMerge::dispose()
1124 {
1125  SolarMutexGuard aGuard;
1126 
1127  if (!m_bDisposing)
1128  {
1129  m_bDisposing = true;
1130 
1131  EventObject aEvtObj( static_cast<XPropertySet *>(this) );
1132  m_aEvtListeners.disposeAndClear( aEvtObj );
1134  m_aPropListeners.disposeAndClear( aEvtObj );
1135  }
1136 }
1137 
1139  const Reference< XEventListener >& rxListener )
1140 {
1141  SolarMutexGuard aGuard;
1142  if (!m_bDisposing && rxListener.is())
1143  m_aEvtListeners.addInterface( rxListener );
1144 }
1145 
1147  const Reference< XEventListener >& rxListener )
1148 {
1149  SolarMutexGuard aGuard;
1150  if (!m_bDisposing && rxListener.is())
1151  m_aEvtListeners.removeInterface( rxListener );
1152 }
1153 
1155  const uno::Reference< XMailMergeListener >& rxListener )
1156 {
1157  SolarMutexGuard aGuard;
1158  if (!m_bDisposing && rxListener.is())
1159  m_aMergeListeners.addInterface( rxListener );
1160 }
1161 
1163  const uno::Reference< XMailMergeListener >& rxListener )
1164 {
1165  SolarMutexGuard aGuard;
1166  if (!m_bDisposing && rxListener.is())
1167  m_aMergeListeners.removeInterface( rxListener );
1168 }
1169 
1171 {
1172  return OUString( "SwXMailMerge" );
1173 }
1174 
1175 sal_Bool SAL_CALL SwXMailMerge::supportsService( const OUString& rServiceName )
1176 {
1177  return cppu::supportsService(this, rServiceName);
1178 }
1179 
1180 uno::Sequence< OUString > SAL_CALL SwXMailMerge::getSupportedServiceNames()
1181 {
1182  uno::Sequence< OUString > aNames(2);
1183  OUString *pName = aNames.getArray();
1184  pName[0] = "com.sun.star.text.MailMerge";
1185  pName[1] = "com.sun.star.sdb.DataAccessDescriptor";
1186  return aNames;
1187 }
1188 
1189 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString m_aDocumentURL
virtual void SAL_CALL removeMailMergeEventListener(const css::uno::Reference< css::text::XMailMergeListener > &xListener) override
bool bCreateSingleFile
Create a single or multiple results.
Definition: dbmgr.hxx:149
::osl::Mutex m_aMutex
const SwXMailMerge * GetMailMergeEvtSrc() const
MailMergeEvent source.
Definition: dbmgr.hxx:292
void MergeCancel()
Definition: dbmgr.cxx:1734
uno::Reference< mail::XSmtpService > ConnectToSmtpServer(SwMailMergeConfigItem const &rConfigItem, uno::Reference< mail::XMailService > &rxInMailService, const OUString &rInMailServerPassword, const OUString &rOutMailServerPassword, weld::Window *pDialogParentWindow)
void SetMailMergeEvtSrc(const SwXMailMerge *pSrc)
Definition: dbmgr.hxx:293
#define WID_DATA_COMMAND_TYPE
Definition: unomap.hxx:264
OUString m_sAttachmentName
#define UNO_NAME_OUTPUT_TYPE
Definition: unoprnms.hxx:728
SwMailMergeConfigItem * pMailMergeConfigItem
Definition: dbmgr.hxx:214
OUString m_sOutServerPassword
void setDataSource(const OUString &_sDataSourceNameOrLocation)
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
#define UNO_NAME_SUBJECT
Definition: unoprnms.hxx:758
static CloseResult CloseModelAndDocSh(Reference< frame::XModel > const &rxModel, SfxObjectShellRef &rxDocSh)
const SfxItemPropertySet * m_pPropSet
OUString m_sSaveFilter
#define WID_OUT_SERVER_PASSWORD
Definition: unomap.hxx:283
#define UNO_NAME_CONNECTION
Definition: unoprnms.hxx:722
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &PropertyName) override
bool UCB_IsReadOnlyFileName(const OUString &rURL)
#define WID_ATTACHMENT_NAME
Definition: unomap.hxx:275
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
static bool LoadFromURL_impl(Reference< frame::XModel > &rxModel, SfxObjectShellRef &rxDocSh, const OUString &rURL, bool bClose)
sal_Int32 addInterface(const css::uno::Reference< css::uno::XInterface > &rxIFace)
css::uno::Reference< css::mail::XSmtpService > xSmtpServer
Definition: dbmgr.hxx:192
OUString m_sAddressFromColumn
#define UNO_NAME_DATA_SOURCE_NAME
Definition: unoprnms.hxx:724
#define WID_SINGLE_PRINT_JOBS
Definition: unomap.hxx:267
#define WID_PRINT_OPTIONS
Definition: unomap.hxx:277
void disposeAndClear(const css::lang::EventObject &rEvt)
bool bSendAsAttachment
Definition: dbmgr.hxx:194
sal_Int16 m_nOutputType
OUString m_sMailBody
#define UNO_NAME_BLIND_COPIES_TO
Definition: unoprnms.hxx:769
virtual css::uno::Any SAL_CALL execute(const css::uno::Sequence< css::beans::NamedValue > &Arguments) override
#define WID_FILE_NAME_FROM_COLUMN
Definition: unomap.hxx:268
css::uno::Reference< css::frame::XModel > m_xModel
css::uno::Reference< css::frame::XModel > GetModel() const
bool UCB_DeleteFile(const OUString &rURL)
Definition: swunohelper.cxx:58
sal_Int32 removeInterface(const css::uno::Reference< css::uno::XInterface > &rxIFace)
#define UNO_NAME_ESCAPE_PROCESSING
Definition: unoprnms.hxx:729
#define WID_SELECTION
Definition: unomap.hxx:255
css::uno::XInterface *SAL_CALL next()
css::uno::Sequence< css::beans::PropertyValue > aSaveToFilterData
Definition: dbmgr.hxx:157
css::uno::Reference< css::beans::XPropertySetInfo > const & getPropertySetInfo() const
#define UNO_NAME_DOCUMENT_URL
Definition: unoprnms.hxx:726
virtual ~SwXMailMerge() override
SwWrtShell & GetWrtShell() const
Definition: view.hxx:400
#define UNO_NAME_SAVE_FILTER_DATA
Definition: unoprnms.hxx:773
SfxApplication * SfxGetpApp()
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
#define UNO_NAME_MODEL
Definition: unoprnms.hxx:723
OUString GetBase() const
Used by the UI to modify the document model.
Definition: wrtsh.hxx:86
OUString m_sAttachmentFilter
bool m_bSendAsAttachment
constexpr auto SFX_INTERFACE_NONE
#define WID_RESULT_SET
Definition: unomap.hxx:256
#define WID_COPIES_TO
Definition: unomap.hxx:280
virtual void SAL_CALL addPropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &xListener) override
Print mail merge.
Definition: dbmgr.hxx:88
#define UNO_NAME_RESULT_SET
Definition: unoprnms.hxx:721
#define UNO_NAME_MAIL_BODY
Definition: unoprnms.hxx:762
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
#define UNO_NAME_SAVE_FILTER_OPTIONS
Definition: unoprnms.hxx:772
#define UNO_NAME_COPIES_TO
Definition: unoprnms.hxx:768
DBManagerOptions
Definition: dbmgr.hxx:85
Send mail merge as email.
Definition: dbmgr.hxx:89
#define WID_FILTER
Definition: unomap.hxx:261
#define UNO_NAME_ATTACHMENT_FILTER
Definition: unoprnms.hxx:764
OUString sSaveToFilter
Definition: dbmgr.hxx:155
sal_Int32 SAL_CALL removeInterface(const key &rKey, const css::uno::Reference< css::uno::XInterface > &rxIFace)
void launchEvent(const css::beans::PropertyChangeEvent &rEvt) const
Create merge doc and keep the doc shell.
Definition: dbmgr.hxx:91
css::uno::Reference< css::frame::XModel > GetBaseModel() const
OUString sMailBody
Definition: dbmgr.hxx:188
virtual void SAL_CALL addMailMergeEventListener(const css::uno::Reference< css::text::XMailMergeListener > &xListener) override
css::uno::Sequence< css::beans::PropertyValue > m_aSaveFilterData
#define WID_SEND_AS_HTML
Definition: unomap.hxx:272
virtual void SAL_CALL removePropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &aListener) override
#define UNO_NAME_SAVE_FILTER
Definition: unoprnms.hxx:767
css::uno::Reference< css::sdbc::XConnection > m_xConnection
OUString m_sSubject
bool Merge(const SwMergeDescriptor &rMergeDesc)
Merging of data records into fields.
Definition: dbmgr.cxx:433
SwDBManager * GetDBManager() const
For evaluation of DB fields (new DB-manager).
Definition: edfld.cxx:340
static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId()
Definition: unotxdoc.cxx:293
OUString sPrefix
Basename incl.
Definition: dbmgr.hxx:172
const IDocumentDeviceAccess & getIDocumentDeviceAccess() const
Provides access to the document device interface.
Definition: viewsh.cxx:2590
OUString sSaveToFilterOptions
Definition: dbmgr.hxx:156
T * get() const
static SW_DLLPUBLIC std::shared_ptr< const SfxFilter > GetFilterOfFormat(const OUString &rFormat, const SfxFilterContainer *pCnt=nullptr)
find for an internal format name the corresponding filter entry
Definition: iodetect.cxx:68
#define WID_SAVE_FILTER
Definition: unomap.hxx:279
#define STR_SW_EVENT_MAIL_MERGE_END
Definition: swevent.hxx:29
sal_Int32 m_nDataCommandType
#define WID_ESCAPE_PROCESSING
Definition: unomap.hxx:266
OUString sSubject
Definition: dbmgr.hxx:187
OUString m_aFileNamePrefix
virtual OUString SAL_CALL getImplementationName() override
virtual const SwPrintData & getPrintData() const =0
Returns the PrintData.
#define WID_DOCUMENT_URL
Definition: unomap.hxx:262
OUString const & GetURL() const
void SetSmartProtocol(INetProtocol eTheSmartScheme)
void SAL_CALL disposeAndClear(const css::lang::EventObject &rEvt)
#define UNO_NAME_PRINT_OPTIONS
Definition: unoprnms.hxx:765
virtual void SAL_CALL removeVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
static osl::Mutex & GetMailMergeMutex()
void SetMergeSilent(bool bVal)
Definition: dbmgr.hxx:296
OUString m_aDataSourceName
#define UNO_NAME_SINGLE_PRINT_JOBS
Definition: unoprnms.hxx:730
int i
OUString sAttachmentName
Definition: dbmgr.hxx:189
#define UNO_NAME_SEND_AS_HTML
Definition: unoprnms.hxx:760
#define WID_SEND_AS_ATTACHMENT
Definition: unomap.hxx:273
#define UNO_NAME_FILE_NAME_PREFIX
Definition: unoprnms.hxx:732
OString stripStart(const OString &rIn, sal_Char c)
#define WID_SAVE_AS_SINGLE_FILE
Definition: unomap.hxx:278
void NotifyEvent(const SfxEventHint &rEvent, bool bSynchron=true)
OUString m_aOutputURL
unsigned char sal_Bool
SfxObjectShellRef m_xDocSh
const SfxItemPropertyMap & getPropertyMap() const
SwDocShell * GetDocShell()
Definition: unotxdoc.hxx:464
#define WID_MAIL_BODY
Definition: unomap.hxx:274
void LaunchMailMergeEvent(const css::text::MailMergeEvent &rData) const
bool m_bEscapeProcessing
#define WID_BLIND_COPIES_TO
Definition: unomap.hxx:281
sal_uInt16 sal_Char * pName
virtual void SAL_CALL dispose() override
css::uno::Sequence< OUString > m_aCopiesTo
bool UCB_IsDirectory(const OUString &rURL)
const SfxItemPropertySimpleEntry * getByName(const OUString &rName) const
SfxViewShell * GetViewShell() const
#define WID_OUTPUT_TYPE
Definition: unomap.hxx:265
CloseResult
css::uno::Sequence< css::beans::PropertyValue > m_aPrintSettings
SwDocShell * GetDocShell()
Definition: view.cxx:1115
#define UNO_NAME_ATTACHMENT_NAME
Definition: unoprnms.hxx:763
#define WID_SAVE_FILTER_DATA
Definition: unomap.hxx:285
#define WID_SAVE_FILTER_OPTIONS
Definition: unomap.hxx:284
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
Provides access to the formatting devices of a document.
MailMergeExecuteFinalizer(SwXMailMerge *mailmerge)
#define WID_DATA_COMMAND
Definition: unomap.hxx:260
virtual void SAL_CALL setPropertyValue(const OUString &aPropertyName, const css::uno::Any &aValue) override
sal_Int32 SAL_CALL addInterface(const key &rKey, const css::uno::Reference< css::uno::XInterface > &r)
#define WID_MODEL
Definition: unomap.hxx:258
#define WID_IN_SERVER_PASSWORD
Definition: unomap.hxx:282
Reference< XMultiServiceFactory > getProcessServiceFactory()
css::uno::Sequence< OUString > aCopiesTo
Definition: dbmgr.hxx:190
#define UNO_NAME_SAVE_AS_SINGLE_FILE
Definition: unoprnms.hxx:766
css::uno::Sequence< css::beans::PropertyValue > aPrintOptions
Definition: dbmgr.hxx:211
void SetPrintSingleJobs(bool b)
Definition: printdata.hxx:164
::utl::SharedUNOComponent< XInterface > SharedComponent
MailMergeExecuteFinalizer & operator=(MailMergeExecuteFinalizer const &)=delete
Save mail merge as files.
Definition: dbmgr.hxx:90
static SfxViewFrame * LoadHiddenDocument(SfxObjectShell const &i_rDoc, SfxInterfaceId i_nViewId)
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
OUString m_sInServerPassword
#define STR_SW_EVENT_MAIL_MERGE
Definition: swevent.hxx:28
#define FILTER_XML
XML filter.
Definition: iodetect.hxx:35
#define UNO_NAME_OUTPUT_URL
Definition: unoprnms.hxx:727
#define WID_DATA_SOURCE_NAME
Definition: unomap.hxx:259
bool m_bSinglePrintJobs
#define UNO_NAME_FILTER
Definition: unoprnms.hxx:725
#define WID_FILE_NAME_PREFIX
Definition: unomap.hxx:269
bool DoInitNew(SfxMedium *pMedium=nullptr)
OUString m_sSaveFilterOptions
virtual void setPrintData(const SwPrintData &rPrtData)=0
Sets the PrintData.
comphelper::OInterfaceContainerHelper2 m_aMergeListeners
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
css::uno::Sequence< OUString > m_aBlindCopiesTo
css::uno::Sequence< OUString > aBlindCopiesTo
Definition: dbmgr.hxx:191
Reference< XComponentContext > getProcessComponentContext()
SwUnoPropertyMapProvider aSwMapProvider
Definition: unomap1.cxx:130
#define WID_CONNECTION
Definition: unomap.hxx:257
TABLE
OUString sDBcolumn
DB column to fetch EMail of Filename from.
Definition: dbmgr.hxx:203
OUString m_aDataCommand
#define UNO_NAME_DAD_COMMAND
Definition: unoprnms.hxx:734
OUString m_aTmpFileName
static OUString GetEventName(sal_Int32 nId)
Definition: docsh.cxx:1341
virtual void CalcLayout() override
To enable set up of StartActions and EndActions.
Definition: edws.cxx:107
OUString m_aFilter
static SfxViewFrame * GetFirst(const SfxObjectShell *pDoc=nullptr, bool bOnlyVisible=true)
#define WID_ADDRESS_FROM_COLUMN
Definition: unomap.hxx:271
#define UNO_NAME_OUT_SERVER_PASSWORD
Definition: unoprnms.hxx:771
#define WID_OUTPUT_URL
Definition: unomap.hxx:263
OPropertyListenerContainerHelper m_aPropListeners
css::uno::XInterface * next()
void reset(const css::uno::Reference< INTERFACE > &_rxComponent, AssignmentMode _eMode=TakeOwnership)
#define UNO_NAME_SEND_AS_ATTACHMENT
Definition: unoprnms.hxx:761
virtual void SAL_CALL cancel() override
bool m_bSaveAsSingleFile
#define WID_ATTACHMENT_FILTER
Definition: unomap.hxx:276
#define WID_MAIL_SUBJECT
Definition: unomap.hxx:270
css::uno::Reference< css::sdbc::XResultSet > m_xResultSet
css::uno::Sequence< css::uno::Any > m_aSelection
OInterfaceContainerHelper *SAL_CALL getContainer(const key &) const
#define UNO_NAME_IN_SERVER_PASSWORD
Definition: unoprnms.hxx:770
comphelper::OInterfaceContainerHelper2 m_aEvtListeners
#define UNO_NAME_SELECTION
Definition: unoprnms.hxx:720
#define UNO_NAME_ADDRESS_FROM_COLUMN
Definition: unoprnms.hxx:759
#define PROPERTY_MAP_MAILMERGE
Definition: unomap.hxx:117
Definition: view.hxx:146
#define UNO_NAME_FILE_NAME_FROM_COLUMN
Definition: unoprnms.hxx:731
static bool DeleteTmpFile_Impl(Reference< frame::XModel > &rxModel, SfxObjectShellRef &rxDocSh, const OUString &rTmpFileURL)
virtual void SAL_CALL addVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
bool SetSmartURL(OUString const &rTheAbsURIRef, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8, FSysStyle eStyle=FSysStyle::Detect)
bool m_bFileNameFromColumn
bool SAL_CALL hasMoreElements() const
SwDBManager * m_pMgr
bool removeSegment(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true)
#define UNO_NAME_DAD_COMMAND_TYPE
Definition: unoprnms.hxx:735
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)