Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <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>
26 : #include <unotools/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 <cppuhelper/supportsservice.hxx>
33 : #include <vcl/timer.hxx>
34 : #include <com/sun/star/sdb/CommandType.hpp>
35 : #include <com/sun/star/text/MailMergeType.hpp>
36 : #include <com/sun/star/text/MailMergeEvent.hpp>
37 : #include <com/sun/star/text/XMailMergeListener.hpp>
38 : #include <com/sun/star/text/XMailMergeBroadcaster.hpp>
39 : #include <com/sun/star/beans/PropertyAttribute.hpp>
40 : #include <com/sun/star/lang/XUnoTunnel.hpp>
41 : #include <com/sun/star/sdbc/XResultSet.hpp>
42 : #include <com/sun/star/sdbc/XConnection.hpp>
43 : #include <com/sun/star/sdbc/XRowSet.hpp>
44 : #include <com/sun/star/frame/Desktop.hpp>
45 : #include <com/sun/star/frame/XComponentLoader.hpp>
46 : #include <com/sun/star/util/XCloseable.hpp>
47 : #include <com/sun/star/util/CloseVetoException.hpp>
48 : #include <com/sun/star/sdbcx/XRowLocate.hpp>
49 : #include <com/sun/star/frame/XStorable.hpp>
50 : #include "com/sun/star/mail/XSmtpService.hpp"
51 : #include <sfx2/viewfrm.hxx>
52 : #include <sfx2/event.hxx>
53 : #include <swevent.hxx>
54 : #include <unomailmerge.hxx>
55 : #include <swdll.hxx>
56 : #include <swmodule.hxx>
57 : #include <unoprnms.hxx>
58 : #include <unomap.hxx>
59 : #include <swunohelper.hxx>
60 : #include <docsh.hxx>
61 : #include <IDocumentDeviceAccess.hxx>
62 : #include <view.hxx>
63 : #include <dbmgr.hxx>
64 : #include <unotxdoc.hxx>
65 : #include <prtopt.hxx>
66 : #include <wrtsh.hxx>
67 : #include <shellio.hxx>
68 : #include <mmconfigitem.hxx>
69 : #include <mailmergehelper.hxx>
70 :
71 : #include <unomid.h>
72 :
73 : #include <boost/scoped_ptr.hpp>
74 :
75 : using namespace ::com::sun::star;
76 : using namespace ::com::sun::star::frame;
77 : using namespace ::com::sun::star::uno;
78 : using namespace ::com::sun::star::lang;
79 : using namespace ::com::sun::star::beans;
80 : using namespace ::com::sun::star::text;
81 : using namespace SWUnoHelper;
82 :
83 : typedef ::utl::SharedUNOComponent< XInterface > SharedComponent;
84 :
85 0 : osl::Mutex & GetMailMergeMutex()
86 : {
87 0 : static osl::Mutex aMutex;
88 0 : return aMutex;
89 : }
90 :
91 : enum CloseResult
92 : {
93 : eSuccess, // successfully closed
94 : eVetoed, // vetoed, ownership transferred to the vetoing instance
95 : eFailed // failed for some unknown reason
96 : };
97 0 : static CloseResult CloseModelAndDocSh(
98 : Reference< frame::XModel > &rxModel,
99 : SfxObjectShellRef &rxDocSh )
100 : {
101 0 : CloseResult eResult = eSuccess;
102 :
103 0 : rxDocSh = 0;
104 :
105 : //! models/documents should never be disposed (they may still be
106 : //! used for printing which is called asynchronously for example)
107 : //! instead call close
108 0 : Reference< util::XCloseable > xClose( rxModel, UNO_QUERY );
109 0 : if (xClose.is())
110 : {
111 : try
112 : {
113 : //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
114 : //! I.e. now that object is responsible for closing the model and doc shell.
115 0 : xClose->close( sal_True );
116 : }
117 0 : catch (const util::CloseVetoException&)
118 : {
119 : //! here we have the problem that the temporary file that is
120 : //! currently being printed will never be deleted. :-(
121 0 : eResult = eVetoed;
122 : }
123 0 : catch (const uno::RuntimeException&)
124 : {
125 0 : eResult = eFailed;
126 : }
127 : }
128 0 : return eResult;
129 : }
130 :
131 0 : static bool LoadFromURL_impl(
132 : Reference< frame::XModel > &rxModel,
133 : SfxObjectShellRef &rxDocSh,
134 : const OUString &rURL,
135 : bool bClose )
136 : throw (RuntimeException)
137 : {
138 : // try to open the document readonly and hidden
139 0 : Reference< frame::XModel > xTmpModel;
140 0 : Sequence < PropertyValue > aArgs( 1 );
141 0 : aArgs[0].Name = "Hidden";
142 0 : sal_Bool bVal = sal_True;
143 0 : aArgs[0].Value <<= bVal;
144 : try
145 : {
146 0 : Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
147 0 : xTmpModel = Reference < XModel >( xDesktop->loadComponentFromURL(
148 0 : rURL, "_blank", 0, aArgs ), UNO_QUERY );
149 : }
150 0 : catch (const Exception&)
151 : {
152 0 : return false;
153 : }
154 :
155 : // try to get the DocShell
156 0 : SwDocShell *pTmpDocShell = 0;
157 0 : Reference < XUnoTunnel > xTunnel( xTmpModel, UNO_QUERY );
158 0 : if (xTunnel.is())
159 : {
160 : SwXTextDocument* pTextDoc = reinterpret_cast<SwXTextDocument *>(
161 0 : xTunnel->getSomething( SwXTextDocument::getUnoTunnelId() ));
162 0 : pTmpDocShell = pTextDoc ? pTextDoc->GetDocShell() : 0;
163 : }
164 :
165 0 : bool bRes = false;
166 0 : if (xTmpModel.is() && pTmpDocShell) // everything available?
167 : {
168 0 : if (bClose)
169 0 : CloseModelAndDocSh( rxModel, rxDocSh );
170 : // set new stuff
171 0 : rxModel = xTmpModel;
172 0 : rxDocSh = pTmpDocShell;
173 0 : bRes = true;
174 : }
175 : else
176 : {
177 : // SfxObjectShellRef is ok here, since the document will be explicitly closed
178 0 : SfxObjectShellRef xTmpDocSh = pTmpDocShell;
179 0 : CloseModelAndDocSh( xTmpModel, xTmpDocSh );
180 : }
181 :
182 0 : return bRes;
183 : }
184 :
185 : namespace
186 : {
187 : class DelayedFileDeletion : public ::cppu::WeakImplHelper1< util::XCloseListener >
188 : {
189 : protected:
190 : ::osl::Mutex m_aMutex;
191 : Reference< util::XCloseable > m_xDocument;
192 : Timer m_aDeleteTimer;
193 : OUString m_sTemporaryFile;
194 : sal_Int32 m_nPendingDeleteAttempts;
195 :
196 : public:
197 : DelayedFileDeletion( const Reference< XModel >& _rxModel,
198 : const OUString& _rTemporaryFile );
199 :
200 : protected:
201 : virtual ~DelayedFileDeletion( );
202 :
203 : // XCloseListener
204 : virtual void SAL_CALL queryClosing( const EventObject& _rSource, sal_Bool _bGetsOwnership ) throw (util::CloseVetoException, RuntimeException, std::exception) SAL_OVERRIDE;
205 : virtual void SAL_CALL notifyClosing( const EventObject& _rSource ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
206 :
207 : // XEventListener
208 : virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
209 :
210 : private:
211 : void implTakeOwnership( );
212 : DECL_LINK( OnTryDeleteFile, void* );
213 :
214 : private:
215 : DelayedFileDeletion( const DelayedFileDeletion& ); // never implemented
216 : DelayedFileDeletion& operator=( const DelayedFileDeletion& ); // never implemented
217 : };
218 :
219 0 : DelayedFileDeletion::DelayedFileDeletion( const Reference< XModel >& _rxModel, const OUString& _rTemporaryFile )
220 : :
221 : m_xDocument( _rxModel, UNO_QUERY )
222 : ,m_sTemporaryFile( _rTemporaryFile )
223 0 : ,m_nPendingDeleteAttempts( 0 )
224 : {
225 0 : osl_atomic_increment( &m_refCount );
226 : try
227 : {
228 0 : if ( m_xDocument.is() )
229 : {
230 0 : m_xDocument->addCloseListener( this );
231 : // successfully added -> keep ourself alive
232 0 : acquire();
233 : }
234 : else {
235 : OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: model is no component!" );
236 : }
237 : }
238 0 : catch (const Exception&)
239 : {
240 : OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: could not register as event listener at the model!" );
241 : }
242 0 : osl_atomic_decrement( &m_refCount );
243 0 : }
244 :
245 0 : IMPL_LINK_NOARG(DelayedFileDeletion, OnTryDeleteFile)
246 : {
247 0 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
248 :
249 0 : bool bSuccess = false;
250 : try
251 : {
252 0 : sal_Bool bDeliverOwnership = ( 0 == m_nPendingDeleteAttempts );
253 : // if this is our last attemt, then anybody which vetoes this has to take the consequences
254 : // (means take the ownership)
255 0 : m_xDocument->close( bDeliverOwnership );
256 0 : bSuccess = true;
257 : }
258 0 : catch (const util::CloseVetoException&)
259 : {
260 : // somebody vetoed -> next try
261 0 : if ( m_nPendingDeleteAttempts )
262 : {
263 : // next attempt
264 0 : --m_nPendingDeleteAttempts;
265 0 : m_aDeleteTimer.Start();
266 : }
267 : else
268 0 : bSuccess = true; // can't do anything here ...
269 : }
270 0 : catch (const Exception&)
271 : {
272 : OSL_FAIL("DelayedFileDeletion::OnTryDeleteFile: caught a strange exception!" );
273 0 : bSuccess = true;
274 : // can't do anything here ...
275 : }
276 :
277 0 : if ( bSuccess )
278 : {
279 0 : SWUnoHelper::UCB_DeleteFile( m_sTemporaryFile );
280 0 : aGuard.clear();
281 0 : release(); // this should be our last reference, we should be dead after this
282 : }
283 0 : return 0L;
284 : }
285 :
286 0 : void DelayedFileDeletion::implTakeOwnership( )
287 : {
288 : // revoke ourself as listener
289 : try
290 : {
291 0 : m_xDocument->removeCloseListener( this );
292 : }
293 0 : catch (const Exception&)
294 : {
295 : OSL_FAIL("DelayedFileDeletion::implTakeOwnership: could not revoke the listener!" );
296 : }
297 :
298 0 : m_aDeleteTimer.SetTimeout( 3000 ); // 3 seconds
299 0 : m_aDeleteTimer.SetTimeoutHdl( LINK( this, DelayedFileDeletion, OnTryDeleteFile ) );
300 0 : m_nPendingDeleteAttempts = 3; // try 3 times at most
301 0 : m_aDeleteTimer.Start( );
302 0 : }
303 :
304 0 : void SAL_CALL DelayedFileDeletion::queryClosing( const EventObject& , sal_Bool _bGetsOwnership ) throw (util::CloseVetoException, RuntimeException, std::exception)
305 : {
306 0 : ::osl::MutexGuard aGuard( m_aMutex );
307 0 : if ( _bGetsOwnership )
308 0 : implTakeOwnership( );
309 :
310 : // always veto: We want to take the ownership ourself, as this is the only chance to delete
311 : // the temporary file which the model is based on
312 0 : throw util::CloseVetoException( );
313 : }
314 :
315 0 : void SAL_CALL DelayedFileDeletion::notifyClosing( const EventObject& ) throw (RuntimeException, std::exception)
316 : {
317 : OSL_FAIL("DelayedFileDeletion::notifyClosing: how this?" );
318 : // this should not happen:
319 : // Either, a foreign instance closes the document, then we should veto this, and take the ownership
320 : // Or, we ourself close the document, then we should not be a listener anymore
321 0 : }
322 :
323 0 : void SAL_CALL DelayedFileDeletion::disposing( const EventObject& ) throw (RuntimeException, std::exception)
324 : {
325 : OSL_FAIL("DelayedFileDeletion::disposing: how this?" );
326 : // this should not happen:
327 : // Either, a foreign instance closes the document, then we should veto this, and take the ownership
328 : // Or, we ourself close the document, then we should not be a listener anymore
329 0 : }
330 :
331 0 : DelayedFileDeletion::~DelayedFileDeletion( )
332 : {
333 0 : }
334 : }
335 :
336 0 : static bool DeleteTmpFile_Impl(
337 : Reference< frame::XModel > &rxModel,
338 : SfxObjectShellRef &rxDocSh,
339 : const OUString &rTmpFileURL )
340 : {
341 0 : bool bRes = false;
342 0 : if (!rTmpFileURL.isEmpty())
343 : {
344 0 : bool bDelete = true;
345 0 : if ( eVetoed == CloseModelAndDocSh( rxModel, rxDocSh ) )
346 : {
347 : // somebody vetoed the closing, and took the ownership of the document
348 : // -> ensure that the temporary file is deleted later on
349 0 : Reference< XEventListener > xEnsureDelete( new DelayedFileDeletion( rxModel, rTmpFileURL ) );
350 : // note: as soon as #106931# is fixed, the whole DelayedFileDeletion is to be superseeded by
351 : // a better solution
352 0 : bDelete = false;
353 : }
354 :
355 0 : rxModel = 0;
356 0 : rxDocSh = 0; // destroy doc shell
357 :
358 0 : if ( bDelete )
359 : {
360 0 : if ( !SWUnoHelper::UCB_DeleteFile( rTmpFileURL ) )
361 : {
362 0 : Reference< XEventListener > xEnsureDelete( new DelayedFileDeletion( rxModel, rTmpFileURL ) );
363 : // same not as above: as soon as #106931#, ...
364 : }
365 : }
366 : else
367 0 : bRes = true; // file will be deleted delayed
368 : }
369 0 : return bRes;
370 : }
371 :
372 0 : SwXMailMerge::SwXMailMerge() :
373 0 : aEvtListeners ( GetMailMergeMutex() ),
374 0 : aMergeListeners ( GetMailMergeMutex() ),
375 0 : aPropListeners ( GetMailMergeMutex() ),
376 0 : pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_MAILMERGE ) ),
377 : nDataCommandType(sdb::CommandType::TABLE),
378 : nOutputType(MailMergeType::PRINTER),
379 : bEscapeProcessing(sal_True), //!! allow to process properties like "Filter", "Order", ...
380 : bSinglePrintJobs(sal_False),
381 : bFileNameFromColumn(sal_False),
382 : bSendAsHTML(sal_False),
383 : bSendAsAttachment(sal_False),
384 : bSaveAsSingleFile(sal_False),
385 : bDisposing(sal_False),
386 0 : m_pMgr(0)
387 : {
388 : // create empty document
389 : // like in: SwModule::InsertEnv (appenv.cxx)
390 0 : xDocSh = new SwDocShell( SFX_CREATE_MODE_STANDARD );
391 0 : xDocSh->DoInitNew( 0 );
392 0 : SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
393 0 : SwView *pView = (SwView*) pFrame->GetViewShell();
394 0 : pView->AttrChangedNotify( &pView->GetWrtShell() ); //So that SelectShell is called.
395 0 : xModel = xDocSh->GetModel();
396 0 : }
397 :
398 0 : SwXMailMerge::~SwXMailMerge()
399 : {
400 0 : if (!aTmpFileName.isEmpty())
401 0 : DeleteTmpFile_Impl( xModel, xDocSh, aTmpFileName );
402 : else // there was no temporary file in use
403 : {
404 : //! we still need to close the model and doc shell manually
405 : //! because there is no automatism that will do that later.
406 : //! #120086#
407 0 : if ( eVetoed == CloseModelAndDocSh( xModel, xDocSh ) )
408 : OSL_FAIL("owner ship transfered to vetoing object!" );
409 :
410 0 : xModel = 0;
411 0 : xDocSh = 0; // destroy doc shell
412 : }
413 0 : }
414 :
415 : // Guarantee object consistence in case of an exception
416 : class MailMergeExecuteFinalizer {
417 : public:
418 0 : MailMergeExecuteFinalizer(SwXMailMerge *mailmerge)
419 0 : : m_pMailMerge(mailmerge)
420 : {
421 : assert(m_pMailMerge); //mailmerge object missing
422 0 : }
423 0 : ~MailMergeExecuteFinalizer()
424 : {
425 0 : osl::MutexGuard pMgrGuard( GetMailMergeMutex() );
426 0 : m_pMailMerge->m_pMgr = 0;
427 0 : }
428 :
429 : private:
430 : // Disallow copy
431 : MailMergeExecuteFinalizer(const MailMergeExecuteFinalizer&) {}
432 :
433 : SwXMailMerge *m_pMailMerge;
434 : };
435 :
436 0 : uno::Any SAL_CALL SwXMailMerge::execute(
437 : const uno::Sequence< beans::NamedValue >& rArguments )
438 : throw (IllegalArgumentException, Exception,
439 : RuntimeException, std::exception)
440 : {
441 0 : SolarMutexGuard aGuard;
442 0 : MailMergeExecuteFinalizer aFinalizer(this);
443 :
444 : // get property values to be used
445 : // (use values from the service as default and override them with
446 : // the values that are provided as arguments)
447 :
448 0 : uno::Sequence< uno::Any > aCurSelection = aSelection;
449 0 : uno::Reference< sdbc::XResultSet > xCurResultSet = xResultSet;
450 0 : uno::Reference< sdbc::XConnection > xCurConnection = xConnection;
451 0 : uno::Reference< frame::XModel > xCurModel = xModel;
452 0 : OUString aCurDataSourceName = aDataSourceName;
453 0 : OUString aCurDataCommand = aDataCommand;
454 0 : OUString aCurFilter = aFilter;
455 0 : OUString aCurDocumentURL = aDocumentURL;
456 0 : OUString aCurOutputURL = aOutputURL;
457 0 : OUString aCurFileNamePrefix = aFileNamePrefix;
458 0 : sal_Int32 nCurDataCommandType = nDataCommandType;
459 0 : sal_Int16 nCurOutputType = nOutputType;
460 0 : sal_Bool bCurEscapeProcessing = bEscapeProcessing;
461 0 : sal_Bool bCurSinglePrintJobs = bSinglePrintJobs;
462 0 : sal_Bool bCurFileNameFromColumn = bFileNameFromColumn;
463 :
464 0 : SfxObjectShellRef xCurDocSh = xDocSh; // the document
465 :
466 0 : const beans::NamedValue *pArguments = rArguments.getConstArray();
467 0 : sal_Int32 nArgs = rArguments.getLength();
468 0 : for (sal_Int32 i = 0; i < nArgs; ++i)
469 : {
470 0 : const OUString &rName = pArguments[i].Name;
471 0 : const Any &rValue = pArguments[i].Value;
472 :
473 0 : sal_Bool bOK = sal_True;
474 0 : if (rName == UNO_NAME_SELECTION)
475 0 : bOK = rValue >>= aCurSelection;
476 0 : else if (rName == UNO_NAME_RESULT_SET)
477 0 : bOK = rValue >>= xCurResultSet;
478 0 : else if (rName == UNO_NAME_CONNECTION)
479 0 : bOK = rValue >>= xCurConnection;
480 0 : else if (rName == UNO_NAME_MODEL)
481 0 : throw PropertyVetoException("Property is read-only: " + rName, static_cast < cppu::OWeakObject * > ( this ) );
482 0 : else if (rName == UNO_NAME_DATA_SOURCE_NAME)
483 0 : bOK = rValue >>= aCurDataSourceName;
484 0 : else if (rName == UNO_NAME_DAD_COMMAND)
485 0 : bOK = rValue >>= aCurDataCommand;
486 0 : else if (rName == UNO_NAME_FILTER)
487 0 : bOK = rValue >>= aCurFilter;
488 0 : else if (rName == UNO_NAME_DOCUMENT_URL)
489 : {
490 0 : bOK = rValue >>= aCurDocumentURL;
491 0 : if (!aCurDocumentURL.isEmpty()
492 0 : && !LoadFromURL_impl( xCurModel, xCurDocSh, aCurDocumentURL, false ))
493 0 : throw RuntimeException("Failed to create document from URL: " + aCurDocumentURL, static_cast < cppu::OWeakObject * > ( this ) );
494 : }
495 0 : else if (rName == UNO_NAME_OUTPUT_URL)
496 : {
497 0 : bOK = rValue >>= aCurOutputURL;
498 0 : if (!aCurOutputURL.isEmpty())
499 : {
500 0 : if (!UCB_IsDirectory(aCurOutputURL))
501 0 : throw IllegalArgumentException("URL does not point to a directory: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 0 );
502 0 : if (UCB_IsReadOnlyFileName(aCurOutputURL))
503 0 : throw IllegalArgumentException("URL is read-only: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 0 );
504 : }
505 : }
506 0 : else if (rName == UNO_NAME_FILE_NAME_PREFIX)
507 0 : bOK = rValue >>= aCurFileNamePrefix;
508 0 : else if (rName == UNO_NAME_DAD_COMMAND_TYPE)
509 0 : bOK = rValue >>= nCurDataCommandType;
510 0 : else if (rName == UNO_NAME_OUTPUT_TYPE)
511 0 : bOK = rValue >>= nCurOutputType;
512 0 : else if (rName == UNO_NAME_ESCAPE_PROCESSING)
513 0 : bOK = rValue >>= bCurEscapeProcessing;
514 0 : else if (rName == UNO_NAME_SINGLE_PRINT_JOBS)
515 0 : bOK = rValue >>= bCurSinglePrintJobs;
516 0 : else if (rName == UNO_NAME_FILE_NAME_FROM_COLUMN)
517 0 : bOK = rValue >>= bCurFileNameFromColumn;
518 0 : else if (rName == UNO_NAME_SUBJECT)
519 0 : bOK = rValue >>= sSubject;
520 0 : else if (rName == UNO_NAME_ADDRESS_FROM_COLUMN)
521 0 : bOK = rValue >>= sAddressFromColumn;
522 0 : else if (rName == UNO_NAME_SEND_AS_HTML)
523 0 : bOK = rValue >>= bSendAsHTML;
524 0 : else if (rName == UNO_NAME_MAIL_BODY)
525 0 : bOK = rValue >>= sMailBody;
526 0 : else if (rName == UNO_NAME_ATTACHMENT_NAME)
527 0 : bOK = rValue >>= sAttachmentName;
528 0 : else if (rName == UNO_NAME_ATTACHMENT_FILTER)
529 0 : bOK = rValue >>= sAttachmentFilter;
530 0 : else if (rName == UNO_NAME_COPIES_TO)
531 0 : bOK = rValue >>= aCopiesTo;
532 0 : else if (rName == UNO_NAME_BLIND_COPIES_TO)
533 0 : bOK = rValue >>= aBlindCopiesTo;
534 0 : else if (rName == UNO_NAME_SEND_AS_ATTACHMENT)
535 0 : bOK = rValue >>= bSendAsAttachment;
536 0 : else if (rName == UNO_NAME_PRINT_OPTIONS)
537 0 : bOK = rValue >>= aPrintSettings;
538 0 : else if (rName == UNO_NAME_SAVE_AS_SINGLE_FILE)
539 0 : bOK = rValue >>= bSaveAsSingleFile;
540 0 : else if (rName == UNO_NAME_SAVE_FILTER)
541 0 : bOK = rValue >>= sSaveFilter;
542 0 : else if (rName == UNO_NAME_SAVE_FILTER_OPTIONS)
543 0 : bOK = rValue >>= sSaveFilterOptions;
544 0 : else if (rName == UNO_NAME_SAVE_FILTER_DATA)
545 0 : bOK = rValue >>= aSaveFilterData;
546 0 : else if (rName == UNO_NAME_IN_SERVER_PASSWORD)
547 0 : bOK = rValue >>= sInServerPassword;
548 0 : else if (rName == UNO_NAME_OUT_SERVER_PASSWORD)
549 0 : bOK = rValue >>= sOutServerPassword;
550 : else
551 0 : throw UnknownPropertyException( OUString( "Property is unknown: " ) + rName, static_cast < cppu::OWeakObject * > ( this ) );
552 :
553 0 : if (!bOK)
554 0 : throw IllegalArgumentException("Property type mismatch or property not set: " + rName, static_cast < cppu::OWeakObject * > ( this ), 0 );
555 : }
556 :
557 : // need to translate the selection: the API here requires a sequence of bookmarks, but the MergeNew
558 : // method we will call below requires a sequence of indicies.
559 0 : if ( aCurSelection.getLength() )
560 : {
561 0 : Sequence< Any > aTranslated( aCurSelection.getLength() );
562 :
563 0 : bool bValid = false;
564 0 : Reference< sdbcx::XRowLocate > xRowLocate( xCurResultSet, UNO_QUERY );
565 0 : if ( xRowLocate.is() )
566 : {
567 :
568 0 : const Any* pBookmarks = aCurSelection.getConstArray();
569 0 : const Any* pBookmarksEnd = pBookmarks + aCurSelection.getLength();
570 0 : Any* pTranslated = aTranslated.getArray();
571 :
572 : try
573 : {
574 0 : bool bEverythingsFine = true;
575 0 : for ( ; ( pBookmarks != pBookmarksEnd ) && bEverythingsFine; ++pBookmarks )
576 : {
577 0 : if ( xRowLocate->moveToBookmark( *pBookmarks ) )
578 0 : *pTranslated <<= xCurResultSet->getRow();
579 : else
580 0 : bEverythingsFine = false;
581 : }
582 0 : if ( bEverythingsFine )
583 0 : bValid = true;
584 : }
585 0 : catch (const Exception&)
586 : {
587 0 : bValid = false;
588 : }
589 : }
590 :
591 0 : if ( !bValid )
592 : {
593 : throw IllegalArgumentException(
594 : OUString( "The current 'Selection' does not describe a valid array of bookmarks, relative to the current 'ResultSet'." ),
595 : static_cast < cppu::OWeakObject * > ( this ),
596 : 0
597 0 : );
598 : }
599 :
600 0 : aCurSelection = aTranslated;
601 : }
602 :
603 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( xCurDocSh, false);
604 0 : SwView *pView = pFrame ? PTR_CAST( SwView, pFrame->GetViewShell() ) : NULL;
605 0 : if (!pView)
606 0 : throw RuntimeException();
607 0 : SwWrtShell &rSh = *pView->GetWrtShellPtr();
608 :
609 : // avoid assertion in 'Update' from Sfx by supplying a shell
610 : // and thus avoiding the SelectShell call in Writers GetState function
611 : // while still in Update of Sfx.
612 : // (GetSelection in Update is not allowed)
613 0 : if (!aCurDocumentURL.isEmpty())
614 0 : pView->AttrChangedNotify( &pView->GetWrtShell() );//So that SelectShell is called.
615 :
616 0 : SharedComponent aRowSetDisposeHelper;
617 0 : if (!xCurResultSet.is())
618 : {
619 0 : if (aCurDataSourceName.isEmpty() || aCurDataCommand.isEmpty() )
620 : {
621 : OSL_FAIL("PropertyValues missing or unset");
622 0 : throw IllegalArgumentException("Either the ResultSet or DataSourceName and DataCommand must be set.", static_cast < cppu::OWeakObject * > ( this ), 0 );
623 : }
624 :
625 : // build ResultSet from DataSourceName, DataCommand and DataCommandType
626 :
627 0 : Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
628 0 : if (xMgr.is())
629 : {
630 0 : Reference< XInterface > xInstance = xMgr->createInstance( "com.sun.star.sdb.RowSet" );
631 0 : aRowSetDisposeHelper.reset( xInstance, SharedComponent::TakeOwnership );
632 0 : Reference< XPropertySet > xRowSetPropSet( xInstance, UNO_QUERY );
633 : OSL_ENSURE( xRowSetPropSet.is(), "failed to get XPropertySet interface from RowSet" );
634 0 : if (xRowSetPropSet.is())
635 : {
636 0 : if (xCurConnection.is())
637 0 : xRowSetPropSet->setPropertyValue( "ActiveConnection", makeAny( xCurConnection ) );
638 0 : xRowSetPropSet->setPropertyValue( "DataSourceName", makeAny( aCurDataSourceName ) );
639 0 : xRowSetPropSet->setPropertyValue( "Command", makeAny( aCurDataCommand ) );
640 0 : xRowSetPropSet->setPropertyValue( "CommandType", makeAny( nCurDataCommandType ) );
641 0 : xRowSetPropSet->setPropertyValue( "EscapeProcessing", makeAny( bCurEscapeProcessing ) );
642 0 : xRowSetPropSet->setPropertyValue( "ApplyFilter", makeAny( sal_True ) );
643 0 : xRowSetPropSet->setPropertyValue( "Filter", makeAny( aCurFilter ) );
644 :
645 0 : Reference< sdbc::XRowSet > xRowSet( xInstance, UNO_QUERY );
646 0 : if (xRowSet.is())
647 0 : xRowSet->execute(); // build ResultSet from properties
648 0 : if( !xCurConnection.is() )
649 0 : xCurConnection.set( xRowSetPropSet->getPropertyValue( "ActiveConnection" ), UNO_QUERY );
650 0 : xCurResultSet = Reference< sdbc::XResultSet >( xRowSet, UNO_QUERY );
651 0 : OSL_ENSURE( xCurResultSet.is(), "failed to build ResultSet" );
652 0 : }
653 0 : }
654 : }
655 :
656 0 : svx::ODataAccessDescriptor aDescriptor;
657 0 : aDescriptor.setDataSource(aCurDataSourceName);
658 0 : aDescriptor[ svx::daConnection ] <<= xCurConnection;
659 0 : aDescriptor[ svx::daCommand ] <<= aCurDataCommand;
660 0 : aDescriptor[ svx::daCommandType ] <<= nCurDataCommandType;
661 0 : aDescriptor[ svx::daEscapeProcessing ] <<= bCurEscapeProcessing;
662 0 : aDescriptor[ svx::daCursor ] <<= xCurResultSet;
663 : // aDescriptor[ svx::daColumnName ] not used
664 : // aDescriptor[ svx::daColumnObject ] not used
665 0 : aDescriptor[ svx::daSelection ] <<= aCurSelection;
666 :
667 : sal_uInt16 nMergeType;
668 0 : switch (nCurOutputType)
669 : {
670 0 : case MailMergeType::PRINTER : nMergeType = DBMGR_MERGE_MAILMERGE; break;
671 0 : case MailMergeType::FILE : nMergeType = DBMGR_MERGE_MAILFILES; break;
672 0 : case MailMergeType::MAIL : nMergeType = DBMGR_MERGE_MAILING; break;
673 : default:
674 0 : throw IllegalArgumentException("Invalid value of property: OutputType", static_cast < cppu::OWeakObject * > ( this ), 0 );
675 : }
676 :
677 0 : SwNewDBMgr* pMgr = rSh.GetNewDBMgr();
678 : //force layout creation
679 0 : rSh.CalcLayout();
680 : OSL_ENSURE( pMgr, "database manager missing" );
681 0 : m_pMgr = pMgr;
682 :
683 0 : SwMergeDescriptor aMergeDesc( nMergeType, rSh, aDescriptor );
684 :
685 0 : boost::scoped_ptr< SwMailMergeConfigItem > pMMConfigItem;
686 0 : uno::Reference< mail::XMailService > xInService;
687 0 : if (MailMergeType::PRINTER == nCurOutputType)
688 : {
689 0 : IDocumentDeviceAccess* pIDDA = rSh.getIDocumentDeviceAccess();
690 0 : SwPrintData aPrtData( pIDDA->getPrintData() );
691 0 : aPrtData.SetPrintSingleJobs( bCurSinglePrintJobs );
692 0 : pIDDA->setPrintData( aPrtData );
693 : // #i25686# printing should not be done asynchronously to prevent dangling offices
694 : // when mail merge is called as command line macro
695 0 : aMergeDesc.bPrintAsync = sal_False;
696 0 : aMergeDesc.aPrintOptions = aPrintSettings;
697 0 : aMergeDesc.bCreateSingleFile = true;
698 : }
699 : else /* FILE and MAIL*/
700 : {
701 0 : INetURLObject aURLObj;
702 0 : aURLObj.SetSmartProtocol( INET_PROT_FILE );
703 :
704 0 : if (!aCurDocumentURL.isEmpty())
705 : {
706 : // if OutputURL or FileNamePrefix are missing get
707 : // them from DocumentURL
708 0 : aURLObj.SetSmartURL( aCurDocumentURL );
709 0 : if (aCurFileNamePrefix.isEmpty())
710 0 : aCurFileNamePrefix = aURLObj.GetBase(); // filename without extension
711 0 : if (aCurOutputURL.isEmpty())
712 : {
713 0 : aURLObj.removeSegment();
714 0 : aCurOutputURL = aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
715 : }
716 : }
717 : else // default empty document without URL
718 : {
719 0 : if (aCurOutputURL.isEmpty())
720 0 : throw RuntimeException("OutputURL is not set and can not be obtained.", static_cast < cppu::OWeakObject * > ( this ) );
721 : }
722 :
723 0 : aURLObj.SetSmartURL( aCurOutputURL );
724 0 : OUString aPath = aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
725 :
726 0 : const OUString aDelim( "/" );
727 0 : if (!aPath.isEmpty() && !aPath.endsWith(aDelim))
728 0 : aPath += aDelim;
729 0 : if (bCurFileNameFromColumn)
730 0 : pMgr->SetEMailColumn( aCurFileNamePrefix );
731 : else
732 : {
733 0 : aPath += aCurFileNamePrefix;
734 0 : pMgr->SetEMailColumn( OUString() );
735 : }
736 0 : pMgr->SetSubject( aPath );
737 0 : if(MailMergeType::FILE == nCurOutputType)
738 : {
739 0 : aMergeDesc.sSaveToFilter = sSaveFilter;
740 0 : aMergeDesc.sSaveToFilterOptions = sSaveFilterOptions;
741 0 : aMergeDesc.aSaveToFilterData = aSaveFilterData;
742 0 : aMergeDesc.bCreateSingleFile = bSaveAsSingleFile;
743 : }
744 : else
745 : {
746 0 : pMgr->SetEMailColumn( sAddressFromColumn );
747 0 : if(sAddressFromColumn.isEmpty())
748 0 : throw RuntimeException("Mail address column not set.", static_cast < cppu::OWeakObject * > ( this ) );
749 0 : aMergeDesc.sSaveToFilter = sAttachmentFilter;
750 0 : aMergeDesc.sSubject = sSubject;
751 0 : aMergeDesc.sMailBody = sMailBody;
752 0 : aMergeDesc.sAttachmentName = sAttachmentName;
753 0 : aMergeDesc.aCopiesTo = aCopiesTo;
754 0 : aMergeDesc.aBlindCopiesTo = aBlindCopiesTo;
755 0 : aMergeDesc.bSendAsHTML = bSendAsHTML;
756 0 : aMergeDesc.bSendAsAttachment = bSendAsAttachment;
757 :
758 0 : aMergeDesc.bCreateSingleFile = sal_False;
759 0 : pMMConfigItem.reset(new SwMailMergeConfigItem);
760 0 : aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
761 0 : aMergeDesc.xSmtpServer = SwMailMergeHelper::ConnectToSmtpServer(
762 0 : *pMMConfigItem,
763 : xInService,
764 0 : sInServerPassword, sOutServerPassword );
765 0 : if( !aMergeDesc.xSmtpServer.is() || !aMergeDesc.xSmtpServer->isConnected())
766 0 : throw RuntimeException("Failed to connect to mail server.", static_cast < cppu::OWeakObject * > ( this ) );
767 0 : }
768 : }
769 :
770 : // save document with temporary filename
771 : const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat(
772 : OUString( FILTER_XML ),
773 0 : SwDocShell::Factory().GetFilterContainer() );
774 0 : OUString aExtension(comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(), '*'));
775 0 : utl::TempFile aTempFile( OUString("SwMM"), &aExtension );
776 0 : aTmpFileName = aTempFile.GetURL();
777 :
778 0 : Reference< XStorable > xStorable( xCurModel, UNO_QUERY );
779 0 : bool bStoredAsTemporary = false;
780 0 : if ( xStorable.is() )
781 : {
782 : try
783 : {
784 0 : xStorable->storeAsURL( aTmpFileName, Sequence< PropertyValue >() );
785 0 : bStoredAsTemporary = true;
786 : }
787 0 : catch (const Exception&)
788 : {
789 : }
790 : }
791 0 : if ( !bStoredAsTemporary )
792 0 : throw RuntimeException("Failed to save temporary file.", static_cast < cppu::OWeakObject * > ( this ) );
793 :
794 0 : pMgr->SetMergeSilent( sal_True ); // suppress dialogs, message boxes, etc.
795 0 : const SwXMailMerge *pOldSrc = pMgr->GetMailMergeEvtSrc();
796 : OSL_ENSURE( !pOldSrc || pOldSrc == this, "Ooops... different event source already set." );
797 0 : pMgr->SetMailMergeEvtSrc( this ); // launch events for listeners
798 :
799 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xCurDocSh));
800 0 : sal_Bool bSucc = pMgr->MergeNew( aMergeDesc );
801 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), xCurDocSh));
802 :
803 0 : pMgr->SetMailMergeEvtSrc( pOldSrc );
804 :
805 0 : if ( xCurModel.get() != xModel.get() )
806 : { // in case it was a temporary model -> close it, and delete the file
807 0 : DeleteTmpFile_Impl( xCurModel, xCurDocSh, aTmpFileName );
808 0 : aTmpFileName = "";
809 : }
810 : // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest)
811 :
812 0 : if (!bSucc)
813 0 : throw Exception("Mail merge failed. Sorry, no further information available.", static_cast < cppu::OWeakObject * > ( this ) );
814 :
815 : //de-initialize services
816 0 : if(xInService.is() && xInService->isConnected())
817 0 : xInService->disconnect();
818 0 : if(aMergeDesc.xSmtpServer.is() && aMergeDesc.xSmtpServer->isConnected())
819 0 : aMergeDesc.xSmtpServer->disconnect();
820 :
821 0 : return makeAny( sal_True );
822 : }
823 :
824 0 : void SAL_CALL SwXMailMerge::cancel() throw (com::sun::star::uno::RuntimeException, std::exception)
825 : {
826 : // Cancel may be called from a second thread, so this protects from m_pMgr
827 : /// cleanup in the execute function.
828 0 : osl::MutexGuard pMgrGuard( GetMailMergeMutex() );
829 0 : if (m_pMgr)
830 0 : m_pMgr->MergeCancel();
831 0 : }
832 :
833 0 : void SwXMailMerge::LaunchMailMergeEvent( const MailMergeEvent &rEvt ) const
834 : {
835 0 : cppu::OInterfaceIteratorHelper aIt( ((SwXMailMerge *) this)->aMergeListeners );
836 0 : while (aIt.hasMoreElements())
837 : {
838 0 : Reference< XMailMergeListener > xRef( aIt.next(), UNO_QUERY );
839 0 : if (xRef.is())
840 0 : xRef->notifyMailMergeEvent( rEvt );
841 0 : }
842 0 : }
843 :
844 0 : void SwXMailMerge::launchEvent( const PropertyChangeEvent &rEvt ) const
845 : {
846 : cppu::OInterfaceContainerHelper *pContainer =
847 0 : aPropListeners.getContainer( rEvt.PropertyHandle );
848 0 : if (pContainer)
849 : {
850 0 : cppu::OInterfaceIteratorHelper aIt( *pContainer );
851 0 : while (aIt.hasMoreElements())
852 : {
853 0 : Reference< XPropertyChangeListener > xRef( aIt.next(), UNO_QUERY );
854 0 : if (xRef.is())
855 0 : xRef->propertyChange( rEvt );
856 0 : }
857 : }
858 0 : }
859 :
860 0 : uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXMailMerge::getPropertySetInfo( )
861 : throw (RuntimeException, std::exception)
862 : {
863 0 : SolarMutexGuard aGuard;
864 0 : static Reference< XPropertySetInfo > aRef = pPropSet->getPropertySetInfo();
865 0 : return aRef;
866 : }
867 :
868 0 : void SAL_CALL SwXMailMerge::setPropertyValue(
869 : const OUString& rPropertyName, const uno::Any& rValue )
870 : throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception)
871 : {
872 0 : SolarMutexGuard aGuard;
873 :
874 0 : const SfxItemPropertySimpleEntry* pCur = pPropSet->getPropertyMap().getByName( rPropertyName );
875 0 : if (!pCur)
876 0 : throw UnknownPropertyException();
877 0 : else if (pCur->nFlags & PropertyAttribute::READONLY)
878 0 : throw PropertyVetoException();
879 : else
880 : {
881 0 : void *pData = NULL;
882 0 : switch (pCur->nWID)
883 : {
884 0 : case WID_SELECTION : pData = &aSelection; break;
885 0 : case WID_RESULT_SET : pData = &xResultSet; break;
886 0 : case WID_CONNECTION : pData = &xConnection; break;
887 0 : case WID_MODEL : pData = &xModel; break;
888 0 : case WID_DATA_SOURCE_NAME : pData = &aDataSourceName; break;
889 0 : case WID_DATA_COMMAND : pData = &aDataCommand; break;
890 0 : case WID_FILTER : pData = &aFilter; break;
891 0 : case WID_DOCUMENT_URL : pData = &aDocumentURL; break;
892 0 : case WID_OUTPUT_URL : pData = &aOutputURL; break;
893 0 : case WID_DATA_COMMAND_TYPE : pData = &nDataCommandType; break;
894 0 : case WID_OUTPUT_TYPE : pData = &nOutputType; break;
895 0 : case WID_ESCAPE_PROCESSING : pData = &bEscapeProcessing; break;
896 0 : case WID_SINGLE_PRINT_JOBS : pData = &bSinglePrintJobs; break;
897 0 : case WID_FILE_NAME_FROM_COLUMN : pData = &bFileNameFromColumn; break;
898 0 : case WID_FILE_NAME_PREFIX : pData = &aFileNamePrefix; break;
899 0 : case WID_MAIL_SUBJECT: pData = &sSubject; break;
900 0 : case WID_ADDRESS_FROM_COLUMN: pData = &sAddressFromColumn; break;
901 0 : case WID_SEND_AS_HTML: pData = &bSendAsHTML; break;
902 0 : case WID_SEND_AS_ATTACHMENT: pData = &bSendAsAttachment; break;
903 0 : case WID_MAIL_BODY: pData = &sMailBody; break;
904 0 : case WID_ATTACHMENT_NAME: pData = &sAttachmentName; break;
905 0 : case WID_ATTACHMENT_FILTER: pData = &sAttachmentFilter;break;
906 0 : case WID_PRINT_OPTIONS: pData = &aPrintSettings; break;
907 0 : case WID_SAVE_AS_SINGLE_FILE: pData = &bSaveAsSingleFile; break;
908 0 : case WID_SAVE_FILTER: pData = &sSaveFilter; break;
909 0 : case WID_SAVE_FILTER_OPTIONS: pData = &sSaveFilterOptions; break;
910 0 : case WID_SAVE_FILTER_DATA: pData = &aSaveFilterData; break;
911 0 : case WID_COPIES_TO: pData = &aCopiesTo; break;
912 0 : case WID_BLIND_COPIES_TO: pData = &aBlindCopiesTo;break;
913 0 : case WID_IN_SERVER_PASSWORD: pData = &sInServerPassword; break;
914 0 : case WID_OUT_SERVER_PASSWORD: pData = &sOutServerPassword; break;
915 : default :
916 : OSL_FAIL("unknown WID");
917 : }
918 0 : Any aOld( pData, pCur->aType );
919 :
920 0 : bool bChanged = false;
921 0 : sal_Bool bOK = sal_True;
922 0 : if (aOld != rValue)
923 : {
924 0 : if (pData == &aSelection)
925 0 : bOK = rValue >>= aSelection;
926 0 : else if (pData == &xResultSet)
927 0 : bOK = rValue >>= xResultSet;
928 0 : else if (pData == &xConnection)
929 0 : bOK = rValue >>= xConnection;
930 0 : else if (pData == &xModel)
931 0 : bOK = rValue >>= xModel;
932 0 : else if (pData == &aDataSourceName)
933 0 : bOK = rValue >>= aDataSourceName;
934 0 : else if (pData == &aDataCommand)
935 0 : bOK = rValue >>= aDataCommand;
936 0 : else if (pData == &aFilter)
937 0 : bOK = rValue >>= aFilter;
938 0 : else if (pData == &aDocumentURL)
939 : {
940 0 : OUString aText;
941 0 : bOK = rValue >>= aText;
942 0 : if (!aText.isEmpty()
943 0 : && !LoadFromURL_impl( xModel, xDocSh, aText, true ))
944 0 : throw RuntimeException("Failed to create document from URL: " + aText, static_cast < cppu::OWeakObject * > ( this ) );
945 0 : aDocumentURL = aText;
946 : }
947 0 : else if (pData == &aOutputURL)
948 : {
949 0 : OUString aText;
950 0 : bOK = rValue >>= aText;
951 0 : if (!aText.isEmpty())
952 : {
953 0 : if (!UCB_IsDirectory(aText))
954 0 : throw IllegalArgumentException("URL does not point to a directory: " + aText, static_cast < cppu::OWeakObject * > ( this ), 0 );
955 0 : if (UCB_IsReadOnlyFileName(aText))
956 0 : throw IllegalArgumentException("URL is read-only: " + aText, static_cast < cppu::OWeakObject * > ( this ), 0 );
957 : }
958 0 : aOutputURL = aText;
959 : }
960 0 : else if (pData == &nDataCommandType)
961 0 : bOK = rValue >>= nDataCommandType;
962 0 : else if (pData == &nOutputType)
963 0 : bOK = rValue >>= nOutputType;
964 0 : else if (pData == &bEscapeProcessing)
965 0 : bOK = rValue >>= bEscapeProcessing;
966 0 : else if (pData == &bSinglePrintJobs)
967 0 : bOK = rValue >>= bSinglePrintJobs;
968 0 : else if (pData == &bFileNameFromColumn)
969 0 : bOK = rValue >>= bFileNameFromColumn;
970 0 : else if (pData == &aFileNamePrefix)
971 0 : bOK = rValue >>= aFileNamePrefix;
972 0 : else if (pData == &sSubject)
973 0 : bOK = rValue >>= sSubject;
974 0 : else if (pData == &sAddressFromColumn)
975 0 : bOK = rValue >>= sAddressFromColumn;
976 0 : else if (pData == &bSendAsHTML)
977 0 : bOK = rValue >>= bSendAsHTML;
978 0 : else if (pData == &bSendAsAttachment)
979 0 : bOK = rValue >>= bSendAsAttachment;
980 0 : else if (pData == &sMailBody)
981 0 : bOK = rValue >>= sMailBody;
982 0 : else if (pData == &sAttachmentName)
983 0 : bOK = rValue >>= sAttachmentName;
984 0 : else if (pData == &sAttachmentFilter)
985 0 : bOK = rValue >>= sAttachmentFilter;
986 0 : else if (pData == &aPrintSettings)
987 0 : bOK = rValue >>= aPrintSettings;
988 0 : else if (pData == &bSaveAsSingleFile)
989 0 : bOK = rValue >>= bSaveAsSingleFile;
990 0 : else if (pData == &sSaveFilter)
991 0 : bOK = rValue >>= sSaveFilter;
992 0 : else if (pData == &sSaveFilterOptions)
993 0 : bOK = rValue >>= sSaveFilterOptions;
994 0 : else if (pData == &aSaveFilterData)
995 0 : bOK = rValue >>= aSaveFilterData;
996 0 : else if (pData == &aCopiesTo)
997 0 : bOK = rValue >>= aCopiesTo;
998 0 : else if (pData == &aBlindCopiesTo)
999 0 : bOK = rValue >>= aBlindCopiesTo;
1000 0 : else if(pData == &sInServerPassword)
1001 0 : bOK = rValue >>= sInServerPassword;
1002 0 : else if(pData == &sOutServerPassword)
1003 0 : bOK = rValue >>= sInServerPassword;
1004 : else {
1005 : OSL_FAIL("invalid pointer" );
1006 : }
1007 : OSL_ENSURE( bOK, "set value failed" );
1008 0 : bChanged = true;
1009 : }
1010 0 : if (!bOK)
1011 0 : throw IllegalArgumentException("Property type mismatch or property not set: " + rPropertyName, static_cast < cppu::OWeakObject * > ( this ), 0 );
1012 :
1013 0 : if (bChanged)
1014 : {
1015 : PropertyChangeEvent aChgEvt( (XPropertySet *) this, rPropertyName,
1016 0 : sal_False, pCur->nWID, aOld, rValue );
1017 0 : launchEvent( aChgEvt );
1018 0 : }
1019 0 : }
1020 0 : }
1021 :
1022 0 : uno::Any SAL_CALL SwXMailMerge::getPropertyValue(
1023 : const OUString& rPropertyName )
1024 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
1025 : {
1026 0 : SolarMutexGuard aGuard;
1027 :
1028 0 : Any aRet;
1029 :
1030 0 : const SfxItemPropertySimpleEntry* pCur = pPropSet->getPropertyMap().getByName( rPropertyName );
1031 0 : if (!pCur)
1032 0 : throw UnknownPropertyException();
1033 : else
1034 : {
1035 0 : switch (pCur->nWID)
1036 : {
1037 0 : case WID_SELECTION : aRet <<= aSelection; break;
1038 0 : case WID_RESULT_SET : aRet <<= xResultSet; break;
1039 0 : case WID_CONNECTION : aRet <<= xConnection; break;
1040 0 : case WID_MODEL : aRet <<= xModel; break;
1041 0 : case WID_DATA_SOURCE_NAME : aRet <<= aDataSourceName; break;
1042 0 : case WID_DATA_COMMAND : aRet <<= aDataCommand; break;
1043 0 : case WID_FILTER : aRet <<= aFilter; break;
1044 0 : case WID_DOCUMENT_URL : aRet <<= aDocumentURL; break;
1045 0 : case WID_OUTPUT_URL : aRet <<= aOutputURL; break;
1046 0 : case WID_DATA_COMMAND_TYPE : aRet <<= nDataCommandType; break;
1047 0 : case WID_OUTPUT_TYPE : aRet <<= nOutputType; break;
1048 0 : case WID_ESCAPE_PROCESSING : aRet <<= bEscapeProcessing; break;
1049 0 : case WID_SINGLE_PRINT_JOBS : aRet <<= bSinglePrintJobs; break;
1050 0 : case WID_FILE_NAME_FROM_COLUMN : aRet <<= bFileNameFromColumn; break;
1051 0 : case WID_FILE_NAME_PREFIX : aRet <<= aFileNamePrefix; break;
1052 0 : case WID_MAIL_SUBJECT: aRet <<= sSubject; break;
1053 0 : case WID_ADDRESS_FROM_COLUMN: aRet <<= sAddressFromColumn; break;
1054 0 : case WID_SEND_AS_HTML: aRet <<= bSendAsHTML; break;
1055 0 : case WID_SEND_AS_ATTACHMENT: aRet <<= bSendAsAttachment; break;
1056 0 : case WID_MAIL_BODY: aRet <<= sMailBody; break;
1057 0 : case WID_ATTACHMENT_NAME: aRet <<= sAttachmentName; break;
1058 0 : case WID_ATTACHMENT_FILTER: aRet <<= sAttachmentFilter;break;
1059 0 : case WID_PRINT_OPTIONS: aRet <<= aPrintSettings; break;
1060 0 : case WID_SAVE_AS_SINGLE_FILE: aRet <<= bSaveAsSingleFile; break;
1061 0 : case WID_SAVE_FILTER: aRet <<= sSaveFilter; break;
1062 0 : case WID_SAVE_FILTER_OPTIONS: aRet <<= sSaveFilterOptions; break;
1063 0 : case WID_SAVE_FILTER_DATA: aRet <<= aSaveFilterData; break;
1064 0 : case WID_COPIES_TO: aRet <<= aCopiesTo; break;
1065 0 : case WID_BLIND_COPIES_TO: aRet <<= aBlindCopiesTo;break;
1066 0 : case WID_IN_SERVER_PASSWORD: aRet <<= sInServerPassword; break;
1067 0 : case WID_OUT_SERVER_PASSWORD: aRet <<= sOutServerPassword; break;
1068 : default :
1069 : OSL_FAIL("unknown WID");
1070 : }
1071 : }
1072 :
1073 0 : return aRet;
1074 : }
1075 :
1076 0 : void SAL_CALL SwXMailMerge::addPropertyChangeListener(
1077 : const OUString& rPropertyName,
1078 : const uno::Reference< beans::XPropertyChangeListener >& rListener )
1079 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
1080 : {
1081 0 : SolarMutexGuard aGuard;
1082 0 : if (!bDisposing && rListener.is())
1083 : {
1084 0 : const SfxItemPropertySimpleEntry* pCur = pPropSet->getPropertyMap().getByName( rPropertyName );
1085 0 : if (pCur)
1086 0 : aPropListeners.addInterface( pCur->nWID, rListener );
1087 : else
1088 0 : throw UnknownPropertyException();
1089 0 : }
1090 0 : }
1091 :
1092 0 : void SAL_CALL SwXMailMerge::removePropertyChangeListener(
1093 : const OUString& rPropertyName,
1094 : const uno::Reference< beans::XPropertyChangeListener >& rListener )
1095 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
1096 : {
1097 0 : SolarMutexGuard aGuard;
1098 0 : if (!bDisposing && rListener.is())
1099 : {
1100 0 : const SfxItemPropertySimpleEntry* pCur = pPropSet->getPropertyMap().getByName( rPropertyName );
1101 0 : if (pCur)
1102 0 : aPropListeners.removeInterface( pCur->nWID, rListener );
1103 : else
1104 0 : throw UnknownPropertyException();
1105 0 : }
1106 0 : }
1107 :
1108 0 : void SAL_CALL SwXMailMerge::addVetoableChangeListener(
1109 : const OUString& /*rPropertyName*/,
1110 : const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ )
1111 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
1112 : {
1113 : // no vetoable property, thus no support for vetoable change listeners
1114 : OSL_FAIL("not implemented");
1115 0 : }
1116 :
1117 0 : void SAL_CALL SwXMailMerge::removeVetoableChangeListener(
1118 : const OUString& /*rPropertyName*/,
1119 : const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ )
1120 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
1121 : {
1122 : // no vetoable property, thus no support for vetoable change listeners
1123 : OSL_FAIL("not implemented");
1124 0 : }
1125 :
1126 0 : void SAL_CALL SwXMailMerge::dispose()
1127 : throw(RuntimeException, std::exception)
1128 : {
1129 0 : SolarMutexGuard aGuard;
1130 :
1131 0 : if (!bDisposing)
1132 : {
1133 0 : bDisposing = sal_True;
1134 :
1135 0 : EventObject aEvtObj( (XPropertySet *) this );
1136 0 : aEvtListeners.disposeAndClear( aEvtObj );
1137 0 : aMergeListeners.disposeAndClear( aEvtObj );
1138 0 : aPropListeners.disposeAndClear( aEvtObj );
1139 0 : }
1140 0 : }
1141 :
1142 0 : void SAL_CALL SwXMailMerge::addEventListener(
1143 : const Reference< XEventListener >& rxListener )
1144 : throw(RuntimeException, std::exception)
1145 : {
1146 0 : SolarMutexGuard aGuard;
1147 0 : if (!bDisposing && rxListener.is())
1148 0 : aEvtListeners.addInterface( rxListener );
1149 0 : }
1150 :
1151 0 : void SAL_CALL SwXMailMerge::removeEventListener(
1152 : const Reference< XEventListener >& rxListener )
1153 : throw(RuntimeException, std::exception)
1154 : {
1155 0 : SolarMutexGuard aGuard;
1156 0 : if (!bDisposing && rxListener.is())
1157 0 : aEvtListeners.removeInterface( rxListener );
1158 0 : }
1159 :
1160 0 : void SAL_CALL SwXMailMerge::addMailMergeEventListener(
1161 : const uno::Reference< XMailMergeListener >& rxListener )
1162 : throw (RuntimeException, std::exception)
1163 : {
1164 0 : SolarMutexGuard aGuard;
1165 0 : if (!bDisposing && rxListener.is())
1166 0 : aMergeListeners.addInterface( rxListener );
1167 0 : }
1168 :
1169 0 : void SAL_CALL SwXMailMerge::removeMailMergeEventListener(
1170 : const uno::Reference< XMailMergeListener >& rxListener )
1171 : throw (RuntimeException, std::exception)
1172 : {
1173 0 : SolarMutexGuard aGuard;
1174 0 : if (!bDisposing && rxListener.is())
1175 0 : aMergeListeners.removeInterface( rxListener );
1176 0 : }
1177 :
1178 0 : OUString SAL_CALL SwXMailMerge::getImplementationName()
1179 : throw(RuntimeException, std::exception)
1180 : {
1181 0 : SolarMutexGuard aGuard;
1182 0 : return SwXMailMerge_getImplementationName();
1183 : }
1184 :
1185 0 : sal_Bool SAL_CALL SwXMailMerge::supportsService( const OUString& rServiceName )
1186 : throw(RuntimeException, std::exception)
1187 : {
1188 0 : return cppu::supportsService(this, rServiceName);
1189 : }
1190 :
1191 0 : uno::Sequence< OUString > SAL_CALL SwXMailMerge::getSupportedServiceNames()
1192 : throw(RuntimeException, std::exception)
1193 : {
1194 0 : SolarMutexGuard aGuard;
1195 0 : return SwXMailMerge_getSupportedServiceNames();
1196 : }
1197 :
1198 0 : uno::Sequence< OUString > SAL_CALL SwXMailMerge_getSupportedServiceNames()
1199 : throw()
1200 : {
1201 0 : uno::Sequence< OUString > aNames(2);
1202 0 : OUString *pName = aNames.getArray();
1203 0 : pName[0] = "com.sun.star.text.MailMerge";
1204 0 : pName[1] = "com.sun.star.sdb.DataAccessDescriptor";
1205 0 : return aNames;
1206 : }
1207 :
1208 0 : OUString SAL_CALL SwXMailMerge_getImplementationName()
1209 : throw()
1210 : {
1211 0 : return OUString( "SwXMailMerge" );
1212 : }
1213 :
1214 0 : uno::Reference< uno::XInterface > SAL_CALL SwXMailMerge_createInstance(
1215 : const uno::Reference< XMultiServiceFactory > & /*rSMgr*/)
1216 : throw( uno::Exception )
1217 : {
1218 0 : SolarMutexGuard aGuard;
1219 :
1220 : //the module may not be loaded
1221 0 : SwGlobals::ensure();
1222 0 : uno::Reference< uno::XInterface > xRef = (cppu::OWeakObject *) new SwXMailMerge();
1223 0 : return xRef;
1224 : }
1225 :
1226 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|