Project JXTA

net.jxta.impl.endpoint
Class BlockingMessenger

java.lang.Object
  extended by net.jxta.util.AbstractSimpleSelectable
      extended by net.jxta.endpoint.AbstractMessenger
          extended by net.jxta.impl.endpoint.BlockingMessenger
All Implemented Interfaces:
Messenger, SimpleSelectable
Direct Known Subclasses:
CbJxMessenger, HttpClientMessenger, HttpServletMessenger, LoopbackMessenger, RelayServerClient.RelayMessenger, RouterMessenger, TcpMessenger, TlsMessenger

public abstract class BlockingMessenger
extends AbstractMessenger

This class is a near-drop-in replacement for the previous BlockingMessenger class. To subclassers (that is, currently, transports) the only difference is that some overloaded methods have a different name (class hierarchy reasons made it impossible to preserve the names without forcing an API change for applications). The other difference which is not API visible, is that it implements the standard MessengerState behaviour and semantics required by the changes in the endpoint framework. This the only base messenger class meant to be extended by outside code that is in the impl tree. The reason being that what it replaces was there already and that new code should not become dependant upon it.


Nested Class Summary
 
Nested classes/interfaces inherited from interface net.jxta.util.SimpleSelectable
SimpleSelectable.IdentityReference
 
Field Summary
 
Fields inherited from class net.jxta.endpoint.AbstractMessenger
DEFAULT_MTU, dstAddress
 
Fields inherited from class net.jxta.util.AbstractSimpleSelectable
identityReference
 
Fields inherited from interface net.jxta.endpoint.Messenger
ANYSTATE, BREAKING, BROKEN, CLOSED, CLOSING, CONNECTED, DISCONNECTED, DISCONNECTING, IDLE, RECONCLOSING, RECONNECTING, RECONSATURATED, RESOLCLOSING, RESOLPENDING, RESOLSATURATED, RESOLVED, RESOLVING, SATURATED, SENDING, SENDINGSATURATED, TERMINAL, UNRESOLVABLE, UNRESOLVED, UNRESOLVING, USABLE
 
Constructor Summary
BlockingMessenger(PeerGroupID homeGroupID, EndpointAddress dest, boolean selfDestruct)
          Constructor.
 
Method Summary
 void close()
          

Some transports historically overload the close method of BlockingMessenger.

protected abstract  void closeImpl()
          Close connection.
 Messenger getChannelMessenger(PeerGroupID redirection, String service, String serviceParam)
           
protected  EndpointAddress getDestAddressToUse(String service, String serviceParam)
          A trivial convenience method that transports still depend upon.
 EndpointAddress getLogicalDestinationAddress()
          

