package org.eclipse.iee.web.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.iee.core.EvaluationContextHolder;
import org.eclipse.iee.core.FileResultContainer;
import org.eclipse.iee.core.IDocumentEvaluator;
import org.eclipse.iee.core.IParameterProvider;
import org.eclipse.iee.core.IResultContainer;
import org.eclipse.iee.core.document.Document;
import org.eclipse.iee.core.store.IDocumentStore;
import org.eclipse.iee.core.store.IEvaluationContextStore;
import org.eclipse.iee.web.RequestParameterProvider;
import org.eclipse.iee.web.renderer.IHTMLDocumentRenderer;
import org.eclipse.iee.web.renderer.IHTMLRendererContext;
import org.eclipse.iee.web.renderer.IResourceRenderContext;
import com.google.common.base.Throwables;
public class TestServlet extends HttpServlet {
private IHTMLDocumentRenderer documentRenderer;
private IDocumentStore documentStore;
private IEvaluationContextStore resultStore;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String pathInfo = req.getPathInfo();
String[] parts = pathInfo.split("/");
String projectLoc = parts[1];
String clazz = parts[2];
boolean isEditMode = "1".equals(req.getParameter("edit"));
Document document = documentStore.getDocument(projectLoc, clazz);
if (document == null) {
do404(req, resp);
return;
}
String evaluationId = req.getParameter("evalId");
IParameterProvider parameterProvider;
IResultContainer container;
if (evaluationId != null) {
parameterProvider = resultStore.getParameterProvider(evaluationId);
container = resultStore.getResultContainer(evaluationId);
} else {
evaluationId = UUID.randomUUID().toString();
parameterProvider = new RequestParameterProvider(req);
container = evaluateDocument(projectLoc, clazz, parameterProvider);
resultStore.putParameterProvider(evaluationId, parameterProvider);
resultStore.putResultContainer(evaluationId, container);
}
String docRoot = req.getContextPath() + req.getServletPath() + '/'
+ URLEncoder.encode(parts[1], "utf-8") + '/'
+ URLEncoder.encode(parts[2], "utf-8");
Enumeration<String> parameterNames = req.getParameterNames();
Map<String, String> params = new HashMap<>();
while (parameterNames.hasMoreElements()) {
String nextElement = parameterNames.nextElement();
params.put(nextElement, req.getParameter(nextElement));
}
if (parts.length == 3) {
IHTMLRendererContext htmlRendererContext = new DefaultHTMLRendererContext(
evaluationId, req, resp, docRoot, params, documentStore,
projectLoc, clazz, container, isEditMode, parameterProvider);
PrintWriter writer = resp.getWriter();
writer.append("<html><head>");
documentRenderer.renderHTMLHead(document, htmlRendererContext);
writer.append("</head><body>");
if (!isEditMode) {
writer.append("<div>");
Map<String, String> editParam = new HashMap<>();
editParam.put("edit", "1");
writer.append("<a href='")
.append(htmlRendererContext.createURL(editParam))
.append("'>Edit</a>");
writer.append("</div>");
}
if (isEditMode) {
writer.append("<form>");
writer.append("<div>");
writer.append("<input type='submit' value='Calculate'>");
writer.append("</div>");
}
documentRenderer.renderHTMLBody(document, htmlRendererContext);
if (isEditMode) {
writer.append("</form>");
}
writer.append("</body></html>");
} else if (parts.length > 3) {
IResourceRenderContext resourceRenderContext = new DefaultResourceRendererContext(
evaluationId, docRoot, params, container, isEditMode,
documentStore, req, resp, projectLoc, clazz,
parameterProvider);
String resourceId;
if (parts.length > 4) {
String[] copyOfRange = Arrays.copyOfRange(parts, 4,
parts.length);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < copyOfRange.length; i++) {
if (i > 0) {
sb.append("/");
}
sb.append(copyOfRange[i]);
}
resourceId = sb.toString();
} else {
resourceId = "";
}
documentRenderer.renderResource(document, parts[3], resourceId,
resourceRenderContext);
}
}
private void do404(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
resp.getWriter().append("<html><body>Sorry. Document is not available.</body></html>");
}
protected IResultContainer evaluateDocument(String projectLoc,
String clazz, IParameterProvider parameterProvider)
throws IOException {
Document document = documentStore.getDocument(projectLoc, clazz);
IResultContainer container = getDocumentEvaluator().evaluate(document, parameterProvider);
return container;
}
protected IResultContainer createResultContainer() {
return new FileResultContainer();
}
protected IDocumentEvaluator getDocumentEvaluator() {
return new IDocumentEvaluator() {
@Override
public IResultContainer evaluate(Document document, IParameterProvider parameterProvider) {
IResultContainer container = createResultContainer();
EvaluationContextHolder.setResultContainer(container);
EvaluationContextHolder.setParameterProvider(parameterProvider);
try {
Class<?> loadClass = documentStore.getDocumentClass(document.getBundle(), document.getName());
initialize(loadClass, parameterProvider);
Method main = loadClass.getMethod("main", String[].class);
main.invoke(null, (Object) new String[] {});
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
EvaluationContextHolder.cleanContext();
}
return container;
}
private void initialize(Class<?> cls, IParameterProvider prd) {
Method[] methods = cls.getMethods();
for (Method method : methods) {
if (method.getName().endsWith("FromProvider") &&
method.getParameterTypes().length == 1 &&
method.getParameterTypes()[0].isAssignableFrom(IParameterProvider.class)) {
try {
method.invoke(null, new Object[] {prd});
} catch (IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
Throwables.propagate(e);
}
}
}
}
};
}
public IHTMLDocumentRenderer getDocumentRenderer() {
return documentRenderer;
}
public void setDocumentRenderer(IHTMLDocumentRenderer documentRenderer) {
this.documentRenderer = documentRenderer;
}
public IDocumentStore getDocumentStore() {
return documentStore;
}
public void setDocumentStore(IDocumentStore documentStore) {
this.documentStore = documentStore;
}
public IEvaluationContextStore getResultStore() {
return resultStore;
}
public void setEvaluationContextStore(IEvaluationContextStore resultStore) {
this.resultStore = resultStore;
}
}