1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: maildispatcher.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include "maildispatcher.hxx"
34 #include "imaildsplistener.hxx"
38 using namespace ::com::sun::star
;
39 using ::rtl::OUString
;
41 typedef std::list
< uno::Reference
<mail::XMailMessage
> > MailMessageContainer_t
;
42 typedef std::list
< ::rtl::Reference
<IMailDispatcherListener
> > MailDispatcherListenerContainer_t
;
44 namespace /* private */
46 /* Generic event notifier for started,
47 stopped, and idle events which are
49 class GenericEventNotifier
52 // pointer to virtual function typedef
53 typedef void (IMailDispatcherListener::*GenericNotificationFunc_t
)(::rtl::Reference
<MailDispatcher
>);
56 GenericNotificationFunc_t notification_function
,
57 ::rtl::Reference
<MailDispatcher
> mail_dispatcher
) :
58 notification_function_(notification_function
),
59 mail_dispatcher_(mail_dispatcher
)
62 void operator() (::rtl::Reference
<IMailDispatcherListener
> listener
) const
63 { (listener
.get()->*notification_function_
)(mail_dispatcher_
); }
66 GenericNotificationFunc_t notification_function_
;
67 ::rtl::Reference
<MailDispatcher
> mail_dispatcher_
;
70 class MailDeliveryNotifier
73 MailDeliveryNotifier(::rtl::Reference
<MailDispatcher
> xMailDispatcher
, uno::Reference
<mail::XMailMessage
> message
) :
74 mail_dispatcher_(xMailDispatcher
),
78 void operator() (::rtl::Reference
<IMailDispatcherListener
> listener
) const
79 { listener
->mailDelivered(mail_dispatcher_
, message_
); }
82 ::rtl::Reference
<MailDispatcher
> mail_dispatcher_
;
83 uno::Reference
<mail::XMailMessage
> message_
;
86 class MailDeliveryErrorNotifier
89 MailDeliveryErrorNotifier(
90 ::rtl::Reference
<MailDispatcher
> xMailDispatcher
,
91 uno::Reference
<mail::XMailMessage
> message
,
92 const ::rtl::OUString
& error_message
) :
93 mail_dispatcher_(xMailDispatcher
),
95 error_message_(error_message
)
98 void operator() (::rtl::Reference
<IMailDispatcherListener
> listener
) const
99 { listener
->mailDeliveryError(mail_dispatcher_
, message_
, error_message_
); }
102 ::rtl::Reference
<MailDispatcher
> mail_dispatcher_
;
103 uno::Reference
<mail::XMailMessage
> message_
;
104 ::rtl::OUString error_message_
;
107 } // namespace private
110 MailDispatcher::MailDispatcher(uno::Reference
<mail::XSmtpService
> mailserver
) :
111 mailserver_ (mailserver
),
113 shutdown_requested_(false),
116 wakening_call_
.reset();
117 mail_dispatcher_active_
.reset();
120 throw uno::RuntimeException();
122 // wait until the mail dispatcher thread is really alive
123 // and has aquired a reference to this instance of the
125 mail_dispatcher_active_
.wait();
128 MailDispatcher::~MailDispatcher()
132 void MailDispatcher::enqueueMailMessage(uno::Reference
<mail::XMailMessage
> message
)
134 ::osl::MutexGuard
thread_status_guard(thread_status_mutex_
);
135 ::osl::MutexGuard
message_container_guard(message_container_mutex_
);
137 OSL_PRECOND(!shutdown_requested_
, "MailDispatcher thread is shuting down already");
139 messages_
.push_back(message
);
141 wakening_call_
.set();
144 uno::Reference
<mail::XMailMessage
> MailDispatcher::dequeueMailMessage()
146 ::osl::MutexGuard
guard(message_container_mutex_
);
147 uno::Reference
<mail::XMailMessage
> message
;
148 if(!messages_
.empty())
150 message
= messages_
.front();
151 messages_
.pop_front();
156 void MailDispatcher::start()
158 OSL_PRECOND(!isStarted(), "MailDispatcher is already started!");
160 ::osl::ClearableMutexGuard
thread_status_guard(thread_status_mutex_
);
162 OSL_PRECOND(!shutdown_requested_
, "MailDispatcher thread is shuting down already");
164 if (!shutdown_requested_
)
167 wakening_call_
.set();
168 thread_status_guard
.clear();
170 MailDispatcherListenerContainer_t
listeners_cloned(cloneListener());
171 std::for_each(listeners_cloned
.begin(), listeners_cloned
.end(), GenericEventNotifier(&IMailDispatcherListener::started
, this));
175 void MailDispatcher::stop()
177 OSL_PRECOND(isStarted(), "MailDispatcher not started!");
179 ::osl::ClearableMutexGuard
thread_status_guard(thread_status_mutex_
);
181 OSL_PRECOND(!shutdown_requested_
, "MailDispatcher thread is shuting down already");
183 if (!shutdown_requested_
)
186 wakening_call_
.reset();
187 thread_status_guard
.clear();
189 MailDispatcherListenerContainer_t
listeners_cloned(cloneListener());
190 std::for_each(listeners_cloned
.begin(), listeners_cloned
.end(), GenericEventNotifier(&IMailDispatcherListener::stopped
, this));
194 void MailDispatcher::shutdown()
196 ::osl::MutexGuard
thread_status_guard(thread_status_mutex_
);
198 OSL_PRECOND(!shutdown_requested_
, "MailDispatcher thread is shuting down already");
200 shutdown_requested_
= true;
201 wakening_call_
.set();
204 bool MailDispatcher::isStarted() const
209 bool MailDispatcher::isRunning() const
215 void MailDispatcher::addListener(::rtl::Reference
<IMailDispatcherListener
> listener
)
217 OSL_PRECOND(!shutdown_requested_
, "MailDispatcher thread is shuting down already");
219 ::osl::MutexGuard
guard(listener_container_mutex_
);
220 listeners_
.push_back(listener
);
223 void MailDispatcher::removeListener(::rtl::Reference
<IMailDispatcherListener
> listener
)
225 OSL_PRECOND(!shutdown_requested_
, "MailDispatcher thread is shuting down already");
227 ::osl::MutexGuard
guard(listener_container_mutex_
);
228 listeners_
.remove(listener
);
231 std::list
< ::rtl::Reference
<IMailDispatcherListener
> > MailDispatcher::cloneListener()
233 ::osl::MutexGuard
guard(listener_container_mutex_
);
237 void MailDispatcher::sendMailMessageNotifyListener(uno::Reference
<mail::XMailMessage
> message
)
241 mailserver_
->sendMailMessage(message
);
242 MailDispatcherListenerContainer_t
listeners_cloned(cloneListener());
243 std::for_each(listeners_cloned
.begin(), listeners_cloned
.end(), MailDeliveryNotifier(this, message
));
245 catch (mail::MailException
& ex
)
247 MailDispatcherListenerContainer_t
listeners_cloned(cloneListener());
248 std::for_each(listeners_cloned
.begin(), listeners_cloned
.end(), MailDeliveryErrorNotifier(this, message
, ex
.Message
));
250 catch (uno::RuntimeException
& ex
)
252 MailDispatcherListenerContainer_t
listeners_cloned(cloneListener());
253 std::for_each(listeners_cloned
.begin(), listeners_cloned
.end(), MailDeliveryErrorNotifier(this, message
, ex
.Message
));
257 void MailDispatcher::run()
259 // aquire a self reference in order to avoid race
260 // conditions. The last client of this class must
261 // call shutdown before releasing his last reference
262 // to this class in order to shutdown this thread
263 // which will release his (the very last reference
264 // to the class and so force their destruction
265 m_xSelfReference
= this;
267 // signal that the mail dispatcher thread is now alive
268 mail_dispatcher_active_
.set();
273 wakening_call_
.wait();
275 ::osl::ClearableMutexGuard
thread_status_guard(thread_status_mutex_
);
276 if (shutdown_requested_
)
279 ::osl::ClearableMutexGuard
message_container_guard(message_container_mutex_
);
281 if (messages_
.size())
283 thread_status_guard
.clear();
284 uno::Reference
<mail::XMailMessage
> message
= messages_
.front();
285 messages_
.pop_front();
286 message_container_guard
.clear();
287 sendMailMessageNotifyListener(message
);
289 else // idle - put ourself to sleep
291 wakening_call_
.reset();
292 message_container_guard
.clear();
293 thread_status_guard
.clear();
294 MailDispatcherListenerContainer_t
listeners_cloned(cloneListener());
295 std::for_each(listeners_cloned
.begin(), listeners_cloned
.end(), GenericEventNotifier(&IMailDispatcherListener::idle
, this));
300 /*-- 27.08.2004 12:04:46---------------------------------------------------
302 -----------------------------------------------------------------------*/
303 void MailDispatcher::onTerminated()
305 //keep the reference until the end of onTerminated() because of the call order in the
306 //_threadFunc() from osl/thread.hxx
307 m_xSelfReference
= 0;