getLogicalDestinationAddress() requires resolution (it's the address advertised by the other end).

protected abstract  EndpointAddress getLogicalDestinationImpl()
          Obtain the logical destination address from the implementer (a transport for example).
 int getState()
           
 boolean isClosed()
          We overload isClosed because many messengers still invoke super.isClosed() for their own implementation and they expect it to be true only when all is shutdown; not while we're closing gently.
protected abstract  boolean isIdleImpl()
          return true if this messenger has not been used for a long time.
 void resolve()
           
 void sendMessageB(Message msg, String service, String serviceParam)
          
protected abstract  boolean sendMessageBImpl(Message message, String service, String param)
          send message. block as needed. throw IOException or runtime exception as needed.
 boolean sendMessageN(Message msg, String service, String serviceParam)
           
 void setOwner(Object owner)
          Sets an owner for this blocking messenger.
protected  void shutdown()
          A transport may call this to cause an orderly closure of its messengers.
 
Methods inherited from class net.jxta.endpoint.AbstractMessenger
flush, getDestinationAddress, getDestinationAddressObject, getMTU, isIdle, isSynchronous, itemChanged, sendMessage, sendMessage, sendMessage, setStateLock, waitState
 
Methods inherited from class net.jxta.util.AbstractSimpleSelectable
getIdentityReference, haveListeners, notifyChange, register, registerListener, unregister, unregisterListener
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface net.jxta.util.SimpleSelectable
getIdentityReference, register, unregister
 

Constructor Detail

BlockingMessenger

public BlockingMessenger(PeerGroupID homeGroupID,
                         EndpointAddress dest,
                         boolean selfDestruct)
Constructor. We start in the CONNECTED state, we pretend to have a queue of size 1, and we can never re-connect. Although this messenger fully respects the asynchronous semantics, it is saturated as soon as one msg is being send, and if not saturated, send is actually performed by the invoker thread. So return is not completely immediate. This is a barely acceptable implementation, but this is also a transition adapter that is bound to disappear one release from now. The main goal is to get things going until transports are adapted.

Parameters:
homeGroupID - the group that this messenger works for. This is the group of the endpoint service or transport that created this messenger.
dest - where messages should be addressed to
selfDestruct - true if this messenger must self close destruct when idle. Warning: If selfDestruct is used, this messenger will remained referenced for as long as isIdleImpl returns false.
Method Detail

setOwner

public void setOwner(Object owner)
Sets an owner for this blocking messenger. Owners are normally canonical messengers. The goal of registering the owner is to keep that owner reachable as long as this blocking messenger is. Canonical messengers are otherwise softly referenced, and so, may be deleted whenever memory is tight. We do not want to use finalizers or the equivalent reference queue mechanism; so we have no idea when a blocking messenger is no-longer referenced by any canonical. In addition it may be expensive to make and so we want to keep it for a while anyway. As a result, instead of keeping a blocking messenger open as long as there is a canonical, we do the opposite: we keep the canonical (owner, here) as long as the blocking messenger is open (and usually beyond, memory allowing). How long a blocking messenger will stay around depends upon that messenger's implementation. That may even be left up to the GC, in the end (if close is not needed AND the messenger is cheap to make). In that case, the owner is likely the only referer, and so both will have the same lifetime.

Parameters:
owner - The object that should be kept referenced at least as long as this one.

getDestAddressToUse

protected EndpointAddress getDestAddressToUse(String service,
                                              String serviceParam)
A trivial convenience method that transports still depend upon. The reason it exists is that it used to be non-trivial, when the group redirection would sometimes be done at this point (the transports could be asked to send to the non-mangled service and param, when the application used the implicit defaults). This is no-longer true: the transport (the blocking messenger) is always invoked with fully defaulted and mangled service name and param. So all we have to do is to paste them all together. Eventually blocking messenger could simply be invoked with an already computed full destination.


shutdown

protected final void shutdown()
A transport may call this to cause an orderly closure of its messengers.


isClosed

public boolean isClosed()
We overload isClosed because many messengers still invoke super.isClosed() for their own implementation and they expect it to be true only when all is shutdown; not while we're closing gently. FIXME - jice@jxta.org 20040413: transports should get a deeper retrofit eventually.

Specified by:
isClosed in interface Messenger
Overrides:
isClosed in class AbstractMessenger

getLogicalDestinationAddress

public final EndpointAddress getLogicalDestinationAddress()

getLogicalDestinationAddress() requires resolution (it's the address advertised by the other end). For a blocking messenger it's easy. We're born resolved. So, just ask the implementor what it is.


close

public final void close()

Some transports historically overload the close method of BlockingMessenger. The final is there to make sure we know about it. However, there should be no harm done if the unchanged code is renamed to closeImpl; even if it calls super.close(). The real problem, however, is transports calling close (was their own, but now it means this one), when they want to break. It will make things look like someone just called close, but it will not actually break anything. However, that will cause the state machine to go through the close process. this will end up calling closeImpl(). That will do.


sendMessageB

public void sendMessageB(Message msg,
                         String service,
                         String serviceParam)
                  throws IOException

Throws:
IOException

sendMessageN

public final boolean sendMessageN(Message msg,
                                  String service,
                                  String serviceParam)

resolve

public final void resolve()

getState

public final int getState()

getChannelMessenger

public final Messenger getChannelMessenger(PeerGroupID redirection,
                                           String service,
                                           String serviceParam)

closeImpl

protected abstract void closeImpl()
Close connection. May fail current send.


sendMessageBImpl

protected abstract boolean sendMessageBImpl(Message message,
                                            String service,
                                            String param)
                                     throws IOException
send message. block as needed. throw IOException or runtime exception as needed. The boolean return value is for historical reasons: so that transports just need to rename their sendMessage() methods. No need to change a bit of the code.

Throws:
IOException

isIdleImpl

protected abstract boolean isIdleImpl()
return true if this messenger has not been used for a long time. The definition of long time is: "so long that closing it is worth the risk of having to re-open". A messenger should self close if it thinks it meets the definition of idle. BlockingMessenger leaves the evaluation to the transport but does the work automatically. Important: if self destruction is used, this method must work; not just return false. See the constructor. In general, if closeImpl does not need to do anyhing, then self destruction is not needed.


getLogicalDestinationImpl

protected abstract EndpointAddress getLogicalDestinationImpl()
Obtain the logical destination address from the implementer (a transport for example).


JXTA J2SE