/* * 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.client.threetier.http; import com.eas.client.settings.SettingsConstants; import com.eas.client.threetier.Request; 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.DisposeServerModuleRequest; import com.eas.client.threetier.requests.ExceptionResponse; import com.eas.client.threetier.requests.ExecuteQueryRequest; 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.CredentialRequest; import com.eas.client.threetier.requests.JsonExceptionResponse; import com.eas.client.threetier.requests.SqlExceptionResponse; import com.eas.util.BinaryUtils; import com.eas.util.JsonUtils; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * * @author mg */ public class PlatypusHttpResponseReader implements PlatypusResponseVisitor { public static final String REPORT_LOCATION_CONTENT_TYPE = "text/platypus-report-location"; protected HttpURLConnection conn; protected int responseCode; protected Request request; private final byte[] bodyContent; public PlatypusHttpResponseReader(Request aRequest, HttpURLConnection aConn, byte[] aBodyContent) throws IOException { super(); request = aRequest; conn = aConn; responseCode = conn.getResponseCode(); bodyContent = aBodyContent; } protected String extractText() throws IOException { if (bodyContent != null) { String contentType = conn.getContentType(); String[] contentTypeCharset = contentType != null ? contentType.split(";") : null; if (contentTypeCharset == null || contentTypeCharset.length == 0) { throw new IOException("Response must contain ContentType header with charset"); } if (!contentTypeCharset[0].toLowerCase().startsWith("text/") && !contentTypeCharset[0].toLowerCase().startsWith("application/json")) { throw new IOException("Response header 'ContentType' must be text/... or application/json"); } if (contentTypeCharset.length > 1) { String[] charsetNameValue = contentTypeCharset[1].split("="); if (charsetNameValue == null || charsetNameValue.length != 2) { throw new IOException("Response must contain ContentType header with charset=... clause"); } if (!charsetNameValue[0].equalsIgnoreCase("charset")) { throw new IOException("Response ContentType must be formatted as following: text/...;charset=..."); } return new String(bodyContent, charsetNameValue[1].trim()); } else { return new String(bodyContent, SettingsConstants.COMMON_ENCODING); } } else { return null; } } @Override public void visit(ExceptionResponse rsp) throws Exception { // Error response has no body } @Override public void visit(AccessControlExceptionResponse rsp) throws Exception { // Error response has no body } @Override public void visit(JsonExceptionResponse rsp) throws Exception { String json = extractText(); rsp.setJsonContent(json); } @Override public void visit(SqlExceptionResponse rsp) throws Exception { // Error response has no body } @Override public void visit(CredentialRequest.Response rsp) throws Exception { String text = extractText(); Pattern userNamePattern = Pattern.compile("\\{\\s*userName\\s*:(.+)\\}"); Matcher m = userNamePattern.matcher(text); if (m.find()) { String userName = m.group(1); rsp.setName(JsonUtils.jsonUnescape(userName)); } } @Override public void visit(ExecuteQueryRequest.Response rsp) throws Exception { String json = extractText(); rsp.setJson(json); } @Override public void visit(LogoutRequest.Response rsp) throws Exception { // response is simple OK } @Override public void visit(RPCRequest.Response rsp) throws Exception { if (conn.getContentType() != null && conn.getContentType().toLowerCase().startsWith(REPORT_LOCATION_CONTENT_TYPE)) { String reportLocation = extractText(); URL currentUrl = conn.getURL(); URL reportUrl = new URL(currentUrl.getProtocol(), currentUrl.getHost(), currentUrl.getPort(), reportLocation); rsp.setResult(reportUrl); } else { String text = extractText(); rsp.setResult(text); } } @Override public void visit(DisposeServerModuleRequest.Response rsp) throws Exception { // response is simple OK } @Override public void visit(ServerModuleStructureRequest.Response rsp) throws Exception { if (responseCode == HttpURLConnection.HTTP_OK) { long timeStamp = conn.getLastModified(); rsp.setTimeStamp(new Date(timeStamp)); rsp.setInfoJson(extractText()); } else if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) { rsp.setInfoJson(null); rsp.setTimeStamp(null); } } @Override public void visit(ResourceRequest.Response rsp) throws Exception { if (responseCode == HttpURLConnection.HTTP_OK) { long timeStamp = conn.getLastModified(); rsp.setTimeStamp(new Date(timeStamp)); if (bodyContent != null) { rsp.setContent(bodyContent); } else { try (InputStream is = conn.getInputStream()) { byte[] content = BinaryUtils.readStream(is, -1); rsp.setContent(content); } } } else if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) { rsp.setContent(null); rsp.setTimeStamp(null); } } @Override public void visit(AppQueryRequest.Response rsp) throws Exception { if (responseCode == HttpURLConnection.HTTP_OK) { long timeStamp = conn.getLastModified(); rsp.setTimeStamp(new Date(timeStamp)); rsp.setAppQueryJson(extractText()); } else if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) { rsp.setAppQueryJson(null); rsp.setTimeStamp(null); } } @Override public void visit(CommitRequest.Response rsp) throws Exception { String text = extractText(); int updated = Double.valueOf(text).intValue(); rsp.setUpdated(updated); } @Override public void visit(ModuleStructureRequest.Response rsp) throws Exception { rsp.setJson(extractText()); } }