package viper.net.server.chunkproxy;


import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
import static org.jboss.netty.handler.codec.http.HttpMethod.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;

import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import javax.ws.rs.Path;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.frame.TooLongFrameException;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.util.CharsetUtil;

import java.io.*;
import java.net.*;
import java.util.concurrent.ConcurrentHashMap;

import viper.net.server.Util;


/**
 * A file server that can serve files from file system and class path.
 * <p/>
 * If you wish to customize the error message, please sub-class and override sendError().
 * Based on Trustin Lee's original file serving example
 */
public class StaticFileServerHandler extends SimpleChannelUpstreamHandler
{
  private final FileContentInfoProvider _fileCache;

  public StaticFileServerHandler(FileContentInfoProvider fileCache)
  {
    _fileCache = fileCache;
  }

  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
    throws Exception
  {
    HttpRequest request = (HttpRequest) e.getMessage();
    if (request.getMethod() != GET)
    {
      sendError(ctx, METHOD_NOT_ALLOWED);
      return;
    }

    String uri = request.getUri();

    final String path = Util.sanitizeUri(uri);
    if (path == null)
    {
      sendError(ctx, FORBIDDEN);
      return;
    }

    FileContentInfo contentInfo = _fileCache.getFileContent(path);

    DefaultHttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
    response.setHeader(HttpHeaders.Names.CONTENT_TYPE, contentInfo.contentType);
    setContentLength(response, contentInfo.content.readableBytes());
    response.setContent(contentInfo.content);
    ChannelFuture writeFuture = e.getChannel().write(response);

    if (!isKeepAlive(request))
    {
      writeFuture.addListener(ChannelFutureListener.CLOSE);
    }
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
    throws Exception
  {
    Channel ch = e.getChannel();
    Throwable cause = e.getCause();
    if (cause instanceof TooLongFrameException)
    {
      sendError(ctx, BAD_REQUEST);
      return;
    }

    cause.printStackTrace();
    if (ch.isConnected())
    {
      sendError(ctx, INTERNAL_SERVER_ERROR);
    }
  }

  private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status)
  {
    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
    response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
    response.setContent(ChannelBuffers.copiedBuffer("Failure: " + status.toString() + "\r\n", CharsetUtil.UTF_8));

    // Close the connection as soon as the error message is sent.
    ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
  }
}

@@ -2404,24 +2404,121 @@
 t(path);%0D%0A%0D%0A
+    if (contentInfo == null)%0D%0A    %7B%0D%0A      sendError(ctx, NOT_FOUND);%0D%0A    %7D%0D%0A    else%0D%0A    %7B%0D%0A  
     DefaultH
@@ -2576,24 +2576,26 @@
 _1_1, OK);%0D%0A
+  
     response
@@ -2668,16 +2668,18 @@
 );%0D%0A    
+ 
+ 
 setConte
@@ -2732,32 +2732,34 @@
 eBytes());%0D%0A    
+  
 response.setCont
@@ -2785,24 +2785,26 @@
 tent);%0D%0A    
+ 
+ 
 ChannelFutur
@@ -2848,30 +2848,30 @@
 response);%0D%0A
-%0D%0A
     
+  
 if (!isKeepA
@@ -2886,27 +2886,31 @@
 uest))%0D%0A    
+  
 %7B%0D%0A
+  
       writeF
@@ -2954,24 +2954,33 @@
 er.CLOSE);%0D%0A
+      %7D%0D%0A
     %7D%0D%0A  %7D%0D%0A

fix npe