/* * Copyright 2012 E.J.I.E., S.A. * * Licencia con arreglo a la EUPL, Versión 1.1 exclusivamente (la «Licencia»); * Solo podrá usarse esta obra si se respeta la Licencia. * Puede obtenerse una copia de la Licencia en * * http://ec.europa.eu/idabc/eupl.html * * Salvo cuando lo exija la legislación aplicable o se acuerde por escrito, * el programa distribuido con arreglo a la Licencia se distribuye «TAL CUAL», * SIN GARANTÍAS NI CONDICIONES DE NINGÚN TIPO, ni expresas ni implícitas. * Véase la Licencia en el idioma concreto que rige los permisos y limitaciones * que establece la Licencia. */ package com.ejie.x38; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import org.springframework.web.filter.DelegatingFilterProxy; import com.ejie.x38.util.IframeXHREmulationUtils; /** * Filtro encargado de modificar la request en caso de que sea necesaria emular * el comportamiento de la gestión de errores HTTP al utilizar iframes. * * @author UDA * */ public class IframeXHREmulationFilter extends DelegatingFilterProxy { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { // Se comprueba si es necesario realizar la emulación. if (IframeXHREmulationUtils.isIframeEmulationRequired(request)){ HttpServletResponse httpServletResponse = (HttpServletResponse)response; // Se genera un wrapper de la response para poder insertar la respuesta indicada en la response dentro de la estructura necesaria. IframeXHREmulationFilter.GenericResponseWrapper wrapper = new IframeXHREmulationFilter.GenericResponseWrapper(httpServletResponse); // Se continúa con la ejecución de la petición. filterChain.doFilter(request, wrapper); // Se escribe la respuesta correspondiente en la response. IframeXHREmulationUtils.writeIframeHttpStatus(httpServletResponse, wrapper.getData(), wrapper.getStatus()); }else{ // En caso de no ser necesaria la emulación se continua con la ejecución. filterChain.doFilter(request, response); } } /** * Wrapper de la response http para permitir su modificación en el proceso * de emular la gestión de errores, del mismo modo que se realiza en * peticiones XHR, en las realizadas mediante iframes. * * @author UDA * */ private class GenericResponseWrapper extends HttpServletResponseWrapper { /** * OutputStream utilizado para almacenar el contenido que se va a * incluir en la request. */ private ByteArrayOutputStream output; /** * ContentType de la request */ private String contentType; /** * Coódigo de error HTTP que se debe de incluir en el contenido de la respuesta final. */ private int httpStatus; /** * Constructor. Recibe como parámetro la response que se va a arropar. * * @param response * Response http. */ public GenericResponseWrapper(HttpServletResponse response) { super(response); output = new ByteArrayOutputStream(); } /** * Devuelve el contenido de la response escrito hasta el momento. * * @return Representación mediante un array de bytes del contenido de la * response. */ public byte[] getData() { return output.toByteArray(); } /** * Devuelve un outputStream para poder escribir el contenido de la * response. */ public ServletOutputStream getOutputStream() { return new FilterServletOutputStream(output); } /** * Devuelve un PrintWriter para poder escribir el contenido de la * response. */ public PrintWriter getWriter() { return new PrintWriter(getOutputStream(), true); } @Override public void setContentType(String type) { this.contentType = type; super.setContentType(type); } @Override public String getContentType() { return contentType; } @Override public void sendError(int sc) throws IOException { httpStatus = sc; super.sendError(sc); } @Override public void sendError(int sc, String msg) throws IOException { httpStatus = sc; super.sendError(sc, msg); } @Override public void setStatus(int sc) { httpStatus = sc; } /** * Getter de la propiedad httpStatus. * * @return Código de estado http. */ public int getStatus() { return httpStatus; } } /** * OutputStream utilizado en el wrapper de la request utilizado en la emulación. * * @author UDA * */ private class FilterServletOutputStream extends ServletOutputStream { /** * DataOutputStream */ private DataOutputStream stream; /** * Constructor. Genera un nuevo OutputStream a partir del indicado como * parámetro * * @param output * OutputStream utilizado para inicializar el nuevo. */ public FilterServletOutputStream(OutputStream output) { stream = new DataOutputStream(output); } @Override public void write(int b) throws IOException { stream.write(b); } @Override public void write(byte[] b) throws IOException { stream.write(b); } @Override public void write(byte[] b, int off, int len) throws IOException { stream.write(b, off, len); } } }