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