package dgm.streaming; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.*; import org.jboss.netty.handler.codec.http.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dgm.streaming.blueprints.GraphCommandListener; import dgm.streaming.blueprints.StreamingGraph; import dgm.streaming.requestmapper.ChannelContext; import dgm.streaming.requestmapper.HttpRequestMapper; import dgm.streaming.requestmapper.RequestHandlerException; import dgm.streaming.requestmapper.handlers.GlobalCommandStreamRequestHandler; import java.nio.charset.Charset; import java.util.List; public final class GraphStreamerHttpHandler extends SimpleChannelHandler { private static final Logger LOGGER = LoggerFactory.getLogger(GraphStreamerHttpHandler.class); private final HttpRequestMapper requestMapper; private final ChannelContext channelContext; private final StreamingGraph streamingGraph; public GraphStreamerHttpHandler(HttpRequestMapper requestMapper, ChannelContext channelContext, StreamingGraph streamingGraph) { this.requestMapper = requestMapper; this.channelContext = channelContext; this.streamingGraph = streamingGraph; } @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { LOGGER.debug("Connection received from"); } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (HttpRequest.class.isAssignableFrom(e.getMessage().getClass())) { HttpRequest request = (HttpRequest) e.getMessage(); Channel channel = e.getChannel(); try { requestMapper.handleRequest(request, channel); } catch (RequestHandlerException rhe) { String errorMessage = "Can not handle request [" + request.getUri() + "]. Reason: " + rhe.getMessage(); LOGGER.error(errorMessage); channel.write(createErrorResponse(rhe)); channel.close(); } } } private HttpResponse createErrorResponse(RequestHandlerException rhe) { HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, rhe.getStatus()); response.setContent(ChannelBuffers.wrappedBuffer(rhe.getMessage().getBytes(Charset.forName("UTF-8")))); return response; } @Override public void channelClosed(ChannelHandlerContext ctx, final ChannelStateEvent event) throws Exception { //TODO: somehow this stuff should be moved into the HttpRequestMapper.RequestHandler interface, so the handlers can 'clean up their own mess'. //now this channel closes, remove it from the context, no more writing to it. channelContext.removeChannel(event.getChannel()); //we also have to check if a streaming.requestmapper.handlers.GlobalCommandStreamRequestHandler.ChannelpushingGraphCommandListener //has been registered for this channel, if so: remove that listener List<GraphCommandListener> listener = streamingGraph.findListeners(new StreamingGraph.GraphCommandListenerFilter() { @Override public boolean matches(GraphCommandListener listener) { if (GlobalCommandStreamRequestHandler.ChannelpushingGraphCommandListener.class.isAssignableFrom(listener.getClass())) { GlobalCommandStreamRequestHandler.ChannelpushingGraphCommandListener channelPushingListener = (GlobalCommandStreamRequestHandler.ChannelpushingGraphCommandListener) listener; if (channelPushingListener.getChannel().equals(event.getChannel())) return true; } return false; } }); if (listener.size() > 0) { //there shouldn't be more than one if(listener.size() > 1) LOGGER.warn("There is more than one ChannelpushingGraphCommandListener registered with the StreamingGraph for channel " + event.getChannel()); streamingGraph.removeGraphCommandListener(listener.get(0)); LOGGER.debug("ChannelpushingGraphCommandListener removed for channel [{}] on account of the fact this channel is closing", event.getChannel()); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { //TODO handle this stuff. } }