Fields Summary |
---|
protected static final int | DEFAULT_TIMEOUTThe default value for the connection timeout. |
protected static final String | TIMEOUT_NAMEThe name of the parameter defining the connection timeout. |
protected static final int | DEFAULT_BACKLOGThe default value for the connection backlog. |
protected static final String | BACKLOG_NAMEThe name of the parameter defining the connection backlog. |
public static final String | HELLO_NAMEThe name of the parameter defining the service hello name. |
private org.apache.james.services.JamesConnectionManager | connectionManagerThe ConnectionManager that spawns and manages service connections. |
protected String | threadGroupThe name of the thread group to be used by this service for
generating connections |
protected org.apache.excalibur.thread.ThreadPool | threadPoolThe thread pool used by this service that holds the threads
that service the client connections. |
protected String | serverSocketTypeThe server socket type used to generate connections for this server. |
protected int | portThe port on which this service will be made available. |
protected InetAddress | bindToNetwork interface to which the service will bind. If not set,
the server binds to all available interfaces. |
protected ServerSocket | serverSocket |
protected String | connectionNameThe name of the connection used by this service. We need to
track this so we can tell the ConnectionManager which service
to disconnect upon shutdown. |
protected Integer | connectionLimitThe maximum number of connections allowed for this service. |
protected int | timeoutThe connection idle timeout. Used primarily to prevent server
problems from hanging a connection. |
protected int | backlogThe connection backlog. |
protected String | helloNameThe hello name for the service. |
private org.apache.avalon.framework.service.ServiceManager | compMgrThe component manager used by this service. |
private volatile boolean | enabledWhether this service is enabled. |
private boolean | m_disposedFlag holding the disposed state of the component. |
Methods Summary |
---|
public void | configure(org.apache.avalon.framework.configuration.Configuration conf)
enabled = conf.getAttributeAsBoolean("enabled", true);
if (!enabled) {
getLogger().info(getServiceType() + " disabled by configuration");
return;
}
Configuration handlerConfiguration = conf.getChild("handler");
// Send the handler subconfiguration to the super class. This
// ensures that the handler config is passed to the handlers.
//
// TODO: This should be rationalized. The handler element of the
// server configuration doesn't really make a whole lot of
// sense. We should modify the config to get rid of it.
// Keeping it for now to maintain backwards compatibility.
super.configure(handlerConfiguration);
port = conf.getChild("port").getValueAsInteger(getDefaultPort());
Configuration serverSocketTypeConf = conf.getChild("serverSocketType", false);
String confSocketType = null;
if (serverSocketTypeConf != null ) {
confSocketType = serverSocketTypeConf.getValue();
}
if (confSocketType == null) {
// Only load the useTLS parameter if a specific socket type has not
// been specified. This maintains backwards compatibility while
// allowing us to have more complex (i.e. multiple SSL configuration)
// deployments
final boolean useTLS = conf.getChild("useTLS").getValueAsBoolean(isDefaultTLSEnabled());
if (useTLS) {
serverSocketType = "ssl";
}
} else {
serverSocketType = confSocketType;
}
StringBuffer infoBuffer;
threadGroup = conf.getChild("threadGroup").getValue(null);
if (threadGroup != null) {
infoBuffer =
new StringBuffer(64)
.append(getServiceType())
.append(" uses thread group: ")
.append(threadGroup);
getLogger().info(infoBuffer.toString());
}
else {
getLogger().info(getServiceType() + " uses default thread group.");
}
try {
final String bindAddress = conf.getChild("bind").getValue(null);
if( null != bindAddress ) {
bindTo = InetAddress.getByName(bindAddress);
infoBuffer =
new StringBuffer(64)
.append(getServiceType())
.append(" bound to: ")
.append(bindTo);
getLogger().info(infoBuffer.toString());
}
}
catch( final UnknownHostException unhe ) {
throw new ConfigurationException( "Malformed bind parameter in configuration of service " + getServiceType(), unhe );
}
String hostName = null;
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException ue) {
hostName = "localhost";
}
infoBuffer =
new StringBuffer(64)
.append(getServiceType())
.append(" is running on: ")
.append(hostName);
getLogger().info(infoBuffer.toString());
Configuration helloConf = handlerConfiguration.getChild(HELLO_NAME);
boolean autodetect = helloConf.getAttributeAsBoolean("autodetect", true);
if (autodetect) {
helloName = hostName;
} else {
helloName = helloConf.getValue("localhost");
}
infoBuffer =
new StringBuffer(64)
.append(getServiceType())
.append(" handler hello name is: ")
.append(helloName);
getLogger().info(infoBuffer.toString());
timeout = handlerConfiguration.getChild(TIMEOUT_NAME).getValueAsInteger(DEFAULT_TIMEOUT);
infoBuffer =
new StringBuffer(64)
.append(getServiceType())
.append(" handler connection timeout is: ")
.append(timeout);
getLogger().info(infoBuffer.toString());
backlog = conf.getChild(BACKLOG_NAME).getValueAsInteger(DEFAULT_BACKLOG);
infoBuffer =
new StringBuffer(64)
.append(getServiceType())
.append(" connection backlog is: ")
.append(backlog);
getLogger().info(infoBuffer.toString());
if (connectionManager instanceof JamesConnectionManager) {
String connectionLimitString = conf.getChild("connectionLimit").getValue(null);
if (connectionLimitString != null) {
try {
connectionLimit = new Integer(connectionLimitString);
} catch (NumberFormatException nfe) {
getLogger().error("Connection limit value is not properly formatted.", nfe);
}
if (connectionLimit.intValue() < 0) {
getLogger().error("Connection limit value cannot be less than zero.");
throw new ConfigurationException("Connection limit value cannot be less than zero.");
}
} else {
connectionLimit = new Integer(((JamesConnectionManager)connectionManager).getMaximumNumberOfOpenConnections());
}
infoBuffer = new StringBuffer(128)
.append(getServiceType())
.append(" will allow a maximum of ")
.append(connectionLimit.intValue())
.append(" connections.");
getLogger().info(infoBuffer.toString());
}
|
public void | dispose()
if (!isEnabled()) {
return;
}
if( m_disposed )
{
if( getLogger().isWarnEnabled() )
{
getLogger().warn( "ignoring disposal request - already disposed" );
}
return;
}
if( getLogger().isDebugEnabled() )
{
getLogger().debug( "disposal" );
}
m_disposed = true;
if( getLogger().isDebugEnabled() )
{
StringBuffer infoBuffer =
new StringBuffer(64).append(getServiceType()).append(
" dispose... ").append(connectionName);
getLogger().debug(infoBuffer.toString());
}
try {
connectionManager.disconnect(connectionName, true);
} catch (final Exception e) {
StringBuffer warnBuffer =
new StringBuffer(64)
.append("Error disconnecting ")
.append(getServiceType())
.append(": ");
getLogger().warn(warnBuffer.toString(), e);
}
compMgr = null;
connectionManager = null;
threadPool = null;
// This is needed to make sure sockets are promptly closed on Windows 2000
// TODO: Check this - shouldn't need to explicitly gc to force socket closure
System.gc();
getLogger().debug(getServiceType() + " ...dispose end");
|
protected int | getDefaultPort()Get the default port for this server type.
It is strongly recommended that subclasses of this class
override this method to specify the default port for their
specific server type.
return 0;
|
public java.lang.String | getNetworkInterface()Returns the address if the network interface the socket is bound to
if (bindTo == null) {
return "All";
} else {
return bindTo.getHostAddress();
}
|
public int | getPort()Returns the port that the service is bound to
return port;
|
public java.lang.String | getServiceType()This method returns the type of service provided by this server.
This should be invariant over the life of the class.
Subclasses may override this implementation. This implementation
parses the complete class name and returns the undecorated class
name.
String name = getClass().getName();
int p = name.lastIndexOf(".");
if (p > 0 && p < name.length() - 2) {
name = name.substring(p + 1);
}
return name;
|
public java.lang.String | getSocketType()Returns the server socket type, plain or SSL
return serverSocketType;
|
protected org.apache.james.util.watchdog.WatchdogFactory | getWatchdogFactory()This constructs the WatchdogFactory that will be used to guard
against runaway or stuck behavior. Should only be called once
by a subclass in its initialize() method.
WatchdogFactory theWatchdogFactory = null;
theWatchdogFactory = new ThreadPerWatchdogFactory(threadPool, timeout);
if (theWatchdogFactory instanceof LogEnabled) {
((LogEnabled)theWatchdogFactory).enableLogging(getLogger());
}
return theWatchdogFactory;
|
public void | initialize()
if (!isEnabled()) {
getLogger().info(getServiceType() + " Disabled");
System.out.println(getServiceType() + " Disabled");
return;
}
getLogger().debug(getServiceType() + " init...");
SocketManager socketManager = (SocketManager) compMgr.lookup(SocketManager.ROLE);
ThreadManager threadManager = (ThreadManager) compMgr.lookup(ThreadManager.ROLE);
if (threadGroup != null) {
threadPool = threadManager.getThreadPool(threadGroup);
} else {
threadPool = threadManager.getDefaultThreadPool();
}
ServerSocketFactory factory = socketManager.getServerSocketFactory(serverSocketType);
ServerSocket serverSocket = factory.createServerSocket(port, backlog, bindTo);
if (null == connectionName) {
final StringBuffer sb = new StringBuffer();
sb.append(serverSocketType);
sb.append(':");
sb.append(port);
if (null != bindTo) {
sb.append('/");
sb.append(bindTo);
}
connectionName = sb.toString();
}
if ((connectionLimit != null) &&
(connectionManager instanceof JamesConnectionManager)) {
if (null != threadPool) {
((JamesConnectionManager)connectionManager).connect(connectionName, serverSocket, this, threadPool, connectionLimit.intValue());
}
else {
((JamesConnectionManager)connectionManager).connect(connectionName, serverSocket, this, connectionLimit.intValue()); // default pool
}
} else {
if (null != threadPool) {
connectionManager.connect(connectionName, serverSocket, this, threadPool);
}
else {
connectionManager.connect(connectionName, serverSocket, this); // default pool
}
}
getLogger().debug(getServiceType() + " ...init end");
StringBuffer logBuffer =
new StringBuffer(64)
.append(getServiceType())
.append(" started ")
.append(connectionName);
String logString = logBuffer.toString();
System.out.println(logString);
getLogger().info(logString);
|
protected boolean | isDefaultTLSEnabled()Get whether TLS is enabled for this server's socket by default.
return false;
|
public final boolean | isEnabled()Describes whether this service is enabled by configuration.
return enabled;
|
protected abstract org.apache.avalon.cornerstone.services.connection.ConnectionHandler | newHandler()Overide this method to create actual instance of connection handler.
|
public void | service(org.apache.avalon.framework.service.ServiceManager comp)
super.service( comp );
compMgr = comp;
connectionManager =
(JamesConnectionManager)compMgr.lookup(JamesConnectionManager.ROLE);
|