All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.aguacate.AguacateServlet Maven / Gradle / Ivy

There is a newer version: 0.10.9
Show newest version
package net.sf.aguacate;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.sf.aguacate.configuration.Configuration;
import net.sf.aguacate.configuration.ConfigurationCoupling;
import net.sf.aguacate.context.ContextValidationResult;
import net.sf.aguacate.function.FunctionEvalResult;
import net.sf.aguacate.http.HttpBodyBuilerCoupling;
import net.sf.aguacate.http.HttpBodyParserCoupling;
import net.sf.aguacate.http.HttpMethods;
import net.sf.aguacate.util.meta.Meta;
import net.sf.aguacate.util.meta.MetaCoupling;
import net.sf.aguacate.util.servlet.ServletUtil;
import net.sf.aguacate.validator.InputValidationResponse;
import net.sf.aguacate.validator.ValidationConversionResult;

public class AguacateServlet extends HttpServlet {

	private static final long serialVersionUID = 6335723473241984651L;

	private static final Logger LOGGER = LogManager.getLogger(AguacateServlet.class);

	private static final Logger LOGGER_INIT = LogManager.getLogger("aguacate.init");

	private static final Logger LOGGER_REQUEST = LogManager.getLogger("aguacate.request");

	@Override
	public void init() throws ServletException {
		super.init();
		String group = "net.sf.aguacate";
		String artifact = "aguacate-servlet";
		Meta meta = MetaCoupling.get(AguacateServlet.class, group, artifact);
		String message = group + " & " + artifact + " & " + meta.getVersion();
		log(message);
		LOGGER_INIT.info(message);
	}

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) {
		if (LOGGER_REQUEST.isInfoEnabled()) {
			String servletPath = request.getServletPath();
			String pathInfo = request.getPathInfo();
			LOGGER_REQUEST.info("request for: {} ~ {}", servletPath, pathInfo);
		}
		String entity = ServletUtil.getEntity(request);
		String method = request.getMethod();
		try {
			Configuration configuration = ConfigurationCoupling.load(entity);
			if (configuration == null) {
				response.setStatus(HttpServletResponse.SC_NOT_FOUND);
			} else {
				if (HttpMethods.acceptsPathParameters(method)) {
					String id = ServletUtil.getId(request);
					if (id == null) {
						if (HttpMethods.optionalPathParameters(method)) {
							String method0 = method + '0';
							if (configuration.accepts(method0)) {
								if (HttpMethods.acceptsBodyRequest(method0)) {
									String contentType = request.getContentType();
									if (contentType == null || contentType.isEmpty()) {
										response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
									} else {
										Map body = HttpBodyParserCoupling.defaultInstance()
												.parse(request);
										if (body == null) {
											response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
										} else {
											validate(configuration, method0, request, response, null, body);
										}
									}
								} else {
									validate(configuration, method0, request, response);
								}
							} else {
								if ("OPTIONS".equals(method)) {
									// TODO: Allow some kind of cache for this string
									response.setHeader("Allow", toHeaderValue(configuration));
									response.setStatus(HttpServletResponse.SC_NO_CONTENT);
								} else {
									response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
								}
							}
						} else {
							// Invalid state
							response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
						}
					} else {
						if (configuration.accepts(method)) {
							if (HttpMethods.acceptsBodyRequest(method)) {
								String contentType = request.getContentType();
								if (contentType == null || contentType.isEmpty()) {
									response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
								} else {
									Map body = HttpBodyParserCoupling.defaultInstance().parse(request);
									if (body == null) {
										response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
									} else {
										validate(configuration, method, request, response, id, body);
									}
								}
							} else {
								validate(configuration, method, request, response, id);
							}
						} else {
							if ("OPTIONS".equals(method)) {
								// TODO: Allow some kind of cache for this string
								response.setHeader("Allow", toHeaderValue(configuration));
								response.setStatus(HttpServletResponse.SC_NO_CONTENT);
							} else {
								response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
							}
						}
					}
				} else {
					if (configuration.accepts(method)) {
						if (HttpMethods.acceptsBodyRequest(method)) {
							String contentType = request.getContentType();
							if (contentType == null || contentType.isEmpty()) {
								response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
							} else {
								Map body = HttpBodyParserCoupling.defaultInstance().parse(request);
								if (body == null) {
									response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
								} else {
									validate(configuration, method, request, response, body);
								}
							}
						} else {
							validate(configuration, method, request, response);
						}
					} else {
						if ("OPTIONS".equals(method)) {
							// TODO: Allow some kind of cache for this string
							response.setHeader("Allow", toHeaderValue(configuration));
							response.setStatus(HttpServletResponse.SC_NO_CONTENT);
						} else {
							response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
						}
					}
				}
			}
		} catch (RuntimeException | IOException e) {
			LOGGER.error(MessageFormat.format("{0}, {1}", entity, method), e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
	}

	String toHeaderValue(Configuration configuration) {
		String[] allowed = configuration.methods();
		StringBuilder builder = new StringBuilder("OPTIONS");
		boolean get = false;
		for (String current : allowed) {
			if ("GET0".equals(current)) {
				if (!get) {
					get = true;
					builder.append(", ");
					builder.append("GET");
				}
			} else {
				if ("GET".equals(current)) {
					if (!get) {
						builder.append(", ");
						builder.append(current);
					}
				} else {
					builder.append(", ");
					builder.append(current);
				}
			}
		}
		String value = builder.toString();
		return value;
	}

	// GET
	void validate(Configuration configuration, String method, HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		LOGGER.info("GET0: {}", method);
		processInput(configuration, method, new InputValidationResponse(new HashMap<>(), null), request, response);
	}

	// GET, DELETE
	void validate(Configuration configuration, String method, HttpServletRequest request, HttpServletResponse response,
			String id) throws IOException {
		LOGGER.info("GET, DELETE: {}", method);
		processInput(configuration, method,
				configuration.getValidatorConverter(method).validate(id, Collections.emptyMap()), request, response);
	}

	// PUT, PATCH
	void validate(Configuration configuration, String method, HttpServletRequest request, HttpServletResponse response,
			String id, Map body) throws IOException {
		LOGGER.info("PUT, DELETE: {}, {}", method, id);
		processInput(configuration, method, configuration.getValidatorConverter(method).validate(id, body), request,
				response);
	}

	// POST
	void validate(Configuration configuration, String method, HttpServletRequest request, HttpServletResponse response,
			Map body) throws IOException {
		LOGGER.info("POST: {}", method);
		processInput(configuration, method, configuration.getValidatorConverter(method).validate(body), request,
				response);
	}

	// TODO: move this method
	void processInput(Configuration configuration, String method, InputValidationResponse validationResponse,
			HttpServletRequest request, HttpServletResponse response) throws IOException {
		if (validationResponse.isSuccess()) {
			Map context = validationResponse.getContext();
			LOGGER.trace("initial context: {}", context);
			ContextValidationResult result = configuration.getContextValidator().validate(request, method, context);
			if (result.isSuccess()) {
				configuration.getContextProcessor().process(request, response, method, context,
						configuration.getOutputFields(method));
			} else {
				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				Map map = new HashMap<>();
				map.put("type", "RULE");
				List rules = new ArrayList<>();
				List errors = result.getErrors();
				LOGGER.trace("errors: {}", errors);
				for (FunctionEvalResult error : errors) {
					rules.add(error.getMessage());
				}
				map.put("rules", rules);
				HttpBodyBuilerCoupling.defaultInstance().build(response, map);
			}
		} else {
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			Map map = new HashMap<>();
			map.put("type", "VALIDATION");
			Map validations = new HashMap<>();
			Map failures = validationResponse.getFailures();
			LOGGER.trace("failures: {}", failures);
			for (Map.Entry entry : failures.entrySet()) {
				validations.put(entry.getKey(), entry.getValue().getMessage());
			}
			map.put("validations", validations);
			HttpBodyBuilerCoupling.defaultInstance().build(response, map);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy