public class CompressionResponseStream extends ServletOutputStream {
protected int compressionThreshold = 0;//
protected byte[] buffer = null;//
protected int bufferCount = 0; //
protected GZIPOutputStream gzipstream = null;
protected boolean closed = false;//
protected int length = -1;
protected HttpServletResponse response = null;
protected ServletOutputStream output = null;
public CompressionResponseStream(HttpServletResponse response)
throws IOException {
super();
closed = false;
this.response = response;
this.output = response.getOutputStream();
}
protected void setBuffer(int threshold) {
compressionThreshold = threshold;
buffer = new byte[compressionThreshold];
}
public void close() throws IOException {
if (closed) {
throw new IOException("This output stream has already been closed");
}
/*
* gzipstream null,
* , ,write gzipstream
*/
if (gzipstream != null) {
flushToGZip();
gzipstream.close();
gzipstream = null;
} else {
if (bufferCount > 0) {
output.write(buffer, 0, bufferCount);
bufferCount = 0;
}
}
output.close();
closed = true;
}
public void flush() throws IOException {
if (closed) {
throw new IOException("Can't flush a closed output stream");
}
if (gzipstream != null) {
gzipstream.flush();
}
}
/**
* buffer gzipstream
*
* @throws IOException
*/
public void flushToGZip() throws IOException {
if (bufferCount > 0) {
writeToGZip(buffer, 0, bufferCount);
bufferCount = 0;
}
}
@Override
public void write(int b) throws IOException {
if (closed) {
throw new IOException("Can't write to a closed output stream");
}
/*
* , buffer gzipstream
*/
if (bufferCount >= buffer.length) {
flushToGZip();
}
buffer[bufferCount++] = (byte) b;
}
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
if (closed) {
throw new IOException("Can't write to a closed output stream");
}
if (len == 0) {
return;
}
/*
* buffer , buffer
*/
if (len <= (buffer.length - bufferCount)) {
System.arraycopy(b, off, buffer, bufferCount, len);
bufferCount += len;
return;
}
/*
* buffer , buffer gzipstream
*/
flushToGZip();
/*
* buffer , buffer , buffer
*/
if (len <= (buffer.length - bufferCount)) {
System.arraycopy(b, off, buffer, bufferCount, len);
bufferCount += len;
return;
}
/*
* buffer , gzipstream
*/
writeToGZip(b, off, len);
}
/**
* gzipstream , gzips
*
* @param b
* @param off
* @param len
* @throws IOException
*/
public void writeToGZip(byte b[], int off, int len) throws IOException {
if (gzipstream == null) {
response.addHeader("Content-Encoding", "gzip");
gzipstream = new GZIPOutputStream(output);
}
gzipstream.write(b, off, len);
}
}
public class CompressionServletResponseWrapper extends
HttpServletResponseWrapper {
protected HttpServletResponse origResponse = null;
protected static final String info = "CompressionServletResponseWrapper";
protected ServletOutputStream stream = null;
protected PrintWriter writer = null;
protected int threshold = 0;
protected String contentType = null;
public CompressionServletResponseWrapper(HttpServletResponse response) {
super(response);
origResponse = response;
}
public void setContentType(String contentType) {
this.contentType = contentType;
origResponse.setContentType(contentType);
}
public void setCompressionThreshold(int threshold) {
this.threshold = threshold;
}
/**
* response
*
* @return
* @throws IOException
*/
public ServletOutputStream createOutputStream() throws IOException {
CompressionResponseStream stream = new CompressionResponseStream(
origResponse);
stream.setBuffer(threshold);
return stream;
}
/**
* Servlet ,Filter
*/
public void finishResponse() {
try {
if (writer != null) {
writer.close();
} else {
if (stream != null) {
stream.close();
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
/**
* flushBuffer
*/
public void flushBuffer() throws IOException {
((CompressionResponseStream) stream).flush();
}
/**
* getOutputStream
*/
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null) {
throw new IllegalStateException(
"getWriter() has already been called for this resposne");
}
if (stream == null) {
stream = createOutputStream();
}
return stream;
}
public PrintWriter getWriter() throws IOException {
if (writer != null) {
return writer;
}
if (stream != null) {
throw new IllegalStateException(
"getOutputStream() has already been called for this resposne");
}
stream = createOutputStream();
String charEnc = origResponse.getCharacterEncoding();
if (charEnc != null) {
writer = new PrintWriter(new OutputStreamWriter(stream, charEnc));
} else {
writer = new PrintWriter(stream);
}
return writer;
}
}
public class CompressionFilter implements Filter {
private FilterConfig config = null;
private int minThreshold = 128;
protected int compressionThreshold;
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
if (filterConfig != null) {
String str = filterConfig.getInitParameter("compressionThreshold");
if (compressionThreshold != 0 & compressionThreshold < minThreshold) {
compressionThreshold = minThreshold;
} else {
//
compressionThreshold = 0;
}
} else {
compressionThreshold = 0;
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
/*
*
*/
if (compressionThreshold == 0) {
chain.doFilter(request, response);
}
/*
* gzip
*/
boolean supportCompression = false;
if (request instanceof HttpServletRequest) {
Enumeration<String> e = ((HttpServletRequest) request)
.getHeaders("Accept-Encoding");
while (e.hasMoreElements()) {
String name = e.nextElement();
if (name.indexOf("gzip") != -1) {
supportCompression = true;
}
}
}
if (!supportCompression) {
chain.doFilter(request, response);
return;
} else {
if (response instanceof HttpServletResponse) {
/*
* Response
*/
CompressionServletResponseWrapper wrapperResponse =
new CompressionServletResponseWrapper(
(HttpServletResponse) response);
wrapperResponse.setCompressionThreshold(compressionThreshold);
try {
chain.doFilter(request, wrapperResponse);
} finally {
wrapperResponse.finishResponse();
}
}
return;
}
}
public void destroy() {
this.config = null;
}
}