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/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 : #include <memory>
70 :
71 : #include <unomid.h>
72 :
73 :
74 : #define SN_MAIL_MERGE "com.sun.star.text.MailMerge"
75 : #define SN_DATA_ACCESS_DESCRIPTOR "com.sun.star.sdb.DataAccessDescriptor"
76 :
77 : using namespace ::com::sun::star;
78 : using namespace ::com::sun::star::frame;
79 : using namespace ::com::sun::star::uno;
80 : using namespace ::com::sun::star::lang;
81 : using namespace ::com::sun::star::beans;
82 : using namespace ::com::sun::star::text;
83 : using ::rtl::OUString;
84 : using namespace SWUnoHelper;
85 :
86 : ////////////////////////////////////////////////////////////
87 :
88 : typedef ::utl::SharedUNOComponent< XInterface > SharedComponent;
89 :
90 : ////////////////////////////////////////////////////////////
91 :
92 0 : osl::Mutex & GetMailMergeMutex()
93 : {
94 0 : static osl::Mutex aMutex;
95 0 : return aMutex;
96 : }
97 :
98 : ////////////////////////////////////////////////////////////
99 :
100 : enum CloseResult
101 : {
102 : eSuccess, // successfully closed
103 : eVetoed, // vetoed, ownership transfered to the vetoing instance
104 : eFailed // failed for some unknown reason
105 : };
106 0 : static CloseResult CloseModelAndDocSh(
107 : Reference< frame::XModel > &rxModel,
108 : SfxObjectShellRef &rxDocSh )
109 : {
110 0 : CloseResult eResult = eSuccess;
111 :
112 0 : rxDocSh = 0;
113 :
114 : //! models/documents should never be disposed (they may still be
115 : //! used for printing which is called asynchronously for example)
116 : //! instead call close
117 0 : Reference< util::XCloseable > xClose( rxModel, UNO_QUERY );
118 0 : if (xClose.is())
119 : {
120 : try
121 : {
122 : //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
123 : //! I.e. now that object is responsible for closing the model and doc shell.
124 0 : xClose->close( sal_True );
125 : }
126 0 : catch (const util::CloseVetoException&)
127 : {
128 : //! here we have the problem that the temporary file that is
129 : //! currently being printed will never be deleted. :-(
130 0 : eResult = eVetoed;
131 : }
132 0 : catch (const uno::RuntimeException&)
133 : {
134 0 : eResult = eFailed;
135 : }
136 : }
137 0 : return eResult;
138 : }
139 :
140 : ////////////////////////////////////////////////////////////
141 :
142 0 : static sal_Bool LoadFromURL_impl(
143 : Reference< frame::XModel > &rxModel,
144 : SfxObjectShellRef &rxDocSh,
145 : const String &rURL,
146 : sal_Bool bClose )
147 : throw (RuntimeException)
148 : {
149 : // try to open the document readonly and hidden
150 0 : Reference< frame::XModel > xTmpModel;
151 0 : Sequence < PropertyValue > aArgs( 1 );
152 0 : aArgs[0].Name = "Hidden";
153 0 : sal_Bool bVal = sal_True;
154 0 : aArgs[0].Value <<= bVal;
155 : try
156 : {
157 0 : Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
158 0 : xTmpModel = Reference < XModel >( xDesktop->loadComponentFromURL(
159 0 : rURL, "_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( "com.sun.star.sdb.RowSet" );
637 0 : aRowSetDisposeHelper.reset( xInstance, SharedComponent::TakeOwnership );
638 0 : Reference< XPropertySet > xRowSetPropSet( xInstance, UNO_QUERY );
639 : OSL_ENSURE( xRowSetPropSet.is(), "failed to get XPropertySet interface from RowSet" );
640 0 : if (xRowSetPropSet.is())
641 : {
642 0 : if (xCurConnection.is())
643 0 : xRowSetPropSet->setPropertyValue( "ActiveConnection", makeAny( xCurConnection ) );
644 0 : xRowSetPropSet->setPropertyValue( "DataSourceName", makeAny( aCurDataSourceName ) );
645 0 : xRowSetPropSet->setPropertyValue( "Command", makeAny( aCurDataCommand ) );
646 0 : xRowSetPropSet->setPropertyValue( "CommandType", makeAny( nCurDataCommandType ) );
647 0 : xRowSetPropSet->setPropertyValue( "EscapeProcessing", makeAny( bCurEscapeProcessing ) );
648 0 : xRowSetPropSet->setPropertyValue( "ApplyFilter", makeAny( sal_True ) );
649 0 : xRowSetPropSet->setPropertyValue( "Filter", makeAny( aCurFilter ) );
650 :
651 0 : Reference< sdbc::XRowSet > xRowSet( xInstance, UNO_QUERY );
652 0 : if (xRowSet.is())
653 0 : xRowSet->execute(); // build ResultSet from properties
654 0 : if( !xCurConnection.is() )
655 0 : xCurConnection.set( xRowSetPropSet->getPropertyValue( "ActiveConnection" ), UNO_QUERY );
656 0 : xCurResultSet = Reference< sdbc::XResultSet >( xRowSet, UNO_QUERY );
657 0 : OSL_ENSURE( xCurResultSet.is(), "failed to build ResultSet" );
658 0 : }
659 0 : }
660 : }
661 :
662 0 : svx::ODataAccessDescriptor aDescriptor;
663 0 : aDescriptor.setDataSource(aCurDataSourceName);
664 0 : aDescriptor[ svx::daConnection ] <<= xCurConnection;
665 0 : aDescriptor[ svx::daCommand ] <<= aCurDataCommand;
666 0 : aDescriptor[ svx::daCommandType ] <<= nCurDataCommandType;
667 0 : aDescriptor[ svx::daEscapeProcessing ] <<= bCurEscapeProcessing;
668 0 : aDescriptor[ svx::daCursor ] <<= xCurResultSet;
669 : // aDescriptor[ svx::daColumnName ] not used
670 : // aDescriptor[ svx::daColumnObject ] not used
671 0 : aDescriptor[ svx::daSelection ] <<= aCurSelection;
672 :
673 : sal_uInt16 nMergeType;
674 0 : switch (nCurOutputType)
675 : {
676 0 : case MailMergeType::PRINTER : nMergeType = DBMGR_MERGE_MAILMERGE; break;
677 0 : case MailMergeType::FILE : nMergeType = DBMGR_MERGE_MAILFILES; break;
678 0 : case MailMergeType::MAIL : nMergeType = DBMGR_MERGE_MAILING; break;
679 : default:
680 0 : throw IllegalArgumentException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Invalid value of property:" ) ) + "OutputType", static_cast < cppu::OWeakObject * > ( this ), 0 );
681 : }
682 :
683 0 : SwNewDBMgr* pMgr = rSh.GetNewDBMgr();
684 : //force layout creation
685 0 : rSh.CalcLayout();
686 : OSL_ENSURE( pMgr, "database manager missing" );
687 :
688 0 : SwMergeDescriptor aMergeDesc( nMergeType, rSh, aDescriptor );
689 :
690 0 : std::auto_ptr< SwMailMergeConfigItem > pMMConfigItem;
691 0 : uno::Reference< mail::XMailService > xInService;
692 0 : if (MailMergeType::PRINTER == nCurOutputType)
693 : {
694 0 : IDocumentDeviceAccess* pIDDA = rSh.getIDocumentDeviceAccess();
695 0 : SwPrintData aPrtData( pIDDA->getPrintData() );
696 0 : aPrtData.SetPrintSingleJobs( bCurSinglePrintJobs );
697 0 : pIDDA->setPrintData( aPrtData );
698 : // #i25686# printing should not be done asynchronously to prevent dangling offices
699 : // when mail merge is called as command line macro
700 0 : aMergeDesc.bPrintAsync = sal_False;
701 0 : aMergeDesc.aPrintOptions = aPrintSettings;
702 0 : aMergeDesc.bCreateSingleFile = true;
703 : }
704 : else /* FILE and MAIL*/
705 : {
706 0 : INetURLObject aURLObj;
707 0 : aURLObj.SetSmartProtocol( INET_PROT_FILE );
708 :
709 0 : if (!aCurDocumentURL.isEmpty())
710 : {
711 : // if OutputURL or FileNamePrefix are missing get
712 : // them from DocumentURL
713 0 : aURLObj.SetSmartURL( aCurDocumentURL );
714 0 : if (aCurFileNamePrefix.isEmpty())
715 0 : aCurFileNamePrefix = aURLObj.GetBase(); // filename without extension
716 0 : if (aCurOutputURL.isEmpty())
717 : {
718 0 : aURLObj.removeSegment();
719 0 : aCurOutputURL = aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
720 : }
721 : }
722 : else // default empty document without URL
723 : {
724 0 : if (aCurOutputURL.isEmpty())
725 0 : throw RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "OutputURL is not set and can not be obtained." ) ), static_cast < cppu::OWeakObject * > ( this ) );
726 : }
727 :
728 0 : aURLObj.SetSmartURL( aCurOutputURL );
729 0 : String aPath = aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
730 :
731 0 : String aDelim = rtl::OUString(INET_PATH_TOKEN);
732 0 : if (aPath.Len() >= aDelim.Len() &&
733 0 : aPath.Copy( aPath.Len()-aDelim.Len() ).CompareTo( aDelim ) != COMPARE_EQUAL)
734 0 : aPath += aDelim;
735 0 : if (bCurFileNameFromColumn)
736 0 : pMgr->SetEMailColumn( aCurFileNamePrefix );
737 : else
738 : {
739 0 : aPath += String( aCurFileNamePrefix );
740 0 : pMgr->SetEMailColumn( String() );
741 : }
742 0 : pMgr->SetSubject( aPath );
743 0 : if(MailMergeType::FILE == nCurOutputType)
744 : {
745 0 : aMergeDesc.sSaveToFilter = sSaveFilter;
746 0 : aMergeDesc.sSaveToFilterOptions = sSaveFilterOptions;
747 0 : aMergeDesc.aSaveToFilterData = aSaveFilterData;
748 0 : aMergeDesc.bCreateSingleFile = bSaveAsSingleFile;
749 : }
750 : else
751 : {
752 0 : pMgr->SetEMailColumn( sAddressFromColumn );
753 0 : if(sAddressFromColumn.isEmpty())
754 0 : throw RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Mail address column not set." ) ), static_cast < cppu::OWeakObject * > ( this ) );
755 0 : aMergeDesc.sSaveToFilter = sAttachmentFilter;
756 0 : aMergeDesc.sSubject = sSubject;
757 0 : aMergeDesc.sMailBody = sMailBody;
758 0 : aMergeDesc.sAttachmentName = sAttachmentName;
759 0 : aMergeDesc.aCopiesTo = aCopiesTo;
760 0 : aMergeDesc.aBlindCopiesTo = aBlindCopiesTo;
761 0 : aMergeDesc.bSendAsHTML = bSendAsHTML;
762 0 : aMergeDesc.bSendAsAttachment = bSendAsAttachment;
763 :
764 0 : aMergeDesc.bCreateSingleFile = sal_False;
765 0 : pMMConfigItem = std::auto_ptr< SwMailMergeConfigItem >(new SwMailMergeConfigItem);
766 0 : aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
767 : aMergeDesc.xSmtpServer = SwMailMergeHelper::ConnectToSmtpServer(
768 0 : *pMMConfigItem,
769 : xInService,
770 0 : sInServerPassword, sOutServerPassword );
771 0 : if( !aMergeDesc.xSmtpServer.is() || !aMergeDesc.xSmtpServer->isConnected())
772 0 : throw RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Failed to connect to mail server." ) ), static_cast < cppu::OWeakObject * > ( this ) );
773 0 : }
774 : }
775 :
776 :
777 : // save document with temporary filename
778 : const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat(
779 : rtl::OUString( FILTER_XML ),
780 0 : SwDocShell::Factory().GetFilterContainer() );
781 0 : String aExtension(comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(), '*'));
782 0 : TempFile aTempFile( OUString("SwMM"), &aExtension );
783 0 : aTmpFileName = aTempFile.GetName();
784 :
785 0 : Reference< XStorable > xStorable( xCurModel, UNO_QUERY );
786 0 : sal_Bool bStoredAsTemporary = sal_False;
787 0 : if ( xStorable.is() )
788 : {
789 : try
790 : {
791 0 : xStorable->storeAsURL( aTmpFileName, Sequence< PropertyValue >() );
792 0 : bStoredAsTemporary = sal_True;
793 : }
794 0 : catch (const Exception&)
795 : {
796 : }
797 : }
798 0 : if ( !bStoredAsTemporary )
799 0 : throw RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Failed to save temporary file." ) ), static_cast < cppu::OWeakObject * > ( this ) );
800 :
801 0 : pMgr->SetMergeSilent( sal_True ); // suppress dialogs, message boxes, etc.
802 0 : const SwXMailMerge *pOldSrc = pMgr->GetMailMergeEvtSrc();
803 : OSL_ENSURE( !pOldSrc || pOldSrc == this, "Ooops... different event source already set." );
804 0 : pMgr->SetMailMergeEvtSrc( this ); // launch events for listeners
805 :
806 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xCurDocSh));
807 0 : sal_Bool bSucc = pMgr->MergeNew( aMergeDesc );
808 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), xCurDocSh));
809 :
810 0 : pMgr->SetMailMergeEvtSrc( pOldSrc );
811 :
812 0 : if ( xCurModel.get() != xModel.get() )
813 : { // in case it was a temporary model -> close it, and delete the file
814 0 : DeleteTmpFile_Impl( xCurModel, xCurDocSh, aTmpFileName );
815 0 : aTmpFileName.Erase();
816 : }
817 : // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest)
818 :
819 0 : if (!bSucc)
820 0 : throw Exception( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Mail merge failed. Sorry, no further information available." ) ), static_cast < cppu::OWeakObject * > ( this ) );
821 :
822 : //de-initialize services
823 0 : if(xInService.is() && xInService->isConnected())
824 0 : xInService->disconnect();
825 0 : if(aMergeDesc.xSmtpServer.is() && aMergeDesc.xSmtpServer->isConnected())
826 0 : aMergeDesc.xSmtpServer->disconnect();
827 :
828 0 : return makeAny( sal_True );
829 : }
830 :
831 0 : void SwXMailMerge::LaunchMailMergeEvent( const MailMergeEvent &rEvt ) const
832 : {
833 0 : cppu::OInterfaceIteratorHelper aIt( ((SwXMailMerge *) this)->aMergeListeners );
834 0 : while (aIt.hasMoreElements())
835 : {
836 0 : Reference< XMailMergeListener > xRef( aIt.next(), UNO_QUERY );
837 0 : if (xRef.is())
838 0 : xRef->notifyMailMergeEvent( rEvt );
839 0 : }
840 0 : }
841 :
842 0 : void SwXMailMerge::launchEvent( const PropertyChangeEvent &rEvt ) const
843 : {
844 : cppu::OInterfaceContainerHelper *pContainer =
845 0 : aPropListeners.getContainer( rEvt.PropertyHandle );
846 0 : if (pContainer)
847 : {
848 0 : cppu::OInterfaceIteratorHelper aIt( *pContainer );
849 0 : while (aIt.hasMoreElements())
850 : {
851 0 : Reference< XPropertyChangeListener > xRef( aIt.next(), UNO_QUERY );
852 0 : if (xRef.is())
853 0 : xRef->propertyChange( rEvt );
854 0 : }
855 : }
856 0 : }
857 :
858 :
859 0 : uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXMailMerge::getPropertySetInfo( )
860 : throw (RuntimeException)
861 : {
862 0 : SolarMutexGuard aGuard;
863 0 : static Reference< XPropertySetInfo > aRef = pPropSet->getPropertySetInfo();
864 0 : return aRef;
865 : }
866 :
867 0 : void SAL_CALL SwXMailMerge::setPropertyValue(
868 : const OUString& rPropertyName, const uno::Any& rValue )
869 : throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
870 : {
871 0 : SolarMutexGuard aGuard;
872 :
873 0 : const SfxItemPropertySimpleEntry* pCur = pPropSet->getPropertyMap().getByName( rPropertyName );
874 0 : if (!pCur)
875 0 : throw UnknownPropertyException();
876 0 : else if (pCur->nFlags & PropertyAttribute::READONLY)
877 0 : throw PropertyVetoException();
878 : else
879 : {
880 0 : void *pData = NULL;
881 0 : const uno::Type* pType = pCur->pType;
882 0 : switch (pCur->nWID)
883 : {
884 0 : case WID_SELECTION : pData = &aSelection; break;
885 0 : case WID_RESULT_SET : pData = &xResultSet; break;
886 0 : case WID_CONNECTION : pData = &xConnection; break;
887 0 : case WID_MODEL : pData = &xModel; break;
888 0 : case WID_DATA_SOURCE_NAME : pData = &aDataSourceName; break;
889 0 : case WID_DATA_COMMAND : pData = &aDataCommand; break;
890 0 : case WID_FILTER : pData = &aFilter; break;
891 0 : case WID_DOCUMENT_URL : pData = &aDocumentURL; break;
892 0 : case WID_OUTPUT_URL : pData = &aOutputURL; break;
893 0 : case WID_DATA_COMMAND_TYPE : pData = &nDataCommandType; break;
894 0 : case WID_OUTPUT_TYPE : pData = &nOutputType; break;
895 0 : case WID_ESCAPE_PROCESSING : pData = &bEscapeProcessing; break;
896 0 : case WID_SINGLE_PRINT_JOBS : pData = &bSinglePrintJobs; break;
897 0 : case WID_FILE_NAME_FROM_COLUMN : pData = &bFileNameFromColumn; break;
898 0 : case WID_FILE_NAME_PREFIX : pData = &aFileNamePrefix; break;
899 0 : case WID_MAIL_SUBJECT: pData = &sSubject; break;
900 0 : case WID_ADDRESS_FROM_COLUMN: pData = &sAddressFromColumn; break;
901 0 : case WID_SEND_AS_HTML: pData = &bSendAsHTML; break;
902 0 : case WID_SEND_AS_ATTACHMENT: pData = &bSendAsAttachment; break;
903 0 : case WID_MAIL_BODY: pData = &sMailBody; break;
904 0 : case WID_ATTACHMENT_NAME: pData = &sAttachmentName; break;
905 0 : case WID_ATTACHMENT_FILTER: pData = &sAttachmentFilter;break;
906 0 : case WID_PRINT_OPTIONS: pData = &aPrintSettings; break;
907 0 : case WID_SAVE_AS_SINGLE_FILE: pData = &bSaveAsSingleFile; break;
908 0 : case WID_SAVE_FILTER: pData = &sSaveFilter; break;
909 0 : case WID_SAVE_FILTER_OPTIONS: pData = &sSaveFilterOptions; break;
910 0 : case WID_SAVE_FILTER_DATA: pData = &aSaveFilterData; break;
911 0 : case WID_COPIES_TO: pData = &aCopiesTo; break;
912 0 : case WID_BLIND_COPIES_TO: pData = &aBlindCopiesTo;break;
913 0 : case WID_IN_SERVER_PASSWORD: pData = &sInServerPassword; break;
914 0 : case WID_OUT_SERVER_PASSWORD: pData = &sOutServerPassword; break;
915 : default :
916 : OSL_FAIL("unknown WID");
917 : }
918 0 : Any aOld( pData, *pType );
919 :
920 0 : sal_Bool bChanged = sal_False;
921 0 : sal_Bool bOK = sal_True;
922 0 : if (aOld != rValue)
923 : {
924 0 : if (pData == &aSelection)
925 0 : bOK = rValue >>= aSelection;
926 0 : else if (pData == &xResultSet)
927 0 : bOK = rValue >>= xResultSet;
928 0 : else if (pData == &xConnection)
929 0 : bOK = rValue >>= xConnection;
930 0 : else if (pData == &xModel)
931 0 : bOK = rValue >>= xModel;
932 0 : else if (pData == &aDataSourceName)
933 0 : bOK = rValue >>= aDataSourceName;
934 0 : else if (pData == &aDataCommand)
935 0 : bOK = rValue >>= aDataCommand;
936 0 : else if (pData == &aFilter)
937 0 : bOK = rValue >>= aFilter;
938 0 : else if (pData == &aDocumentURL)
939 : {
940 0 : OUString aText;
941 0 : bOK = rValue >>= aText;
942 0 : if (!aText.isEmpty()
943 0 : && !LoadFromURL_impl( xModel, xDocSh, aText, sal_True ))
944 0 : throw RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Failed to create document from URL: " ) ) + aText, static_cast < cppu::OWeakObject * > ( this ) );
945 0 : aDocumentURL = aText;
946 : }
947 0 : else if (pData == &aOutputURL)
948 : {
949 0 : OUString aText;
950 0 : bOK = rValue >>= aText;
951 0 : if (!aText.isEmpty())
952 : {
953 0 : if (!UCB_IsDirectory(aText))
954 0 : throw IllegalArgumentException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "URL does not point to a directory: " ) ) + aText, static_cast < cppu::OWeakObject * > ( this ), 0 );
955 0 : if (UCB_IsReadOnlyFileName(aText))
956 0 : throw IllegalArgumentException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "URL is read-only: " ) ) + aText, static_cast < cppu::OWeakObject * > ( this ), 0 );
957 : }
958 0 : aOutputURL = aText;
959 : }
960 0 : else if (pData == &nDataCommandType)
961 0 : bOK = rValue >>= nDataCommandType;
962 0 : else if (pData == &nOutputType)
963 0 : bOK = rValue >>= nOutputType;
964 0 : else if (pData == &bEscapeProcessing)
965 0 : bOK = rValue >>= bEscapeProcessing;
966 0 : else if (pData == &bSinglePrintJobs)
967 0 : bOK = rValue >>= bSinglePrintJobs;
968 0 : else if (pData == &bFileNameFromColumn)
969 0 : bOK = rValue >>= bFileNameFromColumn;
970 0 : else if (pData == &aFileNamePrefix)
971 0 : bOK = rValue >>= aFileNamePrefix;
972 0 : else if (pData == &sSubject)
973 0 : bOK = rValue >>= sSubject;
974 0 : else if (pData == &sAddressFromColumn)
975 0 : bOK = rValue >>= sAddressFromColumn;
976 0 : else if (pData == &bSendAsHTML)
977 0 : bOK = rValue >>= bSendAsHTML;
978 0 : else if (pData == &bSendAsAttachment)
979 0 : bOK = rValue >>= bSendAsAttachment;
980 0 : else if (pData == &sMailBody)
981 0 : bOK = rValue >>= sMailBody;
982 0 : else if (pData == &sAttachmentName)
983 0 : bOK = rValue >>= sAttachmentName;
984 0 : else if (pData == &sAttachmentFilter)
985 0 : bOK = rValue >>= sAttachmentFilter;
986 0 : else if (pData == &aPrintSettings)
987 0 : bOK = rValue >>= aPrintSettings;
988 0 : else if (pData == &bSaveAsSingleFile)
989 0 : bOK = rValue >>= bSaveAsSingleFile;
990 0 : else if (pData == &sSaveFilter)
991 0 : bOK = rValue >>= sSaveFilter;
992 0 : else if (pData == &sSaveFilterOptions)
993 0 : bOK = rValue >>= sSaveFilterOptions;
994 0 : else if (pData == &aSaveFilterData)
995 0 : bOK = rValue >>= aSaveFilterData;
996 0 : else if (pData == &aCopiesTo)
997 0 : bOK = rValue >>= aCopiesTo;
998 0 : else if (pData == &aBlindCopiesTo)
999 0 : bOK = rValue >>= aBlindCopiesTo;
1000 0 : else if(pData == &sInServerPassword)
1001 0 : bOK = rValue >>= sInServerPassword;
1002 0 : else if(pData == &sOutServerPassword)
1003 0 : bOK = rValue >>= sInServerPassword;
1004 : else {
1005 : OSL_FAIL("invalid pointer" );
1006 : }
1007 : OSL_ENSURE( bOK, "set value failed" );
1008 0 : bChanged = sal_True;
1009 : }
1010 0 : if (!bOK)
1011 0 : throw IllegalArgumentException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property type mismatch or property not set: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ), 0 );
1012 :
1013 0 : if (bChanged)
1014 : {
1015 : PropertyChangeEvent aChgEvt( (XPropertySet *) this, rPropertyName,
1016 0 : sal_False, pCur->nWID, aOld, rValue );
1017 0 : launchEvent( aChgEvt );
1018 0 : }
1019 0 : }
1020 0 : }
1021 :
1022 0 : uno::Any SAL_CALL SwXMailMerge::getPropertyValue(
1023 : const OUString& rPropertyName )
1024 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
1025 : {
1026 0 : SolarMutexGuard aGuard;
1027 :
1028 0 : Any aRet;
1029 :
1030 0 : const SfxItemPropertySimpleEntry* pCur = pPropSet->getPropertyMap().getByName( rPropertyName );
1031 0 : if (!pCur)
1032 0 : throw UnknownPropertyException();
1033 : else
1034 : {
1035 0 : switch (pCur->nWID)
1036 : {
1037 0 : case WID_SELECTION : aRet <<= aSelection; break;
1038 0 : case WID_RESULT_SET : aRet <<= xResultSet; break;
1039 0 : case WID_CONNECTION : aRet <<= xConnection; break;
1040 0 : case WID_MODEL : aRet <<= xModel; break;
1041 0 : case WID_DATA_SOURCE_NAME : aRet <<= aDataSourceName; break;
1042 0 : case WID_DATA_COMMAND : aRet <<= aDataCommand; break;
1043 0 : case WID_FILTER : aRet <<= aFilter; break;
1044 0 : case WID_DOCUMENT_URL : aRet <<= aDocumentURL; break;
1045 0 : case WID_OUTPUT_URL : aRet <<= aOutputURL; break;
1046 0 : case WID_DATA_COMMAND_TYPE : aRet <<= nDataCommandType; break;
1047 0 : case WID_OUTPUT_TYPE : aRet <<= nOutputType; break;
1048 0 : case WID_ESCAPE_PROCESSING : aRet <<= bEscapeProcessing; break;
1049 0 : case WID_SINGLE_PRINT_JOBS : aRet <<= bSinglePrintJobs; break;
1050 0 : case WID_FILE_NAME_FROM_COLUMN : aRet <<= bFileNameFromColumn; break;
1051 0 : case WID_FILE_NAME_PREFIX : aRet <<= aFileNamePrefix; break;
1052 0 : case WID_MAIL_SUBJECT: aRet <<= sSubject; break;
1053 0 : case WID_ADDRESS_FROM_COLUMN: aRet <<= sAddressFromColumn; break;
1054 0 : case WID_SEND_AS_HTML: aRet <<= bSendAsHTML; break;
1055 0 : case WID_SEND_AS_ATTACHMENT: aRet <<= bSendAsAttachment; break;
1056 0 : case WID_MAIL_BODY: aRet <<= sMailBody; break;
1057 0 : case WID_ATTACHMENT_NAME: aRet <<= sAttachmentName; break;
1058 0 : case WID_ATTACHMENT_FILTER: aRet <<= sAttachmentFilter;break;
1059 0 : case WID_PRINT_OPTIONS: aRet <<= aPrintSettings; break;
1060 0 : case WID_SAVE_AS_SINGLE_FILE: aRet <<= bSaveAsSingleFile; break;
1061 0 : case WID_SAVE_FILTER: aRet <<= sSaveFilter; break;
1062 0 : case WID_SAVE_FILTER_OPTIONS: aRet <<= sSaveFilterOptions; break;
1063 0 : case WID_SAVE_FILTER_DATA: aRet <<= aSaveFilterData; break;
1064 0 : case WID_COPIES_TO: aRet <<= aCopiesTo; break;
1065 0 : case WID_BLIND_COPIES_TO: aRet <<= aBlindCopiesTo;break;
1066 0 : case WID_IN_SERVER_PASSWORD: aRet <<= sInServerPassword; break;
1067 0 : case WID_OUT_SERVER_PASSWORD: aRet <<= sOutServerPassword; break;
1068 : default :
1069 : OSL_FAIL("unknown WID");
1070 : }
1071 : }
1072 :
1073 0 : return aRet;
1074 : }
1075 :
1076 0 : void SAL_CALL SwXMailMerge::addPropertyChangeListener(
1077 : const OUString& rPropertyName,
1078 : const uno::Reference< beans::XPropertyChangeListener >& rListener )
1079 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
1080 : {
1081 0 : SolarMutexGuard aGuard;
1082 0 : if (!bDisposing && rListener.is())
1083 : {
1084 0 : const SfxItemPropertySimpleEntry* pCur = pPropSet->getPropertyMap().getByName( rPropertyName );
1085 0 : if (pCur)
1086 0 : aPropListeners.addInterface( pCur->nWID, rListener );
1087 : else
1088 0 : throw UnknownPropertyException();
1089 0 : }
1090 0 : }
1091 :
1092 0 : void SAL_CALL SwXMailMerge::removePropertyChangeListener(
1093 : const OUString& rPropertyName,
1094 : const uno::Reference< beans::XPropertyChangeListener >& rListener )
1095 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
1096 : {
1097 0 : SolarMutexGuard aGuard;
1098 0 : if (!bDisposing && rListener.is())
1099 : {
1100 0 : const SfxItemPropertySimpleEntry* pCur = pPropSet->getPropertyMap().getByName( rPropertyName );
1101 0 : if (pCur)
1102 0 : aPropListeners.removeInterface( pCur->nWID, rListener );
1103 : else
1104 0 : throw UnknownPropertyException();
1105 0 : }
1106 0 : }
1107 :
1108 0 : void SAL_CALL SwXMailMerge::addVetoableChangeListener(
1109 : const OUString& /*rPropertyName*/,
1110 : const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ )
1111 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
1112 : {
1113 : // no vetoable property, thus no support for vetoable change listeners
1114 : OSL_FAIL("not implemented");
1115 0 : }
1116 :
1117 0 : void SAL_CALL SwXMailMerge::removeVetoableChangeListener(
1118 : const OUString& /*rPropertyName*/,
1119 : const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ )
1120 : throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
1121 : {
1122 : // no vetoable property, thus no support for vetoable change listeners
1123 : OSL_FAIL("not implemented");
1124 0 : }
1125 :
1126 :
1127 0 : void SAL_CALL SwXMailMerge::dispose()
1128 : throw(RuntimeException)
1129 : {
1130 0 : SolarMutexGuard aGuard;
1131 :
1132 0 : if (!bDisposing)
1133 : {
1134 0 : bDisposing = sal_True;
1135 :
1136 0 : EventObject aEvtObj( (XPropertySet *) this );
1137 0 : aEvtListeners.disposeAndClear( aEvtObj );
1138 0 : aMergeListeners.disposeAndClear( aEvtObj );
1139 0 : aPropListeners.disposeAndClear( aEvtObj );
1140 0 : }
1141 0 : }
1142 :
1143 0 : void SAL_CALL SwXMailMerge::addEventListener(
1144 : const Reference< XEventListener >& rxListener )
1145 : throw(RuntimeException)
1146 : {
1147 0 : SolarMutexGuard aGuard;
1148 0 : if (!bDisposing && rxListener.is())
1149 0 : aEvtListeners.addInterface( rxListener );
1150 0 : }
1151 :
1152 0 : void SAL_CALL SwXMailMerge::removeEventListener(
1153 : const Reference< XEventListener >& rxListener )
1154 : throw(RuntimeException)
1155 : {
1156 0 : SolarMutexGuard aGuard;
1157 0 : if (!bDisposing && rxListener.is())
1158 0 : aEvtListeners.removeInterface( rxListener );
1159 0 : }
1160 :
1161 0 : void SAL_CALL SwXMailMerge::addMailMergeEventListener(
1162 : const uno::Reference< XMailMergeListener >& rxListener )
1163 : throw (RuntimeException)
1164 : {
1165 0 : SolarMutexGuard aGuard;
1166 0 : if (!bDisposing && rxListener.is())
1167 0 : aMergeListeners.addInterface( rxListener );
1168 0 : }
1169 :
1170 0 : void SAL_CALL SwXMailMerge::removeMailMergeEventListener(
1171 : const uno::Reference< XMailMergeListener >& rxListener )
1172 : throw (RuntimeException)
1173 : {
1174 0 : SolarMutexGuard aGuard;
1175 0 : if (!bDisposing && rxListener.is())
1176 0 : aMergeListeners.removeInterface( rxListener );
1177 0 : }
1178 :
1179 0 : OUString SAL_CALL SwXMailMerge::getImplementationName()
1180 : throw(RuntimeException)
1181 : {
1182 0 : SolarMutexGuard aGuard;
1183 0 : return SwXMailMerge_getImplementationName();
1184 : }
1185 :
1186 0 : sal_Bool SAL_CALL SwXMailMerge::supportsService( const OUString& rServiceName )
1187 : throw(RuntimeException)
1188 : {
1189 0 : SolarMutexGuard aGuard;
1190 0 : return rServiceName == SN_MAIL_MERGE || rServiceName == SN_DATA_ACCESS_DESCRIPTOR;
1191 : }
1192 :
1193 0 : uno::Sequence< OUString > SAL_CALL SwXMailMerge::getSupportedServiceNames()
1194 : throw(RuntimeException)
1195 : {
1196 0 : SolarMutexGuard aGuard;
1197 0 : return SwXMailMerge_getSupportedServiceNames();
1198 : }
1199 :
1200 : ////////////////////////////////////////////////////////////
1201 :
1202 0 : uno::Sequence< OUString > SAL_CALL SwXMailMerge_getSupportedServiceNames()
1203 : throw()
1204 : {
1205 0 : uno::Sequence< OUString > aNames(2);
1206 0 : OUString *pName = aNames.getArray();
1207 0 : pName[0] = SN_MAIL_MERGE;
1208 0 : pName[1] = SN_DATA_ACCESS_DESCRIPTOR;
1209 0 : return aNames;
1210 : }
1211 :
1212 9 : OUString SAL_CALL SwXMailMerge_getImplementationName()
1213 : throw()
1214 : {
1215 9 : return OUString( "SwXMailMerge" );
1216 : }
1217 :
1218 0 : uno::Reference< uno::XInterface > SAL_CALL SwXMailMerge_createInstance(
1219 : const uno::Reference< XMultiServiceFactory > & /*rSMgr*/)
1220 : throw( uno::Exception )
1221 : {
1222 0 : SolarMutexGuard aGuard;
1223 :
1224 : //the module may not be loaded
1225 0 : SwGlobals::ensure();
1226 0 : uno::Reference< uno::XInterface > xRef = (cppu::OWeakObject *) new SwXMailMerge();
1227 0 : return xRef;
1228 : }
1229 :
1230 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|