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