xref: /aoo42x/main/sw/source/ui/dbui/maildispatcher.cxx (revision 86e1cf34)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10efeef26fSAndrew Rist  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19efeef26fSAndrew Rist  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir #include "maildispatcher.hxx"
27cdf0e10cSrcweir #include "imaildsplistener.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <algorithm>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir using namespace ::com::sun::star;
32cdf0e10cSrcweir using ::rtl::OUString;
33cdf0e10cSrcweir 
34cdf0e10cSrcweir typedef std::list< uno::Reference<mail::XMailMessage> > MailMessageContainer_t;
35cdf0e10cSrcweir typedef std::list< ::rtl::Reference<IMailDispatcherListener> > MailDispatcherListenerContainer_t;
36cdf0e10cSrcweir 
37cdf0e10cSrcweir namespace /* private */
38cdf0e10cSrcweir {
39cdf0e10cSrcweir     /* Generic event notifier for started,
40cdf0e10cSrcweir        stopped, and idle events which are
41cdf0e10cSrcweir        very similary */
42cdf0e10cSrcweir     class GenericEventNotifier
43cdf0e10cSrcweir     {
44cdf0e10cSrcweir     public:
45cdf0e10cSrcweir         // pointer to virtual function typedef
46cdf0e10cSrcweir         typedef void (IMailDispatcherListener::*GenericNotificationFunc_t)(::rtl::Reference<MailDispatcher>);
47cdf0e10cSrcweir 
GenericEventNotifier(GenericNotificationFunc_t notification_function,::rtl::Reference<MailDispatcher> mail_dispatcher)48cdf0e10cSrcweir         GenericEventNotifier(
49cdf0e10cSrcweir             GenericNotificationFunc_t notification_function,
50cdf0e10cSrcweir             ::rtl::Reference<MailDispatcher> mail_dispatcher) :
51cdf0e10cSrcweir             notification_function_(notification_function),
52cdf0e10cSrcweir             mail_dispatcher_(mail_dispatcher)
53cdf0e10cSrcweir         {}
54cdf0e10cSrcweir 
operator ()(::rtl::Reference<IMailDispatcherListener> listener) const55cdf0e10cSrcweir         void operator() (::rtl::Reference<IMailDispatcherListener> listener) const
56cdf0e10cSrcweir         { (listener.get()->*notification_function_)(mail_dispatcher_); }
57cdf0e10cSrcweir 
58cdf0e10cSrcweir     private:
59cdf0e10cSrcweir         GenericNotificationFunc_t notification_function_;
60cdf0e10cSrcweir         ::rtl::Reference<MailDispatcher> mail_dispatcher_;
61cdf0e10cSrcweir     };
62cdf0e10cSrcweir 
63cdf0e10cSrcweir     class MailDeliveryNotifier
64cdf0e10cSrcweir     {
65cdf0e10cSrcweir     public:
MailDeliveryNotifier(::rtl::Reference<MailDispatcher> xMailDispatcher,uno::Reference<mail::XMailMessage> message)66cdf0e10cSrcweir         MailDeliveryNotifier(::rtl::Reference<MailDispatcher> xMailDispatcher, uno::Reference<mail::XMailMessage> message) :
67cdf0e10cSrcweir             mail_dispatcher_(xMailDispatcher),
68cdf0e10cSrcweir             message_(message)
69cdf0e10cSrcweir         {}
70cdf0e10cSrcweir 
operator ()(::rtl::Reference<IMailDispatcherListener> listener) const71cdf0e10cSrcweir         void operator() (::rtl::Reference<IMailDispatcherListener> listener) const
72cdf0e10cSrcweir         { listener->mailDelivered(mail_dispatcher_, message_); }
73cdf0e10cSrcweir 
74cdf0e10cSrcweir     private:
75cdf0e10cSrcweir         ::rtl::Reference<MailDispatcher> mail_dispatcher_;
76cdf0e10cSrcweir         uno::Reference<mail::XMailMessage> message_;
77cdf0e10cSrcweir     };
78cdf0e10cSrcweir 
79cdf0e10cSrcweir     class MailDeliveryErrorNotifier
80cdf0e10cSrcweir     {
81cdf0e10cSrcweir     public:
MailDeliveryErrorNotifier(::rtl::Reference<MailDispatcher> xMailDispatcher,uno::Reference<mail::XMailMessage> message,const::rtl::OUString & error_message)82cdf0e10cSrcweir         MailDeliveryErrorNotifier(
83cdf0e10cSrcweir             ::rtl::Reference<MailDispatcher> xMailDispatcher,
84cdf0e10cSrcweir             uno::Reference<mail::XMailMessage> message,
85cdf0e10cSrcweir             const ::rtl::OUString& error_message) :
86cdf0e10cSrcweir             mail_dispatcher_(xMailDispatcher),
87cdf0e10cSrcweir             message_(message),
88cdf0e10cSrcweir             error_message_(error_message)
89cdf0e10cSrcweir         {}
90cdf0e10cSrcweir 
operator ()(::rtl::Reference<IMailDispatcherListener> listener) const91cdf0e10cSrcweir         void operator() (::rtl::Reference<IMailDispatcherListener> listener) const
92cdf0e10cSrcweir         { listener->mailDeliveryError(mail_dispatcher_, message_, error_message_); }
93cdf0e10cSrcweir 
94cdf0e10cSrcweir     private:
95cdf0e10cSrcweir         ::rtl::Reference<MailDispatcher> mail_dispatcher_;
96cdf0e10cSrcweir         uno::Reference<mail::XMailMessage> message_;
97cdf0e10cSrcweir         ::rtl::OUString error_message_;
98cdf0e10cSrcweir     };
99cdf0e10cSrcweir 
100cdf0e10cSrcweir } // namespace private
101cdf0e10cSrcweir 
102cdf0e10cSrcweir 
MailDispatcher(uno::Reference<mail::XSmtpService> mailserver)103cdf0e10cSrcweir MailDispatcher::MailDispatcher(uno::Reference<mail::XSmtpService> mailserver) :
104cdf0e10cSrcweir     mailserver_ (mailserver),
105cdf0e10cSrcweir     run_(false),
106cdf0e10cSrcweir     shutdown_requested_(false)
107cdf0e10cSrcweir {
108cdf0e10cSrcweir     wakening_call_.reset();
109cdf0e10cSrcweir     mail_dispatcher_active_.reset();
110cdf0e10cSrcweir 
111cdf0e10cSrcweir     if (!create())
112cdf0e10cSrcweir         throw uno::RuntimeException();
113cdf0e10cSrcweir 
114cdf0e10cSrcweir     // wait until the mail dispatcher thread is really alive
115*86e1cf34SPedro Giffuni     // and has acquired a reference to this instance of the
116cdf0e10cSrcweir     // class
117cdf0e10cSrcweir     mail_dispatcher_active_.wait();
118cdf0e10cSrcweir }
119cdf0e10cSrcweir 
~MailDispatcher()120cdf0e10cSrcweir MailDispatcher::~MailDispatcher()
121cdf0e10cSrcweir {
122cdf0e10cSrcweir }
123cdf0e10cSrcweir 
enqueueMailMessage(uno::Reference<mail::XMailMessage> message)124cdf0e10cSrcweir void MailDispatcher::enqueueMailMessage(uno::Reference<mail::XMailMessage> message)
125cdf0e10cSrcweir {
126cdf0e10cSrcweir     ::osl::MutexGuard thread_status_guard(thread_status_mutex_);
127cdf0e10cSrcweir     ::osl::MutexGuard message_container_guard(message_container_mutex_);
128cdf0e10cSrcweir 
129cdf0e10cSrcweir     OSL_PRECOND(!shutdown_requested_, "MailDispatcher thread is shuting down already");
130cdf0e10cSrcweir 
131cdf0e10cSrcweir     messages_.push_back(message);
132cdf0e10cSrcweir     if (run_)
133cdf0e10cSrcweir         wakening_call_.set();
134cdf0e10cSrcweir }
135cdf0e10cSrcweir 
dequeueMailMessage()136cdf0e10cSrcweir uno::Reference<mail::XMailMessage> MailDispatcher::dequeueMailMessage()
137cdf0e10cSrcweir {
138cdf0e10cSrcweir     ::osl::MutexGuard guard(message_container_mutex_);
139cdf0e10cSrcweir     uno::Reference<mail::XMailMessage> message;
140cdf0e10cSrcweir     if(!messages_.empty())
141cdf0e10cSrcweir     {
142cdf0e10cSrcweir         message = messages_.front();
143cdf0e10cSrcweir         messages_.pop_front();
144cdf0e10cSrcweir     }
145cdf0e10cSrcweir     return message;
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
start()148cdf0e10cSrcweir void MailDispatcher::start()
149cdf0e10cSrcweir {
150cdf0e10cSrcweir     OSL_PRECOND(!isStarted(), "MailDispatcher is already started!");
151cdf0e10cSrcweir 
152cdf0e10cSrcweir     ::osl::ClearableMutexGuard thread_status_guard(thread_status_mutex_);
153cdf0e10cSrcweir 
154cdf0e10cSrcweir     OSL_PRECOND(!shutdown_requested_, "MailDispatcher thread is shuting down already");
155cdf0e10cSrcweir 
156cdf0e10cSrcweir     if (!shutdown_requested_)
157cdf0e10cSrcweir     {
158cdf0e10cSrcweir         run_ = true;
159cdf0e10cSrcweir         wakening_call_.set();
160cdf0e10cSrcweir         thread_status_guard.clear();
161cdf0e10cSrcweir 
162cdf0e10cSrcweir         MailDispatcherListenerContainer_t listeners_cloned(cloneListener());
163cdf0e10cSrcweir         std::for_each(listeners_cloned.begin(), listeners_cloned.end(), GenericEventNotifier(&IMailDispatcherListener::started, this));
164cdf0e10cSrcweir     }
165cdf0e10cSrcweir }
166cdf0e10cSrcweir 
stop()167cdf0e10cSrcweir void MailDispatcher::stop()
168cdf0e10cSrcweir {
169cdf0e10cSrcweir     OSL_PRECOND(isStarted(), "MailDispatcher not started!");
170cdf0e10cSrcweir 
171cdf0e10cSrcweir     ::osl::ClearableMutexGuard thread_status_guard(thread_status_mutex_);
172cdf0e10cSrcweir 
173cdf0e10cSrcweir     OSL_PRECOND(!shutdown_requested_, "MailDispatcher thread is shuting down already");
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     if (!shutdown_requested_)
176cdf0e10cSrcweir     {
177cdf0e10cSrcweir         run_ = false;
178cdf0e10cSrcweir         wakening_call_.reset();
179cdf0e10cSrcweir         thread_status_guard.clear();
180cdf0e10cSrcweir 
181cdf0e10cSrcweir         MailDispatcherListenerContainer_t listeners_cloned(cloneListener());
182cdf0e10cSrcweir         std::for_each(listeners_cloned.begin(), listeners_cloned.end(), GenericEventNotifier(&IMailDispatcherListener::stopped, this));
183cdf0e10cSrcweir     }
184cdf0e10cSrcweir }
185cdf0e10cSrcweir 
shutdown()186cdf0e10cSrcweir void MailDispatcher::shutdown()
187cdf0e10cSrcweir {
188cdf0e10cSrcweir     ::osl::MutexGuard thread_status_guard(thread_status_mutex_);
189cdf0e10cSrcweir 
190cdf0e10cSrcweir     OSL_PRECOND(!shutdown_requested_, "MailDispatcher thread is shuting down already");
191cdf0e10cSrcweir 
192cdf0e10cSrcweir     shutdown_requested_ = true;
193cdf0e10cSrcweir     wakening_call_.set();
194cdf0e10cSrcweir }
195cdf0e10cSrcweir 
isStarted() const196cdf0e10cSrcweir bool MailDispatcher::isStarted() const
197cdf0e10cSrcweir {
198cdf0e10cSrcweir     return run_;
199cdf0e10cSrcweir }
200cdf0e10cSrcweir 
addListener(::rtl::Reference<IMailDispatcherListener> listener)201cdf0e10cSrcweir void MailDispatcher::addListener(::rtl::Reference<IMailDispatcherListener> listener)
202cdf0e10cSrcweir {
203cdf0e10cSrcweir     OSL_PRECOND(!shutdown_requested_, "MailDispatcher thread is shuting down already");
204cdf0e10cSrcweir 
205cdf0e10cSrcweir     ::osl::MutexGuard guard(listener_container_mutex_);
206cdf0e10cSrcweir     listeners_.push_back(listener);
207cdf0e10cSrcweir }
208cdf0e10cSrcweir 
removeListener(::rtl::Reference<IMailDispatcherListener> listener)209cdf0e10cSrcweir void MailDispatcher::removeListener(::rtl::Reference<IMailDispatcherListener> listener)
210cdf0e10cSrcweir {
211cdf0e10cSrcweir     OSL_PRECOND(!shutdown_requested_, "MailDispatcher thread is shuting down already");
212cdf0e10cSrcweir 
213cdf0e10cSrcweir     ::osl::MutexGuard guard(listener_container_mutex_);
214cdf0e10cSrcweir     listeners_.remove(listener);
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
cloneListener()217cdf0e10cSrcweir std::list< ::rtl::Reference<IMailDispatcherListener> > MailDispatcher::cloneListener()
218cdf0e10cSrcweir {
219cdf0e10cSrcweir     ::osl::MutexGuard guard(listener_container_mutex_);
220cdf0e10cSrcweir     return listeners_;
221cdf0e10cSrcweir }
222cdf0e10cSrcweir 
sendMailMessageNotifyListener(uno::Reference<mail::XMailMessage> message)223cdf0e10cSrcweir void MailDispatcher::sendMailMessageNotifyListener(uno::Reference<mail::XMailMessage> message)
224cdf0e10cSrcweir {
225cdf0e10cSrcweir     try
226cdf0e10cSrcweir     {
227cdf0e10cSrcweir         mailserver_->sendMailMessage(message);
228cdf0e10cSrcweir         MailDispatcherListenerContainer_t listeners_cloned(cloneListener());
229cdf0e10cSrcweir         std::for_each(listeners_cloned.begin(), listeners_cloned.end(), MailDeliveryNotifier(this, message));
230cdf0e10cSrcweir     }
231cdf0e10cSrcweir     catch (mail::MailException& ex)
232cdf0e10cSrcweir     {
233cdf0e10cSrcweir         MailDispatcherListenerContainer_t listeners_cloned(cloneListener());
234cdf0e10cSrcweir         std::for_each(listeners_cloned.begin(), listeners_cloned.end(), MailDeliveryErrorNotifier(this, message, ex.Message));
235cdf0e10cSrcweir     }
236cdf0e10cSrcweir     catch (uno::RuntimeException& ex)
237cdf0e10cSrcweir     {
238cdf0e10cSrcweir         MailDispatcherListenerContainer_t listeners_cloned(cloneListener());
239cdf0e10cSrcweir         std::for_each(listeners_cloned.begin(), listeners_cloned.end(), MailDeliveryErrorNotifier(this, message, ex.Message));
240cdf0e10cSrcweir     }
241cdf0e10cSrcweir }
242cdf0e10cSrcweir 
run()243cdf0e10cSrcweir void MailDispatcher::run()
244cdf0e10cSrcweir {
245*86e1cf34SPedro Giffuni     // acquire a self reference in order to avoid race
246cdf0e10cSrcweir     // conditions. The last client of this class must
247cdf0e10cSrcweir     // call shutdown before releasing his last reference
248cdf0e10cSrcweir     // to this class in order to shutdown this thread
249cdf0e10cSrcweir     // which will release his (the very last reference
250cdf0e10cSrcweir     // to the class and so force their destruction
251cdf0e10cSrcweir     m_xSelfReference = this;
252cdf0e10cSrcweir 
253cdf0e10cSrcweir     // signal that the mail dispatcher thread is now alive
254cdf0e10cSrcweir     mail_dispatcher_active_.set();
255cdf0e10cSrcweir 
256cdf0e10cSrcweir     for(;;)
257cdf0e10cSrcweir     {
258cdf0e10cSrcweir         wakening_call_.wait();
259cdf0e10cSrcweir 
260cdf0e10cSrcweir         ::osl::ClearableMutexGuard thread_status_guard(thread_status_mutex_);
261cdf0e10cSrcweir         if (shutdown_requested_)
262cdf0e10cSrcweir            break;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir         ::osl::ClearableMutexGuard message_container_guard(message_container_mutex_);
265cdf0e10cSrcweir 
266cdf0e10cSrcweir         if (messages_.size())
267cdf0e10cSrcweir         {
268cdf0e10cSrcweir             thread_status_guard.clear();
269cdf0e10cSrcweir             uno::Reference<mail::XMailMessage> message = messages_.front();
270cdf0e10cSrcweir             messages_.pop_front();
271cdf0e10cSrcweir             message_container_guard.clear();
272cdf0e10cSrcweir             sendMailMessageNotifyListener(message);
273cdf0e10cSrcweir         }
274cdf0e10cSrcweir         else // idle - put ourself to sleep
275cdf0e10cSrcweir         {
276cdf0e10cSrcweir             wakening_call_.reset();
277cdf0e10cSrcweir             message_container_guard.clear();
278cdf0e10cSrcweir             thread_status_guard.clear();
279cdf0e10cSrcweir             MailDispatcherListenerContainer_t listeners_cloned(cloneListener());
280cdf0e10cSrcweir             std::for_each(listeners_cloned.begin(), listeners_cloned.end(), GenericEventNotifier(&IMailDispatcherListener::idle, this));
281cdf0e10cSrcweir         }
282cdf0e10cSrcweir     } // end for        SSH ALI
283cdf0e10cSrcweir }
284cdf0e10cSrcweir /*-- 27.08.2004 12:04:46---------------------------------------------------
285cdf0e10cSrcweir 
286cdf0e10cSrcweir   -----------------------------------------------------------------------*/
onTerminated()287cdf0e10cSrcweir void MailDispatcher::onTerminated()
288cdf0e10cSrcweir {
289cdf0e10cSrcweir     //keep the reference until the end of onTerminated() because of the call order in the
290cdf0e10cSrcweir     //_threadFunc() from osl/thread.hxx
291cdf0e10cSrcweir     m_xSelfReference = 0;
292cdf0e10cSrcweir }
293