cz.cuni.amis.pogamut.base.communication.connection.impl
Class AbstractConnection<ADDRESS extends IWorldConnectionAddress>

java.lang.Object
  extended by cz.cuni.amis.pogamut.base.communication.connection.impl.AbstractConnection<ADDRESS>
All Implemented Interfaces:
IWorldConnection<ADDRESS>, IWorldReaderProvider, IWorldWriterProvider, IComponent
Direct Known Subclasses:
SocketConnection

public abstract class AbstractConnection<ADDRESS extends IWorldConnectionAddress>
extends java.lang.Object
implements IWorldConnection<ADDRESS>

Implementation of the basic connection to the world server. Note that it has some nice features :-)

This implementation is THREAD-SAFE! It is IComponent!

Calling getReader().read(), getWriter().write() is synchronized as well!

Reader and writer can be got in advance (no need to start() the connection before getReader() or getWriter() is invoked).

Calling reader.close() or writer.close() will stop() the connection as well ... you don't have to have this instance referenced directly.

Whenever an exception is thrown during read/write operation, the connection is immediately stop()ed, not kill()ed and IStoppedEvent is broadcasted. The flag will be changed correctly as well.

... if you're waiting on the reader.read() and the socket is closed meanwhile, be ready to catch the SocketException ...

The instance of the class can be reused (e.g. you may start(), stop() it repeatedly).

All you have to implement:

  1. unsyncConnect(IConnectionAddress address) - no need to care of anything else then connection to 'address' + provide correct behavior for getConnectionReader(), getConnectionWriter()
  2. unsyncClose() - just close the connection, no need to care of anything else
  3. Reader getConnectionReader() - if connection is up, return raw reader for your connection (no extra assumptions), it will be wrapped with ConnectionReader ... if conection is down, return null
  4. Writer getConnectionWriter() - if connection is down, return raw writer for your connection (no extra assumptions), it will be wrapped with ConnectionWriter ... if conection is down, return null
You might want to override method getMessageEnd() to return correct "message-end" string, so the messages are correctly split by the readers/writers.

Ignores IComponentControlHelper.startPaused(), performs IComponentControlHelper.start() in both start cases.


Field Summary
protected  ADDRESS address
          Current remote side address of the connection.
static Token COMPONENT_ID
           
protected  ComponentController<IComponent> controller
          Control helper starting/stopping the component.
static java.lang.String DEFAULT_LINE_END
           
protected  IComponentBus eventBus
          Event bus of the agent.
protected  LogCategory log
          Special category for the connection.
 
Constructor Summary
AbstractConnection(ADDRESS address, ComponentDependencies dependencies, IComponentBus bus, IAgentLogger logger)
           
AbstractConnection(ComponentDependencies dependencies, IComponentBus bus, IAgentLogger logger)
           
 
Method Summary
 ADDRESS getAddress()
          Get the descriptor of the connection's remote side.
 Token getComponentId()
          Unique identification of the component.
protected abstract  java.io.Reader getConnectionReader()
          This should return plain reader for the current connection.
protected abstract  java.io.Writer getConnectionWriter()
          This should return plain writer for the current connection.
 LogCategory getLog()
           
 java.lang.String getMessageEnd()
           
 WorldReader getReader()
          To be used by (usually) IParser upon IParser.start() method call to obtain a world reader.
 WorldWriter getWriter()
          To be used on ICommandSerializer.start() method to obtain a writer into the world.
 void setAddress(ADDRESS address)
          Sets the connection address to the object.
 void setLogMessages(boolean logMessages)
          Sets whether to log the messages that are sent/received through writer/reader.
 java.lang.String toString()
           
protected abstract  void unsyncClose()
          Inner unsynchronized implementation of the close(), should close the connection to the remote side without throwing any exception.
protected abstract  void unsyncConnect(ADDRESS address)
          Inner implementation of connect, unsynchronized, this is called from connect(IConnectionDescriptor).
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

COMPONENT_ID

public static final Token COMPONENT_ID

DEFAULT_LINE_END

public static final java.lang.String DEFAULT_LINE_END
See Also:
Constant Field Values

address

protected ADDRESS extends IWorldConnectionAddress address
Current remote side address of the connection.


log

protected LogCategory log
Special category for the connection.


eventBus

protected IComponentBus eventBus
Event bus of the agent.


controller

protected ComponentController<IComponent> controller
Control helper starting/stopping the component.

Constructor Detail

AbstractConnection

public AbstractConnection(ComponentDependencies dependencies,
                          IComponentBus bus,
                          IAgentLogger logger)

AbstractConnection

public AbstractConnection(ADDRESS address,
                          ComponentDependencies dependencies,
                          IComponentBus bus,
                          IAgentLogger logger)
Method Detail

unsyncConnect

protected abstract void unsyncConnect(ADDRESS address)
                               throws ConnectionException
Inner implementation of connect, unsynchronized, this is called from connect(IConnectionDescriptor). This is called only iff the connection is down and the address is a new address.

Throws:
ConnectionException

unsyncClose

protected abstract void unsyncClose()
Inner unsynchronized implementation of the close(), should close the connection to the remote side without throwing any exception. You may be sure that the connection is up (according to the flag) when this method is called.


getConnectionReader

protected abstract java.io.Reader getConnectionReader()
                                               throws ConnectionException
This should return plain reader for the current connection. If connection is down, this should throw WorldConnectionException. We will wrap this reader with our own implementation that is capable of sniffing messages as they come (if required).

Returns:
Throws:
ConnectionException

getConnectionWriter

protected abstract java.io.Writer getConnectionWriter()
                                               throws ConnectionException
This should return plain writer for the current connection. If connection is down, this should throw WorldConnectionException. We will wrap this writer with our own implementation that is capable of sniffing messages as they go (if required).

Returns:
Throws:
ConnectionException

getComponentId

public Token getComponentId()
Description copied from interface: IComponent
Unique identification of the component.

Specified by:
getComponentId in interface IComponent
Returns:

getLog

public LogCategory getLog()

setAddress

public void setAddress(ADDRESS address)
                throws ConnectionException
Description copied from interface: IWorldConnection
Sets the connection address to the object.

If the object is connected - it throws exception AlreadyConnectedException

Specified by:
setAddress in interface IWorldConnection<ADDRESS extends IWorldConnectionAddress>
Throws:
ConnectionException

getWriter

public WorldWriter getWriter()
                      throws ConnectionException
Description copied from interface: IWorldWriterProvider
To be used on ICommandSerializer.start() method to obtain a writer into the world.

Use writer.close() to stop the writer.

Specified by:
getWriter in interface IWorldWriterProvider
Returns:
Throws:
ConnectionException

getReader

public WorldReader getReader()
                      throws ConnectionException
Description copied from interface: IWorldReaderProvider
To be used by (usually) IParser upon IParser.start() method call to obtain a world reader.

Use reader.close() to close the connection.

Specified by:
getReader in interface IWorldReaderProvider
Returns:
Throws:
ConnectionException

getAddress

public ADDRESS getAddress()
Description copied from interface: IWorldConnection
Get the descriptor of the connection's remote side.

Specified by:
getAddress in interface IWorldConnection<ADDRESS extends IWorldConnectionAddress>
Returns:

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object

setLogMessages

public void setLogMessages(boolean logMessages)
Description copied from interface: IWorldConnection
Sets whether to log the messages that are sent/received through writer/reader. Note that logging those messages is costly operation and may slow things a lot. That's why this is OFF as DEFAULT.

Specified by:
setLogMessages in interface IWorldConnection<ADDRESS extends IWorldConnectionAddress>

getMessageEnd

public java.lang.String getMessageEnd()