/*
* Copyright (c) 2004-2007 Sun Microsystems, Inc. All rights reserved.
*
* The Sun Project JXTA(TM) Software License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowledgment: "This product includes software
* developed by Sun Microsystems, Inc. for JXTA(TM) technology."
* Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
* not be used to endorse or promote products derived from this software
* without prior written permission. For written permission, please contact
* Project JXTA at http://www.jxta.org.
*
* 5. Products derived from this software may not be called "JXTA", nor may
* "JXTA" appear in their name, without prior written permission of Sun.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN
* MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JXTA is a registered trademark of Sun Microsystems, Inc. in the United
* States and other countries.
*
* Please see the license information page at :
* <http://www.jxta.org/project/www/license.html> for instructions on use of
* the license in source files.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many individuals
* on behalf of Project JXTA. For more information on Project JXTA, please see
* http://www.jxta.org.
*
* This license is based on the BSD license adopted by the Apache Foundation.
*/
package net.jxta.endpoint;
import net.jxta.peergroup.PeerGroupID;
import net.jxta.util.SimpleSelectable;
import java.io.IOException;
/**
* A Messenger is used to send messages to a destination.
* <p/>
* This interface specifies the allowed observable states for a messenger. (fine grain). This serves to normalize
* the state machines of the various messenger implementations and allows for more meaningful diagnostics. Implementations may
* use substates by adding high order bits, but these should never be reported by the public state observation methods. Most
* implementations will not use all these states.
* <p/>
* <p/>Each valid state is represented by a integer that is a power of 2.
* <p/>
* <p/>The (coarse grain) constants: <code>USABLE, RESOLVED, TERMINAL, IDLE, SATURATED</code> represent meaningful partitions of the space of
* states.
* <p/>
* <p/>The value of each constant is the bitwise <code>OR</code> of the states for which a given predicate is true: usable or not,
* confirmed or not, etc. Therefore the value of predicate <code>p</code> in state <code>s</code> is <code>(s & p)!=0</code>.
* <p/>
* <p/>These particular predicates are chosen so that they have a relevant truth value for all states. Therefore the bitwise negation
* of the corresponding constants represents the obvious: <code>~USABLE</code> really lists all states that mean "not USABLE".
* <p/>
* <p/>These constants may be combined by bit logic operators to represent more predicates. {@link #waitState} accepts such values as
* a parameter.
* <p/>
* <p/>Applications should depend on the coarse grain constants, rather than those denoting discrete states.
*
* @see net.jxta.endpoint.EndpointService
* @see net.jxta.util.SimpleSelector
* @see net.jxta.endpoint.EndpointAddress
* @see net.jxta.endpoint.Message
* @see MessengerState
*/
public interface Messenger extends SimpleSelectable {
/**
* No message was ever submitted for sending. No connection has ever been attempted.
*/
public static final int UNRESOLVED = 0x1;
/**
* Initial connection is being attempted. No message is pending.
*/
public static final int RESOLVING = 0x2;
/**
* Currently connected. No message is pending (being sent implies pending).
*/
public static final int CONNECTED = 0x4;
/**
* Currently not connected. No message is pending.
*/
public static final int DISCONNECTED = 0x8;
/**
* Initial connection is being attempted. Messages are pending.
*/
public static final int RESOLPENDING = 0x10;
/**
* Initial connection is being attempted. Messages are pending. New messages may not be submitted at this time.
*/
public static final int RESOLSATURATED = 0x20;
/**
* Currently connected and sending messages.
*/
public static final int SENDING = 0x40;
/**
* Currently sending messages.New messages may not be submitted at this time.
*/
public static final int SENDINGSATURATED = 0x80;
/**
* Currently trying to re-establish connection. Messages are pending.
*/
public static final int RECONNECTING = 0x100;
/**
* Currently trying to re-establish connection. New messages may not be submitted at this time.
*/
public static final int RECONSATURATED = 0x200;
/**
* Attempting initial connection. Close has been requested. Messages are pending.
* New messages may no longer be submitted.
*/
public static final int RESOLCLOSING = 0x400;
/**
* Currently sending messages. Close has been requested. New messages may no longer be submitted.
*/
public static final int CLOSING = 0x800;
/**
* Trying to re-establish connection. Close has been requested. Messages are pending.
* New messages may no longer be submitted.
*/
public static final int RECONCLOSING = 0x1000;
/**
* Failed to establish initial connection. Pending messages are being rejected. New messages may no longer be submitted.
*/
public static final int UNRESOLVING = 0x2000;
/**
* Failed to re-establish connection. Pending messages are being rejected. New messages may no longer be submitted.
*/
public static final int BREAKING = 0x4000;
/**
* Breaking established connection for expedite closure. Pending messages are being rejected.
* New messages may no longer be submitted.
*/
public static final int DISCONNECTING = 0x8000;
/**
* Failed to establish initial connection. New messages may no longer be submitted. State will never change again.
*/
public static final int UNRESOLVABLE = 0x10000;
/**
* Failed to re-establish connection. New messages may no longer be submitted. State will never change again.
*/
public static final int BROKEN = 0x20000;
/**
* Closed as requested. All pending messages could be sent. New messages may no longer be submitted.
* State will never change again.
*/
public static final int CLOSED = 0x40000;
/**
* The bitwise OR of all valid states.
*/
public static final int ANYSTATE = 0x7FFFF;
/* Predicates. */
/**
* Composite state.<p/>
* <p/>
* Not known to be broken.
* Messenger may be used to send messages. Viability has not been evaluated yet.
* This is the most useful predicate to applications. USABLE means that
* it is reasonable to try and send a message.
*/
public static final int USABLE = (UNRESOLVED | RESOLVING | CONNECTED | DISCONNECTED | RESOLPENDING | RESOLSATURATED | SENDING
| SENDINGSATURATED | RECONNECTING | RECONSATURATED);
/**
* Composite state.
* <p/>
* <ul>
* <li>Messenger was once resolved.</p>
* <li>Messenger was at least once proven viable. Current usability is
* not asserted. For example a messenger may be found to be in a
* TERMINAL state, but also be in a RESOLVED state. Thus proving that
* the destination of the messenger is sometimes valid.</li>
* </ul>
*/
public static final int RESOLVED = (CONNECTED | SENDING | SENDINGSATURATED | CLOSING | CLOSED | DISCONNECTED | RECONNECTING
| RECONSATURATED | RECONCLOSING | BREAKING | DISCONNECTING | BROKEN);
/**
* Composite state.
* <p/>
* Messenger has terminated its useful life. State will never change any more.
*/
public static final int TERMINAL = (UNRESOLVABLE | CLOSED | BROKEN);
/**
* Composite state.
* <p/>
* Any message that may have been submitted in the past has been either sent or failed already.
* If a messenger is in a state <code>IDLE & RESOLVED & USABLE</code>, then the expected delay in sending a message
* is minimal.
*/
public static final int IDLE = (UNRESOLVED | RESOLVING | CONNECTED | DISCONNECTED | UNRESOLVABLE | CLOSED | BROKEN);
/**
* Composite state.
* <p/>
* This messenger cannot take new messages for now. All available buffering space is occupied.
* Note that only the usable states can be saturated. Once a messenger is in the process of terminating
* and thus takes no new messages anyway, it no-longer shows as saturated.
*/
public static final int SATURATED = (RESOLSATURATED | SENDINGSATURATED | RECONSATURATED);
/**
* Returns the current state.
*
* @return one of the legal discrete state values.
*/
public int getState();
/**
* Blocks unless and until the current state is or has become one of the desired values. The observable states are guaranteed
* to be represented by a single bit. Multiple desired values may be specified by passing them <code>OR</code>ed together.
* <p/>
* This class defines the list of constants that may be used and how these may be combined.
* <p/>
* Note that the state can change as soon as this method returns, so any observation is only an indication of the
* past. Synchronizing on the object itself has no other effect than interfering with other threads doing the same. Obviously,
* certain transitions cannot happen unless a new message is submitted. So unless another thread is using a messenger, it is
* safe to assume that a non-saturated messenger will not become saturated spontaneously. Note that messengers returned by
* different endpoint service interface objects (what {@link net.jxta.peergroup.PeerGroup#getEndpointService()} returns) are
* different. However a given endpoint interface object will return an existing messenger to the same exact destination if
* there is a {@link Messenger#USABLE} one.
* <p/>
* With an unshared messenger, one can wait for any change with {@code waitState(~getState(), 0);}.
* <p/>
* Note that it is advisable to always include {@link #TERMINAL} as part
* of the desired states with unless being blocked past the messenger
* termination is an acceptable behaviour.
* <p/>
* Examples:<p/>
* <p/>
* Ensure that the messenger can take more messages (or is {@code UNUSABLE}): {@code waitState(~SATURATED)}<p/>
* <p/>
* Ensure that all submitted messages have been sent: {@code waitState(TERMINAL | IDLE)}
* <p/>
* Ensure that the messenger is already resolved and can take more messages: {@code waitState(TERMINAL | (RESOLVED & ~SATURATED))}
*
* @param wantedStates The binary OR of the desired states.
* @param timeout The maximum number of milliseconds to wait. A timeout of 0 means no time limit.
* @return The desired state that was reached or the current state when time ran out.
* @throws InterruptedException If the invoking thread was interrupted before the condition was realized.
*/
int waitState(int wantedStates, long timeout) throws InterruptedException;
/**
* Add a listener to this messenger, which will be notified when
* the state of the messenger changes. This can be used to detect
* when network errors occur asynchronously, rather than blocking
* in waitState
*/
void addStateListener(MessengerStateListener listener);
/**
* Remove a previously added listener. If the listener is already
* removed, this has no effect.
*/
void removeStateListener(MessengerStateListener listener);
/**
* Returns {@code true} if this messenger is closed and no longer
* accepting messages to be sent. This is a shortcut for
* {@code (getState() & USABLE == 0)}. Once closed, a messenger should be
* discarded.
*
* @return {@code true} if this messenger is closed, otherwise {@code false}.
*/
boolean isClosed();
/**
* Returns the destination of this messenger.
*
* @return The destination address of this messenger
* @see Messenger#getLogicalDestinationAddress()
*/
EndpointAddress getDestinationAddress();
/**
* Returns the logical destination of this messenger. This may be a
* different address than is returned by
* {@link #getDestinationAddress() getDestinationAddress} and refers to
* the entity which is located at the destination address.
* <p/>
* By analogy, a telephone number would be the destination address, and
* the owner of that telephone number would be the logical destination.
* Each logical destination may be known by one or more destination
* addresses.
*
* @return EndpointAddress the logical destination address of this messenger.
* @see #getDestinationAddress()
*/
EndpointAddress getLogicalDestinationAddress();
/**
* Returns the maximum message size that this messenger can be used to send.
* The limit refers to the cumulative size of application level elements.
* The various {@code sendMessage()} variants will refuse to send messages
* that exceed this limit.
*
* @return the limit.
*/
long getMTU();
/**
* If applicable, returns another messenger that will send messages to the same destination address than this one, but with
* the specified default service and serviceParam, possibly rewriting addresses to ensure delivery through the specified
* redirection. This is not generally useful to applications and most messengers will return null. This method is needed
* by the EndpointService when interacting with Messengers provided by Transport modules. If you are not implementing a
* Transport module, then you can ignore this method.
* <p/>
* <b>Important:</b> The channel so obtained is not configured to support the {@link #sendMessage(Message,String,String,
*OutgoingMessageEventListener)} legacy method. If use of this method is desired, {@link ChannelMessenger#setMessageWatcher}
* must be used first.
*
* @param redirection The requested redirection. The resulting channel messenger will use this to force
* delivery of the message only in the specified group (or possibly descendents, but not parents). If null the local
* group is assumed. This redirection is applied only to messages that are sent to a service name and service param that
* do not imply a group redirection.
* @param service The service to which the resulting channel will send messages, when they are not sent to a
* specified service.
* @param serviceParam The service parameter that the resulting channel will use to send messages, when no parameter is
* specified.
* @return a channelMessenger as specified.
* @see MessageSender#getMessenger(EndpointAddress,Object)
*/
Messenger getChannelMessenger(PeerGroupID redirection, String service, String serviceParam);
/**
* Close this messenger after processing any pending messages. This method
* is not blocking. Upon return, the messenger will be in one of the non
* {@link #USABLE} states, which means that no message may be sent through
* it. Any other effect of this method, such as an underlying connection
* being closed, or all pending messages being processed, may be deferred
* indefinitely. When the messenger has completely processed the closure
* request, it will be in one of the {@link #TERMINAL} states (which are
* also {@link #IDLE} states). Therefore, if one is interested in the
* outcome of the closure, one may wait for the messenger to be in a
* {@link #TERMINAL} or {@link #IDLE} state, and check which it is.
* {@link #CLOSED} denotes success (all outstanding messages have been
* sent), as opposed to {@link #UNRESOLVABLE} or {@link #BROKEN}.
*/
void close();
/**
* Makes sure that all outstanding messages have been processed;
* successfully or not. This method waits unless and until the state of the
* messenger is an {@link #IDLE} state. If the reached state is neither
* {@link #CLOSED} or any {@link #USABLE} state, then it throws an
* IOException. Else it returns silently.<p/>
*
* <p/><b>If another thread keeps sending messages, this method may never
* return.</b>
*
* <p/>This method is deliberately simple. If a timeout needs to be
* provided, or if more detailed conditions are required, the
* {@link #waitState(int,long)} and {@link #getState()} methods should be
* used. For example :
*
* <p/><code><pre>
* int myFlush(long notTooLong) {
* messenger.waitState(IDLE, notTooLong);
* if ((messenger.getState() & IDLE) == 0) return TOOLONG;
* if ((messenger.getState() & USABLE) != 0) return FLUSHED;
* if (messenger.getState() == CLOSED) return CLOSEDANDFLUSHED;
* return BROKEN;
* }
* </pre></code>
*
* <p/>Note: {@link #close()} being asynchronous, it is valid to invoke
* <code>flush()</code> after <code>close()</code> as a form of synchronous
* variant of <code>close()</code>. If this messenger is not shared with any
* other thread, then invoking <code>flush()</code> before
* <code>close</code> is a more familiar means of achieving the same effect.
*
* @throws IOException This messenger failed before processing all
* outstanding messages successfully.
*/
void flush() throws IOException;
/**
* Force the messenger to start resolving if it is not resolved yet. Any
* attempt at sending a message has the same effect, but the message may
* fail as a result, depending upon the method used.
*/
void resolve();
/**
* Simple sending: blocks until the message was accepted for sending or the messenger is not {@link #USABLE}; whichever occurs
* first. If a service name and service param are specified, they will replace those specified at construction for the
* purpose of sending this message only.<p/>
* <p/>
* Error Handling:
* <p/>
* <ul>
* <li>An {@link java.io.IOException} means that this message is invalid or that this messenger is now in one of the non {@link
* #USABLE} states and may no longer send new messages, and means that the message was not sent. The exact state of the
* messenger may be obtained from the {@link #getState()} method. If no exception is thrown, the message is accepted for
* sending and may or may not be fully processed.</li>
* <p/>
* <li>The invoker may have confirmation of completion by observing the message's properties. When the message has been
* fully processed, {@link Message#getMessageProperty(Object) Message#getMessageProperty(Messenger.class)} will return an
* object of class {@link OutgoingMessageEvent}. Changes in a message's set of properties may be tracked by selecting the
* message. If an exception was thrown, the message's properties will not be modified
* <p/>
* <li>There is no guarantee that the process of sending the message will not fail after that method returned. If this messenger
* subsequently reaches an {@link #IDLE} state that is either {@link #CLOSED} or a {@link #USABLE} state, then it may be inferred
* that all outstanding messages have been processed without this messenger detecting an error.</li>
* </ul>
* <p/>
* <p/><b>WARNING:</b> The Message object should not be reused or modified until completely processed. Concurrent modification
* of a message while a messenger is sending the message will produce incorrect and unpredictable results. If completion is
* not monitored, the message should <b>never</b> be reused. If necessary, a clone of the message may be provided to
* {@link #sendMessageB}:
* <p/>
* <p/><code><pre>
* messenger.sendMessageB( (Message) myMessage.clone(), theService, theParam );
* </pre></code>
* <p/>
* There is no guarantee that a message successfully sent will actually be received.<p/>
*
* @param msg the message
* @param service Optionally replaces the service in the destination
* address. If {@code null} then the destination address's default
* service will be used. If the empty string ("") is used then
* no service is included in the destination address.
* @param serviceParam Optionally replaces the service param in the
* destination address. If {@code null} then the destination address's
* default service parameter will be used. If the empty string ("") is used
* then no service param is included in the destination address.
* @throws IOException Thrown if the message cannot be sent.
*/
void sendMessageB(Message msg, String service, String serviceParam) throws IOException;
/**
* Sends a message to the destination specified at construction. If a service name and service param are specified, they will
* replace those specified at construction for the purpose of sending this message only.
* <p/>
* This method is identical to {@link #sendMessage(Message,String,String)}, except that it does not throw an exception. The invoker
* has to retrieve a detailed status from the message if needed.
* <p/>
* Error Handling: <ul>
* <li>A return result of {@code false} indicates that the message was not accepted to be sent. This may be due to
* local resource limits being reached or to the messenger being in a state that is not {@link #USABLE} or to the message
* being invalid. The exact cause of the failure can be retrieved from the message by using
* {@link Message#getMessageProperty(Object) <code>Message.getMessageProperty(Messenger.class)</code>}. If appropriate,
* another attempt at sending the message, may be made after waiting for the congestion to clear (for example by using
* {@link #waitState(int,long)}).</li>
* <p/>
* <li>A return result of {@code true} indicates that the message was accepted for sending. <b>It does not imply that
* the message will be sent or that the destination will receive the message.</b> There will be no indication by this method
* of any errors in sending the message. If this messenger subsequently reaches an {@link #IDLE} state that is either {@link
* #CLOSED} or a {@link #USABLE} state, then it may be inferred that all outstanding messages have been processed without this
* messenger detecting an error.</li>
* <p/>
* <li>The invoker may have confirmation of completion (successful or not) by observing the message's properties. When the
* message has been fully processed, {@link Message#getMessageProperty(Object) <code>Message.getMessageProperty(Messenger.class)</code>}
* will return an object of class {@link OutgoingMessageEvent}. Changes in a message's set of properties may be tracked by
* selecting the message.</li>
* </ul>
* <p/>
* <p/><b>WARNING:</b> The Message object should not be reused or modified until completely processed. Concurrent modification
* of a message while a messenger is sending the message will produce incorrect and unpredictable results. If completion is
* not monitored, the message should <b>never</b> be reused. If necessary, a clone of the message may be provided to
* {@link #sendMessageN}:
* <p/>
* <p/><code><pre>
* messenger.sendMessageN( (Message) myMessage.clone(), theService, theParam );
* </pre></code>
* <p/>
* There is no guarantee that a message successfully sent will actually be received.<p/>
*
* @param msg The message to send.
* @param service Optionally replaces the service in the destination
* address. If {@code null} then the destination address's default
* service will be used. If the empty string ("") is used then
* no service is included in the destination address.
* @param serviceParam Optionally replaces the service param in the
* destination address. If {@code null} then the destination address's
* default service parameter will be used. If the empty string ("") is used
* then no service param is included in the destination address.
* @return boolean {@code true} if the message has been accepted for sending, otherwise {@code false}.
*/
boolean sendMessageN(Message msg, String service, String serviceParam);
/**
* Sends a message to the destination specified at construction as if by
* invoking {@link #sendMessage(Message,String,String) sendMessage(msg, null, null)}
*
* @param msg The message to send.
* @return boolean {@code true} if the message has been accepted for sending, otherwise {@code false}.
* @throws IOException Thrown if the message cannot be sent.
*/
boolean sendMessage(Message msg) throws IOException;
/**
* Sends a message to the destination specified at construction. If a service name and service param are specified, they will
* replace those specified at construction for the purpose of sending this message only.
* <p/>
* Error Handling:
* <p/>
* <ul>
* <p/>
* <li>An {@link java.io.IOException} means that this message is invalid or that this messenger is now in one of the
* non {@link #USABLE} states and may no longer send new messages, and that the message was not sent. The exact state of
* the messenger may be obtained from the {@link #getState()} method.</li>
* <p/>
* <li>A return result of {@code false} indicates that the message was not accepted to be sent. Usually this is due to
* local resource limits being reached. If needed, another attempt at sending the message, may be made after waiting for the
* congestion to clear (for example by using {@link #waitState(int,long)}).</li>
* <p/>
* <li>A return result of {@code true} indicates that the message was accepted for sending. <b>It does not imply that
* the message will be sent or that the destination will receive the message.</b> There will be no immediate indication of any
* errors in sending the message. If this messenger subsequently reaches an {@link #IDLE} state that is either {@link #CLOSED}
* or a {@link #USABLE} state, then it may be inferred that all outstanding messages have been processed without this
* messenger detecting an error.</li>
* <p/>
* <li>The invoker may have confirmation of completion by observing the message's properties. When the message has been fully
* processed, {@link Message#getMessageProperty(Object) <code>Message.getMessageProperty(Messenger.class)</code>} will return
* an object of class {@link OutgoingMessageEvent}. Changes in a message's set of properties may be tracked by selecting
* the message.
* <p/>
* </ul>
* <p/>
* <p/><b>WARNING:</b> The Message object should not be reused or modified until completely processed. Concurrent modification
* of a message while a messenger is sending the message will produce incorrect and unpredictable results. If completion is
* not monitored, the message should <b>never</b> be reused. If necessary, a clone of the message may be provided to
* <code>sendMessage</code>:
* <p/>
* <code><pre>
* messenger.sendMessage( (Message) myMessage.clone(), theService, theParam );
* </pre></code>
* <p/>
* There is no guarantee that a message successfully sent will actually be received.<p/>
* <p/>
* <b>Limitation:</b> using this method along with {@link net.jxta.util.SimpleSelector#select} on the same message may occasionally
* cause some errors to not be thrown. Prefer {@link #sendMessageN} when using {@link net.jxta.util.SimpleSelector#select}.
* <p/>
* This is a legacy method. Modern code should prefer the other methods and select messages.
*
* @param msg The message to send.
* @param service Optionally replaces the service in the destination
* address. If {@code null} then the destination address's default
* service will be used. If the empty string ("") is used then
* no service is included in the destination address.
* @param serviceParam Optionally replaces the service param in the
* destination address. If {@code null} then the destination address's
* default service parameter will be used. If the empty string ("") is used
* then no service param is included in the destination address.
* @return boolean {@code true} if the message has been accepted for sending, otherwise {@code false}.
* @throws IOException Thrown if the message cannot be sent.
*/
boolean sendMessage(Message msg, String service, String serviceParam) throws IOException;
/**
* Sends a message to the destination specified at construction. If a service name and service param are specified, they will
* replace those specified at construction for the purpose of sending this message only.
* <p/>
* <b>WARNING:</b> The Message object should not be reused or modified until the message has been fully processed.
* Concurrent modification of a message while a messenger is sending the message will produce incorrect and unpredictable
* results. If a listener is provided it is invoked after the message is considered fully processed. However it is recommended
* not to reuse or otherwise modify a messages after sending it. If necessary, a clone of the message may be provided to
* <code>sendMessage</code>:
* <p/>
* <code><pre>
* messenger.sendMessage( (Message) myMessage.clone() );
* </pre></code>
* <p/>
* Error Handling:
* <p/>
* <ul>
* <p/>
* <li>If a listener was provided, it will always be invoked. Depending upon the outcome either the
* {@link OutgoingMessageEventListener#messageSendFailed(OutgoingMessageEvent)} or the {@link
* OutgoingMessageEventListener#messageSendSucceeded(OutgoingMessageEvent)} method will be invoked:<p/>
* <p/>
* <ul>
* <p/>
* <li>If the message could not be accepted for sending due to temporary resource saturation,
* <code>messageSendFailed</code> will be invoked. The {@link Throwable} object returned by the {@link
* OutgoingMessageEvent#getFailure()} method of the passed event object will be null.</li>
* <p/>
* <li>If the message could not be accepted for sending due to the messenger not being {@link #USABLE},
* <code>messageSendFailed</code> will be invoked. The {@link Throwable} object returned by the {@link
* OutgoingMessageEvent#getFailure()} method of the passed event object will reflect the messenger's condition.</li>
* <p/>
* <li>If the message is accepted for sending but later fails, then <code>messageSendFailed</code> will be invoked. The
* {@link Throwable} object returned by the {@link OutgoingMessageEvent#getFailure()} method of the passed event object
* will reflect the origin of the failure.</li>
* <p/>
* <li>If the message is accepted for sending and later succeeds, then <code>messageSendSucceeded</code> will be
* invoked.</li>
* <p/>
* </ul></li>
* <p/>
* <li>If a listener was provided, it is always possible that it is invoked before this method returns.</li>
* <p/>
* <li>If no listener was provided, </b> There will be no notification of any errors nor success in sending the message. If
* this messenger subsequently reaches an {@link #IDLE} state that is either {@link #CLOSED} or a {@link #USABLE} state, then it
* may be inferred that all outstanding messages have been processed without this messenger detecting an error.</li>
* <p/>
* <li>This method does not throw exceptions. As a result, when used with a {@code null} listener, it provides very
* little feedback to the invoker. A messenger should be abandoned once it is in one of the {@link #TERMINAL} states.</li>
* <p/>
* </ul>
* <p/>
* As with all <code>sendMessage</code> methods, success is not a guarantee that the message will actually be received.
* <p/>
* <p/>This is a legacy method. Modern code should prefer the other methods and select messages. If a listener API is preferred, it is possible to use a {@link ListenerAdaptor} object explicitly to have a listener called.
*
* @param msg The message to send.
* @param service Optionally replaces the service in the destination
* address. If {@code null} then the destination address's default
* service will be used. If the empty string ("") is used then
* no service is included in the destination address.
* @param serviceParam Optionally replaces the service param in the
* destination address. If {@code null} then the destination address's
* default service parameter will be used. If the empty string ("") is used
* then no service param is included in the destination address.
* @param listener listener for events about this message or null if no notification is desired.
* @throws UnsupportedOperationException If this messenger is not a channel or was not given a {@link ListenerAdaptor}.
* (all messengers obtained through {@link EndpointService#getMessenger} are configured properly.
*/
void sendMessage(Message msg, String service, String serviceParam, OutgoingMessageEventListener listener);
}