/**
   * Override this to customize the server.
   *
   * <p>
   *
   * <p>(By default, this delegates to serveFile() and allows directory listing.)
   *
   * @param session The HTTP session
   * @return HTTP response, see class Response for details
   */
  public Response serve(IHTTPSession session) {
    Map<String, String> files = new HashMap<String, String>();
    Method method = session.getMethod();
    if (Method.PUT.equals(method) || Method.POST.equals(method)) {
      try {
        session.parseBody(files);
      } catch (IOException ioe) {
        return new Response(
            Response.Status.INTERNAL_ERROR,
            MIME_PLAINTEXT,
            "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
      } catch (ResponseException re) {
        return new Response(re.getStatus(), MIME_PLAINTEXT, re.getMessage());
      }
    }

    Map<String, String> parms = session.getParms();
    parms.put(QUERY_STRING_PARAMETER, session.getQueryParameterString());
    return serve(session.getUri(), method, session.getHeaders(), parms, files);
  }
    @Override
    public void parseBody(Map<String, String> files) throws IOException, ResponseException {
      RandomAccessFile randomAccessFile = null;
      BufferedReader in = null;
      try {

        randomAccessFile = getTmpBucket();

        long size;
        if (headers.containsKey("content-length")) {
          size = Integer.parseInt(headers.get("content-length"));
        } else if (splitbyte < rlen) {
          size = rlen - splitbyte;
        } else {
          size = 0;
        }

        // Now read all the body and write it to f
        byte[] buf = new byte[512];
        while (rlen >= 0 && size > 0) {
          rlen = inputStream.read(buf, 0, (int) Math.min(size, 512));
          size -= rlen;
          if (rlen > 0) {
            randomAccessFile.write(buf, 0, rlen);
          }
        }

        // Get the raw body as a byte []
        ByteBuffer fbuf =
            randomAccessFile
                .getChannel()
                .map(FileChannel.MapMode.READ_ONLY, 0, randomAccessFile.length());
        randomAccessFile.seek(0);

        // Create a BufferedReader for easily reading it as string.
        InputStream bin = new FileInputStream(randomAccessFile.getFD());
        in = new BufferedReader(new InputStreamReader(bin));

        // If the method is POST, there may be parameters
        // in data section, too, read it:
        if (Method.POST.equals(method)) {
          String contentType = "";
          String contentTypeHeader = headers.get("content-type");

          StringTokenizer st = null;
          if (contentTypeHeader != null) {
            st = new StringTokenizer(contentTypeHeader, ",; ");
            if (st.hasMoreTokens()) {
              contentType = st.nextToken();
            }
          }

          if ("multipart/form-data".equalsIgnoreCase(contentType)) {
            // Handle multipart/form-data
            if (!st.hasMoreTokens()) {
              throw new ResponseException(
                  Response.Status.BAD_REQUEST,
                  "BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html");
            }

            String boundaryStartString = "boundary=";
            int boundaryContentStart =
                contentTypeHeader.indexOf(boundaryStartString) + boundaryStartString.length();
            String boundary =
                contentTypeHeader.substring(boundaryContentStart, contentTypeHeader.length());
            if (boundary.startsWith("\"") && boundary.endsWith("\"")) {
              boundary = boundary.substring(1, boundary.length() - 1);
            }

            decodeMultipartData(boundary, fbuf, in, parms, files);
          } else {
            String postLine = "";
            StringBuilder postLineBuffer = new StringBuilder();
            char pbuf[] = new char[512];
            int read = in.read(pbuf);
            while (read >= 0 && !postLine.endsWith("\r\n")) {
              postLine = String.valueOf(pbuf, 0, read);
              postLineBuffer.append(postLine);
              read = in.read(pbuf);
            }
            postLine = postLineBuffer.toString().trim();
            // Handle application/x-www-form-urlencoded
            if ("application/x-www-form-urlencoded".equalsIgnoreCase(contentType)) {
              decodeParms(postLine, parms);
            } else if (postLine.length() != 0) {
              // Special case for raw POST data => create a
              // special files entry "postData" with raw content
              // data
              files.put("postData", postLine);
            }
          }
        } else if (Method.PUT.equals(method)) {
          files.put("content", saveTmpFile(fbuf, 0, fbuf.limit()));
        }
      } finally {
        safeClose(randomAccessFile);
        safeClose(in);
      }
    }