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