1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/svapp.hxx>
21 #include <osl/mutex.hxx>
22 #include <svl/itemprop.hxx>
23 #include <svl/urihelper.hxx>
24 #include <svx/dataaccessdescriptor.hxx>
25 #include <tools/shl.hxx> // GetAppData
26 #include <tools/tempfile.hxx>
27 #include <sfx2/app.hxx>
28 #include <sfx2/docfile.hxx>
29 #include <sfx2/docfilt.hxx>
30 #include <comphelper/processfactory.hxx>
31 #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/text/XMailMergeBroadcaster.hpp>
38 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #include <com/sun/star/lang/XUnoTunnel.hpp>
40 #include <com/sun/star/sdbc/XResultSet.hpp>
41 #include <com/sun/star/sdbc/XConnection.hpp>
42 #include <com/sun/star/sdbc/XRowSet.hpp>
43 #include <com/sun/star/frame/Desktop.hpp>
44 #include <com/sun/star/frame/XComponentLoader.hpp>
45 #include <com/sun/star/util/XCloseable.hpp>
46 #include <com/sun/star/util/CloseVetoException.hpp>
47 #include <com/sun/star/sdbcx/XRowLocate.hpp>
48 #include <com/sun/star/frame/XStorable.hpp>
49 #include "com/sun/star/mail/XSmtpService.hpp"
50 #include <sfx2/viewfrm.hxx>
51 #include <sfx2/event.hxx>
52 #include <swevent.hxx>
53 #include <unomailmerge.hxx>
55 #include <swmodule.hxx>
56 #include <unoprnms.hxx>
58 #include <swunohelper.hxx>
60 #include <IDocumentDeviceAccess.hxx>
63 #include <unotxdoc.hxx>
66 #include <shellio.hxx>
67 #include <mmconfigitem.hxx>
68 #include <mailmergehelper.hxx>
74 #define SN_MAIL_MERGE "com.sun.star.text.MailMerge"
75 #define SN_DATA_ACCESS_DESCRIPTOR "com.sun.star.sdb.DataAccessDescriptor"
77 using namespace ::com::sun::star
;
78 using namespace ::com::sun::star::frame
;
79 using namespace ::com::sun::star::uno
;
80 using namespace ::com::sun::star::lang
;
81 using namespace ::com::sun::star::beans
;
82 using namespace ::com::sun::star::text
;
83 using namespace SWUnoHelper
;
85 ////////////////////////////////////////////////////////////
87 typedef ::utl::SharedUNOComponent
< XInterface
> SharedComponent
;
89 ////////////////////////////////////////////////////////////
91 osl::Mutex
& GetMailMergeMutex()
93 static osl::Mutex aMutex
;
97 ////////////////////////////////////////////////////////////
101 eSuccess
, // successfully closed
102 eVetoed
, // vetoed, ownership transferred to the vetoing instance
103 eFailed
// failed for some unknown reason
105 static CloseResult
CloseModelAndDocSh(
106 Reference
< frame::XModel
> &rxModel
,
107 SfxObjectShellRef
&rxDocSh
)
109 CloseResult eResult
= eSuccess
;
113 //! models/documents should never be disposed (they may still be
114 //! used for printing which is called asynchronously for example)
115 //! instead call close
116 Reference
< util::XCloseable
> xClose( rxModel
, UNO_QUERY
);
121 //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
122 //! I.e. now that object is responsible for closing the model and doc shell.
123 xClose
->close( sal_True
);
125 catch (const util::CloseVetoException
&)
127 //! here we have the problem that the temporary file that is
128 //! currently being printed will never be deleted. :-(
131 catch (const uno::RuntimeException
&)
139 ////////////////////////////////////////////////////////////
141 static bool LoadFromURL_impl(
142 Reference
< frame::XModel
> &rxModel
,
143 SfxObjectShellRef
&rxDocSh
,
146 throw (RuntimeException
)
148 // try to open the document readonly and hidden
149 Reference
< frame::XModel
> xTmpModel
;
150 Sequence
< PropertyValue
> aArgs( 1 );
151 aArgs
[0].Name
= "Hidden";
152 sal_Bool bVal
= sal_True
;
153 aArgs
[0].Value
<<= bVal
;
156 Reference
< XDesktop2
> xDesktop
= Desktop::create( ::comphelper::getProcessComponentContext() );
157 xTmpModel
= Reference
< XModel
>( xDesktop
->loadComponentFromURL(
158 rURL
, "_blank", 0, aArgs
), UNO_QUERY
);
160 catch (const Exception
&)
165 // try to get the DocShell
166 SwDocShell
*pTmpDocShell
= 0;
167 Reference
< XUnoTunnel
> xTunnel( xTmpModel
, UNO_QUERY
);
170 SwXTextDocument
* pTextDoc
= reinterpret_cast<SwXTextDocument
*>(
171 xTunnel
->getSomething( SwXTextDocument::getUnoTunnelId() ));
172 pTmpDocShell
= pTextDoc
? pTextDoc
->GetDocShell() : 0;
176 if (xTmpModel
.is() && pTmpDocShell
) // everything available?
179 CloseModelAndDocSh( rxModel
, rxDocSh
);
182 rxDocSh
= pTmpDocShell
;
187 // SfxObjectShellRef is ok here, since the document will be explicitly closed
188 SfxObjectShellRef xTmpDocSh
= pTmpDocShell
;
189 CloseModelAndDocSh( xTmpModel
, xTmpDocSh
);
195 //==========================================================
198 class DelayedFileDeletion
: public ::cppu::WeakImplHelper1
< util::XCloseListener
>
201 ::osl::Mutex m_aMutex
;
202 Reference
< util::XCloseable
> m_xDocument
;
203 Timer m_aDeleteTimer
;
204 String m_sTemporaryFile
;
205 sal_Int32 m_nPendingDeleteAttempts
;
208 DelayedFileDeletion( const Reference
< XModel
>& _rxModel
,
209 const String
& _rTemporaryFile
);
212 ~DelayedFileDeletion( );
215 virtual void SAL_CALL
queryClosing( const EventObject
& _rSource
, sal_Bool _bGetsOwnership
) throw (util::CloseVetoException
, RuntimeException
);
216 virtual void SAL_CALL
notifyClosing( const EventObject
& _rSource
) throw (RuntimeException
);
219 virtual void SAL_CALL
disposing( const EventObject
& Source
) throw (RuntimeException
);
222 void implTakeOwnership( );
223 DECL_LINK( OnTryDeleteFile
, void* );
226 DelayedFileDeletion( const DelayedFileDeletion
& ); // never implemented
227 DelayedFileDeletion
& operator=( const DelayedFileDeletion
& ); // never implemented
230 //------------------------------------------------------
231 DelayedFileDeletion::DelayedFileDeletion( const Reference
< XModel
>& _rxModel
, const String
& _rTemporaryFile
)
233 m_xDocument( _rxModel
, UNO_QUERY
)
234 ,m_sTemporaryFile( _rTemporaryFile
)
235 ,m_nPendingDeleteAttempts( 0 )
237 osl_atomic_increment( &m_refCount
);
240 if ( m_xDocument
.is() )
242 m_xDocument
->addCloseListener( this );
243 // successfully added -> keep ourself alive
247 OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: model is no component!" );
250 catch (const Exception
&)
252 OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: could not register as event listener at the model!" );
254 osl_atomic_decrement( &m_refCount
);
257 //--------------------------------------------------------------------
258 IMPL_LINK_NOARG(DelayedFileDeletion
, OnTryDeleteFile
)
260 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
262 bool bSuccess
= false;
265 sal_Bool bDeliverOwnership
= ( 0 == m_nPendingDeleteAttempts
);
266 // if this is our last attemt, then anybody which vetoes this has to take the consequences
267 // (means take the ownership)
268 m_xDocument
->close( bDeliverOwnership
);
271 catch (const util::CloseVetoException
&)
273 // somebody vetoed -> next try
274 if ( m_nPendingDeleteAttempts
)
277 --m_nPendingDeleteAttempts
;
278 m_aDeleteTimer
.Start();
281 bSuccess
= true; // can't do anything here ...
283 catch (const Exception
&)
285 OSL_FAIL("DelayedFileDeletion::OnTryDeleteFile: caught a strange exception!" );
287 // can't do anything here ...
292 SWUnoHelper::UCB_DeleteFile( m_sTemporaryFile
);
294 release(); // this should be our last reference, we should be dead after this
299 //--------------------------------------------------------------------
300 void DelayedFileDeletion::implTakeOwnership( )
302 // revoke ourself as listener
305 m_xDocument
->removeCloseListener( this );
307 catch (const Exception
&)
309 OSL_FAIL("DelayedFileDeletion::implTakeOwnership: could not revoke the listener!" );
312 m_aDeleteTimer
.SetTimeout( 3000 ); // 3 seconds
313 m_aDeleteTimer
.SetTimeoutHdl( LINK( this, DelayedFileDeletion
, OnTryDeleteFile
) );
314 m_nPendingDeleteAttempts
= 3; // try 3 times at most
315 m_aDeleteTimer
.Start( );
318 //--------------------------------------------------------------------
319 void SAL_CALL
DelayedFileDeletion::queryClosing( const EventObject
& , sal_Bool _bGetsOwnership
) throw (util::CloseVetoException
, RuntimeException
)
321 ::osl::MutexGuard
aGuard( m_aMutex
);
322 if ( _bGetsOwnership
)
323 implTakeOwnership( );
325 // always veto: We want to take the ownership ourself, as this is the only chance to delete
326 // the temporary file which the model is based on
327 throw util::CloseVetoException( );
330 //--------------------------------------------------------------------
331 void SAL_CALL
DelayedFileDeletion::notifyClosing( const EventObject
& ) throw (RuntimeException
)
333 OSL_FAIL("DelayedFileDeletion::notifyClosing: how this?" );
334 // this should not happen:
335 // Either, a foreign instance closes the document, then we should veto this, and take the ownership
336 // Or, we ourself close the document, then we should not be a listener anymore
339 //------------------------------------------------------
340 void SAL_CALL
DelayedFileDeletion::disposing( const EventObject
& ) throw (RuntimeException
)
342 OSL_FAIL("DelayedFileDeletion::disposing: how this?" );
343 // this should not happen:
344 // Either, a foreign instance closes the document, then we should veto this, and take the ownership
345 // Or, we ourself close the document, then we should not be a listener anymore
348 //------------------------------------------------------
349 DelayedFileDeletion::~DelayedFileDeletion( )
354 ////////////////////////////////////////////////////////////
356 static bool DeleteTmpFile_Impl(
357 Reference
< frame::XModel
> &rxModel
,
358 SfxObjectShellRef
&rxDocSh
,
359 const String
&rTmpFileURL
)
362 if (rTmpFileURL
.Len())
365 if ( eVetoed
== CloseModelAndDocSh( rxModel
, rxDocSh
) )
367 // somebody vetoed the closing, and took the ownership of the document
368 // -> ensure that the temporary file is deleted later on
369 Reference
< XEventListener
> xEnsureDelete( new DelayedFileDeletion( rxModel
, rTmpFileURL
) );
370 // note: as soon as #106931# is fixed, the whole DelayedFileDeletion is to be superseeded by
376 rxDocSh
= 0; // destroy doc shell
380 if ( !SWUnoHelper::UCB_DeleteFile( rTmpFileURL
) )
382 Reference
< XEventListener
> xEnsureDelete( new DelayedFileDeletion( rxModel
, rTmpFileURL
) );
383 // same not as above: as soon as #106931#, ...
387 bRes
= true; // file will be deleted delayed
392 ////////////////////////////////////////////////////////////
394 SwXMailMerge::SwXMailMerge() :
395 aEvtListeners ( GetMailMergeMutex() ),
396 aMergeListeners ( GetMailMergeMutex() ),
397 aPropListeners ( GetMailMergeMutex() ),
398 pPropSet( aSwMapProvider
.GetPropertySet( PROPERTY_MAP_MAILMERGE
) ),
399 bSendAsHTML(sal_False
),
400 bSendAsAttachment(sal_False
),
401 bSaveAsSingleFile(sal_False
)
404 // create empty document
405 // like in: SwModule::InsertEnv (appenv.cxx)
406 SwDocShell
*pDocShell
= new SwDocShell( SFX_CREATE_MODE_STANDARD
);
408 xDocSh
->DoInitNew( 0 );
409 SfxViewFrame
*pFrame
= SfxViewFrame::LoadHiddenDocument( *xDocSh
, 0 );
410 SwView
*pView
= (SwView
*) pFrame
->GetViewShell();
411 pView
->AttrChangedNotify( &pView
->GetWrtShell() );//Damit SelectShell gerufen wird.
413 xModel
= pDocShell
->GetModel();
415 nDataCommandType
= sdb::CommandType::TABLE
;
416 nOutputType
= MailMergeType::PRINTER
;
417 bEscapeProcessing
= sal_True
; //!! allow to process properties like "Filter", "Order", ...
418 bSinglePrintJobs
= sal_False
;
419 bFileNameFromColumn
= sal_False
;
421 bDisposing
= sal_False
;
424 SwXMailMerge::~SwXMailMerge()
426 if (aTmpFileName
.Len())
427 DeleteTmpFile_Impl( xModel
, xDocSh
, aTmpFileName
);
428 else // there was no temporary file in use
430 //! we still need to close the model and doc shell manually
431 //! because there is no automatism that will do that later.
433 if ( eVetoed
== CloseModelAndDocSh( xModel
, xDocSh
) )
434 OSL_FAIL("owner ship transfered to vetoing object!" );
437 xDocSh
= 0; // destroy doc shell
441 uno::Any SAL_CALL
SwXMailMerge::execute(
442 const uno::Sequence
< beans::NamedValue
>& rArguments
)
443 throw (IllegalArgumentException
, Exception
, RuntimeException
)
445 SolarMutexGuard aGuard
;
448 // get property values to be used
449 // (use values from the service as default and override them with
450 // the values that are provided as arguments)
452 uno::Sequence
< uno::Any
> aCurSelection
= aSelection
;
453 uno::Reference
< sdbc::XResultSet
> xCurResultSet
= xResultSet
;
454 uno::Reference
< sdbc::XConnection
> xCurConnection
= xConnection
;
455 uno::Reference
< frame::XModel
> xCurModel
= xModel
;
456 OUString aCurDataSourceName
= aDataSourceName
;
457 OUString aCurDataCommand
= aDataCommand
;
458 OUString aCurFilter
= aFilter
;
459 OUString aCurDocumentURL
= aDocumentURL
;
460 OUString aCurOutputURL
= aOutputURL
;
461 OUString aCurFileNamePrefix
= aFileNamePrefix
;
462 sal_Int32 nCurDataCommandType
= nDataCommandType
;
463 sal_Int16 nCurOutputType
= nOutputType
;
464 sal_Bool bCurEscapeProcessing
= bEscapeProcessing
;
465 sal_Bool bCurSinglePrintJobs
= bSinglePrintJobs
;
466 sal_Bool bCurFileNameFromColumn
= bFileNameFromColumn
;
468 SfxObjectShellRef xCurDocSh
= xDocSh
; // the document
470 const beans::NamedValue
*pArguments
= rArguments
.getConstArray();
471 sal_Int32 nArgs
= rArguments
.getLength();
472 for (sal_Int32 i
= 0; i
< nArgs
; ++i
)
474 const OUString
&rName
= pArguments
[i
].Name
;
475 const Any
&rValue
= pArguments
[i
].Value
;
477 sal_Bool bOK
= sal_True
;
478 if (rName
.equalsAscii( GetPropName( UNO_NAME_SELECTION
) ))
479 bOK
= rValue
>>= aCurSelection
;
480 else if (rName
.equalsAscii( GetPropName( UNO_NAME_RESULT_SET
) ))
481 bOK
= rValue
>>= xCurResultSet
;
482 else if (rName
.equalsAscii( GetPropName( UNO_NAME_CONNECTION
) ))
483 bOK
= rValue
>>= xCurConnection
;
484 else if (rName
.equalsAscii( GetPropName( UNO_NAME_MODEL
) ))
485 throw PropertyVetoException( OUString( "Property is read-only: " ) + rName
, static_cast < cppu::OWeakObject
* > ( this ) );
486 else if (rName
.equalsAscii( GetPropName( UNO_NAME_DATA_SOURCE_NAME
) ))
487 bOK
= rValue
>>= aCurDataSourceName
;
488 else if (rName
.equalsAscii( GetPropName( UNO_NAME_DAD_COMMAND
) ))
489 bOK
= rValue
>>= aCurDataCommand
;
490 else if (rName
.equalsAscii( GetPropName( UNO_NAME_FILTER
) ))
491 bOK
= rValue
>>= aCurFilter
;
492 else if (rName
.equalsAscii( GetPropName( UNO_NAME_DOCUMENT_URL
) ))
494 bOK
= rValue
>>= aCurDocumentURL
;
495 if (!aCurDocumentURL
.isEmpty()
496 && !LoadFromURL_impl( xCurModel
, xCurDocSh
, aCurDocumentURL
, false ))
497 throw RuntimeException( OUString( "Failed to create document from URL: " ) + aCurDocumentURL
, static_cast < cppu::OWeakObject
* > ( this ) );
499 else if (rName
.equalsAscii( GetPropName( UNO_NAME_OUTPUT_URL
) ))
501 bOK
= rValue
>>= aCurOutputURL
;
502 if (!aCurOutputURL
.isEmpty())
504 if (!UCB_IsDirectory(aCurOutputURL
))
505 throw IllegalArgumentException( OUString( "URL does not point to a directory: " ) + aCurOutputURL
, static_cast < cppu::OWeakObject
* > ( this ), 0 );
506 if (UCB_IsReadOnlyFileName(aCurOutputURL
))
507 throw IllegalArgumentException( OUString( "URL is read-only: " ) + aCurOutputURL
, static_cast < cppu::OWeakObject
* > ( this ), 0 );
510 else if (rName
.equalsAscii( GetPropName( UNO_NAME_FILE_NAME_PREFIX
) ))
511 bOK
= rValue
>>= aCurFileNamePrefix
;
512 else if (rName
.equalsAscii( GetPropName( UNO_NAME_DAD_COMMAND_TYPE
) ))
513 bOK
= rValue
>>= nCurDataCommandType
;
514 else if (rName
.equalsAscii( GetPropName( UNO_NAME_OUTPUT_TYPE
) ))
515 bOK
= rValue
>>= nCurOutputType
;
516 else if (rName
.equalsAscii( GetPropName( UNO_NAME_ESCAPE_PROCESSING
) ))
517 bOK
= rValue
>>= bCurEscapeProcessing
;
518 else if (rName
.equalsAscii( GetPropName( UNO_NAME_SINGLE_PRINT_JOBS
) ))
519 bOK
= rValue
>>= bCurSinglePrintJobs
;
520 else if (rName
.equalsAscii( GetPropName( UNO_NAME_FILE_NAME_FROM_COLUMN
) ))
521 bOK
= rValue
>>= bCurFileNameFromColumn
;
522 else if (rName
.equalsAscii( GetPropName( UNO_NAME_SUBJECT
) ))
523 bOK
= rValue
>>= sSubject
;
524 else if (rName
.equalsAscii( GetPropName( UNO_NAME_ADDRESS_FROM_COLUMN
) ))
525 bOK
= rValue
>>= sAddressFromColumn
;
526 else if (rName
.equalsAscii( GetPropName( UNO_NAME_SEND_AS_HTML
) ))
527 bOK
= rValue
>>= bSendAsHTML
;
528 else if (rName
.equalsAscii( GetPropName( UNO_NAME_MAIL_BODY
) ))
529 bOK
= rValue
>>= sMailBody
;
530 else if (rName
.equalsAscii( GetPropName( UNO_NAME_ATTACHMENT_NAME
) ))
531 bOK
= rValue
>>= sAttachmentName
;
532 else if (rName
.equalsAscii( GetPropName( UNO_NAME_ATTACHMENT_FILTER
) ))
533 bOK
= rValue
>>= sAttachmentFilter
;
534 else if (rName
.equalsAscii( GetPropName( UNO_NAME_COPIES_TO
) ))
535 bOK
= rValue
>>= aCopiesTo
;
536 else if (rName
.equalsAscii( GetPropName( UNO_NAME_BLIND_COPIES_TO
) ))
537 bOK
= rValue
>>= aBlindCopiesTo
;
538 else if (rName
.equalsAscii( GetPropName( UNO_NAME_SEND_AS_ATTACHMENT
) ))
539 bOK
= rValue
>>= bSendAsAttachment
;
540 else if (rName
.equalsAscii( GetPropName( UNO_NAME_PRINT_OPTIONS
) ))
541 bOK
= rValue
>>= aPrintSettings
;
542 else if (rName
.equalsAscii( GetPropName( UNO_NAME_SAVE_AS_SINGLE_FILE
) ))
543 bOK
= rValue
>>= bSaveAsSingleFile
;
544 else if (rName
.equalsAscii( GetPropName( UNO_NAME_SAVE_FILTER
) ))
545 bOK
= rValue
>>= sSaveFilter
;
546 else if (rName
.equalsAscii( GetPropName( UNO_NAME_SAVE_FILTER_OPTIONS
) ))
547 bOK
= rValue
>>= sSaveFilterOptions
;
548 else if (rName
.equalsAscii( GetPropName( UNO_NAME_SAVE_FILTER_DATA
) ))
549 bOK
= rValue
>>= aSaveFilterData
;
550 else if (rName
.equalsAscii( GetPropName( UNO_NAME_IN_SERVER_PASSWORD
) ))
551 bOK
= rValue
>>= sInServerPassword
;
552 else if (rName
.equalsAscii( GetPropName( UNO_NAME_OUT_SERVER_PASSWORD
) ))
553 bOK
= rValue
>>= sOutServerPassword
;
555 throw UnknownPropertyException( OUString( "Property is unknown: " ) + rName
, static_cast < cppu::OWeakObject
* > ( this ) );
558 throw IllegalArgumentException( OUString( "Property type mismatch or property not set: " ) + rName
, static_cast < cppu::OWeakObject
* > ( this ), 0 );
561 // need to translate the selection: the API here requires a sequence of bookmarks, but the MergeNew
562 // method we will call below requires a sequence of indicies.
563 if ( aCurSelection
.getLength() )
565 Sequence
< Any
> aTranslated( aCurSelection
.getLength() );
568 Reference
< sdbcx::XRowLocate
> xRowLocate( xCurResultSet
, UNO_QUERY
);
569 if ( xRowLocate
.is() )
572 const Any
* pBookmarks
= aCurSelection
.getConstArray();
573 const Any
* pBookmarksEnd
= pBookmarks
+ aCurSelection
.getLength();
574 Any
* pTranslated
= aTranslated
.getArray();
578 bool bEverythingsFine
= true;
579 for ( ; ( pBookmarks
!= pBookmarksEnd
) && bEverythingsFine
; ++pBookmarks
)
581 if ( xRowLocate
->moveToBookmark( *pBookmarks
) )
582 *pTranslated
<<= xCurResultSet
->getRow();
584 bEverythingsFine
= false;
586 if ( bEverythingsFine
)
589 catch (const Exception
&)
597 throw IllegalArgumentException(
598 OUString( "The current 'Selection' does not describe a valid array of bookmarks, relative to the current 'ResultSet'." ),
599 static_cast < cppu::OWeakObject
* > ( this ),
604 aCurSelection
= aTranslated
;
607 SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst( xCurDocSh
, sal_False
);
608 SwView
*pView
= PTR_CAST( SwView
, pFrame
->GetViewShell() );
610 throw RuntimeException();
611 SwWrtShell
&rSh
= *pView
->GetWrtShellPtr();
613 // avoid assertion in 'Update' from Sfx by supplying a shell
614 // and thus avoiding the SelectShell call in Writers GetState function
615 // while still in Update of Sfx.
616 // (GetSelection in Update is not allowed)
617 if (!aCurDocumentURL
.isEmpty())
618 pView
->AttrChangedNotify( &pView
->GetWrtShell() );//Damit SelectShell gerufen wird.
620 SharedComponent aRowSetDisposeHelper
;
621 if (!xCurResultSet
.is())
623 if (aCurDataSourceName
.isEmpty() || aCurDataCommand
.isEmpty() )
625 OSL_FAIL("PropertyValues missing or unset");
626 throw IllegalArgumentException( OUString( "Either the ResultSet or DataSourceName and DataCommand must be set." ), static_cast < cppu::OWeakObject
* > ( this ), 0 );
630 // build ResultSet from DataSourceName, DataCommand and DataCommandType
632 Reference
< XMultiServiceFactory
> xMgr( ::comphelper::getProcessServiceFactory() );
635 Reference
< XInterface
> xInstance
= xMgr
->createInstance( "com.sun.star.sdb.RowSet" );
636 aRowSetDisposeHelper
.reset( xInstance
, SharedComponent::TakeOwnership
);
637 Reference
< XPropertySet
> xRowSetPropSet( xInstance
, UNO_QUERY
);
638 OSL_ENSURE( xRowSetPropSet
.is(), "failed to get XPropertySet interface from RowSet" );
639 if (xRowSetPropSet
.is())
641 if (xCurConnection
.is())
642 xRowSetPropSet
->setPropertyValue( "ActiveConnection", makeAny( xCurConnection
) );
643 xRowSetPropSet
->setPropertyValue( "DataSourceName", makeAny( aCurDataSourceName
) );
644 xRowSetPropSet
->setPropertyValue( "Command", makeAny( aCurDataCommand
) );
645 xRowSetPropSet
->setPropertyValue( "CommandType", makeAny( nCurDataCommandType
) );
646 xRowSetPropSet
->setPropertyValue( "EscapeProcessing", makeAny( bCurEscapeProcessing
) );
647 xRowSetPropSet
->setPropertyValue( "ApplyFilter", makeAny( sal_True
) );
648 xRowSetPropSet
->setPropertyValue( "Filter", makeAny( aCurFilter
) );
650 Reference
< sdbc::XRowSet
> xRowSet( xInstance
, UNO_QUERY
);
652 xRowSet
->execute(); // build ResultSet from properties
653 if( !xCurConnection
.is() )
654 xCurConnection
.set( xRowSetPropSet
->getPropertyValue( "ActiveConnection" ), UNO_QUERY
);
655 xCurResultSet
= Reference
< sdbc::XResultSet
>( xRowSet
, UNO_QUERY
);
656 OSL_ENSURE( xCurResultSet
.is(), "failed to build ResultSet" );
661 svx::ODataAccessDescriptor aDescriptor
;
662 aDescriptor
.setDataSource(aCurDataSourceName
);
663 aDescriptor
[ svx::daConnection
] <<= xCurConnection
;
664 aDescriptor
[ svx::daCommand
] <<= aCurDataCommand
;
665 aDescriptor
[ svx::daCommandType
] <<= nCurDataCommandType
;
666 aDescriptor
[ svx::daEscapeProcessing
] <<= bCurEscapeProcessing
;
667 aDescriptor
[ svx::daCursor
] <<= xCurResultSet
;
668 // aDescriptor[ svx::daColumnName ] not used
669 // aDescriptor[ svx::daColumnObject ] not used
670 aDescriptor
[ svx::daSelection
] <<= aCurSelection
;
672 sal_uInt16 nMergeType
;
673 switch (nCurOutputType
)
675 case MailMergeType::PRINTER
: nMergeType
= DBMGR_MERGE_MAILMERGE
; break;
676 case MailMergeType::FILE : nMergeType
= DBMGR_MERGE_MAILFILES
; break;
677 case MailMergeType::MAIL
: nMergeType
= DBMGR_MERGE_MAILING
; break;
679 throw IllegalArgumentException( OUString( "Invalid value of property:" ) + "OutputType", static_cast < cppu::OWeakObject
* > ( this ), 0 );
682 SwNewDBMgr
* pMgr
= rSh
.GetNewDBMgr();
683 //force layout creation
685 OSL_ENSURE( pMgr
, "database manager missing" );
687 SwMergeDescriptor
aMergeDesc( nMergeType
, rSh
, aDescriptor
);
689 std::auto_ptr
< SwMailMergeConfigItem
> pMMConfigItem
;
690 uno::Reference
< mail::XMailService
> xInService
;
691 if (MailMergeType::PRINTER
== nCurOutputType
)
693 IDocumentDeviceAccess
* pIDDA
= rSh
.getIDocumentDeviceAccess();
694 SwPrintData
aPrtData( pIDDA
->getPrintData() );
695 aPrtData
.SetPrintSingleJobs( bCurSinglePrintJobs
);
696 pIDDA
->setPrintData( aPrtData
);
697 // #i25686# printing should not be done asynchronously to prevent dangling offices
698 // when mail merge is called as command line macro
699 aMergeDesc
.bPrintAsync
= sal_False
;
700 aMergeDesc
.aPrintOptions
= aPrintSettings
;
701 aMergeDesc
.bCreateSingleFile
= true;
703 else /* FILE and MAIL*/
705 INetURLObject aURLObj
;
706 aURLObj
.SetSmartProtocol( INET_PROT_FILE
);
708 if (!aCurDocumentURL
.isEmpty())
710 // if OutputURL or FileNamePrefix are missing get
711 // them from DocumentURL
712 aURLObj
.SetSmartURL( aCurDocumentURL
);
713 if (aCurFileNamePrefix
.isEmpty())
714 aCurFileNamePrefix
= aURLObj
.GetBase(); // filename without extension
715 if (aCurOutputURL
.isEmpty())
717 aURLObj
.removeSegment();
718 aCurOutputURL
= aURLObj
.GetMainURL( INetURLObject::DECODE_TO_IURI
);
721 else // default empty document without URL
723 if (aCurOutputURL
.isEmpty())
724 throw RuntimeException( OUString( "OutputURL is not set and can not be obtained." ), static_cast < cppu::OWeakObject
* > ( this ) );
727 aURLObj
.SetSmartURL( aCurOutputURL
);
728 String aPath
= aURLObj
.GetMainURL( INetURLObject::DECODE_TO_IURI
);
730 String aDelim
= OUString(INET_PATH_TOKEN
);
731 if (aPath
.Len() >= aDelim
.Len() &&
732 aPath
.Copy( aPath
.Len()-aDelim
.Len() ).CompareTo( aDelim
) != COMPARE_EQUAL
)
734 if (bCurFileNameFromColumn
)
735 pMgr
->SetEMailColumn( aCurFileNamePrefix
);
738 aPath
+= String( aCurFileNamePrefix
);
739 pMgr
->SetEMailColumn( String() );
741 pMgr
->SetSubject( aPath
);
742 if(MailMergeType::FILE == nCurOutputType
)
744 aMergeDesc
.sSaveToFilter
= sSaveFilter
;
745 aMergeDesc
.sSaveToFilterOptions
= sSaveFilterOptions
;
746 aMergeDesc
.aSaveToFilterData
= aSaveFilterData
;
747 aMergeDesc
.bCreateSingleFile
= bSaveAsSingleFile
;
751 pMgr
->SetEMailColumn( sAddressFromColumn
);
752 if(sAddressFromColumn
.isEmpty())
753 throw RuntimeException( OUString( "Mail address column not set." ), static_cast < cppu::OWeakObject
* > ( this ) );
754 aMergeDesc
.sSaveToFilter
= sAttachmentFilter
;
755 aMergeDesc
.sSubject
= sSubject
;
756 aMergeDesc
.sMailBody
= sMailBody
;
757 aMergeDesc
.sAttachmentName
= sAttachmentName
;
758 aMergeDesc
.aCopiesTo
= aCopiesTo
;
759 aMergeDesc
.aBlindCopiesTo
= aBlindCopiesTo
;
760 aMergeDesc
.bSendAsHTML
= bSendAsHTML
;
761 aMergeDesc
.bSendAsAttachment
= bSendAsAttachment
;
763 aMergeDesc
.bCreateSingleFile
= sal_False
;
764 pMMConfigItem
= std::auto_ptr
< SwMailMergeConfigItem
>(new SwMailMergeConfigItem
);
765 aMergeDesc
.pMailMergeConfigItem
= pMMConfigItem
.get();
766 aMergeDesc
.xSmtpServer
= SwMailMergeHelper::ConnectToSmtpServer(
769 sInServerPassword
, sOutServerPassword
);
770 if( !aMergeDesc
.xSmtpServer
.is() || !aMergeDesc
.xSmtpServer
->isConnected())
771 throw RuntimeException( OUString( "Failed to connect to mail server." ), static_cast < cppu::OWeakObject
* > ( this ) );
776 // save document with temporary filename
777 const SfxFilter
*pSfxFlt
= SwIoSystem::GetFilterOfFormat(
778 OUString( FILTER_XML
),
779 SwDocShell::Factory().GetFilterContainer() );
780 String
aExtension(comphelper::string::stripStart(pSfxFlt
->GetDefaultExtension(), '*'));
781 TempFile
aTempFile( OUString("SwMM"), &aExtension
);
782 aTmpFileName
= aTempFile
.GetName();
784 Reference
< XStorable
> xStorable( xCurModel
, UNO_QUERY
);
785 bool bStoredAsTemporary
= false;
786 if ( xStorable
.is() )
790 xStorable
->storeAsURL( aTmpFileName
, Sequence
< PropertyValue
>() );
791 bStoredAsTemporary
= true;
793 catch (const Exception
&)
797 if ( !bStoredAsTemporary
)
798 throw RuntimeException( OUString( "Failed to save temporary file." ), static_cast < cppu::OWeakObject
* > ( this ) );
800 pMgr
->SetMergeSilent( sal_True
); // suppress dialogs, message boxes, etc.
801 const SwXMailMerge
*pOldSrc
= pMgr
->GetMailMergeEvtSrc();
802 OSL_ENSURE( !pOldSrc
|| pOldSrc
== this, "Ooops... different event source already set." );
803 pMgr
->SetMailMergeEvtSrc( this ); // launch events for listeners
805 SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE
, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE
), xCurDocSh
));
806 sal_Bool bSucc
= pMgr
->MergeNew( aMergeDesc
);
807 SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END
, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END
), xCurDocSh
));
809 pMgr
->SetMailMergeEvtSrc( pOldSrc
);
811 if ( xCurModel
.get() != xModel
.get() )
812 { // in case it was a temporary model -> close it, and delete the file
813 DeleteTmpFile_Impl( xCurModel
, xCurDocSh
, aTmpFileName
);
814 aTmpFileName
.Erase();
816 // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest)
819 throw Exception( OUString( "Mail merge failed. Sorry, no further information available." ), static_cast < cppu::OWeakObject
* > ( this ) );
821 //de-initialize services
822 if(xInService
.is() && xInService
->isConnected())
823 xInService
->disconnect();
824 if(aMergeDesc
.xSmtpServer
.is() && aMergeDesc
.xSmtpServer
->isConnected())
825 aMergeDesc
.xSmtpServer
->disconnect();
827 return makeAny( sal_True
);
830 void SwXMailMerge::LaunchMailMergeEvent( const MailMergeEvent
&rEvt
) const
832 cppu::OInterfaceIteratorHelper
aIt( ((SwXMailMerge
*) this)->aMergeListeners
);
833 while (aIt
.hasMoreElements())
835 Reference
< XMailMergeListener
> xRef( aIt
.next(), UNO_QUERY
);
837 xRef
->notifyMailMergeEvent( rEvt
);
841 void SwXMailMerge::launchEvent( const PropertyChangeEvent
&rEvt
) const
843 cppu::OInterfaceContainerHelper
*pContainer
=
844 aPropListeners
.getContainer( rEvt
.PropertyHandle
);
847 cppu::OInterfaceIteratorHelper
aIt( *pContainer
);
848 while (aIt
.hasMoreElements())
850 Reference
< XPropertyChangeListener
> xRef( aIt
.next(), UNO_QUERY
);
852 xRef
->propertyChange( rEvt
);
858 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
SwXMailMerge::getPropertySetInfo( )
859 throw (RuntimeException
)
861 SolarMutexGuard aGuard
;
862 static Reference
< XPropertySetInfo
> aRef
= pPropSet
->getPropertySetInfo();
866 void SAL_CALL
SwXMailMerge::setPropertyValue(
867 const OUString
& rPropertyName
, const uno::Any
& rValue
)
868 throw (UnknownPropertyException
, PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
870 SolarMutexGuard aGuard
;
872 const SfxItemPropertySimpleEntry
* pCur
= pPropSet
->getPropertyMap().getByName( rPropertyName
);
874 throw UnknownPropertyException();
875 else if (pCur
->nFlags
& PropertyAttribute::READONLY
)
876 throw PropertyVetoException();
880 const uno::Type
* pType
= pCur
->pType
;
883 case WID_SELECTION
: pData
= &aSelection
; break;
884 case WID_RESULT_SET
: pData
= &xResultSet
; break;
885 case WID_CONNECTION
: pData
= &xConnection
; break;
886 case WID_MODEL
: pData
= &xModel
; break;
887 case WID_DATA_SOURCE_NAME
: pData
= &aDataSourceName
; break;
888 case WID_DATA_COMMAND
: pData
= &aDataCommand
; break;
889 case WID_FILTER
: pData
= &aFilter
; break;
890 case WID_DOCUMENT_URL
: pData
= &aDocumentURL
; break;
891 case WID_OUTPUT_URL
: pData
= &aOutputURL
; break;
892 case WID_DATA_COMMAND_TYPE
: pData
= &nDataCommandType
; break;
893 case WID_OUTPUT_TYPE
: pData
= &nOutputType
; break;
894 case WID_ESCAPE_PROCESSING
: pData
= &bEscapeProcessing
; break;
895 case WID_SINGLE_PRINT_JOBS
: pData
= &bSinglePrintJobs
; break;
896 case WID_FILE_NAME_FROM_COLUMN
: pData
= &bFileNameFromColumn
; break;
897 case WID_FILE_NAME_PREFIX
: pData
= &aFileNamePrefix
; break;
898 case WID_MAIL_SUBJECT
: pData
= &sSubject
; break;
899 case WID_ADDRESS_FROM_COLUMN
: pData
= &sAddressFromColumn
; break;
900 case WID_SEND_AS_HTML
: pData
= &bSendAsHTML
; break;
901 case WID_SEND_AS_ATTACHMENT
: pData
= &bSendAsAttachment
; break;
902 case WID_MAIL_BODY
: pData
= &sMailBody
; break;
903 case WID_ATTACHMENT_NAME
: pData
= &sAttachmentName
; break;
904 case WID_ATTACHMENT_FILTER
: pData
= &sAttachmentFilter
;break;
905 case WID_PRINT_OPTIONS
: pData
= &aPrintSettings
; break;
906 case WID_SAVE_AS_SINGLE_FILE
: pData
= &bSaveAsSingleFile
; break;
907 case WID_SAVE_FILTER
: pData
= &sSaveFilter
; break;
908 case WID_SAVE_FILTER_OPTIONS
: pData
= &sSaveFilterOptions
; break;
909 case WID_SAVE_FILTER_DATA
: pData
= &aSaveFilterData
; break;
910 case WID_COPIES_TO
: pData
= &aCopiesTo
; break;
911 case WID_BLIND_COPIES_TO
: pData
= &aBlindCopiesTo
;break;
912 case WID_IN_SERVER_PASSWORD
: pData
= &sInServerPassword
; break;
913 case WID_OUT_SERVER_PASSWORD
: pData
= &sOutServerPassword
; break;
915 OSL_FAIL("unknown WID");
917 Any
aOld( pData
, *pType
);
919 bool bChanged
= false;
920 sal_Bool bOK
= sal_True
;
923 if (pData
== &aSelection
)
924 bOK
= rValue
>>= aSelection
;
925 else if (pData
== &xResultSet
)
926 bOK
= rValue
>>= xResultSet
;
927 else if (pData
== &xConnection
)
928 bOK
= rValue
>>= xConnection
;
929 else if (pData
== &xModel
)
930 bOK
= rValue
>>= xModel
;
931 else if (pData
== &aDataSourceName
)
932 bOK
= rValue
>>= aDataSourceName
;
933 else if (pData
== &aDataCommand
)
934 bOK
= rValue
>>= aDataCommand
;
935 else if (pData
== &aFilter
)
936 bOK
= rValue
>>= aFilter
;
937 else if (pData
== &aDocumentURL
)
940 bOK
= rValue
>>= aText
;
942 && !LoadFromURL_impl( xModel
, xDocSh
, aText
, true ))
943 throw RuntimeException( OUString( "Failed to create document from URL: " ) + aText
, static_cast < cppu::OWeakObject
* > ( this ) );
944 aDocumentURL
= aText
;
946 else if (pData
== &aOutputURL
)
949 bOK
= rValue
>>= aText
;
950 if (!aText
.isEmpty())
952 if (!UCB_IsDirectory(aText
))
953 throw IllegalArgumentException( OUString( "URL does not point to a directory: " ) + aText
, static_cast < cppu::OWeakObject
* > ( this ), 0 );
954 if (UCB_IsReadOnlyFileName(aText
))
955 throw IllegalArgumentException( OUString( "URL is read-only: " ) + aText
, static_cast < cppu::OWeakObject
* > ( this ), 0 );
959 else if (pData
== &nDataCommandType
)
960 bOK
= rValue
>>= nDataCommandType
;
961 else if (pData
== &nOutputType
)
962 bOK
= rValue
>>= nOutputType
;
963 else if (pData
== &bEscapeProcessing
)
964 bOK
= rValue
>>= bEscapeProcessing
;
965 else if (pData
== &bSinglePrintJobs
)
966 bOK
= rValue
>>= bSinglePrintJobs
;
967 else if (pData
== &bFileNameFromColumn
)
968 bOK
= rValue
>>= bFileNameFromColumn
;
969 else if (pData
== &aFileNamePrefix
)
970 bOK
= rValue
>>= aFileNamePrefix
;
971 else if (pData
== &sSubject
)
972 bOK
= rValue
>>= sSubject
;
973 else if (pData
== &sAddressFromColumn
)
974 bOK
= rValue
>>= sAddressFromColumn
;
975 else if (pData
== &bSendAsHTML
)
976 bOK
= rValue
>>= bSendAsHTML
;
977 else if (pData
== &bSendAsAttachment
)
978 bOK
= rValue
>>= bSendAsAttachment
;
979 else if (pData
== &sMailBody
)
980 bOK
= rValue
>>= sMailBody
;
981 else if (pData
== &sAttachmentName
)
982 bOK
= rValue
>>= sAttachmentName
;
983 else if (pData
== &sAttachmentFilter
)
984 bOK
= rValue
>>= sAttachmentFilter
;
985 else if (pData
== &aPrintSettings
)
986 bOK
= rValue
>>= aPrintSettings
;
987 else if (pData
== &bSaveAsSingleFile
)
988 bOK
= rValue
>>= bSaveAsSingleFile
;
989 else if (pData
== &sSaveFilter
)
990 bOK
= rValue
>>= sSaveFilter
;
991 else if (pData
== &sSaveFilterOptions
)
992 bOK
= rValue
>>= sSaveFilterOptions
;
993 else if (pData
== &aSaveFilterData
)
994 bOK
= rValue
>>= aSaveFilterData
;
995 else if (pData
== &aCopiesTo
)
996 bOK
= rValue
>>= aCopiesTo
;
997 else if (pData
== &aBlindCopiesTo
)
998 bOK
= rValue
>>= aBlindCopiesTo
;
999 else if(pData
== &sInServerPassword
)
1000 bOK
= rValue
>>= sInServerPassword
;
1001 else if(pData
== &sOutServerPassword
)
1002 bOK
= rValue
>>= sInServerPassword
;
1004 OSL_FAIL("invalid pointer" );
1006 OSL_ENSURE( bOK
, "set value failed" );
1010 throw IllegalArgumentException( OUString( "Property type mismatch or property not set: " ) + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ), 0 );
1014 PropertyChangeEvent
aChgEvt( (XPropertySet
*) this, rPropertyName
,
1015 sal_False
, pCur
->nWID
, aOld
, rValue
);
1016 launchEvent( aChgEvt
);
1021 uno::Any SAL_CALL
SwXMailMerge::getPropertyValue(
1022 const OUString
& rPropertyName
)
1023 throw (UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1025 SolarMutexGuard aGuard
;
1029 const SfxItemPropertySimpleEntry
* pCur
= pPropSet
->getPropertyMap().getByName( rPropertyName
);
1031 throw UnknownPropertyException();
1036 case WID_SELECTION
: aRet
<<= aSelection
; break;
1037 case WID_RESULT_SET
: aRet
<<= xResultSet
; break;
1038 case WID_CONNECTION
: aRet
<<= xConnection
; break;
1039 case WID_MODEL
: aRet
<<= xModel
; break;
1040 case WID_DATA_SOURCE_NAME
: aRet
<<= aDataSourceName
; break;
1041 case WID_DATA_COMMAND
: aRet
<<= aDataCommand
; break;
1042 case WID_FILTER
: aRet
<<= aFilter
; break;
1043 case WID_DOCUMENT_URL
: aRet
<<= aDocumentURL
; break;
1044 case WID_OUTPUT_URL
: aRet
<<= aOutputURL
; break;
1045 case WID_DATA_COMMAND_TYPE
: aRet
<<= nDataCommandType
; break;
1046 case WID_OUTPUT_TYPE
: aRet
<<= nOutputType
; break;
1047 case WID_ESCAPE_PROCESSING
: aRet
<<= bEscapeProcessing
; break;
1048 case WID_SINGLE_PRINT_JOBS
: aRet
<<= bSinglePrintJobs
; break;
1049 case WID_FILE_NAME_FROM_COLUMN
: aRet
<<= bFileNameFromColumn
; break;
1050 case WID_FILE_NAME_PREFIX
: aRet
<<= aFileNamePrefix
; break;
1051 case WID_MAIL_SUBJECT
: aRet
<<= sSubject
; break;
1052 case WID_ADDRESS_FROM_COLUMN
: aRet
<<= sAddressFromColumn
; break;
1053 case WID_SEND_AS_HTML
: aRet
<<= bSendAsHTML
; break;
1054 case WID_SEND_AS_ATTACHMENT
: aRet
<<= bSendAsAttachment
; break;
1055 case WID_MAIL_BODY
: aRet
<<= sMailBody
; break;
1056 case WID_ATTACHMENT_NAME
: aRet
<<= sAttachmentName
; break;
1057 case WID_ATTACHMENT_FILTER
: aRet
<<= sAttachmentFilter
;break;
1058 case WID_PRINT_OPTIONS
: aRet
<<= aPrintSettings
; break;
1059 case WID_SAVE_AS_SINGLE_FILE
: aRet
<<= bSaveAsSingleFile
; break;
1060 case WID_SAVE_FILTER
: aRet
<<= sSaveFilter
; break;
1061 case WID_SAVE_FILTER_OPTIONS
: aRet
<<= sSaveFilterOptions
; break;
1062 case WID_SAVE_FILTER_DATA
: aRet
<<= aSaveFilterData
; break;
1063 case WID_COPIES_TO
: aRet
<<= aCopiesTo
; break;
1064 case WID_BLIND_COPIES_TO
: aRet
<<= aBlindCopiesTo
;break;
1065 case WID_IN_SERVER_PASSWORD
: aRet
<<= sInServerPassword
; break;
1066 case WID_OUT_SERVER_PASSWORD
: aRet
<<= sOutServerPassword
; break;
1068 OSL_FAIL("unknown WID");
1075 void SAL_CALL
SwXMailMerge::addPropertyChangeListener(
1076 const OUString
& rPropertyName
,
1077 const uno::Reference
< beans::XPropertyChangeListener
>& rListener
)
1078 throw (UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1080 SolarMutexGuard aGuard
;
1081 if (!bDisposing
&& rListener
.is())
1083 const SfxItemPropertySimpleEntry
* pCur
= pPropSet
->getPropertyMap().getByName( rPropertyName
);
1085 aPropListeners
.addInterface( pCur
->nWID
, rListener
);
1087 throw UnknownPropertyException();
1091 void SAL_CALL
SwXMailMerge::removePropertyChangeListener(
1092 const OUString
& rPropertyName
,
1093 const uno::Reference
< beans::XPropertyChangeListener
>& rListener
)
1094 throw (UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1096 SolarMutexGuard aGuard
;
1097 if (!bDisposing
&& rListener
.is())
1099 const SfxItemPropertySimpleEntry
* pCur
= pPropSet
->getPropertyMap().getByName( rPropertyName
);
1101 aPropListeners
.removeInterface( pCur
->nWID
, rListener
);
1103 throw UnknownPropertyException();
1107 void SAL_CALL
SwXMailMerge::addVetoableChangeListener(
1108 const OUString
& /*rPropertyName*/,
1109 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/ )
1110 throw (UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1112 // no vetoable property, thus no support for vetoable change listeners
1113 OSL_FAIL("not implemented");
1116 void SAL_CALL
SwXMailMerge::removeVetoableChangeListener(
1117 const OUString
& /*rPropertyName*/,
1118 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/ )
1119 throw (UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1121 // no vetoable property, thus no support for vetoable change listeners
1122 OSL_FAIL("not implemented");
1126 void SAL_CALL
SwXMailMerge::dispose()
1127 throw(RuntimeException
)
1129 SolarMutexGuard aGuard
;
1133 bDisposing
= sal_True
;
1135 EventObject
aEvtObj( (XPropertySet
*) this );
1136 aEvtListeners
.disposeAndClear( aEvtObj
);
1137 aMergeListeners
.disposeAndClear( aEvtObj
);
1138 aPropListeners
.disposeAndClear( aEvtObj
);
1142 void SAL_CALL
SwXMailMerge::addEventListener(
1143 const Reference
< XEventListener
>& rxListener
)
1144 throw(RuntimeException
)
1146 SolarMutexGuard aGuard
;
1147 if (!bDisposing
&& rxListener
.is())
1148 aEvtListeners
.addInterface( rxListener
);
1151 void SAL_CALL
SwXMailMerge::removeEventListener(
1152 const Reference
< XEventListener
>& rxListener
)
1153 throw(RuntimeException
)
1155 SolarMutexGuard aGuard
;
1156 if (!bDisposing
&& rxListener
.is())
1157 aEvtListeners
.removeInterface( rxListener
);
1160 void SAL_CALL
SwXMailMerge::addMailMergeEventListener(
1161 const uno::Reference
< XMailMergeListener
>& rxListener
)
1162 throw (RuntimeException
)
1164 SolarMutexGuard aGuard
;
1165 if (!bDisposing
&& rxListener
.is())
1166 aMergeListeners
.addInterface( rxListener
);
1169 void SAL_CALL
SwXMailMerge::removeMailMergeEventListener(
1170 const uno::Reference
< XMailMergeListener
>& rxListener
)
1171 throw (RuntimeException
)
1173 SolarMutexGuard aGuard
;
1174 if (!bDisposing
&& rxListener
.is())
1175 aMergeListeners
.removeInterface( rxListener
);
1178 OUString SAL_CALL
SwXMailMerge::getImplementationName()
1179 throw(RuntimeException
)
1181 SolarMutexGuard aGuard
;
1182 return SwXMailMerge_getImplementationName();
1185 sal_Bool SAL_CALL
SwXMailMerge::supportsService( const OUString
& rServiceName
)
1186 throw(RuntimeException
)
1188 SolarMutexGuard aGuard
;
1189 return rServiceName
== SN_MAIL_MERGE
|| rServiceName
== SN_DATA_ACCESS_DESCRIPTOR
;
1192 uno::Sequence
< OUString
> SAL_CALL
SwXMailMerge::getSupportedServiceNames()
1193 throw(RuntimeException
)
1195 SolarMutexGuard aGuard
;
1196 return SwXMailMerge_getSupportedServiceNames();
1199 ////////////////////////////////////////////////////////////
1201 uno::Sequence
< OUString
> SAL_CALL
SwXMailMerge_getSupportedServiceNames()
1204 uno::Sequence
< OUString
> aNames(2);
1205 OUString
*pName
= aNames
.getArray();
1206 pName
[0] = SN_MAIL_MERGE
;
1207 pName
[1] = SN_DATA_ACCESS_DESCRIPTOR
;
1211 OUString SAL_CALL
SwXMailMerge_getImplementationName()
1214 return OUString( "SwXMailMerge" );
1217 uno::Reference
< uno::XInterface
> SAL_CALL
SwXMailMerge_createInstance(
1218 const uno::Reference
< XMultiServiceFactory
> & /*rSMgr*/)
1219 throw( uno::Exception
)
1221 SolarMutexGuard aGuard
;
1223 //the module may not be loaded
1224 SwGlobals::ensure();
1225 uno::Reference
< uno::XInterface
> xRef
= (cppu::OWeakObject
*) new SwXMailMerge();
1229 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */