// Path: jflask/src/main/java/net/jflask/ErrorHandler.java
// public interface ErrorHandler {
//   /**
//    * Handles an error (either a 404 error due to invalid URL or a 500 error
//    * due to an exception thrown by a handler).
//    *
//    * @param status the request status sent back to client
//    * @param request the request sent by client
//    * @param t optional error (null in case of 404)
//    */
//   void onError(int status, Request request, Throwable t);
// }
// 
// Path: jflask/src/main/java/net/jflask/Request.java
// public interface Request {
// 
//   /**
//    * Returns the part of this request's URL from the protocol name up to the
//    * query string in the first line of the HTTP request.
//    */
//   String getRequestURI();
// 
//   /**
//    * Returns the query string contained in request URL after the path. This
//    * method returns <code>null</code> if the URL does not have a query string.
//    * Same as the value of the CGI variable QUERY_STRING.
//    *
//    * @return a <code>String</code> containing the query string or
//    *         <code>null</code> if the URL contains no query string
//    */
// 
//   String getQueryString();
//   
//   /**
//    * Returns the HTTP verb (GET, POST, etc.) used in the request.
//    */
//   String getMethod();
// 
//   /**
//    * Returns parameter submitted in the query string, eg. if URL =
//    * "...?key=value", getArg("key", null) returns "value".
//    *
//    * @param name
//    * @param def the default value to return if specified parameter in unset
//    * @return the parameter found in the query string or specified default value
//    */
//   String getArg(String name, String def);
// 
//   /**
//    * Returns a field from form data (only valid for POST requests).
//    */
//   String getForm(String field);
// 
//   /**
//    * Returns a list containing all occurrences of a given parameter in query
//    * string, or an empty list if none is found.
//    *
//    * @param name the parameter's name
//    */
//   List<String> getArgs(String name);
// 
//   InputStream getInputStream();
// }
// 
// Path: jflask/src/main/java/net/jflask/SunRequest.java
// public class SunRequest implements Request, Response {
// 
//   private final HttpExchange exchange;
// 
//   private final int qsMark;
// 
//   private final String uri;
// 
//   private String form;
// 
//   public SunRequest(HttpExchange r) {
//     this.exchange = r;
//     this.uri = r.getRequestURI().toString();
//     this.qsMark = uri.indexOf('?');
//   }
// 
//   public String getRequestURI() {
//     return qsMark >= 0 ? uri.substring(0, qsMark) : uri;
//   }
// 
//   public String getQueryString() {
//     return qsMark >= 0 ? uri.substring(qsMark + 1) : null;
//   }
// 
//   public HttpExchange getExchange() {
//     return exchange;
//   }
// 
//   public String getMethod() {
//     return exchange.getRequestMethod();
//   }
// 
//   public String getArg(String name, String def) {
//     if (qsMark == -1)
//       return def;
//     return parseArg(name, def, getQueryString());
//   }
// 
//   private String parseArg(String name, String def, String encoded) {
//     String[] tok = encoded.split("&");
//     for (String s : tok) {
//       if (s.startsWith(name)) {
//         if (s.length() > name.length() && s.charAt(name.length()) == '=')
//           return s.substring(name.length() + 1);
//       }
//     }
//     return def;
//   }
// 
//   @Override
//   public String getForm(String field) {
//     try {
//       if (form == null)
//         form = new String(IO.readFully(getInputStream()));
//       return parseArg(field, null, form);
//     }
//     catch (IOException e) {
//       throw new RuntimeException(e);
//     }
//   }
// 
//   public List<String> getArgs(String name) {
//     // TODO
//     return null;
//   }
// 
//   public InputStream getInputStream() {
//     return exchange.getRequestBody();
//   }
// 
//   // /////////// Response methods
// 
//   public void addHeader(String header, String value) {
//     exchange.getResponseHeaders().add(header, value);
//   }
// 
//   public void setStatus(int status) {
//     try {
//       exchange.sendResponseHeaders(status, 0);
//     }
//     catch (IOException e) {
//       throw new RuntimeException(e);
//     }
//   }
// 
//   public OutputStream getOutputStream() {
//     return exchange.getResponseBody();
//   }
// 
// }
// 
// Path: jflask/src/test/java/net/jflask/test/util/HttpException.java
// public class HttpException extends RuntimeException {
//   private final int responseCode;
// 
//   public HttpException(int responseCode, String message) {
//     super(message);
//     this.responseCode = responseCode;
//   }
// 
//   public int getResponseCode() {
//     return responseCode;
//   }
// }


import java.io.IOException;
import com.sun.net.httpserver.HttpExchange;
import net.jflask.ErrorHandler;
import net.jflask.Request;
import net.jflask.Route;
import net.jflask.SunRequest;
import net.jflask.test.util.HttpException;
import org.junit.Assert;
import org.junit.Test;
package net.jflask.test;



/**
 * @author pcdv
 */
public class ErrorHandlerTest extends AbstractAppTest {

  @Route("/")
  public String foo() {
    throw new IllegalStateException("fail");
  }

