CompressResponseWrapper.java

package com.ziesemer.utils.web.compressFilter;

import java.io.Closeable;
import java.io.IOException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

/**
 * <p>{@link HttpServletResponseWrapper} that:<ul>
 * 	<li>passes the &quot;compressing&quot; {@link ServletOutputStream} to {@link HttpServletResponse#getOutputStream()}.</li>
 * 	<li>filters any attempt to call {@link HttpServletResponse#setContentLength(int)}
 * 		or otherwise set the &quot;Content-Length&quot; header.
 * 		(HTTP/1.1 &quot;chunked&quot; encoding will/must be used.  See
 * 		<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1">RFC 2616 section 3.6.1</a>.)</li>
 * </ul></p>
 * @author Mark A. Ziesemer
 * <a href="http://www.ziesemer.com">&lt;www.ziesemer.com&gt;</a>
 */
abstract class CompressResponseWrapper extends HttpServletResponseWrapper implements Closeable{
	
	protected final HttpServletResponse response;
	protected final String contentEncoding;
	
	protected ServletOutputStream encodingStream;

	CompressResponseWrapper(final HttpServletResponse response, final String contentEncoding){
		super(response);
		this.response = response;
		this.contentEncoding = contentEncoding;
	}
	
	@Override
	public ServletOutputStream getOutputStream() throws IOException{
		response.setHeader("Content-Encoding", contentEncoding);
		if(encodingStream == null){
			encodingStream = getEncodingOutputStream();
		}
		return encodingStream;
	}
	
	protected abstract ServletOutputStream getEncodingOutputStream() throws IOException;
	
	protected boolean filterHeader(final String name){
		return "Content-Length".equals(name);
	}
	
	@Override
	public void setContentLength(final int length){
		// Do not send.
	}
	
	@Override
	public void addHeader(final String name, final String value){
		if(!filterHeader(name)){
			super.addHeader(name, value);
		}
	}
	
	@Override
	public void addIntHeader(final String name, final int value){
		if(!filterHeader(name)){
			super.addIntHeader(name, value);
		}
	}
	
	@Override
	public void setHeader(final String name, final String value){
		if(!filterHeader(name)){
			super.setHeader(name, value);
		}
	}
	
	@Override
	public void setIntHeader(final String name, final int value){
		if(!filterHeader(name)){
			super.setIntHeader(name, value);
		}
	}
	
	public void close() throws IOException{
		if(encodingStream != null){
			encodingStream.close();
		}
	}
}