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