  /**
   * Check that a error handler can customize the response sent to the client.
   */
  @Test
  public void testHandlerSendsContent() throws Exception {
    app.addErrorHandler(new ErrorHandler() {
      @Override
      public void onError(int status, Request request, Throwable t) {
        // this is a hack (future version should allow to do it in a clean way)
        HttpExchange ex = ((SunRequest) request).getExchange();
        try {
          ex.sendResponseHeaders(555, 0);
          ex.getResponseBody().write("hello".getBytes());
          ex.close();
        }
        catch (IOException ignored) {
        }
      }
    });

    try {
      client.get("/");
    }
// Path: jflask/src/main/java/net/jflask/ErrorHandler.java
// public interface ErrorHandler {
//   /**
//    * Handles an error (either a 404 error due to invalid URL or a 500 error
//    * due to an exception thrown by a handler).
//    *
//    * @param status the request status sent back to client
//    * @param request the request sent by client
//    * @param t optional error (null in case of 404)
//    */
//   void onError(int status, Request request, Throwable t);
// }
// 
// Path: jflask/src/main/java/net/jflask/Request.java
// public interface Request {
// 
//   /**
//    * Returns the part of this request's URL from the protocol name up to the
//    * query string in the first line of the HTTP request.
//    */
//   String getRequestURI();
// 
//   /**
//    * Returns the query string contained in request URL after the path. This
//    * method returns <code>null</code> if the URL does not have a query string.
//    * Same as the value of the CGI variable QUERY_STRING.
//    *
//    * @return a <code>String</code> containing the query string or
//    *         <code>null</code> if the URL contains no query string
//    */
// 
//   String getQueryString();
//   
//   /**
//    * Returns the HTTP verb (GET, POST, etc.) used in the request.
//    */
//   String getMethod();
// 
//   /**
//    * Returns parameter submitted in the query string, eg. if URL =
//    * "...?key=value", getArg("key", null) returns "value".
//    *
//    * @param name
//    * @param def the default value to return if specified parameter in unset
//    * @return the parameter found in the query string or specified default value
//    */
//   String getArg(String name, String def);
// 
//   /**
//    * Returns a field from form data (only valid for POST requests).
//    */
//   String getForm(String field);
// 
//   /**
//    * Returns a list containing all occurrences of a given parameter in query
//    * string, or an empty list if none is found.
//    *
//    * @param name the parameter's name
//    */
//   List<String> getArgs(String name);
// 
//   InputStream getInputStream();
// }
// 
// Path: jflask/src/main/java/net/jflask/SunRequest.java
// public class SunRequest implements Request, Response {
// 
//   private final HttpExchange exchange;
// 
//   private final int qsMark;
// 
//   private final String uri;
// 
//   private String form;
// 
//   public SunRequest(HttpExchange r) {
//     this.exchange = r;
//     this.uri = r.getRequestURI().toString();
//     this.qsMark = uri.indexOf('?');
//   }
// 
//   public String getRequestURI() {
//     return qsMark >= 0 ? uri.substring(0, qsMark) : uri;
//   }
// 
//   public String getQueryString() {
//     return qsMark >= 0 ? uri.substring(qsMark + 1) : null;
//   }
// 
//   public HttpExchange getExchange() {
//     return exchange;
//   }
// 
//   public String getMethod() {
//     return exchange.getRequestMethod();
//   }
// 
//   public String getArg(String name, String def) {
//     if (qsMark == -1)
//       return def;
//     return parseArg(name, def, getQueryString());
//   }
// 
//   private String parseArg(String name, String def, String encoded) {
//     String[] tok = encoded.split("&");
//     for (String s : tok) {
//       if (s.startsWith(name)) {
//         if (s.length() > name.length() && s.charAt(name.length()) == '=')
//           return s.substring(name.length() + 1);
//       }
//     }
//     return def;
//   }
// 
//   @Override
//   public String getForm(String field) {
//     try {
//       if (form == null)
//         form = new String(IO.readFully(getInputStream()));
//       return parseArg(field, null, form);
//     }
//     catch (IOException e) {
//       throw new RuntimeException(e);
//     }
//   }
// 
//   public List<String> getArgs(String name) {
//     // TODO
//     return null;
//   }
// 
//   public InputStream getInputStream() {
//     return exchange.getRequestBody();
//   }
// 
//   // /////////// Response methods
// 
//   public void addHeader(String header, String value) {
//     exchange.getResponseHeaders().add(header, value);
//   }
// 
//   public void setStatus(int status) {
//     try {
//       exchange.sendResponseHeaders(status, 0);
//     }
//     catch (IOException e) {
//       throw new RuntimeException(e);
//     }
//   }
// 
//   public OutputStream getOutputStream() {
//     return exchange.getResponseBody();
//   }
// 
// }
// 
// Path: jflask/src/test/java/net/jflask/test/util/HttpException.java
// public class HttpException extends RuntimeException {
//   private final int responseCode;
// 
//   public HttpException(int responseCode, String message) {
//     super(message);
//     this.responseCode = responseCode;
//   }
// 
//   public int getResponseCode() {
//     return responseCode;
//   }
// }


// Path: jflask/src/test/java/net/jflask/test/ErrorHandlerTest.java
import java.io.IOException;
import com.sun.net.httpserver.HttpExchange;
import net.jflask.ErrorHandler;
import net.jflask.Request;
import net.jflask.Route;
import net.jflask.SunRequest;
import net.jflask.test.util.HttpException;
import org.junit.Assert;
import org.junit.Test;

package net.jflask.test;



/**
 * @author pcdv
 */
public class ErrorHandlerTest extends AbstractAppTest {

  @Route("/")
  public String foo() {
    throw new IllegalStateException("fail");
  }

  /**
   * Check that a error handler can customize the response sent to the client.
   */
  @Test
  public void testHandlerSendsContent() throws Exception {
    app.addErrorHandler(new ErrorHandler() {
      @Override
      public void onError(int status, Request request, Throwable t) {
        // this is a hack (future version should allow to do it in a clean way)
        HttpExchange ex = ((SunRequest) request).getExchange();
        try {
          ex.sendResponseHeaders(555, 0);
          ex.getResponseBody().write("hello".getBytes());
          ex.close();
        }
        catch (IOException ignored) {
        }
      }
    });

    try {
      client.get("/");
    }
    catch (HttpException e) {