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 <swevent.hxx>
53 : #include <unomailmerge.hxx>
54 : #include <swdll.hxx>
55 : #include <swmodule.hxx>
56 : #include <unoprnms.hxx>
57 : #include <unomap.hxx>
58 : #include <swunohelper.hxx>
59 : #include <docsh.hxx>
60 : #include <IDocumentDeviceAccess.hxx>
61 : #include <view.hxx>
62 : #include <dbmgr.hxx>
63 : #include <unotxdoc.hxx>
64 : #include <prtopt.hxx>
65 : #include <wrtsh.hxx>
66 : #include <shellio.hxx>
67 : #include <mmconfigitem.hxx>
68 : #include <mailmergehelper.hxx>
69 :
70 : #include <unomid.h>
71 :
72 : #include <boost/noncopyable.hpp>
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 16 : osl::Mutex & GetMailMergeMutex()
86 : {
87 16 : static osl::Mutex aMutex;
88 16 : 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 8 : static CloseResult CloseModelAndDocSh(
98 : Reference< frame::XModel > &rxModel,
99 : SfxObjectShellRef &rxDocSh )
100 : {
101 8 : CloseResult eResult = eSuccess;
102 :
103 8 : 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 8 : Reference< util::XCloseable > xClose( rxModel, UNO_QUERY );
109 8 : 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 8 : 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 8 : return eResult;
129 : }
130 :
131 4 : 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 4 : Reference< frame::XModel > xTmpModel;
140 8 : Sequence < PropertyValue > aArgs( 1 );
141 4 : aArgs[0].Name = "Hidden";
142 4 : bool bVal = true;
143 4 : aArgs[0].Value <<= bVal;
144 : try
145 : {
146 4 : Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
147 12 : xTmpModel = Reference < XModel >( xDesktop->loadComponentFromURL(
148 12 : 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 4 : SwDocShell *pTmpDocShell = 0;
157 8 : Reference < XUnoTunnel > xTunnel( xTmpModel, UNO_QUERY );
158 4 : if (xTunnel.is())
159 : {
160 : SwXTextDocument* pTextDoc = reinterpret_cast<SwXTextDocument *>(
161 4 : xTunnel->getSomething( SwXTextDocument::getUnoTunnelId() ));
162 4 : pTmpDocShell = pTextDoc ? pTextDoc->GetDocShell() : 0;
163 : }
164 :
165 4 : bool bRes = false;
166 4 : if (xTmpModel.is() && pTmpDocShell) // everything available?
167 : {
168 4 : if (bClose)
169 0 : CloseModelAndDocSh( rxModel, rxDocSh );
170 : // set new stuff
171 4 : rxModel = xTmpModel;
172 4 : rxDocSh = pTmpDocShell;
173 4 : 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 8 : return bRes;
183 : }
184 :
185 : namespace
186 : {
187 : class DelayedFileDeletion : public ::cppu::WeakImplHelper1< util::XCloseListener >,
188 : private boost::noncopyable
189 : {
190 : protected:
191 : ::osl::Mutex m_aMutex;
192 : Reference< util::XCloseable > m_xDocument;
193 : Timer m_aDeleteTimer;
194 : OUString m_sTemporaryFile;
195 : sal_Int32 m_nPendingDeleteAttempts;
196 :
197 : public:
198 : DelayedFileDeletion( const Reference< XModel >& _rxModel,
199 : const OUString& _rTemporaryFile );
200 :
201 : protected:
202 : virtual ~DelayedFileDeletion( );
203 :
204 : // XCloseListener
205 : virtual void SAL_CALL queryClosing( const EventObject& _rSource, sal_Bool _bGetsOwnership ) throw (util::CloseVetoException, RuntimeException, std::exception) SAL_OVERRIDE;
206 : virtual void SAL_CALL notifyClosing( const EventObject& _rSource ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
207 :
208 : // XEventListener
209 : virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
210 :
211 : private:
212 : void implTakeOwnership( );
213 : DECL_LINK( OnTryDeleteFile, void* );
214 : };
215 :
216 0 : DelayedFileDeletion::DelayedFileDeletion( const Reference< XModel >& _rxModel, const OUString& _rTemporaryFile )
217 : :
218 : m_xDocument( _rxModel, UNO_QUERY )
219 : ,m_sTemporaryFile( _rTemporaryFile )
220 0 : ,m_nPendingDeleteAttempts( 0 )
221 : {
222 0 : osl_atomic_increment( &m_refCount );
223 : try
224 : {
225 0 : if ( m_xDocument.is() )
226 : {
227 0 : m_xDocument->addCloseListener( this );
228 : // successfully added -> keep ourself alive
229 0 : acquire();
230 : }
231 : else {
232 : OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: model is no component!" );
233 : }
234 : }
235 0 : catch (const Exception&)
236 : {
237 : OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: could not register as event listener at the model!" );
238 : }
239 0 : osl_atomic_decrement( &m_refCount );
240 0 : }
241 :
242 0 : IMPL_LINK_NOARG(DelayedFileDeletion, OnTryDeleteFile)
243 : {
244 0 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
245 :
246 0 : bool bSuccess = false;
247 : try
248 : {
249 0 : bool bDeliverOwnership = ( 0 == m_nPendingDeleteAttempts );
250 : // if this is our last attemt, then anybody which vetoes this has to take the consequences
251 : // (means take the ownership)
252 0 : m_xDocument->close( bDeliverOwnership );
253 0 : bSuccess = true;
254 : }
255 0 : catch (const util::CloseVetoException&)
256 : {
257 : // somebody vetoed -> next try
258 0 : if ( m_nPendingDeleteAttempts )
259 : {
260 : // next attempt
261 0 : --m_nPendingDeleteAttempts;
262 0 : m_aDeleteTimer.Start();
263 : }
264 : else
265 0 : bSuccess = true; // can't do anything here ...
266 : }
267 0 : catch (const Exception&)
268 : {
269 : OSL_FAIL("DelayedFileDeletion::OnTryDeleteFile: caught a strange exception!" );
270 0 : bSuccess = true;
271 : // can't do anything here ...
272 : }
273 :
274 0 : if ( bSuccess )
275 : {
276 0 : SWUnoHelper::UCB_DeleteFile( m_sTemporaryFile );
277 0 : aGuard.clear();
278 0 : release(); // this should be our last reference, we should be dead after this
279 : }
280 0 : return 0L;
281 : }
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 4 : static bool DeleteTmpFile_Impl(
334 : Reference< frame::XModel > &rxModel,
335 : SfxObjectShellRef &rxDocSh,
336 : const OUString &rTmpFileURL )
337 : {
338 4 : bool bRes = false;
339 4 : if (!rTmpFileURL.isEmpty())
340 : {
341 4 : bool bDelete = true;
342 4 : 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 4 : rxModel = 0;
353 4 : rxDocSh = 0; // destroy doc shell
354 :
355 4 : if ( bDelete )
356 : {
357 4 : 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 4 : return bRes;
367 : }
368 :
369 4 : SwXMailMerge::SwXMailMerge() :
370 4 : aEvtListeners ( GetMailMergeMutex() ),
371 4 : aMergeListeners ( GetMailMergeMutex() ),
372 4 : aPropListeners ( GetMailMergeMutex() ),
373 4 : 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 20 : m_pMgr(0)
384 : {
385 : // create empty document
386 : // like in: SwModule::InsertEnv (appenv.cxx)
387 4 : xDocSh = new SwDocShell( SFX_CREATE_MODE_STANDARD );
388 4 : xDocSh->DoInitNew( 0 );
389 4 : SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
390 4 : SwView *pView = (SwView*) pFrame->GetViewShell();
391 4 : pView->AttrChangedNotify( &pView->GetWrtShell() ); //So that SelectShell is called.
392 4 : xModel = xDocSh->GetModel();
393 4 : }
394 :
395 12 : SwXMailMerge::~SwXMailMerge()
396 : {
397 4 : 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 4 : if ( eVetoed == CloseModelAndDocSh( xModel, xDocSh ) )
405 : OSL_FAIL("owner ship transfered to vetoing object!" );
406 :
407 4 : xModel = 0;
408 4 : xDocSh = 0; // destroy doc shell
409 : }
410 8 : }
411 :
412 : // Guarantee object consistence in case of an exception
413 : class MailMergeExecuteFinalizer: private boost::noncopyable {
414 : public:
415 4 : MailMergeExecuteFinalizer(SwXMailMerge *mailmerge)
416 4 : : m_pMailMerge(mailmerge)
417 : {
418 : assert(m_pMailMerge); //mailmerge object missing
419 4 : }
420 4 : ~MailMergeExecuteFinalizer()
421 : {
422 4 : osl::MutexGuard pMgrGuard( GetMailMergeMutex() );
423 4 : m_pMailMerge->m_pMgr = 0;
424 4 : }
425 :
426 : private:
427 : SwXMailMerge *m_pMailMerge;
428 : };
429 :
430 4 : uno::Any SAL_CALL SwXMailMerge::execute(
431 : const uno::Sequence< beans::NamedValue >& rArguments )
432 : throw (IllegalArgumentException, Exception,
433 : RuntimeException, std::exception)
434 : {
435 4 : SolarMutexGuard aGuard;
436 8 : 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 8 : uno::Sequence< uno::Any > aCurSelection = aSelection;
443 8 : uno::Reference< sdbc::XResultSet > xCurResultSet = xResultSet;
444 8 : uno::Reference< sdbc::XConnection > xCurConnection = xConnection;
445 8 : uno::Reference< frame::XModel > xCurModel = xModel;
446 8 : OUString aCurDataSourceName = aDataSourceName;
447 8 : OUString aCurDataCommand = aDataCommand;
448 8 : OUString aCurFilter = aFilter;
449 8 : OUString aCurDocumentURL = aDocumentURL;
450 8 : OUString aCurOutputURL = aOutputURL;
451 8 : OUString aCurFileNamePrefix = aFileNamePrefix;
452 4 : sal_Int32 nCurDataCommandType = nDataCommandType;
453 4 : sal_Int16 nCurOutputType = nOutputType;
454 4 : bool bCurEscapeProcessing = bEscapeProcessing;
455 4 : bool bCurSinglePrintJobs = bSinglePrintJobs;
456 4 : bool bCurFileNameFromColumn = bFileNameFromColumn;
457 :
458 8 : SfxObjectShellRef xCurDocSh = xDocSh; // the document
459 :
460 4 : const beans::NamedValue *pArguments = rArguments.getConstArray();
461 4 : sal_Int32 nArgs = rArguments.getLength();
462 32 : for (sal_Int32 i = 0; i < nArgs; ++i)
463 : {
464 28 : const OUString &rName = pArguments[i].Name;
465 28 : const Any &rValue = pArguments[i].Value;
466 :
467 28 : bool bOK = true;
468 28 : if (rName == UNO_NAME_SELECTION)
469 0 : bOK = rValue >>= aCurSelection;
470 28 : else if (rName == UNO_NAME_RESULT_SET)
471 0 : bOK = rValue >>= xCurResultSet;
472 28 : else if (rName == UNO_NAME_CONNECTION)
473 0 : bOK = rValue >>= xCurConnection;
474 28 : else if (rName == UNO_NAME_MODEL)
475 0 : throw PropertyVetoException("Property is read-only: " + rName, static_cast < cppu::OWeakObject * > ( this ) );
476 28 : else if (rName == UNO_NAME_DATA_SOURCE_NAME)
477 4 : bOK = rValue >>= aCurDataSourceName;
478 24 : else if (rName == UNO_NAME_DAD_COMMAND)
479 4 : bOK = rValue >>= aCurDataCommand;
480 20 : else if (rName == UNO_NAME_FILTER)
481 0 : bOK = rValue >>= aCurFilter;
482 20 : else if (rName == UNO_NAME_DOCUMENT_URL)
483 : {
484 4 : bOK = rValue >>= aCurDocumentURL;
485 8 : if (!aCurDocumentURL.isEmpty()
486 4 : && !LoadFromURL_impl( xCurModel, xCurDocSh, aCurDocumentURL, false ))
487 0 : throw RuntimeException("Failed to create document from URL: " + aCurDocumentURL, static_cast < cppu::OWeakObject * > ( this ) );
488 : }
489 16 : else if (rName == UNO_NAME_OUTPUT_URL)
490 : {
491 4 : bOK = rValue >>= aCurOutputURL;
492 4 : if (!aCurOutputURL.isEmpty())
493 : {
494 4 : if (!UCB_IsDirectory(aCurOutputURL))
495 0 : throw IllegalArgumentException("URL does not point to a directory: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 0 );
496 4 : if (UCB_IsReadOnlyFileName(aCurOutputURL))
497 0 : throw IllegalArgumentException("URL is read-only: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 0 );
498 : }
499 : }
500 12 : else if (rName == UNO_NAME_FILE_NAME_PREFIX)
501 4 : bOK = rValue >>= aCurFileNamePrefix;
502 8 : else if (rName == UNO_NAME_DAD_COMMAND_TYPE)
503 4 : bOK = rValue >>= nCurDataCommandType;
504 4 : else if (rName == UNO_NAME_OUTPUT_TYPE)
505 4 : 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 28 : 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 4 : 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 : }
576 0 : if ( bEverythingsFine )
577 0 : bValid = true;
578 : }
579 0 : catch (const Exception&)
580 : {
581 0 : bValid = false;
582 : }
583 : }
584 :
585 0 : if ( !bValid )
586 : {
587 : throw IllegalArgumentException(
588 : "The current 'Selection' does not describe a valid array of bookmarks, relative to the current 'ResultSet'.",
589 : static_cast < cppu::OWeakObject * > ( this ),
590 : 0
591 0 : );
592 : }
593 :
594 0 : aCurSelection = aTranslated;
595 : }
596 :
597 4 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( xCurDocSh, false);
598 4 : SwView *pView = pFrame ? PTR_CAST( SwView, pFrame->GetViewShell() ) : NULL;
599 4 : if (!pView)
600 0 : throw RuntimeException();
601 4 : SwWrtShell &rSh = *pView->GetWrtShellPtr();
602 :
603 : // avoid assertion in 'Update' from Sfx by supplying a shell
604 : // and thus avoiding the SelectShell call in Writers GetState function
605 : // while still in Update of Sfx.
606 : // (GetSelection in Update is not allowed)
607 4 : if (!aCurDocumentURL.isEmpty())
608 4 : pView->AttrChangedNotify( &pView->GetWrtShell() );//So that SelectShell is called.
609 :
610 8 : SharedComponent aRowSetDisposeHelper;
611 4 : if (!xCurResultSet.is())
612 : {
613 4 : if (aCurDataSourceName.isEmpty() || aCurDataCommand.isEmpty() )
614 : {
615 : OSL_FAIL("PropertyValues missing or unset");
616 0 : throw IllegalArgumentException("Either the ResultSet or DataSourceName and DataCommand must be set.", static_cast < cppu::OWeakObject * > ( this ), 0 );
617 : }
618 :
619 : // build ResultSet from DataSourceName, DataCommand and DataCommandType
620 :
621 4 : Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
622 4 : if (xMgr.is())
623 : {
624 4 : Reference< XInterface > xInstance = xMgr->createInstance( "com.sun.star.sdb.RowSet" );
625 4 : aRowSetDisposeHelper.reset( xInstance, SharedComponent::TakeOwnership );
626 8 : Reference< XPropertySet > xRowSetPropSet( xInstance, UNO_QUERY );
627 : OSL_ENSURE( xRowSetPropSet.is(), "failed to get XPropertySet interface from RowSet" );
628 4 : if (xRowSetPropSet.is())
629 : {
630 4 : if (xCurConnection.is())
631 0 : xRowSetPropSet->setPropertyValue( "ActiveConnection", makeAny( xCurConnection ) );
632 4 : xRowSetPropSet->setPropertyValue( "DataSourceName", makeAny( aCurDataSourceName ) );
633 4 : xRowSetPropSet->setPropertyValue( "Command", makeAny( aCurDataCommand ) );
634 4 : xRowSetPropSet->setPropertyValue( "CommandType", makeAny( nCurDataCommandType ) );
635 4 : xRowSetPropSet->setPropertyValue( "EscapeProcessing", makeAny( bCurEscapeProcessing ) );
636 4 : xRowSetPropSet->setPropertyValue( "ApplyFilter", makeAny( sal_True ) );
637 4 : xRowSetPropSet->setPropertyValue( "Filter", makeAny( aCurFilter ) );
638 :
639 4 : Reference< sdbc::XRowSet > xRowSet( xInstance, UNO_QUERY );
640 4 : if (xRowSet.is())
641 4 : xRowSet->execute(); // build ResultSet from properties
642 4 : if( !xCurConnection.is() )
643 4 : xCurConnection.set( xRowSetPropSet->getPropertyValue( "ActiveConnection" ), UNO_QUERY );
644 4 : xCurResultSet = Reference< sdbc::XResultSet >( xRowSet, UNO_QUERY );
645 4 : OSL_ENSURE( xCurResultSet.is(), "failed to build ResultSet" );
646 4 : }
647 4 : }
648 : }
649 :
650 8 : svx::ODataAccessDescriptor aDescriptor;
651 4 : aDescriptor.setDataSource(aCurDataSourceName);
652 4 : aDescriptor[ svx::daConnection ] <<= xCurConnection;
653 4 : aDescriptor[ svx::daCommand ] <<= aCurDataCommand;
654 4 : aDescriptor[ svx::daCommandType ] <<= nCurDataCommandType;
655 4 : aDescriptor[ svx::daEscapeProcessing ] <<= bCurEscapeProcessing;
656 4 : aDescriptor[ svx::daCursor ] <<= xCurResultSet;
657 : // aDescriptor[ svx::daColumnName ] not used
658 : // aDescriptor[ svx::daColumnObject ] not used
659 4 : aDescriptor[ svx::daSelection ] <<= aCurSelection;
660 :
661 : DBManagerOptions nMergeType;
662 4 : switch (nCurOutputType)
663 : {
664 0 : case MailMergeType::PRINTER : nMergeType = DBMGR_MERGE_PRINTER; break;
665 0 : case MailMergeType::FILE : nMergeType = DBMGR_MERGE_FILE; break;
666 0 : case MailMergeType::MAIL : nMergeType = DBMGR_MERGE_EMAIL; break;
667 4 : case MailMergeType::SHELL : nMergeType = DBMGR_MERGE_SHELL; break;
668 : default:
669 0 : throw IllegalArgumentException("Invalid value of property: OutputType", static_cast < cppu::OWeakObject * > ( this ), 0 );
670 : }
671 :
672 4 : SwDBManager* pMgr = rSh.GetDBManager();
673 : //force layout creation
674 4 : rSh.CalcLayout();
675 : OSL_ENSURE( pMgr, "database manager missing" );
676 4 : m_pMgr = pMgr;
677 :
678 4 : SwMergeDescriptor aMergeDesc( nMergeType, rSh, aDescriptor );
679 :
680 8 : boost::scoped_ptr< SwMailMergeConfigItem > pMMConfigItem;
681 8 : uno::Reference< mail::XMailService > xInService;
682 4 : switch (nCurOutputType)
683 : {
684 : case MailMergeType::PRINTER:
685 : {
686 0 : IDocumentDeviceAccess* pIDDA = rSh.getIDocumentDeviceAccess();
687 0 : SwPrintData aPrtData( pIDDA->getPrintData() );
688 0 : aPrtData.SetPrintSingleJobs( bCurSinglePrintJobs );
689 0 : pIDDA->setPrintData( aPrtData );
690 : // #i25686# printing should not be done asynchronously to prevent dangling offices
691 : // when mail merge is called as command line macro
692 0 : aMergeDesc.bPrintAsync = false;
693 0 : aMergeDesc.aPrintOptions = aPrintSettings;
694 0 : aMergeDesc.bCreateSingleFile = true;
695 : }
696 0 : break;
697 : case MailMergeType::SHELL:
698 4 : aMergeDesc.bCreateSingleFile = true;
699 4 : pMMConfigItem.reset(new SwMailMergeConfigItem);
700 4 : aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
701 4 : break;
702 : case MailMergeType::FILE:
703 : case MailMergeType::MAIL:
704 : {
705 0 : INetURLObject aURLObj;
706 0 : aURLObj.SetSmartProtocol( INET_PROT_FILE );
707 :
708 0 : if (!aCurDocumentURL.isEmpty())
709 : {
710 : // if OutputURL or FileNamePrefix are missing get
711 : // them from DocumentURL
712 0 : aURLObj.SetSmartURL( aCurDocumentURL );
713 0 : if (aCurFileNamePrefix.isEmpty())
714 0 : aCurFileNamePrefix = aURLObj.GetBase(); // filename without extension
715 0 : if (aCurOutputURL.isEmpty())
716 : {
717 0 : aURLObj.removeSegment();
718 0 : aCurOutputURL = aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
719 : }
720 : }
721 : else // default empty document without URL
722 : {
723 0 : if (aCurOutputURL.isEmpty())
724 0 : throw RuntimeException("OutputURL is not set and can not be obtained.", static_cast < cppu::OWeakObject * > ( this ) );
725 : }
726 :
727 0 : aURLObj.SetSmartURL( aCurOutputURL );
728 0 : OUString aPath = aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
729 :
730 0 : const OUString aDelim( "/" );
731 0 : if (!aPath.isEmpty() && !aPath.endsWith(aDelim))
732 0 : aPath += aDelim;
733 0 : if (bCurFileNameFromColumn)
734 0 : pMgr->SetEMailColumn( aCurFileNamePrefix );
735 : else
736 : {
737 0 : aPath += aCurFileNamePrefix;
738 0 : pMgr->SetEMailColumn( OUString() );
739 : }
740 0 : pMgr->SetSubject( aPath );
741 0 : if(MailMergeType::FILE == nCurOutputType)
742 : {
743 0 : aMergeDesc.sSaveToFilter = sSaveFilter;
744 0 : aMergeDesc.sSaveToFilterOptions = sSaveFilterOptions;
745 0 : aMergeDesc.aSaveToFilterData = aSaveFilterData;
746 0 : aMergeDesc.bCreateSingleFile = bSaveAsSingleFile;
747 : }
748 : else
749 : {
750 0 : pMgr->SetEMailColumn( sAddressFromColumn );
751 0 : if(sAddressFromColumn.isEmpty())
752 0 : throw RuntimeException("Mail address column not set.", static_cast < cppu::OWeakObject * > ( this ) );
753 0 : aMergeDesc.sSaveToFilter = sAttachmentFilter;
754 0 : aMergeDesc.sSubject = sSubject;
755 0 : aMergeDesc.sMailBody = sMailBody;
756 0 : aMergeDesc.sAttachmentName = sAttachmentName;
757 0 : aMergeDesc.aCopiesTo = aCopiesTo;
758 0 : aMergeDesc.aBlindCopiesTo = aBlindCopiesTo;
759 0 : aMergeDesc.bSendAsHTML = bSendAsHTML;
760 0 : aMergeDesc.bSendAsAttachment = bSendAsAttachment;
761 :
762 0 : aMergeDesc.bCreateSingleFile = false;
763 0 : pMMConfigItem.reset(new SwMailMergeConfigItem);
764 0 : aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
765 0 : aMergeDesc.xSmtpServer = SwMailMergeHelper::ConnectToSmtpServer(
766 0 : *pMMConfigItem,
767 : xInService,
768 0 : sInServerPassword, sOutServerPassword );
769 0 : if( !aMergeDesc.xSmtpServer.is() || !aMergeDesc.xSmtpServer->isConnected())
770 0 : throw RuntimeException("Failed to connect to mail server.", static_cast < cppu::OWeakObject * > ( this ) );
771 0 : }
772 : }
773 0 : break;
774 : }
775 :
776 : // save document with temporary filename
777 : const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat(
778 : OUString( FILTER_XML ),
779 4 : SwDocShell::Factory().GetFilterContainer() );
780 4 : OUString aExtension(comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(), '*'));
781 8 : utl::TempFile aTempFile( "SwMM", true, &aExtension );
782 4 : aTmpFileName = aTempFile.GetURL();
783 :
784 8 : Reference< XStorable > xStorable( xCurModel, UNO_QUERY );
785 4 : bool bStoredAsTemporary = false;
786 4 : if ( xStorable.is() )
787 : {
788 : try
789 : {
790 4 : xStorable->storeAsURL( aTmpFileName, Sequence< PropertyValue >() );
791 4 : bStoredAsTemporary = true;
792 : }
793 0 : catch (const Exception&)
794 : {
795 : }
796 : }
797 4 : if ( !bStoredAsTemporary )
798 0 : throw RuntimeException("Failed to save temporary file.", static_cast < cppu::OWeakObject * > ( this ) );
799 :
800 4 : pMgr->SetMergeSilent( true ); // suppress dialogs, message boxes, etc.
801 4 : const SwXMailMerge *pOldSrc = pMgr->GetMailMergeEvtSrc();
802 : OSL_ENSURE( !pOldSrc || pOldSrc == this, "Ooops... different event source already set." );
803 4 : pMgr->SetMailMergeEvtSrc( this ); // launch events for listeners
804 :
805 4 : SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xCurDocSh));
806 4 : bool bSucc = pMgr->MergeNew( aMergeDesc );
807 4 : SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), xCurDocSh));
808 :
809 4 : pMgr->SetMailMergeEvtSrc( pOldSrc );
810 :
811 4 : if ( xCurModel.get() != xModel.get() )
812 : { // in case it was a temporary model -> close it, and delete the file
813 4 : DeleteTmpFile_Impl( xCurModel, xCurDocSh, aTmpFileName );
814 4 : aTmpFileName = "";
815 : }
816 : // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest)
817 :
818 4 : if (!bSucc)
819 0 : throw Exception("Mail merge failed. Sorry, no further information available.", static_cast < cppu::OWeakObject * > ( this ) );
820 :
821 : //de-initialize services
822 4 : if(xInService.is() && xInService->isConnected())
823 0 : xInService->disconnect();
824 4 : if(aMergeDesc.xSmtpServer.is() && aMergeDesc.xSmtpServer->isConnected())
825 0 : aMergeDesc.xSmtpServer->disconnect();
826 :
827 4 : if (DBMGR_MERGE_SHELL == nMergeType)
828 : {
829 4 : SwXTextDocument *xTextDoc = new SwXTextDocument( aMergeDesc.pMailMergeConfigItem->GetTargetView()->GetDocShell() );
830 4 : return makeAny( Reference< XComponent >( xTextDoc->queryInterface( XComponent::static_type() ), css::uno::UNO_QUERY) );
831 : }
832 : else
833 12 : return makeAny( sal_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 10 : void SwXMailMerge::LaunchMailMergeEvent( const MailMergeEvent &rEvt ) const
846 : {
847 10 : cppu::OInterfaceIteratorHelper aIt( ((SwXMailMerge *) this)->aMergeListeners );
848 20 : while (aIt.hasMoreElements())
849 : {
850 0 : Reference< XMailMergeListener > xRef( aIt.next(), UNO_QUERY );
851 0 : if (xRef.is())
852 0 : xRef->notifyMailMergeEvent( rEvt );
853 10 : }
854 10 : }
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( (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( (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 : SolarMutexGuard aGuard;
1194 0 : return SwXMailMerge_getImplementationName();
1195 : }
1196 :
1197 0 : sal_Bool SAL_CALL SwXMailMerge::supportsService( const OUString& rServiceName )
1198 : throw(RuntimeException, std::exception)
1199 : {
1200 0 : return cppu::supportsService(this, rServiceName);
1201 : }
1202 :
1203 0 : uno::Sequence< OUString > SAL_CALL SwXMailMerge::getSupportedServiceNames()
1204 : throw(RuntimeException, std::exception)
1205 : {
1206 0 : SolarMutexGuard aGuard;
1207 0 : return SwXMailMerge_getSupportedServiceNames();
1208 : }
1209 :
1210 2 : uno::Sequence< OUString > SAL_CALL SwXMailMerge_getSupportedServiceNames()
1211 : throw()
1212 : {
1213 2 : uno::Sequence< OUString > aNames(2);
1214 2 : OUString *pName = aNames.getArray();
1215 2 : pName[0] = "com.sun.star.text.MailMerge";
1216 2 : pName[1] = "com.sun.star.sdb.DataAccessDescriptor";
1217 2 : return aNames;
1218 : }
1219 :
1220 96 : OUString SAL_CALL SwXMailMerge_getImplementationName()
1221 : throw()
1222 : {
1223 96 : return OUString( "SwXMailMerge" );
1224 : }
1225 :
1226 4 : uno::Reference< uno::XInterface > SAL_CALL SwXMailMerge_createInstance(
1227 : const uno::Reference< XMultiServiceFactory > & /*rSMgr*/)
1228 : throw( uno::Exception )
1229 : {
1230 4 : SolarMutexGuard aGuard;
1231 :
1232 : //the module may not be loaded
1233 4 : SwGlobals::ensure();
1234 4 : uno::Reference< uno::XInterface > xRef = (cppu::OWeakObject *) new SwXMailMerge();
1235 4 : return xRef;
1236 270 : }
1237 :
1238 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|