LCOV - code coverage report
Current view: top level - sw/source/uibase/uno - unomailmerge.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 216 658 32.8 %
Date: 2014-11-03 Functions: 16 42 38.1 %
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 <swevent.hxx>
      53             : #include <unomailmerge.hxx>
      54             : #include <swdll.hxx>
      55             : #include <swmodule.hxx>
      56             : #include <unoprnms.hxx>
      57             : #include <unomap.hxx>
      58             : #include <swunohelper.hxx>
      59             : #include <docsh.hxx>
      60             : #include <IDocumentDeviceAccess.hxx>
      61             : #include <view.hxx>
      62             : #include <dbmgr.hxx>
      63             : #include <unotxdoc.hxx>
      64             : #include <prtopt.hxx>
      65             : #include <wrtsh.hxx>
      66             : #include <shellio.hxx>
      67             : #include <mmconfigitem.hxx>
      68             : #include <mailmergehelper.hxx>
      69             : 
      70             : #include <unomid.h>
      71             : 
      72             : #include <boost/noncopyable.hpp>
      73             : #include <boost/scoped_ptr.hpp>
      74             : 
      75             : using namespace ::com::sun::star;
      76             : using namespace ::com::sun::star::frame;
      77             : using namespace ::com::sun::star::uno;
      78             : using namespace ::com::sun::star::lang;
      79             : using namespace ::com::sun::star::beans;
      80             : using namespace ::com::sun::star::text;
      81             : using namespace SWUnoHelper;
      82             : 
      83             : typedef ::utl::SharedUNOComponent< XInterface > SharedComponent;
      84             : 
      85          16 : osl::Mutex &    GetMailMergeMutex()
      86             : {
      87          16 :     static osl::Mutex   aMutex;
      88          16 :     return aMutex;
      89             : }
      90             : 
      91             : enum CloseResult
      92             : {
      93             :     eSuccess,       // successfully closed
      94             :     eVetoed,        // vetoed, ownership transferred to the vetoing instance
      95             :     eFailed         // failed for some unknown reason
      96             : };
      97           8 : static CloseResult CloseModelAndDocSh(
      98             :        Reference< frame::XModel > &rxModel,
      99             :        SfxObjectShellRef &rxDocSh )
     100             : {
     101           8 :     CloseResult eResult = eSuccess;
     102             : 
     103           8 :     rxDocSh = 0;
     104             : 
     105             :     //! models/documents should never be disposed (they may still be
     106             :     //! used for printing which is called asynchronously for example)
     107             :     //! instead call close
     108           8 :     Reference< util::XCloseable > xClose( rxModel, UNO_QUERY );
     109           8 :     if (xClose.is())
     110             :     {
     111             :         try
     112             :         {
     113             :             //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
     114             :             //! I.e. now that object is responsible for closing the model and doc shell.
     115           8 :             xClose->close( sal_True );
     116             :         }
     117           0 :         catch (const util::CloseVetoException&)
     118             :         {
     119             :             //! here we have the problem that the temporary file that is
     120             :             //! currently being printed will never be deleted. :-(
     121           0 :             eResult = eVetoed;
     122             :         }
     123           0 :         catch (const uno::RuntimeException&)
     124             :         {
     125           0 :             eResult = eFailed;
     126             :         }
     127             :     }
     128           8 :     return eResult;
     129             : }
     130             : 
     131           4 : static bool LoadFromURL_impl(
     132             :         Reference< frame::XModel > &rxModel,
     133             :         SfxObjectShellRef &rxDocSh,
     134             :         const OUString &rURL,
     135             :         bool bClose )
     136             :     throw (RuntimeException)
     137             : {
     138             :     // try to open the document readonly and hidden
     139           4 :     Reference< frame::XModel > xTmpModel;
     140           8 :     Sequence < PropertyValue > aArgs( 1 );
     141           4 :     aArgs[0].Name = "Hidden";
     142           4 :     bool bVal = true;
     143           4 :     aArgs[0].Value <<= bVal;
     144             :     try
     145             :     {
     146           4 :         Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
     147          12 :         xTmpModel = Reference < XModel >( xDesktop->loadComponentFromURL(
     148          12 :                 rURL, "_blank", 0, aArgs ), UNO_QUERY );
     149             :     }
     150           0 :     catch (const Exception&)
     151             :     {
     152           0 :         return false;
     153             :     }
     154             : 
     155             :     // try to get the DocShell
     156           4 :     SwDocShell *pTmpDocShell = 0;
     157           8 :     Reference < XUnoTunnel > xTunnel( xTmpModel, UNO_QUERY );
     158           4 :     if (xTunnel.is())
     159             :     {
     160             :         SwXTextDocument* pTextDoc = reinterpret_cast<SwXTextDocument *>(
     161           4 :                 xTunnel->getSomething( SwXTextDocument::getUnoTunnelId() ));
     162           4 :         pTmpDocShell = pTextDoc ? pTextDoc->GetDocShell() : 0;
     163             :     }
     164             : 
     165           4 :     bool bRes = false;
     166           4 :     if (xTmpModel.is() && pTmpDocShell)    // everything available?
     167             :     {
     168           4 :         if (bClose)
     169           0 :             CloseModelAndDocSh( rxModel, rxDocSh );
     170             :         // set new stuff
     171           4 :         rxModel = xTmpModel;
     172           4 :         rxDocSh = pTmpDocShell;
     173           4 :         bRes = true;
     174             :     }
     175             :     else
     176             :     {
     177             :         // SfxObjectShellRef is ok here, since the document will be explicitly closed
     178           0 :         SfxObjectShellRef xTmpDocSh = pTmpDocShell;
     179           0 :         CloseModelAndDocSh( xTmpModel, xTmpDocSh );
     180             :     }
     181             : 
     182           8 :     return bRes;
     183             : }
     184             : 
     185             : namespace
     186             : {
     187             :     class DelayedFileDeletion : public ::cppu::WeakImplHelper1< util::XCloseListener >,
     188             :                                 private boost::noncopyable
     189             :     {
     190             :     protected:
     191             :         ::osl::Mutex                    m_aMutex;
     192             :         Reference< util::XCloseable >   m_xDocument;
     193             :         Timer                           m_aDeleteTimer;
     194             :         OUString                        m_sTemporaryFile;
     195             :         sal_Int32                       m_nPendingDeleteAttempts;
     196             : 
     197             :     public:
     198             :         DelayedFileDeletion( const Reference< XModel >& _rxModel,
     199             :                              const OUString& _rTemporaryFile );
     200             : 
     201             :     protected:
     202             :         virtual ~DelayedFileDeletion( );
     203             : 
     204             :         // XCloseListener
     205             :         virtual void SAL_CALL queryClosing( const EventObject& _rSource, sal_Bool _bGetsOwnership ) throw (util::CloseVetoException, RuntimeException, std::exception) SAL_OVERRIDE;
     206             :         virtual void SAL_CALL notifyClosing( const EventObject& _rSource ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     207             : 
     208             :         // XEventListener
     209             :         virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     210             : 
     211             :     private:
     212             :         void implTakeOwnership( );
     213             :         DECL_LINK( OnTryDeleteFile, void* );
     214             :     };
     215             : 
     216           0 :     DelayedFileDeletion::DelayedFileDeletion( const Reference< XModel >& _rxModel, const OUString& _rTemporaryFile )
     217             :         :
     218             :         m_xDocument( _rxModel, UNO_QUERY )
     219             :         ,m_sTemporaryFile( _rTemporaryFile )
     220           0 :         ,m_nPendingDeleteAttempts( 0 )
     221             :     {
     222           0 :         osl_atomic_increment( &m_refCount );
     223             :         try
     224             :         {
     225           0 :             if ( m_xDocument.is() )
     226             :             {
     227           0 :                 m_xDocument->addCloseListener( this );
     228             :                 // successfully added -> keep ourself alive
     229           0 :                 acquire();
     230             :             }
     231             :             else {
     232             :                 OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: model is no component!" );
     233             :             }
     234             :         }
     235           0 :         catch (const Exception&)
     236             :         {
     237             :             OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: could not register as event listener at the model!" );
     238             :         }
     239           0 :         osl_atomic_decrement( &m_refCount );
     240           0 :     }
     241             : 
     242           0 :     IMPL_LINK_NOARG(DelayedFileDeletion, OnTryDeleteFile)
     243             :     {
     244           0 :         ::osl::ClearableMutexGuard aGuard( m_aMutex );
     245             : 
     246           0 :         bool bSuccess = false;
     247             :         try
     248             :         {
     249           0 :             bool bDeliverOwnership = ( 0 == m_nPendingDeleteAttempts );
     250             :                 // if this is our last attemt, then anybody which vetoes this has to take the consequences
     251             :                 // (means take the ownership)
     252           0 :             m_xDocument->close( bDeliverOwnership );
     253           0 :             bSuccess = true;
     254             :         }
     255           0 :         catch (const util::CloseVetoException&)
     256             :         {
     257             :             // somebody vetoed -> next try
     258           0 :             if ( m_nPendingDeleteAttempts )
     259             :             {
     260             :                 // next attempt
     261           0 :                 --m_nPendingDeleteAttempts;
     262           0 :                 m_aDeleteTimer.Start();
     263             :             }
     264             :             else
     265           0 :                 bSuccess = true;    // can't do anything here ...
     266             :         }
     267           0 :         catch (const Exception&)
     268             :         {
     269             :             OSL_FAIL("DelayedFileDeletion::OnTryDeleteFile: caught a strange exception!" );
     270           0 :             bSuccess = true;
     271             :                 // can't do anything here ...
     272             :         }
     273             : 
     274           0 :         if ( bSuccess )
     275             :         {
     276           0 :             SWUnoHelper::UCB_DeleteFile( m_sTemporaryFile );
     277           0 :             aGuard.clear();
     278           0 :             release();  // this should be our last reference, we should be dead after this
     279             :         }
     280           0 :         return 0L;
     281             :     }
     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           4 : static bool DeleteTmpFile_Impl(
     334             :         Reference< frame::XModel > &rxModel,
     335             :         SfxObjectShellRef &rxDocSh,
     336             :         const OUString &rTmpFileURL )
     337             : {
     338           4 :     bool bRes = false;
     339           4 :     if (!rTmpFileURL.isEmpty())
     340             :     {
     341           4 :         bool bDelete = true;
     342           4 :         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           4 :         rxModel = 0;
     353           4 :         rxDocSh = 0; // destroy doc shell
     354             : 
     355           4 :         if ( bDelete )
     356             :         {
     357           4 :             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           4 :     return bRes;
     367             : }
     368             : 
     369           4 : SwXMailMerge::SwXMailMerge() :
     370           4 :     aEvtListeners   ( GetMailMergeMutex() ),
     371           4 :     aMergeListeners ( GetMailMergeMutex() ),
     372           4 :     aPropListeners  ( GetMailMergeMutex() ),
     373           4 :     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          20 :     m_pMgr(0)
     384             : {
     385             :     // create empty document
     386             :     // like in: SwModule::InsertEnv (appenv.cxx)
     387           4 :     xDocSh = new SwDocShell( SFX_CREATE_MODE_STANDARD );
     388           4 :     xDocSh->DoInitNew( 0 );
     389           4 :     SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
     390           4 :     SwView *pView = (SwView*) pFrame->GetViewShell();
     391           4 :     pView->AttrChangedNotify( &pView->GetWrtShell() ); //So that SelectShell is called.
     392           4 :     xModel = xDocSh->GetModel();
     393           4 : }
     394             : 
     395          12 : SwXMailMerge::~SwXMailMerge()
     396             : {
     397           4 :     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           4 :         if ( eVetoed == CloseModelAndDocSh( xModel, xDocSh ) )
     405             :             OSL_FAIL("owner ship transfered to vetoing object!" );
     406             : 
     407           4 :         xModel = 0;
     408           4 :         xDocSh = 0; // destroy doc shell
     409             :     }
     410           8 : }
     411             : 
     412             : // Guarantee object consistence in case of an exception
     413             : class MailMergeExecuteFinalizer: private boost::noncopyable {
     414             : public:
     415           4 :     MailMergeExecuteFinalizer(SwXMailMerge *mailmerge)
     416           4 :         : m_pMailMerge(mailmerge)
     417             :     {
     418             :         assert(m_pMailMerge); //mailmerge object missing
     419           4 :     }
     420           4 :     ~MailMergeExecuteFinalizer()
     421             :     {
     422           4 :         osl::MutexGuard pMgrGuard( GetMailMergeMutex() );
     423           4 :         m_pMailMerge->m_pMgr = 0;
     424           4 :     }
     425             : 
     426             : private:
     427             :     SwXMailMerge *m_pMailMerge;
     428             : };
     429             : 
     430           4 : uno::Any SAL_CALL SwXMailMerge::execute(
     431             :         const uno::Sequence< beans::NamedValue >& rArguments )
     432             :     throw (IllegalArgumentException, Exception,
     433             :            RuntimeException, std::exception)
     434             : {
     435           4 :     SolarMutexGuard aGuard;
     436           8 :     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           8 :     uno::Sequence< uno::Any >           aCurSelection   = aSelection;
     443           8 :     uno::Reference< sdbc::XResultSet >  xCurResultSet   = xResultSet;
     444           8 :     uno::Reference< sdbc::XConnection > xCurConnection  = xConnection;
     445           8 :     uno::Reference< frame::XModel >     xCurModel       = xModel;
     446           8 :     OUString   aCurDataSourceName       = aDataSourceName;
     447           8 :     OUString   aCurDataCommand          = aDataCommand;
     448           8 :     OUString   aCurFilter               = aFilter;
     449           8 :     OUString   aCurDocumentURL          = aDocumentURL;
     450           8 :     OUString   aCurOutputURL            = aOutputURL;
     451           8 :     OUString   aCurFileNamePrefix       = aFileNamePrefix;
     452           4 :     sal_Int32  nCurDataCommandType      = nDataCommandType;
     453           4 :     sal_Int16  nCurOutputType           = nOutputType;
     454           4 :     bool   bCurEscapeProcessing     = bEscapeProcessing;
     455           4 :     bool   bCurSinglePrintJobs      = bSinglePrintJobs;
     456           4 :     bool   bCurFileNameFromColumn   = bFileNameFromColumn;
     457             : 
     458           8 :     SfxObjectShellRef xCurDocSh = xDocSh;   // the document
     459             : 
     460           4 :     const beans::NamedValue *pArguments = rArguments.getConstArray();
     461           4 :     sal_Int32 nArgs = rArguments.getLength();
     462          32 :     for (sal_Int32 i = 0;  i < nArgs;  ++i)
     463             :     {
     464          28 :         const OUString &rName   = pArguments[i].Name;
     465          28 :         const Any &rValue       = pArguments[i].Value;
     466             : 
     467          28 :         bool bOK = true;
     468          28 :         if (rName == UNO_NAME_SELECTION)
     469           0 :             bOK = rValue >>= aCurSelection;
     470          28 :         else if (rName == UNO_NAME_RESULT_SET)
     471           0 :             bOK = rValue >>= xCurResultSet;
     472          28 :         else if (rName == UNO_NAME_CONNECTION)
     473           0 :             bOK = rValue >>= xCurConnection;
     474          28 :         else if (rName == UNO_NAME_MODEL)
     475           0 :             throw PropertyVetoException("Property is read-only: " + rName, static_cast < cppu::OWeakObject * > ( this ) );
     476          28 :         else if (rName == UNO_NAME_DATA_SOURCE_NAME)
     477           4 :             bOK = rValue >>= aCurDataSourceName;
     478          24 :         else if (rName == UNO_NAME_DAD_COMMAND)
     479           4 :             bOK = rValue >>= aCurDataCommand;
     480          20 :         else if (rName == UNO_NAME_FILTER)
     481           0 :             bOK = rValue >>= aCurFilter;
     482          20 :         else if (rName == UNO_NAME_DOCUMENT_URL)
     483             :         {
     484           4 :             bOK = rValue >>= aCurDocumentURL;
     485           8 :             if (!aCurDocumentURL.isEmpty()
     486           4 :                 && !LoadFromURL_impl( xCurModel, xCurDocSh, aCurDocumentURL, false ))
     487           0 :                 throw RuntimeException("Failed to create document from URL: " + aCurDocumentURL, static_cast < cppu::OWeakObject * > ( this ) );
     488             :         }
     489          16 :         else if (rName == UNO_NAME_OUTPUT_URL)
     490             :         {
     491           4 :             bOK = rValue >>= aCurOutputURL;
     492           4 :             if (!aCurOutputURL.isEmpty())
     493             :             {
     494           4 :                 if (!UCB_IsDirectory(aCurOutputURL))
     495           0 :                     throw IllegalArgumentException("URL does not point to a directory: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 0 );
     496           4 :                 if (UCB_IsReadOnlyFileName(aCurOutputURL))
     497           0 :                     throw IllegalArgumentException("URL is read-only: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 0 );
     498             :             }
     499             :         }
     500          12 :         else if (rName == UNO_NAME_FILE_NAME_PREFIX)
     501           4 :             bOK = rValue >>= aCurFileNamePrefix;
     502           8 :         else if (rName == UNO_NAME_DAD_COMMAND_TYPE)
     503           4 :             bOK = rValue >>= nCurDataCommandType;
     504           4 :         else if (rName == UNO_NAME_OUTPUT_TYPE)
     505           4 :             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          28 :         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           4 :     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             :                 }
     576           0 :                 if ( bEverythingsFine )
     577           0 :                     bValid = true;
     578             :             }
     579           0 :             catch (const Exception&)
     580             :             {
     581           0 :                 bValid = false;
     582             :             }
     583             :         }
     584             : 
     585           0 :         if ( !bValid )
     586             :         {
     587             :             throw IllegalArgumentException(
     588             :                 "The current 'Selection' does not describe a valid array of bookmarks, relative to the current 'ResultSet'.",
     589             :                 static_cast < cppu::OWeakObject * > ( this ),
     590             :                 0
     591           0 :             );
     592             :         }
     593             : 
     594           0 :         aCurSelection = aTranslated;
     595             :     }
     596             : 
     597           4 :     SfxViewFrame*   pFrame = SfxViewFrame::GetFirst( xCurDocSh, false);
     598           4 :     SwView *pView = pFrame ? PTR_CAST( SwView, pFrame->GetViewShell() ) : NULL;
     599           4 :     if (!pView)
     600           0 :         throw RuntimeException();
     601           4 :     SwWrtShell &rSh = *pView->GetWrtShellPtr();
     602             : 
     603             :     // avoid assertion in 'Update' from Sfx by supplying a shell
     604             :     // and thus avoiding the SelectShell call in Writers GetState function
     605             :     // while still in Update of Sfx.
     606             :     // (GetSelection in Update is not allowed)
     607           4 :     if (!aCurDocumentURL.isEmpty())
     608           4 :         pView->AttrChangedNotify( &pView->GetWrtShell() );//So that SelectShell is called.
     609             : 
     610           8 :     SharedComponent aRowSetDisposeHelper;
     611           4 :     if (!xCurResultSet.is())
     612             :     {
     613           4 :         if (aCurDataSourceName.isEmpty() || aCurDataCommand.isEmpty() )
     614             :         {
     615             :             OSL_FAIL("PropertyValues missing or unset");
     616           0 :             throw IllegalArgumentException("Either the ResultSet or DataSourceName and DataCommand must be set.", static_cast < cppu::OWeakObject * > ( this ), 0 );
     617             :         }
     618             : 
     619             :         // build ResultSet from DataSourceName, DataCommand and DataCommandType
     620             : 
     621           4 :         Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
     622           4 :         if (xMgr.is())
     623             :         {
     624           4 :             Reference< XInterface > xInstance = xMgr->createInstance( "com.sun.star.sdb.RowSet" );
     625           4 :             aRowSetDisposeHelper.reset( xInstance, SharedComponent::TakeOwnership );
     626           8 :             Reference< XPropertySet > xRowSetPropSet( xInstance, UNO_QUERY );
     627             :             OSL_ENSURE( xRowSetPropSet.is(), "failed to get XPropertySet interface from RowSet" );
     628           4 :             if (xRowSetPropSet.is())
     629             :             {
     630           4 :                 if (xCurConnection.is())
     631           0 :                     xRowSetPropSet->setPropertyValue( "ActiveConnection",  makeAny( xCurConnection ) );
     632           4 :                 xRowSetPropSet->setPropertyValue( "DataSourceName",    makeAny( aCurDataSourceName ) );
     633           4 :                 xRowSetPropSet->setPropertyValue( "Command",           makeAny( aCurDataCommand ) );
     634           4 :                 xRowSetPropSet->setPropertyValue( "CommandType",       makeAny( nCurDataCommandType ) );
     635           4 :                 xRowSetPropSet->setPropertyValue( "EscapeProcessing",  makeAny( bCurEscapeProcessing ) );
     636           4 :                 xRowSetPropSet->setPropertyValue( "ApplyFilter",       makeAny( sal_True ) );
     637           4 :                 xRowSetPropSet->setPropertyValue( "Filter",            makeAny( aCurFilter ) );
     638             : 
     639           4 :                 Reference< sdbc::XRowSet > xRowSet( xInstance, UNO_QUERY );
     640           4 :                 if (xRowSet.is())
     641           4 :                     xRowSet->execute(); // build ResultSet from properties
     642           4 :                 if( !xCurConnection.is() )
     643           4 :                     xCurConnection.set( xRowSetPropSet->getPropertyValue( "ActiveConnection" ), UNO_QUERY );
     644           4 :                 xCurResultSet = Reference< sdbc::XResultSet >( xRowSet, UNO_QUERY );
     645           4 :                 OSL_ENSURE( xCurResultSet.is(), "failed to build ResultSet" );
     646           4 :             }
     647           4 :         }
     648             :     }
     649             : 
     650           8 :     svx::ODataAccessDescriptor aDescriptor;
     651           4 :     aDescriptor.setDataSource(aCurDataSourceName);
     652           4 :     aDescriptor[ svx::daConnection ]         <<= xCurConnection;
     653           4 :     aDescriptor[ svx::daCommand ]            <<= aCurDataCommand;
     654           4 :     aDescriptor[ svx::daCommandType ]        <<= nCurDataCommandType;
     655           4 :     aDescriptor[ svx::daEscapeProcessing ]   <<= bCurEscapeProcessing;
     656           4 :     aDescriptor[ svx::daCursor ]             <<= xCurResultSet;
     657             :     // aDescriptor[ svx::daColumnName ]      not used
     658             :     // aDescriptor[ svx::daColumnObject ]    not used
     659           4 :     aDescriptor[ svx::daSelection ]          <<= aCurSelection;
     660             : 
     661             :     DBManagerOptions nMergeType;
     662           4 :     switch (nCurOutputType)
     663             :     {
     664           0 :         case MailMergeType::PRINTER : nMergeType = DBMGR_MERGE_PRINTER; break;
     665           0 :         case MailMergeType::FILE    : nMergeType = DBMGR_MERGE_FILE; break;
     666           0 :         case MailMergeType::MAIL    : nMergeType = DBMGR_MERGE_EMAIL; break;
     667           4 :         case MailMergeType::SHELL   : nMergeType = DBMGR_MERGE_SHELL; break;
     668             :         default:
     669           0 :             throw IllegalArgumentException("Invalid value of property: OutputType", static_cast < cppu::OWeakObject * > ( this ), 0 );
     670             :     }
     671             : 
     672           4 :     SwDBManager* pMgr = rSh.GetDBManager();
     673             :     //force layout creation
     674           4 :     rSh.CalcLayout();
     675             :     OSL_ENSURE( pMgr, "database manager missing" );
     676           4 :     m_pMgr = pMgr;
     677             : 
     678           4 :     SwMergeDescriptor aMergeDesc( nMergeType, rSh, aDescriptor );
     679             : 
     680           8 :     boost::scoped_ptr< SwMailMergeConfigItem > pMMConfigItem;
     681           8 :     uno::Reference< mail::XMailService > xInService;
     682           4 :     switch (nCurOutputType)
     683             :     {
     684             :     case MailMergeType::PRINTER:
     685             :         {
     686           0 :             IDocumentDeviceAccess* pIDDA = rSh.getIDocumentDeviceAccess();
     687           0 :             SwPrintData aPrtData( pIDDA->getPrintData() );
     688           0 :             aPrtData.SetPrintSingleJobs( bCurSinglePrintJobs );
     689           0 :             pIDDA->setPrintData( aPrtData );
     690             :             // #i25686# printing should not be done asynchronously to prevent dangling offices
     691             :             // when mail merge is called as command line macro
     692           0 :             aMergeDesc.bPrintAsync = false;
     693           0 :             aMergeDesc.aPrintOptions = aPrintSettings;
     694           0 :             aMergeDesc.bCreateSingleFile = true;
     695             :         }
     696           0 :         break;
     697             :     case MailMergeType::SHELL:
     698           4 :         aMergeDesc.bCreateSingleFile = true;
     699           4 :         pMMConfigItem.reset(new SwMailMergeConfigItem);
     700           4 :         aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
     701           4 :         break;
     702             :     case MailMergeType::FILE:
     703             :     case MailMergeType::MAIL:
     704             :         {
     705           0 :             INetURLObject aURLObj;
     706           0 :             aURLObj.SetSmartProtocol( INET_PROT_FILE );
     707             : 
     708           0 :             if (!aCurDocumentURL.isEmpty())
     709             :             {
     710             :                 // if OutputURL or FileNamePrefix are missing get
     711             :                 // them from DocumentURL
     712           0 :                 aURLObj.SetSmartURL( aCurDocumentURL );
     713           0 :                 if (aCurFileNamePrefix.isEmpty())
     714           0 :                     aCurFileNamePrefix = aURLObj.GetBase(); // filename without extension
     715           0 :                 if (aCurOutputURL.isEmpty())
     716             :                 {
     717           0 :                     aURLObj.removeSegment();
     718           0 :                     aCurOutputURL = aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
     719             :                 }
     720             :             }
     721             :             else    // default empty document without URL
     722             :             {
     723           0 :                 if (aCurOutputURL.isEmpty())
     724           0 :                     throw RuntimeException("OutputURL is not set and can not be obtained.", static_cast < cppu::OWeakObject * > ( this ) );
     725             :             }
     726             : 
     727           0 :             aURLObj.SetSmartURL( aCurOutputURL );
     728           0 :             OUString aPath = aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
     729             : 
     730           0 :             const OUString aDelim( "/" );
     731           0 :             if (!aPath.isEmpty() && !aPath.endsWith(aDelim))
     732           0 :                 aPath += aDelim;
     733           0 :             if (bCurFileNameFromColumn)
     734           0 :                 pMgr->SetEMailColumn( aCurFileNamePrefix );
     735             :             else
     736             :             {
     737           0 :                 aPath += aCurFileNamePrefix;
     738           0 :                 pMgr->SetEMailColumn( OUString() );
     739             :             }
     740           0 :             pMgr->SetSubject( aPath );
     741           0 :             if(MailMergeType::FILE == nCurOutputType)
     742             :             {
     743           0 :                 aMergeDesc.sSaveToFilter = sSaveFilter;
     744           0 :                 aMergeDesc.sSaveToFilterOptions = sSaveFilterOptions;
     745           0 :                 aMergeDesc.aSaveToFilterData = aSaveFilterData;
     746           0 :                 aMergeDesc.bCreateSingleFile = bSaveAsSingleFile;
     747             :             }
     748             :             else
     749             :             {
     750           0 :                 pMgr->SetEMailColumn( sAddressFromColumn );
     751           0 :                 if(sAddressFromColumn.isEmpty())
     752           0 :                     throw RuntimeException("Mail address column not set.", static_cast < cppu::OWeakObject * > ( this ) );
     753           0 :                 aMergeDesc.sSaveToFilter     = sAttachmentFilter;
     754           0 :                 aMergeDesc.sSubject          = sSubject;
     755           0 :                 aMergeDesc.sMailBody         = sMailBody;
     756           0 :                 aMergeDesc.sAttachmentName   = sAttachmentName;
     757           0 :                 aMergeDesc.aCopiesTo         = aCopiesTo;
     758           0 :                 aMergeDesc.aBlindCopiesTo    = aBlindCopiesTo;
     759           0 :                 aMergeDesc.bSendAsHTML       = bSendAsHTML;
     760           0 :                 aMergeDesc.bSendAsAttachment = bSendAsAttachment;
     761             : 
     762           0 :                 aMergeDesc.bCreateSingleFile = false;
     763           0 :                 pMMConfigItem.reset(new SwMailMergeConfigItem);
     764           0 :                 aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
     765           0 :                 aMergeDesc.xSmtpServer = SwMailMergeHelper::ConnectToSmtpServer(
     766           0 :                         *pMMConfigItem,
     767             :                         xInService,
     768           0 :                         sInServerPassword, sOutServerPassword );
     769           0 :                 if( !aMergeDesc.xSmtpServer.is() || !aMergeDesc.xSmtpServer->isConnected())
     770           0 :                     throw RuntimeException("Failed to connect to mail server.", static_cast < cppu::OWeakObject * > ( this ) );
     771           0 :             }
     772             :         }
     773           0 :         break;
     774             :     }
     775             : 
     776             :     // save document with temporary filename
     777             :     const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat(
     778             :             OUString( FILTER_XML ),
     779           4 :             SwDocShell::Factory().GetFilterContainer() );
     780           4 :     OUString aExtension(comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(), '*'));
     781           8 :     utl::TempFile aTempFile( "SwMM", true, &aExtension );
     782           4 :     aTmpFileName = aTempFile.GetURL();
     783             : 
     784           8 :     Reference< XStorable > xStorable( xCurModel, UNO_QUERY );
     785           4 :     bool bStoredAsTemporary = false;
     786           4 :     if ( xStorable.is() )
     787             :     {
     788             :         try
     789             :         {
     790           4 :             xStorable->storeAsURL( aTmpFileName, Sequence< PropertyValue >() );
     791           4 :             bStoredAsTemporary = true;
     792             :         }
     793           0 :         catch (const Exception&)
     794             :         {
     795             :         }
     796             :     }
     797           4 :     if ( !bStoredAsTemporary )
     798           0 :         throw RuntimeException("Failed to save temporary file.", static_cast < cppu::OWeakObject * > ( this ) );
     799             : 
     800           4 :     pMgr->SetMergeSilent( true );       // suppress dialogs, message boxes, etc.
     801           4 :     const SwXMailMerge *pOldSrc = pMgr->GetMailMergeEvtSrc();
     802             :     OSL_ENSURE( !pOldSrc || pOldSrc == this, "Ooops... different event source already set." );
     803           4 :     pMgr->SetMailMergeEvtSrc( this );   // launch events for listeners
     804             : 
     805           4 :     SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xCurDocSh));
     806           4 :     bool bSucc = pMgr->MergeNew( aMergeDesc );
     807           4 :     SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), xCurDocSh));
     808             : 
     809           4 :     pMgr->SetMailMergeEvtSrc( pOldSrc );
     810             : 
     811           4 :     if ( xCurModel.get() != xModel.get() )
     812             :     {   // in case it was a temporary model -> close it, and delete the file
     813           4 :         DeleteTmpFile_Impl( xCurModel, xCurDocSh, aTmpFileName );
     814           4 :         aTmpFileName = "";
     815             :     }
     816             :     // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest)
     817             : 
     818           4 :     if (!bSucc)
     819           0 :         throw Exception("Mail merge failed. Sorry, no further information available.", static_cast < cppu::OWeakObject * > ( this ) );
     820             : 
     821             :     //de-initialize services
     822           4 :     if(xInService.is() && xInService->isConnected())
     823           0 :         xInService->disconnect();
     824           4 :     if(aMergeDesc.xSmtpServer.is() && aMergeDesc.xSmtpServer->isConnected())
     825           0 :         aMergeDesc.xSmtpServer->disconnect();
     826             : 
     827           4 :     if (DBMGR_MERGE_SHELL == nMergeType)
     828             :     {
     829           4 :         SwXTextDocument *xTextDoc = new SwXTextDocument( aMergeDesc.pMailMergeConfigItem->GetTargetView()->GetDocShell() );
     830           4 :         return makeAny( Reference< XComponent >( xTextDoc->queryInterface( XComponent::static_type() ), css::uno::UNO_QUERY) );
     831             :     }
     832             :     else
     833          12 :         return makeAny( sal_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          10 : void SwXMailMerge::LaunchMailMergeEvent( const MailMergeEvent &rEvt ) const
     846             : {
     847          10 :     cppu::OInterfaceIteratorHelper aIt( ((SwXMailMerge *) this)->aMergeListeners );
     848          20 :     while (aIt.hasMoreElements())
     849             :     {
     850           0 :         Reference< XMailMergeListener > xRef( aIt.next(), UNO_QUERY );
     851           0 :         if (xRef.is())
     852           0 :             xRef->notifyMailMergeEvent( rEvt );
     853          10 :     }
     854          10 : }
     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( (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( (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 :     SolarMutexGuard aGuard;
    1194           0 :     return SwXMailMerge_getImplementationName();
    1195             : }
    1196             : 
    1197           0 : sal_Bool SAL_CALL SwXMailMerge::supportsService( const OUString& rServiceName )
    1198             :     throw(RuntimeException, std::exception)
    1199             : {
    1200           0 :     return cppu::supportsService(this, rServiceName);
    1201             : }
    1202             : 
    1203           0 : uno::Sequence< OUString > SAL_CALL SwXMailMerge::getSupportedServiceNames()
    1204             :     throw(RuntimeException, std::exception)
    1205             : {
    1206           0 :     SolarMutexGuard aGuard;
    1207           0 :     return SwXMailMerge_getSupportedServiceNames();
    1208             : }
    1209             : 
    1210           2 : uno::Sequence< OUString > SAL_CALL SwXMailMerge_getSupportedServiceNames()
    1211             :     throw()
    1212             : {
    1213           2 :     uno::Sequence< OUString > aNames(2);
    1214           2 :     OUString *pName = aNames.getArray();
    1215           2 :     pName[0] = "com.sun.star.text.MailMerge";
    1216           2 :     pName[1] = "com.sun.star.sdb.DataAccessDescriptor";
    1217           2 :     return aNames;
    1218             : }
    1219             : 
    1220          96 : OUString SAL_CALL SwXMailMerge_getImplementationName()
    1221             :     throw()
    1222             : {
    1223          96 :     return OUString( "SwXMailMerge" );
    1224             : }
    1225             : 
    1226           4 : uno::Reference< uno::XInterface > SAL_CALL SwXMailMerge_createInstance(
    1227             :         const uno::Reference< XMultiServiceFactory > & /*rSMgr*/)
    1228             :     throw( uno::Exception )
    1229             : {
    1230           4 :     SolarMutexGuard aGuard;
    1231             : 
    1232             :     //the module may not be loaded
    1233           4 :     SwGlobals::ensure();
    1234           4 :     uno::Reference< uno::XInterface > xRef = (cppu::OWeakObject *) new SwXMailMerge();
    1235           4 :     return xRef;
    1236         270 : }
    1237             : 
    1238             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10