org.xsocket.connection.HandlerAdapter Maven / Gradle / Ivy
/*
* Copyright (c) xlightweb.org, 2006 - 2010. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
* The latest copy of this software may be found on http://www.xsocket.org/
*/
package org.xsocket.connection;
import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.xsocket.DataConverter;
import org.xsocket.Execution;
import org.xsocket.ILifeCycle;
import org.xsocket.MaxReadSizeExceededException;
import org.xsocket.SerializedTaskQueue;
/**
*
* @author [email protected]
*/
class HandlerAdapter {
private static final Logger LOG = Logger.getLogger(HandlerAdapter.class.getName());
private static final IHandler NULL_HANDLER = new NullHandler();
private static final HandlerAdapter NULL_HANDLER_ADAPTER = new HandlerAdapter(NULL_HANDLER, ConnectionUtils.getHandlerInfo(NULL_HANDLER));
private final IHandler handler;
private final IHandlerInfo handlerInfo;
HandlerAdapter(IHandler handler, IHandlerInfo handlerInfo) {
this.handler = handler;
this.handlerInfo = handlerInfo;
}
static HandlerAdapter newInstance(IHandler handler) {
if (handler == null) {
return NULL_HANDLER_ADAPTER;
} else {
IHandlerInfo handlerInfo = ConnectionUtils.getHandlerInfo(handler);
return new HandlerAdapter(handler, handlerInfo);
}
}
final IHandler getHandler() {
return handler;
}
final IHandlerInfo getHandlerInfo() {
return handlerInfo;
}
private static String printHandler(Object handler) {
return handler.getClass().getName() + "#" + handler.hashCode();
}
public boolean onConnect(final INonBlockingConnection connection, final SerializedTaskQueue taskQueue, final Executor workerpool) throws IOException, BufferUnderflowException, MaxReadSizeExceededException {
if (handlerInfo.isConnectHandler()) {
if (handlerInfo.isUnsynchronized()) {
performOnConnect(connection, taskQueue, (IConnectHandler) handler);
} else {
if (getHandlerInfo().isConnectHandlerMultithreaded()) {
taskQueue.performMultiThreaded(new PerformOnConnectTask(connection, taskQueue, (IConnectHandler) handler), workerpool);
} else {
taskQueue.performNonThreaded(new PerformOnConnectTask(connection, taskQueue, (IConnectHandler) handler), workerpool);
}
}
}
return true;
}
private static final class PerformOnConnectTask implements Runnable {
private final IConnectHandler handler;
private final INonBlockingConnection connection;
private final SerializedTaskQueue taskQueue;
public PerformOnConnectTask(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IConnectHandler handler) {
this.connection = connection;
this.taskQueue = taskQueue;
this.handler = handler;
}
public void run() {
performOnConnect(connection, taskQueue, handler);
}
}
private static boolean performOnConnect(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IConnectHandler handler) {
try {
handler.onConnect(connection);
} catch (MaxReadSizeExceededException mee) {
LOG.warning("[" + connection.getId() + "] closing connection because max readsize is reached by handling onConnect by appHandler. " + printHandler(handler) + " Reason: " + mee.toString());
closeSilence(connection);
} catch (BufferUnderflowException bue) {
// ignore
} catch (IOException ioe) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] closing connection because an error has been occured by handling onConnect by appHandler. " + printHandler(handler) + " Reason: " + ioe.toString());
}
closeSilence(connection);
} catch (Throwable t) {
LOG.warning("[" + connection.getId() + "] closing connection. Error occured by performing onConnect of " + printHandler(handler) + " " + t.toString());
closeSilence(connection);
}
return false;
}
public boolean onData(INonBlockingConnection connection, SerializedTaskQueue taskQueue, Executor workerpool, boolean ignoreException, boolean isUnsynchronized) throws IOException, BufferUnderflowException, MaxReadSizeExceededException {
if (handlerInfo.isDataHandler()) {
if (handlerInfo.isUnsynchronized()) {
performOnData(connection, taskQueue, ignoreException, (IDataHandler) handler);
} else {
if (getHandlerInfo().isDataHandlerMultithreaded()) {
taskQueue.performMultiThreaded(new PerformOnDataTask(connection, taskQueue, ignoreException, (IDataHandler) handler), workerpool);
} else {
if (isUnsynchronized) {
performOnData(connection, taskQueue, ignoreException, (IDataHandler) handler);
} else {
taskQueue.performNonThreaded(new PerformOnDataTask(connection, taskQueue, ignoreException, (IDataHandler) handler), workerpool);
}
}
}
} else {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] assigned handler " + printHandler(handler) + " is not a data handler");
}
}
return true;
}
private static final class PerformOnDataTask implements Runnable {
private final IDataHandler handler;
private final INonBlockingConnection connection;
private final SerializedTaskQueue taskQueue;
private final boolean ignoreException;
public PerformOnDataTask(INonBlockingConnection connection, SerializedTaskQueue taskQueue, boolean ignoreException, IDataHandler handler) {
this.connection = connection;
this.taskQueue = taskQueue;
this.ignoreException = ignoreException;
this.handler = handler;
}
public void run() {
performOnData(connection, taskQueue, ignoreException, handler);
}
@Override
public String toString() {
return "PerformOnDataTask#" + hashCode() + " " + connection.getId();
}
}
private static void performOnData(INonBlockingConnection connection, SerializedTaskQueue taskQueue, boolean ignoreException, IDataHandler handler) {
try {
// loop until readQueue is empty or nor processing has been done (readQueue has not been modified)
while ((connection.available() != 0) && !connection.isReceivingSuspended()) {
if (connection.getHandler() != handler) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] handler " + " replaced by " + connection.getHandler() + ". stop handling data for old handler");
}
return;
}
int version = connection.getReadBufferVersion();
// calling onData method of the handler (return value will be ignored)
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] calling onData method of handler " + printHandler(handler));
}
handler.onData(connection);
if (version == connection.getReadBufferVersion()) {
return;
}
}
} catch (MaxReadSizeExceededException mee) {
if (!ignoreException) {
LOG.warning("[" + connection.getId() + "] closing connection because max readsize is reached by handling onData by appHandler. " + printHandler(handler) + " Reason: " + mee.toString());
closeSilence(connection);
}
} catch (BufferUnderflowException bue) {
// ignore
} catch (IOException ioe) {
if (!ignoreException) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] closing connection because an error has been occured by handling data by appHandler. " + printHandler(handler) + " Reason: " + DataConverter.toString(ioe));
}
closeSilence(connection);
}
} catch (Throwable t) {
if (!ignoreException) {
LOG.warning("[" + connection.getId() + "] closing connection. Error occured by performing onData of " + printHandler(handler) + " " + t.toString());
closeSilence(connection);
}
}
}
public boolean onDisconnect(INonBlockingConnection connection, SerializedTaskQueue taskQueue, Executor workerpool, boolean isUnsynchronized) throws IOException {
if (handlerInfo.isDisconnectHandler()) {
if (handlerInfo.isUnsynchronized()) {
performOnDisconnect(connection, taskQueue, (IDisconnectHandler) handler);
} else {
if (getHandlerInfo().isDisconnectHandlerMultithreaded()) {
taskQueue.performMultiThreaded(new PerformOnDisconnectTask(connection, taskQueue, (IDisconnectHandler) handler), workerpool);
} else {
if (isUnsynchronized) {
performOnDisconnect(connection, taskQueue, (IDisconnectHandler) handler);
} else {
taskQueue.performNonThreaded(new PerformOnDisconnectTask(connection, taskQueue, (IDisconnectHandler) handler), workerpool);
}
}
}
}
return true;
}
private static final class PerformOnDisconnectTask implements Runnable {
private final IDisconnectHandler handler;
private final INonBlockingConnection connection;
private final SerializedTaskQueue taskQueue;
public PerformOnDisconnectTask(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IDisconnectHandler handler) {
this.connection = connection;
this.taskQueue = taskQueue;
this.handler = handler;
}
public void run() {
performOnDisconnect(connection, taskQueue, handler);
}
@Override
public String toString() {
return "PerformOnDisconnectTask#" + hashCode() + " " + connection.getId();
}
}
private static void performOnDisconnect(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IDisconnectHandler handler) {
try {
handler.onDisconnect(connection);
} catch (MaxReadSizeExceededException mee) {
// ignore
} catch (BufferUnderflowException bue) {
// ignore
} catch (IOException ioe) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] io exception occured while performing onDisconnect multithreaded " + printHandler(handler) + " " + ioe.toString());
}
} catch (Throwable t) {
LOG.warning("[" + connection.getId() + "] Error occured by performing onDisconnect off " + printHandler(handler) + " " + t.toString());
}
}
public boolean onConnectException(final INonBlockingConnection connection, final SerializedTaskQueue taskQueue, Executor workerpool, final IOException ioe) throws IOException {
if (handlerInfo.isConnectExceptionHandler()) {
if (handlerInfo.isUnsynchronized()) {
performOnConnectException(connection, taskQueue, ioe, (IConnectExceptionHandler) handler);
} else {
if (getHandlerInfo().isConnectExceptionHandlerMultithreaded()) {
taskQueue.performMultiThreaded(new PerformOnConnectExceptionTask(connection, taskQueue, ioe, (IConnectExceptionHandler) handler), workerpool);
} else {
taskQueue.performNonThreaded(new PerformOnConnectExceptionTask(connection, taskQueue, ioe, (IConnectExceptionHandler) handler), workerpool);
}
}
}
return true;
}
private static final class PerformOnConnectExceptionTask implements Runnable {
private final IConnectExceptionHandler handler;
private final INonBlockingConnection connection;
private final SerializedTaskQueue taskQueue;
private final IOException ioe;
public PerformOnConnectExceptionTask(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IOException ioe, IConnectExceptionHandler handler) {
this.connection = connection;
this.taskQueue = taskQueue;
this.ioe = ioe;
this.handler = handler;
}
public void run() {
try {
performOnConnectException(connection, taskQueue, ioe, handler);
} catch (MaxReadSizeExceededException mee) {
LOG.warning("[" + connection.getId() + "] closing connection because max readsize is reached by handling onConnectException by appHandler. " + printHandler(handler) + " Reason: " + mee.toString());
closeSilence(connection);
} catch (BufferUnderflowException bue) {
// ignore
} catch (IOException e) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] closing connection. An io exception occured while performing onConnectException multithreaded " + printHandler(handler) + " " + e.toString());
}
closeSilence(connection);
} catch (Throwable t) {
LOG.warning("[" + connection.getId() + "] closing connection. Error occured by performing onConnectionException of " + printHandler(handler) + " " + t.toString());
closeSilence(connection);
}
}
}
private static boolean performOnConnectException(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IOException ioe, IConnectExceptionHandler handler) throws IOException {
try {
return handler.onConnectException(connection, ioe);
} catch (RuntimeException re) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] closing connection because an error has been occured by handling onDisconnect by appHandler. " + printHandler(handler) + " Reason: " + re.toString());
}
closeSilence(connection);
throw re;
} catch (IOException e) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] closing connection because an error has been occured by handling onDisconnect by appHandler. " + printHandler(handler) + " Reason: " + ioe.toString());
}
closeSilence(connection);
throw ioe;
}
}
public boolean onIdleTimeout(final INonBlockingConnection connection, final SerializedTaskQueue taskQueue, Executor workerpool) throws IOException {
if (handlerInfo.isIdleTimeoutHandler()) {
if (handlerInfo.isUnsynchronized()) {
performOnIdleTimeout(connection, taskQueue, (IIdleTimeoutHandler) handler);
} else {
if (getHandlerInfo().isIdleTimeoutHandlerMultithreaded()) {
taskQueue.performMultiThreaded(new PerformOnIdleTimeoutTask(connection, taskQueue, (IIdleTimeoutHandler) handler), workerpool);
} else {
taskQueue.performNonThreaded(new PerformOnIdleTimeoutTask(connection, taskQueue, (IIdleTimeoutHandler) handler), workerpool);
}
}
} else {
closeSilence(connection);
}
return true;
}
private static final class PerformOnIdleTimeoutTask implements Runnable {
private final IIdleTimeoutHandler handler;
private final INonBlockingConnection connection;
private final SerializedTaskQueue taskQueue;
public PerformOnIdleTimeoutTask(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IIdleTimeoutHandler handler) {
this.connection = connection;
this.taskQueue = taskQueue;
this.handler = handler;
}
public void run() {
performOnIdleTimeout(connection, taskQueue, handler);
}
}
private static void performOnIdleTimeout(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IIdleTimeoutHandler handler) {
try {
boolean isHandled = handler.onIdleTimeout(connection);
if (!isHandled) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] closing connection because idle timeout has been occured and timeout handler returns true)");
}
closeSilence(connection);
}
} catch (MaxReadSizeExceededException mee) {
LOG.warning("[" + connection.getId() + "] closing connection because max readsize is reached by handling onIdleTimeout by appHandler. " + printHandler(handler) + " Reason: " + mee.toString());
closeSilence(connection);
} catch (BufferUnderflowException bue) {
// ignore
} catch (IOException ioe) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] closing connection. An IO exception occured while performing onIdleTimeout multithreaded " + printHandler(handler) + " " + ioe.toString());
}
closeSilence(connection);
} catch (Throwable t) {
LOG.warning("[" + connection.getId() + "] closing connection. Error occured by performing onIdleTimeout of " + printHandler(handler) + " " + t.toString());
closeSilence(connection);
}
}
public boolean onConnectionTimeout(INonBlockingConnection connection, SerializedTaskQueue taskQueue, Executor workerpool) throws IOException {
if (handlerInfo.isConnectionTimeoutHandler()) {
if (handlerInfo.isUnsynchronized()) {
performOnConnectionTimeout(connection, taskQueue, (IConnectionTimeoutHandler) handler);
} else {
if (getHandlerInfo().isConnectionTimeoutHandlerMultithreaded()) {
taskQueue.performMultiThreaded(new PerformOnConnectionTimeoutTask(connection, taskQueue, (IConnectionTimeoutHandler) handler), workerpool);
} else {
taskQueue.performNonThreaded(new PerformOnConnectionTimeoutTask(connection, taskQueue, (IConnectionTimeoutHandler) handler), workerpool);
}
}
} else {
closeSilence(connection);
}
return true;
}
private static final class PerformOnConnectionTimeoutTask implements Runnable {
private final IConnectionTimeoutHandler handler;
private final INonBlockingConnection connection;
private final SerializedTaskQueue taskQueue;
public PerformOnConnectionTimeoutTask(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IConnectionTimeoutHandler handler) {
this.connection = connection;
this.taskQueue = taskQueue;
this.handler = handler;
}
public void run() {
performOnConnectionTimeout(connection, taskQueue, handler);
}
}
private static void performOnConnectionTimeout(INonBlockingConnection connection, SerializedTaskQueue taskQueue, IConnectionTimeoutHandler handler) {
try {
boolean isHandled = handler.onConnectionTimeout(connection);
if (!isHandled) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("[" + connection.getId() + "] closing connection because connection timeout has been occured and timeout handler returns true)");
}
closeSilence(connection);
}
} catch (MaxReadSizeExceededException mee) {
LOG.warning("[" + connection.getId() + "] closing connection because max readsize hasbeen reached by handling onConnectionTimeout by appHandler. " + printHandler(handler) + " Reason: " + mee.toString());
closeSilence(connection);
} catch (BufferUnderflowException bue) {
// ignore
} catch (IOException ioe) {
LOG.warning("[" + connection.getId() + "] closing connection because an error has been occured by handling onConnectionTimeout by appHandler. " + handler + " Reason: " + ioe.toString());
closeSilence(connection);
} catch (Throwable t) {
LOG.warning("[" + connection.getId() + "] closing connection. Error occured by performing onConnectionTimeout of " + printHandler(handler) + " " + t.toString());
closeSilence(connection);
}
}
public final void onInit() {
if (handlerInfo.isLifeCycle()) {
((ILifeCycle) handler).onInit();
}
}
public final void onDestroy() {
if (handlerInfo.isLifeCycle()) {
try {
((ILifeCycle) handler).onDestroy();
} catch (IOException ioe) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("exception occured by destroying " + printHandler(handler) + " " + ioe.toString());
}
}
}
}
HandlerAdapter getConnectionInstance() {
if (handlerInfo.isConnectionScoped()) {
try {
IHandler hdlCopy = (IHandler) ((IConnectionScoped) handler).clone();
return new HandlerAdapter(hdlCopy, handlerInfo);
} catch (CloneNotSupportedException cnse) {
throw new RuntimeException(cnse.toString());
}
} else {
return this;
}
}
private static void closeSilence(INonBlockingConnection connection) {
try {
connection.close();
} catch (Exception e) {
// eat and log exception
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("error occured by closing connection " + connection + " " + e.toString());
}
}
}
@Execution(Execution.NONTHREADED)
private static final class NullHandler implements IHandler {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy