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

prompto.server.UserServlet Maven / Gradle / Ivy

There is a newer version: 0.1.57
Show newest version
package prompto.server;

import java.io.IOException;
import java.util.Map;

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import prompto.debug.ProcessDebugger;
import prompto.declaration.IMethodDeclaration;
import prompto.expression.ValueExpression;
import prompto.expression.IExpression;
import prompto.expression.MethodSelector;
import prompto.grammar.ArgumentList;
import prompto.intrinsic.PromptoBinary;
import prompto.intrinsic.PromptoDocument;
import prompto.reader.JSONReader;
import prompto.runtime.ApplicationContext;
import prompto.runtime.Context;
import prompto.runtime.Interpreter;
import prompto.runtime.Standalone;
import prompto.runtime.VoidResult;
import prompto.statement.MethodCall;
import prompto.type.DocumentType;
import prompto.type.TextType;
import prompto.utils.Logger;
import prompto.value.BinaryValue;
import prompto.value.DocumentValue;
import prompto.value.IValue;
import prompto.value.ListValue;
import prompto.value.TextValue;
import prompto.value.TupleValue;


@SuppressWarnings("serial")
public class UserServlet extends CleverServlet {

	static final Logger logger = new Logger();

	IMethodDeclaration method;
	
	public UserServlet(IMethodDeclaration method) {
		this.method = method;
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		setMultipartConfig(new MultipartConfigElement(System.getProperty("java.io.tmpdir")));
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try {
			Thread.currentThread().setName(this.getClass().getSimpleName());
			logger.info(()->"Processing GET " + req.getRequestURI());
			Context local = getWorkerContext();
			DocumentValue document = paramsToDocument(local, req.getParameterMap());
			IValue value = interpret(local, document);
			if(value!=null)
				sendValue(req, resp, value);
		} catch(Throwable t) {
			logger.error(()->"While processing GET " + req.getRequestURI(), t);
			resp.setStatus(500);
		}
	}
	
	private Context getWorkerContext() {
		Context context = ApplicationContext.get().newLocalContext();
		ProcessDebugger processDebugger = ProcessDebugger.getInstance();
		if(processDebugger!=null)
			Standalone.startWorkerDebugger(Thread.currentThread(), context);
		return context;
	}

	private IValue interpret(Context context, DocumentValue document) {
		IExpression args = new ValueExpression(DocumentType.instance(), document);
		ArgumentList arguments = Interpreter.buildArguments(method, args);
		MethodCall call = new MethodCall(new MethodSelector(method.getId()), arguments);
		return call.interpret(context);	
	}

	private DocumentValue paramsToDocument(Context context, Map params) {
		DocumentValue document = new DocumentValue();
		params.forEach((n, l)->{
			TextValue name = new TextValue(n);
			if(l.length==1)
				document.setItem(context, name, new TextValue(l[0]));
			else {
				ListValue list = new ListValue(TextType.instance());
				for(String value : l)
					list.addItem(new TextValue(value));
				document.setItem(context, name, list);
			}
		});
		return document;
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try {
			logger.info(()->"Processing POST " + req.getRequestURI());
			IValue value = null;
			String contentType = req.getContentType();
			if(contentType==null)
				contentType = "application/x-www-form-urlencoded";
			if(contentType.startsWith("application/json"))
				value = doPostJson(req, resp);
			else if(contentType.startsWith("application/x-www-form-urlencoded"))
				value = doPostUrlEncoded(req, resp);
			else if(contentType.startsWith("multipart/form-data"))
				value = doPostMultipart(req, resp);
			else
				resp.sendError(415);
			if(value!=null)
				sendValue(req, resp, value);
		} catch(Throwable t) {
			logger.error(()->"While processing POST " + req.getRequestURI(), t);
			resp.setStatus(500);
		}
	}

	private void sendValue(HttpServletRequest req, HttpServletResponse resp, IValue value) throws IOException {
		if(value==null || value==VoidResult.instance())
			return;
		if(value instanceof TextValue) {
			try(var writer = resp.getWriter()) {
				resp.setContentType("text/plain");
				writer.write(((TextValue)value).getStorableData());
				return;
			}
		}
		if(value instanceof BinaryValue) {
			try(var output = resp.getOutputStream()) {
				PromptoBinary binary = ((BinaryValue)value).getData();
				resp.setContentType(binary.getMimeType());
				output.write(binary.getBytes());
				return;
			}
					
		} 
		if(value instanceof TupleValue) {
			TupleValue tuple = (TupleValue)value;
			if(tuple.getLength()>=2) {
				IValue content = tuple.getItem(0);
				IValue mimeType = tuple.getItem(1);
				if(content.getType()==TextType.instance() && mimeType.getType()==TextType.instance()) {
					try(var writer = resp.getWriter()) {
						resp.setContentType(((TextValue)mimeType).getStorableData());
						writer.write(((TextValue)content).getStorableData());
						return;
					}
				}
			}
		}
		try(var writer = resp.getWriter()) {
			writer.write("Unsupported result: " + value.getType().getTypeName());
		}
	}

	private IValue doPostMultipart(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
		Map parts = readPartsAsObjects(req);
		PromptoDocument document = new PromptoDocument<>(parts);
		Context context = getWorkerContext();
		DocumentValue documentValue = new DocumentValue(context, document, true);
		return interpret(context, documentValue);
	}

	private IValue doPostUrlEncoded(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		Context context = getWorkerContext();
		DocumentValue document = paramsToDocument(context, req.getParameterMap());
		return interpret(context, document);
	}

	private IValue doPostJson(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		try(var input = req.getInputStream()) {
			Object object = JSONReader.read(input);
			if(object instanceof PromptoDocument) {
				Context context = getWorkerContext();
				DocumentValue document = new DocumentValue(context, (PromptoDocument)object, true);
				return interpret(context, document);
			} else {
				resp.sendError(415);
				return null;
			}
		}
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy