package com.epam.wilma.test.server;
/*==========================================================================
Copyright 2013-2017 EPAM Systems
This file is part of Wilma.
Wilma is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Wilma is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Wilma. If not, see <http://www.gnu.org/licenses/>.
===========================================================================*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import com.epam.wilma.test.server.compress.Decompressor;
import com.epam.wilma.test.server.compress.fis.FastInfosetDecompressor;
import com.epam.wilma.test.server.compress.gzip.GzipCompressor;
import com.epam.wilma.test.server.compress.gzip.GzipDecompressor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Jetty handler that is able to handle requests coming to /example with one of the given XMLs in the request body.
* @author Marton_Sereg
*
*/
public class ExampleHandler extends AbstractHandler {
private static final String FIS_RESPONSE = "example.xml.fis";
private static final String EXAMPLE_XML = "example.xml";
private static final String EXAMPLE_JSON = "example.json";
private static final String WILMA_LOGGER_ID = "Wilma-Logger-ID";
private static final String PATH_OK = "/ok";
private static final String PATH_NOT_IMPLEMENTED = "/sendnotimplemented";
private static final String PATH_BAD_GATWAY = "/sendbadgateway";
private static final String PATH_SERVICE_UNAVAILABLE = "/sendserviceunavailable";
private static final String PATH_INTERNAL_SERVER_ERROR = "/sendinternalservererror";
private static final String PATH_SEND_BAD_FIS = "/sendbadfis";
private static final String PATH_REPLICATOR = "/replicator";
private static final int WAIT_IN_MILLIS = 61000;
private static final String ACCEPT_ENCODING = "Accept-Encoding";
private static final String ACCEPT_HEADER = "Accept";
private static final String CONTENT_TYPE = "Content-type";
private static final String CONTENT_ENCODING = "Content-Encoding";
private static final String GZIP_TYPE = "gzip";
private static final String FASTINFOSET_TYPE = "application/fastinfoset";
private static final String XML_TYPE = "application/xml";
private static final String ANY_TYPE = "*/*";
private static final String PATH_TO_HANDLE = "/example";
private static final String PATH_TO_TIMEOUT = "/sendtimeout";
private final Logger logger = LoggerFactory.getLogger(ExampleHandler.class);
private final InputStreamConverter inputStreamConverter;
private final Decompressor fisDecompressor = new FastInfosetDecompressor();
private final GzipDecompressor gzipDecompresser = new GzipDecompressor();
private final GzipCompressor gzipCompressor = new GzipCompressor();
/**
* Constructor with InputStreamConverter.
* @param inputStreamConverter to inject
*/
public ExampleHandler(final InputStreamConverter inputStreamConverter) {
this.inputStreamConverter = inputStreamConverter;
}
@Override
public void handle(final String path, final Request baseRequest, final HttpServletRequest httpServletRequest,
final HttpServletResponse httpServletResponse) throws IOException, ServletException {
if (PATH_TO_HANDLE.equals(path) || PATH_OK.equals(path)) {
byte[] byteArray = null;
String requestBody = "";
String contentEncodingHeader = httpServletRequest.getHeader(CONTENT_ENCODING);
if (contentEncodingHeader != null && contentEncodingHeader.contains(GZIP_TYPE)) {
byteArray = gzipDecompresser.decompress(httpServletRequest.getInputStream()).toByteArray();
requestBody = IOUtils.toString(byteArray, "utf-8");
}
String headerField = httpServletRequest.getHeader(CONTENT_TYPE);
if (headerField != null && headerField.contains(FASTINFOSET_TYPE)) {
if (byteArray != null) {
requestBody = fisDecompressor.decompress(new ByteArrayInputStream(byteArray));
} else {
requestBody = fisDecompressor.decompress(httpServletRequest.getInputStream());
}
} else if (headerField != null && headerField.contains(XML_TYPE)) {
if (byteArray == null) {
requestBody = inputStreamConverter.getStringFromStream(httpServletRequest.getInputStream());
}
}
if (PATH_OK.equals(path)) {
//ok, send back the test server version
requestBody = getClass().getPackage().getImplementationTitle();
}
if ("".equals(requestBody)) {
ByteArrayOutputStream writer = new ByteArrayOutputStream();
IOUtils.copy(httpServletRequest.getInputStream(), writer);
requestBody = IOUtils.toString(writer.toByteArray(), "utf-8"); //default request body content
}
setAnswer(baseRequest, httpServletRequest, httpServletResponse, requestBody);
} else if (baseRequest.getRequestURI().startsWith(PATH_REPLICATOR)) {
//send a replicator answer back
InputStream json = getXmlFromFile(EXAMPLE_JSON); //getXml? who cares
httpServletResponse.setContentType("application/json");
httpServletResponse.setCharacterEncoding("UTF-8");
byte[] responseBodyAsBytes = IOUtils.toByteArray(json, json.available());
//Encodes response body with gzip if client accepts gzip encoding
if (httpServletRequest.getHeader(ACCEPT_ENCODING) != null && httpServletRequest.getHeader(ACCEPT_ENCODING).contains(GZIP_TYPE)) {
ByteArrayOutputStream gzipped = gzipCompressor.compress(new ByteArrayInputStream(responseBodyAsBytes));
responseBodyAsBytes = gzipped.toByteArray();
httpServletResponse.addHeader(CONTENT_ENCODING, GZIP_TYPE);
}
httpServletResponse.getOutputStream().write(responseBodyAsBytes);
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
} else {
generateBadResponses(path, httpServletRequest, httpServletResponse, baseRequest);
generateErrorCode(path, httpServletResponse);
}
}
private void generateBadResponses(String path, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Request baseRequest) throws IOException {
if (PATH_SEND_BAD_FIS.equals(path)) {
byte[] responseBodyAsBytes;
if (httpServletRequest.getHeader(ACCEPT_HEADER).contains(FASTINFOSET_TYPE)) {
InputStream xml = getXmlFromFile(EXAMPLE_XML);
httpServletResponse.setContentType("application/fastinfoset");
httpServletResponse.setCharacterEncoding("UTF-8");
responseBodyAsBytes = IOUtils.toByteArray(xml, xml.available());
//Encodes response body with gzip if client accepts gzip encoding
if (httpServletRequest.getHeader(ACCEPT_ENCODING) != null && httpServletRequest.getHeader(ACCEPT_ENCODING).contains(GZIP_TYPE)) {
ByteArrayOutputStream gzipped = gzipCompressor.compress(new ByteArrayInputStream(responseBodyAsBytes));
responseBodyAsBytes = gzipped.toByteArray();
httpServletResponse.addHeader(CONTENT_ENCODING, GZIP_TYPE);
}
httpServletResponse.getOutputStream().write(responseBodyAsBytes);
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
}
}
}
private void generateErrorCode(final String path, final HttpServletResponse httpServletResponse)
throws ServletException, IOException {
if (PATH_TO_TIMEOUT.equals(path)) {
try {
Thread.sleep(WAIT_IN_MILLIS);
} catch (Exception e) {
throw new ServletException("Thread's wait failed....", e);
}
} else if (PATH_INTERNAL_SERVER_ERROR.equals(path)) {
httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} else if (PATH_SERVICE_UNAVAILABLE.equals(path)) {
httpServletResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} else if (PATH_BAD_GATWAY.equals(path)) {
httpServletResponse.sendError(HttpServletResponse.SC_BAD_GATEWAY);
} else if (PATH_NOT_IMPLEMENTED.equals(path)) {
httpServletResponse.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
}
}
private void setAnswer(final Request baseRequest, final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse,
final String requestBody) throws IOException {
boolean needVersionAnswer = requestBody.contains("Wilma Test Server");
if (answerShouldBeSent(requestBody) || needVersionAnswer) {
byte[] responseBodyAsBytes = null;
if (((httpServletRequest.getHeader(CONTENT_TYPE) != null) && (httpServletRequest.getHeader(CONTENT_TYPE).contains("text/plain")))
|| (needVersionAnswer)) {
//just send the request back + Wilma-Logger-ID in front, if exists
String answer = requestBody;
if (httpServletRequest.getHeader(WILMA_LOGGER_ID) != null) {
answer = httpServletRequest.getHeader(WILMA_LOGGER_ID) + " " + requestBody;
}
httpServletResponse.setContentType("text/plain");
httpServletResponse.setCharacterEncoding("UTF-8");
responseBodyAsBytes = answer.getBytes();
logger.info("Received message:\n-----------\n" + requestBody + "\n-----------");
} else if (httpServletRequest.getHeader(ACCEPT_HEADER) == null) {
httpServletResponse.getWriter().println("Missing accept header!");
} else if (httpServletRequest.getHeader(ACCEPT_HEADER).contains(XML_TYPE) || httpServletRequest.getHeader(ACCEPT_HEADER).contains(ANY_TYPE)) {
InputStream xml = getXmlFromFile(EXAMPLE_XML);
httpServletResponse.setContentType("application/xml;charset=UTF-8");
responseBodyAsBytes = (inputStreamConverter.getStringFromStream(xml)).getBytes();
} else if (httpServletRequest.getHeader(ACCEPT_HEADER).contains(FASTINFOSET_TYPE)) {
InputStream xml = getXmlFromFile(FIS_RESPONSE);
httpServletResponse.setContentType("application/fastinfoset");
httpServletResponse.setCharacterEncoding("UTF-8");
responseBodyAsBytes = IOUtils.toByteArray(xml, xml.available());
}
if (responseBodyAsBytes != null) {
//first copy wilma message id to the response, if necessary
if (httpServletRequest.getHeader(WILMA_LOGGER_ID) != null) {
httpServletResponse.addHeader(WILMA_LOGGER_ID, httpServletRequest.getHeader(WILMA_LOGGER_ID));
}
//Encodes response body with gzip if client accepts gzip encoding
if (httpServletRequest.getHeader(ACCEPT_ENCODING) != null && httpServletRequest.getHeader(ACCEPT_ENCODING).contains(GZIP_TYPE)) {
ByteArrayOutputStream gzipped = gzipCompressor.compress(new ByteArrayInputStream(responseBodyAsBytes));
responseBodyAsBytes = gzipped.toByteArray();
httpServletResponse.addHeader(CONTENT_ENCODING, GZIP_TYPE);
}
httpServletResponse.getOutputStream().write(responseBodyAsBytes);
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
}
}
}
private boolean answerShouldBeSent(final String requestBody) {
return requestBody.contains("exampleID=\"123\"") || requestBody.contains("exampleID=\"456\"")
|| requestBody.contains("<exampleID2>101</exampleID2>") || requestBody.contains("NEED_ANSWER");
}
InputStream getXmlFromFile(final String filename) {
return this.getClass().getClassLoader().getResourceAsStream(filename);
}
}