/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.eas.server.httpservlet;
import com.eas.client.report.Report;
import com.eas.client.settings.SettingsConstants;
import com.eas.client.threetier.http.PlatypusHttpConstants;
import com.eas.client.threetier.http.PlatypusHttpResponseReader;
import com.eas.client.threetier.requests.AccessControlExceptionResponse;
import com.eas.client.threetier.requests.AppQueryRequest;
import com.eas.client.threetier.requests.CommitRequest;
import com.eas.client.threetier.requests.ServerModuleStructureRequest;
import com.eas.client.threetier.requests.CredentialRequest;
import com.eas.client.threetier.requests.DisposeServerModuleRequest;
import com.eas.client.threetier.requests.ExceptionResponse;
import com.eas.client.threetier.requests.ExecuteQueryRequest;
import com.eas.client.threetier.requests.JsonExceptionResponse;
import com.eas.client.threetier.requests.RPCRequest;
import com.eas.client.threetier.requests.LogoutRequest;
import com.eas.client.threetier.requests.ModuleStructureRequest;
import com.eas.client.threetier.requests.PlatypusResponseVisitor;
import com.eas.client.threetier.requests.ResourceRequest;
import com.eas.client.threetier.requests.SqlExceptionResponse;
import com.eas.script.Scripts;
import com.eas.util.IdGenerator;
import com.eas.util.JsonUtils;
import com.eas.util.RowsetJsonConstants;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jdk.nashorn.api.scripting.JSObject;
/**
*
* @author mg
*/
public class PlatypusHttpResponseWriter implements PlatypusResponseVisitor {
protected HttpServletResponse servletResponse;
protected HttpServletRequest servletRequest;
protected AsyncContext async;
protected Scripts.Space space;
protected String userName;
public PlatypusHttpResponseWriter(HttpServletResponse aServletResponse, HttpServletRequest aServletRequest, Scripts.Space aSpace, String aUserName, AsyncContext aAsync) {
super();
servletRequest = aServletRequest;
servletResponse = aServletResponse;
space = aSpace;
userName = aUserName;
async = aAsync;
}
@Override
public void visit(ExceptionResponse resp) throws Exception {
servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, resp.getErrorMessage());
async.complete();
}
@Override
public void visit(AccessControlExceptionResponse acer) throws Exception {
/*
// we can't send HttpServletResponse.SC_UNAUTHORIZED without knowlege about login mechanisms
// of Sevlet/J2EE container.
if (resp.isNotLoggedIn()) {
servletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, resp.getErrorMessage());
} else {
servletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, resp.getErrorMessage());
}
*/
servletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, acer.getErrorMessage());
async.complete();
}
@Override
public void visit(JsonExceptionResponse jer) throws Exception {
servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, jer.getErrorMessage());
async.complete();
}
@Override
public void visit(SqlExceptionResponse ser) throws Exception {
servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ser.getErrorMessage());
async.complete();
}
@Override
public void visit(CredentialRequest.Response resp) throws Exception {
String name = ((CredentialRequest.Response) resp).getName();
StringBuilder content = JsonUtils.o(new StringBuilder("userName"), JsonUtils.s(name));
writeJsonResponse(content.toString(), servletResponse, async);
}
@Override
public void visit(ExecuteQueryRequest.Response rsp) throws Exception {
makeResponseNotCacheable(servletResponse);
ExecuteQueryRequest.Response resp = (ExecuteQueryRequest.Response) rsp;
writeJsonResponse(resp.getJson(), servletResponse, async);
}
@Override
public void visit(LogoutRequest.Response resp) throws Exception {
// logout is processed out of this class
}
@Override
public void visit(RPCRequest.Response resp) throws Exception {
final Object result = ((RPCRequest.Response) resp).getResult();
makeResponseNotCacheable(servletResponse);
if (result instanceof String) {
writeJsonResponse((String) result, servletResponse, async);
} else if (result instanceof Report) {
writeReportResponse((Report) result);
} else if (result instanceof JSObject) {
/*
JSObject jsResult = (JSObject) result;
JSObject p = space.lookupInGlobal("P");
if (p != null) {
Object reportClass = p.getMember("Report");
if (jsResult.isInstanceOf(reportClass)) {
Report report = (Report) ((JSObject) jsResult.getMember("unwrap")).call(null, new Object[]{});
writeReportResponse(report);
} else {
writeJsonResponse(space.toJson(result), servletResponse, async);
}
} else {
writeJsonResponse(space.toJson(result), servletResponse, async);
}
*/
writeJsonResponse(space.toJson(result), servletResponse, async);
} else {// including null result
writeJsonResponse(space.toJson(space.toJs(result)), servletResponse, async);
}
}
protected void writeReportResponse(Report report) throws URISyntaxException, IOException {
String docsRoot = servletRequest.getServletContext().getRealPath("/");
String userHomeInApplication = "/reports/" + userName + "/";
File userDir = new File(docsRoot + userHomeInApplication);
if (!userDir.exists()) {
userDir.mkdirs();
}
String suffix = "." + report.getFormat();
String reportName = report.getName();
if (reportName.toLowerCase().endsWith(suffix.toLowerCase())) {
reportName = reportName.substring(0, reportName.length() - suffix.length());
}
reportName += "-" + IdGenerator.genId() + suffix;
File rep = new File(docsRoot + userHomeInApplication + reportName);
try (FileOutputStream out = new FileOutputStream(rep)) {
out.write(report.getBody());
out.flush();
}
String reportLocation = userHomeInApplication + reportName;
if (!"/".equals(servletRequest.getContextPath())) {
reportLocation = servletRequest.getContextPath() + reportLocation;
}
reportLocation = new URI(null, null, reportLocation, null).toASCIIString();
writeResponse(reportLocation, servletResponse, PlatypusHttpResponseReader.REPORT_LOCATION_CONTENT_TYPE, async);
}
@Override
public void visit(DisposeServerModuleRequest.Response resp) throws Exception {
// simple OK response is needed
async.complete();
}
@Override
public void visit(ServerModuleStructureRequest.Response resp) throws Exception {
ServerModuleStructureRequest.Response csmr = (ServerModuleStructureRequest.Response) resp;
if (csmr.getInfoJson() != null) {
assert resp.getTimeStamp() != null;
servletResponse.setDateHeader(PlatypusHttpConstants.HEADER_LAST_MODIFIED, resp.getTimeStamp().getTime());
writeJsonResponse(resp.getInfoJson(), servletResponse, async);
} else {
servletResponse.sendError(HttpURLConnection.HTTP_NOT_MODIFIED);
async.complete();
}
}
@Override
public void visit(ResourceRequest.Response resp) throws Exception {
// resources are processed out of this class by servlet container
}
@Override
public void visit(AppQueryRequest.Response resp) throws Exception {
AppQueryRequest.Response aqr = ((AppQueryRequest.Response) resp);
if (aqr.getAppQueryJson() != null) {
assert resp.getTimeStamp() != null;
servletResponse.setDateHeader(PlatypusHttpConstants.HEADER_LAST_MODIFIED, resp.getTimeStamp().getTime());
writeJsonResponse(aqr.getAppQueryJson(), servletResponse, async);
} else {
servletResponse.sendError(HttpURLConnection.HTTP_NOT_MODIFIED);
async.complete();
}
}
@Override
public void visit(CommitRequest.Response resp) throws Exception {
writeJsonResponse(resp.getUpdated() + "", servletResponse, async);
}
@Override
public void visit(ModuleStructureRequest.Response resp) throws Exception {
makeResponseNotCacheable(servletResponse);
writeJsonResponse(resp.getJson(), servletResponse, async);
}
private static void makeResponseNotCacheable(HttpServletResponse aHttpResponse) {
aHttpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
aHttpResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0.
aHttpResponse.setDateHeader("Expires", 0);// Proxies
}
private static void writeResponse(String aResponse, HttpServletResponse aHttpResponse, String aContentType, AsyncContext aAsync) throws UnsupportedEncodingException, IOException {
byte[] bytes = aResponse.getBytes(SettingsConstants.COMMON_ENCODING);
aHttpResponse.setCharacterEncoding(SettingsConstants.COMMON_ENCODING);
if (aHttpResponse.getContentType() == null) {
aHttpResponse.setContentType(aContentType);
}
aHttpResponse.setContentLength(bytes.length);
aHttpResponse.getOutputStream().write(bytes);
aHttpResponse.getOutputStream().flush();
if (aAsync != null) {
aAsync.complete();
}
}
public static void writeJsonResponse(String aResponse, HttpServletResponse aHttpResponse, AsyncContext aAsync) throws UnsupportedEncodingException, IOException {
writeResponse(aResponse, aHttpResponse, RowsetJsonConstants.JSON_CONTENTTYPE, aAsync);
}
}