package org.openstack.atlas.api.filters;
import org.openstack.atlas.api.filters.helpers.AcceptTypes;
import org.openstack.atlas.api.filters.helpers.MediaType;
import org.openstack.atlas.api.filters.wrappers.BufferedRequestWrapper;
import org.openstack.atlas.api.helpers.reflection.UriClassDiscover;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JsonValidationFilter extends ValidationFilter {
private final Log LOG = LogFactory.getLog(JsonValidationFilter.class);
@Override
public void init(FilterConfig config) throws ServletException {
this.setConfig(config);
}
@Override
public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain fc) throws IOException, ServletException {
Class classForUri;
Object somePojo = null;
HttpServletRequest hreq = (HttpServletRequest) sreq;
HttpServletResponse hresp = (HttpServletResponse) sresp;
String accept = hreq.getHeader("Accept");
BufferedRequestWrapper breq = new BufferedRequestWrapper(hreq);
String body = readFromInputStream(breq.getInputStream());
String method = hreq.getMethod();
MediaType contentMedia = MediaType.newInstance(hreq.getContentType());
String overrideAccept;
AcceptTypes ats = AcceptTypes.getPrefferedAcceptTypes(accept);
String acceptType = ats.findSuitableMediaType(JSON, XML);
// TODO: Remove for production
if (isHeaderTrue(hreq, "bypass-vjson")) {
fc.doFilter(breq, sresp);
return;
}
if (acceptType == null) {
acceptType = JSON; // Default to Json
}
// Skip this filter if the request isn't XML
if (!MediaType.matches(contentMedia, MediaType.newInstance(JSON))) {
fc.doFilter(breq, sresp);
return;
}
if (method == null
|| containsMethod(method, "GET", "DELETE")
|| body.length() == 0) {
fc.doFilter(breq, sresp);
return;
}
overrideAccept = overideAcceptType(hreq.getRequestURI());
if (overrideAccept != null) {
acceptType = overrideAccept;
}
classForUri = UriClassDiscover.getClassForUri(hreq.getRequestURI());
if (classForUri == null) {
String errMsg = "JsonValidator could not determine the class to validate against: URI="
+ hreq.getRequestURI() + " : validation skipped.";
LOG.warn(errMsg);
fc.doFilter(breq, sresp);
return;
}
try {
somePojo = mapper.readValue(body, classForUri);
} catch (Exception ex) {
String errMsg = "JSON does not match the expected schema";
String logMsg = getExtendedStackTrace(ex);
LOG.error(logMsg);
if (acceptType.equalsIgnoreCase(XML)) {
sendXMLErrorResponse(hreq, hresp, BADREQ, errMsg);
return;
}
if (acceptType.equalsIgnoreCase(JSON)) {
sendJSONErrorResponse(hreq, hresp, BADREQ, errMsg);
return;
}
}
fc.doFilter(breq, sresp);
}
@Override
public void destroy() {
}
}