LCOV - code coverage report
Current view: top level - sw/source/uibase/uno - unomailmerge.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 225 648 34.7 %
Date: 2015-06-13 12:38:46 Functions: 13 39 33.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11