package com.yammer.dropwizard.jetty;

import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * An {@link ErrorHandler} subclass which returns concise, {@code text/plain} error messages.
 */
public class QuietErrorHandler extends ErrorHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(QuietErrorHandler.class);

    /*
     * Sadly, this class is basically untestable.
     */
    private static final ImmutableSet<String> ALLOWED_METHODS = ImmutableSet.of(
            HttpMethods.GET, HttpMethods.HEAD, HttpMethods.POST, HttpMethods.PUT, HttpMethods.DELETE
    );

    @Override
    public void handle(String target,
                       Request baseRequest,
                       HttpServletRequest request,
                       HttpServletResponse response) throws IOException {
        final AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection();
        final Response jettyResponse = connection.getResponse();
        jettyResponse.setStatus(jettyResponse.getStatus());

        connection.getRequest().setHandled(true);
        final String method = request.getMethod();
        
        if (!ALLOWED_METHODS.contains(method)) {
            return;
        }

        response.setContentType(MimeTypes.TEXT_PLAIN_UTF_8);
        if (getCacheControl() != null) {
            response.setHeader(HttpHeaders.CACHE_CONTROL, getCacheControl());
        }

        final StringBuilder builder = new StringBuilder(4096);
        builder.append(errorMessage(request, jettyResponse.getStatus())).append('\n').append('\n');
        final byte[] bytes = builder.toString().getBytes(Charsets.UTF_8);
        response.setContentLength(bytes.length);
        final ServletOutputStream output = response.getOutputStream();
        try {
            output.write(bytes);
        } finally {
            output.close();
        }
    }

    private static String errorMessage(HttpServletRequest request, int status) {
        try {
            final ResourceBundle bundle = ResourceBundle.getBundle("HttpErrorMessages",
                                                                   request.getLocale());
            final String message = bundle.getString(Integer.toString(status));
            if (message != null) {
                final MessageFormat format = new MessageFormat(message, request.getLocale());
                return format.format(new Object[]{request.getMethod()});
            }
        } catch (MissingResourceException e) {
            LOGGER.error("Unable to load HttpErrorMessages.properties", e);
        }
        return "Your request could not be processed: " + HttpGenerator.getReasonBuffer(status);
    }
}

@@ -1059,16 +1059,74 @@
 .class);
+%0A    private static final int RESPONSE_BUFFER_SIZE = 4096;
 %0A%0A    /*
@@ -1688,24 +1688,116 @@
 nnection();%0A
+        if (connection != null) %7B%0A            connection.getRequest().setHandled(true);%0A    
         fina
@@ -1857,16 +1857,20 @@
         
+ 
+   
 jettyRes
@@ -1914,32 +1914,36 @@
 us());%0A%0A        
+    
 connection.getRe
@@ -1968,32 +1968,36 @@
 (true);%0A        
+ 
+   
 final String met
@@ -2027,25 +2027,21 @@
 ();%0A
-   
+%0A
      
-%0A
        
- 
 if (
@@ -2085,24 +2085,28 @@
             
+    
 return;%0A    
@@ -2101,35 +2101,43 @@
 return;%0A        
+   
+ 
 %7D%0A%0A
+    
         response
@@ -2185,24 +2185,28 @@
 8);%0A        
+  
+  
 if (getCache
@@ -2218,32 +2218,36 @@
 ol() != null) %7B%0A
+    
             resp
@@ -2308,35 +2308,43 @@
 rol());%0A        
+  
+  
 %7D%0A%0A
+    
         final St
@@ -2387,15 +2387,35 @@
 der(
-4096);%0A
+RESPONSE_BUFFER_SIZE);%0A    
     
@@ -2482,29 +2482,69 @@
 atus()))
-.append('%5Cn')
+%0A                   .append('%5Cn')%0A                   
 .append(
@@ -2550,16 +2550,20 @@
 ('%5Cn');%0A
+    
         
@@ -2628,32 +2628,36 @@
 UTF_8);%0A        
+    
 response.setCont
@@ -2685,24 +2685,28 @@
 h);%0A        
+   
+ 
 final Servle
@@ -2756,32 +2756,36 @@
 ream();%0A        
+    
 try %7B%0A          
@@ -2782,24 +2782,28 @@
             
+   
+ 
 output.write
@@ -2819,16 +2819,20 @@
         
+    
 %7D finall
@@ -2843,24 +2843,28 @@
             
+   
+ 
 output.close
@@ -2863,24 +2863,38 @@
 ut.close();%0A
+            %7D%0A
         %7D%0A  

Make sure we're not throwing NPEs during shutdown.