<commit_before>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

package foam.nanos.http;

import foam.core.X;
import foam.nanos.http.Command;
import foam.nanos.http.Format;
import foam.nanos.http.HttpParameters;
import foam.nanos.logger.Logger;
import foam.nanos.logger.PrefixLogger;
import foam.util.SafetyUtil;
import java.io.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HttpParametersWebAgent
  extends ProxyWebAgent
{
  public static final int BUFFER_SIZE = 4096;

  protected static ThreadLocal<StringBuilder> sb = new ThreadLocal<StringBuilder>() {
    @Override
    protected StringBuilder initialValue() {
      return new StringBuilder();
    }

    @Override
    public StringBuilder get() {
      StringBuilder b = super.get();
      b.setLength(0);
      return b;
    }
  };

  protected Class parametersClass = DefaultHttpParameters.class;

  public HttpParametersWebAgent() {}
  public HttpParametersWebAgent(WebAgent delegate) {
    setDelegate(delegate);
  }

  public HttpParametersWebAgent(String parametersClassName, WebAgent delegate) {
    setParametersClass(parametersClassName);
    setDelegate(delegate);
  }

  public void setParametersClass(String parametersClassName) {
    try {
      this.parametersClass = Class.forName(parametersClassName);
    } catch (ClassNotFoundException exception) {
      throw new RuntimeException(exception);
    }
  }

  public void execute(X x) {
    Logger              logger = (Logger) x.get("logger");
    HttpServletRequest  req    = x.get(HttpServletRequest.class);
    HttpServletResponse resp   = x.get(HttpServletResponse.class);

    logger = new PrefixLogger(new Object[] { this.getClass().getSimpleName() }, logger);

    if ( req == null || resp == null ) {
      logger.error(new java.lang.IllegalArgumentException("Context missing HttpServletRequest, HttpServletResponse"));
      return;
    }

    String         methodName      = req.getMethod();
    String         accept          = req.getHeader("Accept");
    String         contentType     = req.getHeader("Content-Type");
    HttpParameters parameters      = null;
    Command        command         = null;
    String         cmd             = req.getParameter("cmd");

    logger.debug("methodName", methodName);

    try {
      parameters = (HttpParameters) x.create(this.parametersClass);
    } catch (ClassCastException exception) {
      throw new RuntimeException(exception);
    }

    // Capture 'data' on all requests
    if ( ! SafetyUtil.isEmpty(req.getParameter("data")) ) {
      logger.debug("data", req.getParameter("data"));
      logger.debug("cmd", req.getParameter("cmd"));
      logger.debug("format", req.getParameter("format"));

      parameters.set("data", req.getParameter("data"));
    } else {
      //
      // When content-type is other than application/x-www-form-urlencoded, the
      // HttpServletRequest.reader stream must be processes manually to extract
      // parameters from the body.
      //
      // Future considerations for partial parameters in the POST URI
      // see examples: https://technologyconversations.com/2014/08/12/rest-api-with-json/
      //
      try {

        int read   = 0;
        int count  = 0;
        int length = req.getContentLength();

        StringBuilder  builder = sb.get();
        char[] cbuffer = new char[BUFFER_SIZE];
        BufferedReader reader  = new BufferedReader(new InputStreamReader(req.getInputStream()));

        while ( ( read = reader.read(cbuffer, 0, BUFFER_SIZE)) != -1 && count < length ) {
          builder.append(cbuffer, 0, read);
          count += read;
        }
        logger.debug("reader data:", builder.toString());
        if ( ! SafetyUtil.isEmpty(builder.toString()) ) {
          parameters.set("data", builder.toString());
        }
      } catch (IOException e) {
        try {
          resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Failed to parse body/data.");
        } catch (IOException ioe) {
          // nop
        }
        return;
      }
    }

    if ( ! "application/x-www-form-urlencoded".equals(contentType) ) {
      if ( ! SafetyUtil.isEmpty(cmd) ) {
        switch ( cmd.toLowerCase() ) {
          case "put":
            command = Command.put;
            break;
          case "select":
            command = Command.select;
            if ( ! SafetyUtil.isEmpty(req.getParameter("id")) ) {
              parameters.set("id", req.getParameter("id"));
              logger.debug("id", req.getParameter("id"));
            }
            break;
          case "remove":
            command = Command.remove;
            parameters.set("id", req.getParameter("id"));
            logger.debug("id", req.getParameter("id"));
            break;
        }
      } else {
        switch ( methodName.toUpperCase() ) {
          case "POST":
            command = Command.put;
            break;
          case "PUT":
            command = Command.put;
            break;
          case "DELETE":
            command = Command.remove;
            break;
          case "GET":
            command = Command.remove;
            break;
          default:
            logger.warning("cmd/method could not be determined, defaulting to SELECT.");
            break;
        }
      }


//      switch ( methodName.toUpperCase() ) {
//        case "POST":
//          command = Command.put;
//          break;
//        case "PUT":
//          command = Command.put;
//          break;<commit_msg>set and modified HTTP POST PUT DELETE's default command<commit_after>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

package foam.nanos.http;

import foam.core.X;
import foam.nanos.http.Command;
import foam.nanos.http.Format;
import foam.nanos.http.HttpParameters;
import foam.nanos.logger.Logger;
import foam.nanos.logger.PrefixLogger;
import foam.util.SafetyUtil;
import java.io.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HttpParametersWebAgent
  extends ProxyWebAgent
{
  public static final int BUFFER_SIZE = 4096;

  protected static ThreadLocal<StringBuilder> sb = new ThreadLocal<StringBuilder>() {
    @Override
    protected StringBuilder initialValue() {
      return new StringBuilder();
    }

    @Override
    public StringBuilder get() {
      StringBuilder b = super.get();
      b.setLength(0);
      return b;
    }
  };

  protected Class parametersClass = DefaultHttpParameters.class;

  public HttpParametersWebAgent() {}
  public HttpParametersWebAgent(WebAgent delegate) {
    setDelegate(delegate);
  }

  public HttpParametersWebAgent(String parametersClassName, WebAgent delegate) {
    setParametersClass(parametersClassName);
    setDelegate(delegate);
  }

  public void setParametersClass(String parametersClassName) {
    try {
      this.parametersClass = Class.forName(parametersClassName);
    } catch (ClassNotFoundException exception) {
      throw new RuntimeException(exception);
    }
  }

  public void execute(X x) {
    Logger              logger = (Logger) x.get("logger");
    HttpServletRequest  req    = x.get(HttpServletRequest.class);
    HttpServletResponse resp   = x.get(HttpServletResponse.class);

    logger = new PrefixLogger(new Object[] { this.getClass().getSimpleName() }, logger);

    if ( req == null || resp == null ) {
      logger.error(new java.lang.IllegalArgumentException("Context missing HttpServletRequest, HttpServletResponse"));
      return;
    }

    String         methodName      = req.getMethod();
    String         accept          = req.getHeader("Accept");
    String         contentType     = req.getHeader("Content-Type");
    HttpParameters parameters      = null;
    Command        command         = null;
    String         cmd             = req.getParameter("cmd");

    logger.debug("methodName", methodName);

    try {
      parameters = (HttpParameters) x.create(this.parametersClass);
    } catch (ClassCastException exception) {
      throw new RuntimeException(exception);
    }

    // Capture 'data' on all requests
    if ( ! SafetyUtil.isEmpty(req.getParameter("data")) ) {
      logger.debug("data", req.getParameter("data"));
      logger.debug("cmd", req.getParameter("cmd"));
      logger.debug("format", req.getParameter("format"));

      parameters.set("data", req.getParameter("data"));
    } else {
      //
      // When content-type is other than application/x-www-form-urlencoded, the
      // HttpServletRequest.reader stream must be processes manually to extract
      // parameters from the body.
      //
      // Future considerations for partial parameters in the POST URI
      // see examples: https://technologyconversations.com/2014/08/12/rest-api-with-json/
      //
      try {

        int read   = 0;
        int count  = 0;
        int length = req.getContentLength();

        StringBuilder  builder = sb.get();
        char[] cbuffer = new char[BUFFER_SIZE];
        BufferedReader reader  = new BufferedReader(new InputStreamReader(req.getInputStream()));

        while ( ( read = reader.read(cbuffer, 0, BUFFER_SIZE)) != -1 && count < length ) {
          builder.append(cbuffer, 0, read);
          count += read;
        }
        logger.debug("reader data:", builder.toString());
        if ( ! SafetyUtil.isEmpty(builder.toString()) ) {
          parameters.set("data", builder.toString());
        }
      } catch (IOException e) {
        try {
          resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Failed to parse body/data.");
        } catch (IOException ioe) {
          // nop
        }
        return;
      }
    }

    if ( ! "application/x-www-form-urlencoded".equals(contentType) ) {
      if ( ! SafetyUtil.isEmpty(cmd) ) {
        switch ( cmd.toLowerCase() ) {
          case "put":
            command = Command.put;
            break;
          case "select":
            command = Command.select;
            if ( ! SafetyUtil.isEmpty(req.getParameter("id")) ) {
              parameters.set("id", req.getParameter("id"));
              logger.debug("id", req.getParameter("id"));
            }
            break;
          case "remove":
            command = Command.remove;
            parameters.set("id", req.getParameter("id"));
            logger.debug("id", req.getParameter("id"));
            break;
        }
      } else {
        switch ( methodName.toUpperCase() ) {  // set default command
          case "POST":
            command = Command.put;
            break;
          case "PUT":
            command = Command.put;
            break;
          case "DELETE":
            command = Command.remove;
            break;
          case "GET":
            command = Command.select;
            break;
          default:
            command = Command.select;
            logger.warning("cmd/method could not be determined, defaulting to SELECT.");
            break;
        }
      }


//      switch ( methodName.toUpperCase() ) {
//        case "POST":
//          command = Command.put;
//          break;
//        case "PUT":
//          command = Command.put;
//          break;
{'fraction_non_alphanumeric': 0.11885390873717722, 'fraction_numerical': 0.004244782454899187, 'mean_word_length': 2.2684971098265896, 'pattern_counts': {'":': 18, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7051624', 'n_tokens_mistral': 3043, 'n_tokens_neox': 2979, 'n_words': 686}