// // ======================================================================== // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.http.gzip; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.Set; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import org.eclipse.jetty.util.StringUtil; /*------------------------------------------------------------ */ /** */ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapper { public static final int DEFAULT_BUFFER_SIZE = 8192; public static final int DEFAULT_MIN_COMPRESS_SIZE = 256; private Set _mimeTypes; private int _bufferSize=DEFAULT_BUFFER_SIZE; private int _minCompressSize=DEFAULT_MIN_COMPRESS_SIZE; protected HttpServletRequest _request; private PrintWriter _writer; private AbstractCompressedStream _compressedStream; private String _etag; private long _contentLength=-1; private boolean _noCompression; /* ------------------------------------------------------------ */ public CompressedResponseWrapper(HttpServletRequest request, HttpServletResponse response) { super(response); _request = request; } /* ------------------------------------------------------------ */ public long getContentLength() { return _contentLength; } /* ------------------------------------------------------------ */ public int getBufferSize() { return _bufferSize; } /* ------------------------------------------------------------ */ public int getMinCompressSize() { return _minCompressSize; } /* ------------------------------------------------------------ */ public String getETag() { return _etag; } /* ------------------------------------------------------------ */ public HttpServletRequest getRequest() { return _request; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMimeTypes(java.util.Set) */ public void setMimeTypes(Set mimeTypes) { _mimeTypes = mimeTypes; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setBufferSize(int) */ @Override public void setBufferSize(int bufferSize) { _bufferSize = bufferSize; if (_compressedStream!=null) _compressedStream.setBufferSize(bufferSize); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMinCompressSize(int) */ public void setMinCompressSize(int minCompressSize) { _minCompressSize = minCompressSize; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentType(java.lang.String) */ @Override public void setContentType(String ct) { super.setContentType(ct); if (!_noCompression) { if (ct!=null) { int colon=ct.indexOf(";"); if (colon>0) ct=ct.substring(0,colon); } if ((_compressedStream==null || _compressedStream.getOutputStream()==null) && (_mimeTypes==null && ct!=null && ct.contains("gzip") || _mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct))))) { noCompression(); } } } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int, java.lang.String) */ @Override public void setStatus(int sc, String sm) { super.setStatus(sc,sm); if (sc<200 || sc==204 || sc==205 || sc>=300) noCompression(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int) */ @Override public void setStatus(int sc) { super.setStatus(sc); if (sc<200 || sc==204 || sc==205 || sc>=300) noCompression(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentLength(int) */ @Override public void setContentLength(int length) { if (_noCompression) super.setContentLength(length); else setContentLength((long)length); } /* ------------------------------------------------------------ */ protected void setContentLength(long length) { _contentLength=length; if (_compressedStream!=null) _compressedStream.setContentLength(); else if (_noCompression && _contentLength>=0) { HttpServletResponse response = (HttpServletResponse)getResponse(); if(_contentLength=0) { if (_contentLength < Integer.MAX_VALUE) super.setContentLength((int)_contentLength); else super.setHeader("Content-Length",Long.toString(_contentLength)); } if(_etag!=null) super.setHeader("ETag",_etag); } } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setHeader(java.lang.String, java.lang.String) */ @Override public void setHeader(String name, String value) { if (_noCompression) super.setHeader(name,value); else if ("content-length".equalsIgnoreCase(name)) { setContentLength(Long.parseLong(value)); } else if ("content-type".equalsIgnoreCase(name)) { setContentType(value); } else if ("content-encoding".equalsIgnoreCase(name)) { super.setHeader(name,value); if (!isCommitted()) { noCompression(); } } else if ("etag".equalsIgnoreCase(name)) _etag=value; else super.setHeader(name,value); } /* ------------------------------------------------------------ */ @Override public boolean containsHeader(String name) { if (!_noCompression && "etag".equalsIgnoreCase(name) && _etag!=null) return true; return super.containsHeader(name); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getOutputStream() */ @Override public ServletOutputStream getOutputStream() throws IOException { if (_compressedStream==null) { if (getResponse().isCommitted() || _noCompression) return getResponse().getOutputStream(); _compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse()); } else if (_writer!=null) throw new IllegalStateException("getWriter() called"); return _compressedStream; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getWriter() */ @Override public PrintWriter getWriter() throws IOException { if (_writer==null) { if (_compressedStream!=null) throw new IllegalStateException("getOutputStream() called"); if (getResponse().isCommitted() || _noCompression) return getResponse().getWriter(); _compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse()); _writer=newWriter(_compressedStream,getCharacterEncoding()); } return _writer; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setIntHeader(java.lang.String, int) */ @Override public void setIntHeader(String name, int value) { if ("content-length".equalsIgnoreCase(name)) { _contentLength=value; if (_compressedStream!=null) _compressedStream.setContentLength(); } else super.setIntHeader(name,value); } /* ------------------------------------------------------------ */ /** * Allows derived implementations to replace PrintWriter implementation. * * @param out the out * @param encoding the encoding * @return the prints the writer * @throws UnsupportedEncodingException the unsupported encoding exception */ protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException { return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding)); } /* ------------------------------------------------------------ */ /** *@return the underlying CompressedStream implementation */ protected abstract AbstractCompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response) throws IOException; }