/*
* MockWebSocketResponseHandler.java
*
* Created on Jan 30, 2012, 12:20:45 PM
*
* Description: .
*
* Copyright (C) Jan 30, 2012, Stephen L. Reed, Texai.org.
*
*/
package org.texai.network.netty.handler;
import net.jcip.annotations.NotThreadSafe;
import org.apache.log4j.Logger;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame;
import org.jboss.netty.util.CharsetUtil;
import org.texai.util.StringUtils;
import org.texai.util.TexaiException;
/**
*
* @author reed
*/
@NotThreadSafe
public class MockWebSocketResponseHandler extends AbstractWebSocketResponseHandler {
/** the logger */
private static final Logger LOGGER = Logger.getLogger(MockWebSocketResponseHandler.class);
/** the web socket client handshaker */
private final WebSocketClientHandshaker webSocketClientHandshaker;
/** the synchronization lock to resume the client when the handshake is completed */
final Object clientResume_lock;
/** Constructs a new MockWebSocketResponseHandler instance.
*
* @param webSocketClientHandshaker the web socket client handshaker
* @param clientResume_lock the synchronization lock to resume the client when the handshake is completed
*/
public MockWebSocketResponseHandler(
final WebSocketClientHandshaker webSocketClientHandshaker,
final Object clientResume_lock) {
//Preconditions
assert webSocketClientHandshaker != null : "webSocketClientHandshaker must not be null";
assert clientResume_lock != null : "clientResume_lock must not be null";
this.webSocketClientHandshaker = webSocketClientHandshaker;
this.clientResume_lock = clientResume_lock;
}
/** Handles a received web socket message.
*
* @param channelHandlerContext the channel handler context
* @param messageEvent the message event
* @throws Exception when an exception occurs
*/
@Override
public void messageReceived(
final ChannelHandlerContext channelHandlerContext,
final MessageEvent messageEvent) throws Exception {
//Preconditions
assert channelHandlerContext != null : "channelHandlerContext must not be null";
assert messageEvent != null : "messageEvent must not be null";
final Channel channel = channelHandlerContext.getChannel();
if (!webSocketClientHandshaker.isHandshakeComplete()) {
LOGGER.info("finishing web socket client handshake");
webSocketClientHandshaker.finishHandshake(channel, (HttpResponse) messageEvent.getMessage());
LOGGER.info("web socket client handshake completed");
synchronized (clientResume_lock) {
// resume the waiting client thread
clientResume_lock.notify();
}
return;
}
LOGGER.info("received " + messageEvent.getMessage().getClass().getSimpleName());
if (messageEvent.getMessage() instanceof HttpResponse) {
final HttpResponse httpResponse = (HttpResponse) messageEvent.getMessage();
throw new TexaiException("Unexpected HttpResponse (status=" + httpResponse.getStatus() + ", content="
+ httpResponse.getContent().toString(CharsetUtil.UTF_8) + ")");
}
final WebSocketFrame webSocketFrame = (WebSocketFrame) messageEvent.getMessage();
if (webSocketFrame instanceof TextWebSocketFrame) {
TextWebSocketFrame textWebSocketFrame = (TextWebSocketFrame) webSocketFrame;
LOGGER.info("web socket client received message: " + textWebSocketFrame.getText());
} else if (webSocketFrame instanceof PongWebSocketFrame) {
LOGGER.info("web socket client received pong");
} else if (webSocketFrame instanceof CloseWebSocketFrame) {
LOGGER.info("web socket client received closing");
channel.close();
}
}
/** Closes the channel.
*
* @param channelHandlerContext the channel handler context
* @param channelStateEvent the channel state event
* @throws Exception when an exception occurs
*/
@Override
public void channelClosed(
final ChannelHandlerContext channelHandlerContext,
final ChannelStateEvent channelStateEvent) throws Exception {
LOGGER.info("web socket client disconnected");
}
/** Catches an otherwise uncaught exception.
*
* @param channelHandlerContext the channel handler context
* @param exceptionEvent
* @throws Exception
*/
@Override
public void exceptionCaught(
final ChannelHandlerContext channelHandlerContext,
final ExceptionEvent exceptionEvent) throws Exception {
//Preconditions
assert channelHandlerContext != null : "channelHandlerContext must not be null";
assert exceptionEvent != null : "exceptionEvent must not be null";
LOGGER.info(StringUtils.getStackTraceAsString(exceptionEvent.getCause()));
exceptionEvent.getChannel().close();
}
}