103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.http.gzip;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.OutputStream;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.OutputStreamWriter;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.PrintWriter;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.UnsupportedEncodingException;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set;
2703928aee4356845252ac6b662d5c72c29903813eJake Slack
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletOutputStream;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletRequest;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletResponse;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletResponseWrapper;
3203928aee4356845252ac6b662d5c72c29903813eJake Slack
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.StringUtil;
3403928aee4356845252ac6b662d5c72c29903813eJake Slack
3503928aee4356845252ac6b662d5c72c29903813eJake Slack/*------------------------------------------------------------ */
3603928aee4356845252ac6b662d5c72c29903813eJake Slack/**
3703928aee4356845252ac6b662d5c72c29903813eJake Slack */
3803928aee4356845252ac6b662d5c72c29903813eJake Slackpublic abstract class CompressedResponseWrapper extends HttpServletResponseWrapper
3903928aee4356845252ac6b662d5c72c29903813eJake Slack{
4003928aee4356845252ac6b662d5c72c29903813eJake Slack
4103928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final int DEFAULT_BUFFER_SIZE = 8192;
4203928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final int DEFAULT_MIN_COMPRESS_SIZE = 256;
4303928aee4356845252ac6b662d5c72c29903813eJake Slack
4403928aee4356845252ac6b662d5c72c29903813eJake Slack    private Set<String> _mimeTypes;
4503928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _bufferSize=DEFAULT_BUFFER_SIZE;
4603928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _minCompressSize=DEFAULT_MIN_COMPRESS_SIZE;
4703928aee4356845252ac6b662d5c72c29903813eJake Slack    protected HttpServletRequest _request;
4803928aee4356845252ac6b662d5c72c29903813eJake Slack
4903928aee4356845252ac6b662d5c72c29903813eJake Slack    private PrintWriter _writer;
5003928aee4356845252ac6b662d5c72c29903813eJake Slack    private AbstractCompressedStream _compressedStream;
5103928aee4356845252ac6b662d5c72c29903813eJake Slack    private String _etag;
5203928aee4356845252ac6b662d5c72c29903813eJake Slack    private long _contentLength=-1;
5303928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _noCompression;
5403928aee4356845252ac6b662d5c72c29903813eJake Slack
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
5603928aee4356845252ac6b662d5c72c29903813eJake Slack    public CompressedResponseWrapper(HttpServletRequest request, HttpServletResponse response)
5703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
5803928aee4356845252ac6b662d5c72c29903813eJake Slack        super(response);
5903928aee4356845252ac6b662d5c72c29903813eJake Slack        _request = request;
6003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6103928aee4356845252ac6b662d5c72c29903813eJake Slack
6203928aee4356845252ac6b662d5c72c29903813eJake Slack
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getContentLength()
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
6603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _contentLength;
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6803928aee4356845252ac6b662d5c72c29903813eJake Slack
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getBufferSize()
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _bufferSize;
7303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7403928aee4356845252ac6b662d5c72c29903813eJake Slack
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getMinCompressSize()
7703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _minCompressSize;
7903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8003928aee4356845252ac6b662d5c72c29903813eJake Slack
8103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getETag()
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _etag;
8503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8603928aee4356845252ac6b662d5c72c29903813eJake Slack
8703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8803928aee4356845252ac6b662d5c72c29903813eJake Slack    public HttpServletRequest getRequest()
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _request;
9103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9203928aee4356845252ac6b662d5c72c29903813eJake Slack
9303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
9503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMimeTypes(java.util.Set)
9603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
9703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setMimeTypes(Set<String> mimeTypes)
9803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9903928aee4356845252ac6b662d5c72c29903813eJake Slack        _mimeTypes = mimeTypes;
10003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10103928aee4356845252ac6b662d5c72c29903813eJake Slack
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
10403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setBufferSize(int)
10503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
10603928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setBufferSize(int bufferSize)
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10903928aee4356845252ac6b662d5c72c29903813eJake Slack        _bufferSize = bufferSize;
11003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_compressedStream!=null)
11103928aee4356845252ac6b662d5c72c29903813eJake Slack            _compressedStream.setBufferSize(bufferSize);
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11303928aee4356845252ac6b662d5c72c29903813eJake Slack
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
11603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMinCompressSize(int)
11703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
11803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setMinCompressSize(int minCompressSize)
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12003928aee4356845252ac6b662d5c72c29903813eJake Slack        _minCompressSize = minCompressSize;
12103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12203928aee4356845252ac6b662d5c72c29903813eJake Slack
12303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
12403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
12503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentType(java.lang.String)
12603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
12703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setContentType(String ct)
12903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13003928aee4356845252ac6b662d5c72c29903813eJake Slack        super.setContentType(ct);
13103928aee4356845252ac6b662d5c72c29903813eJake Slack
13203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!_noCompression)
13303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
13403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (ct!=null)
13503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
13603928aee4356845252ac6b662d5c72c29903813eJake Slack                int colon=ct.indexOf(";");
13703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (colon>0)
13803928aee4356845252ac6b662d5c72c29903813eJake Slack                    ct=ct.substring(0,colon);
13903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
14003928aee4356845252ac6b662d5c72c29903813eJake Slack
14103928aee4356845252ac6b662d5c72c29903813eJake Slack            if ((_compressedStream==null || _compressedStream.getOutputStream()==null) &&
14203928aee4356845252ac6b662d5c72c29903813eJake Slack                    (_mimeTypes==null && ct!=null && ct.contains("gzip") ||
14303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
14403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
14503928aee4356845252ac6b662d5c72c29903813eJake Slack                noCompression();
14603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
14703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
14803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14903928aee4356845252ac6b662d5c72c29903813eJake Slack
15003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
15103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
15203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int, java.lang.String)
15303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
15403928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
15503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setStatus(int sc, String sm)
15603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15703928aee4356845252ac6b662d5c72c29903813eJake Slack        super.setStatus(sc,sm);
15803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (sc<200 || sc==204 || sc==205 || sc>=300)
15903928aee4356845252ac6b662d5c72c29903813eJake Slack            noCompression();
16003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16103928aee4356845252ac6b662d5c72c29903813eJake Slack
16203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
16403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int)
16503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
16603928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
16703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setStatus(int sc)
16803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16903928aee4356845252ac6b662d5c72c29903813eJake Slack        super.setStatus(sc);
17003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (sc<200 || sc==204 || sc==205 || sc>=300)
17103928aee4356845252ac6b662d5c72c29903813eJake Slack            noCompression();
17203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17303928aee4356845252ac6b662d5c72c29903813eJake Slack
17403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
17503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
17603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentLength(int)
17703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
17803928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
17903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setContentLength(int length)
18003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_noCompression)
18203928aee4356845252ac6b662d5c72c29903813eJake Slack            super.setContentLength(length);
18303928aee4356845252ac6b662d5c72c29903813eJake Slack        else
18403928aee4356845252ac6b662d5c72c29903813eJake Slack            setContentLength((long)length);
18503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
18603928aee4356845252ac6b662d5c72c29903813eJake Slack
18703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
18803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void setContentLength(long length)
18903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
19003928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentLength=length;
19103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_compressedStream!=null)
19203928aee4356845252ac6b662d5c72c29903813eJake Slack            _compressedStream.setContentLength();
19303928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (_noCompression && _contentLength>=0)
19403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
19503928aee4356845252ac6b662d5c72c29903813eJake Slack            HttpServletResponse response = (HttpServletResponse)getResponse();
19603928aee4356845252ac6b662d5c72c29903813eJake Slack            if(_contentLength<Integer.MAX_VALUE)
19703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
19803928aee4356845252ac6b662d5c72c29903813eJake Slack                response.setContentLength((int)_contentLength);
19903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
20003928aee4356845252ac6b662d5c72c29903813eJake Slack            else
20103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
20203928aee4356845252ac6b662d5c72c29903813eJake Slack                response.setHeader("Content-Length", Long.toString(_contentLength));
20303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
20403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20603928aee4356845252ac6b662d5c72c29903813eJake Slack
20703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
20903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#addHeader(java.lang.String, java.lang.String)
21003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
21103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
21203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addHeader(String name, String value)
21303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
21403928aee4356845252ac6b662d5c72c29903813eJake Slack        if ("content-length".equalsIgnoreCase(name))
21503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
21603928aee4356845252ac6b662d5c72c29903813eJake Slack            _contentLength=Long.parseLong(value);
21703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_compressedStream!=null)
21803928aee4356845252ac6b662d5c72c29903813eJake Slack                _compressedStream.setContentLength();
21903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22003928aee4356845252ac6b662d5c72c29903813eJake Slack        else if ("content-type".equalsIgnoreCase(name))
22103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22203928aee4356845252ac6b662d5c72c29903813eJake Slack            setContentType(value);
22303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22403928aee4356845252ac6b662d5c72c29903813eJake Slack        else if ("content-encoding".equalsIgnoreCase(name))
22503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22603928aee4356845252ac6b662d5c72c29903813eJake Slack            super.addHeader(name,value);
22703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!isCommitted())
22803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
22903928aee4356845252ac6b662d5c72c29903813eJake Slack                noCompression();
23003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
23103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
23203928aee4356845252ac6b662d5c72c29903813eJake Slack        else if ("etag".equalsIgnoreCase(name))
23303928aee4356845252ac6b662d5c72c29903813eJake Slack            _etag=value;
23403928aee4356845252ac6b662d5c72c29903813eJake Slack        else
23503928aee4356845252ac6b662d5c72c29903813eJake Slack            super.addHeader(name,value);
23603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
23703928aee4356845252ac6b662d5c72c29903813eJake Slack
23803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
23903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
24003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#flushBuffer()
24103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
24203928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
24303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void flushBuffer() throws IOException
24403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
24503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_writer!=null)
24603928aee4356845252ac6b662d5c72c29903813eJake Slack            _writer.flush();
24703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_compressedStream!=null)
24803928aee4356845252ac6b662d5c72c29903813eJake Slack            _compressedStream.flush();
24903928aee4356845252ac6b662d5c72c29903813eJake Slack        else
25003928aee4356845252ac6b662d5c72c29903813eJake Slack            getResponse().flushBuffer();
25103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
25203928aee4356845252ac6b662d5c72c29903813eJake Slack
25303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
25403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
25503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#reset()
25603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
25703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
25803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void reset()
25903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
26003928aee4356845252ac6b662d5c72c29903813eJake Slack        super.reset();
26103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_compressedStream!=null)
26203928aee4356845252ac6b662d5c72c29903813eJake Slack            _compressedStream.resetBuffer();
26303928aee4356845252ac6b662d5c72c29903813eJake Slack        _writer=null;
26403928aee4356845252ac6b662d5c72c29903813eJake Slack        _compressedStream=null;
26503928aee4356845252ac6b662d5c72c29903813eJake Slack        _noCompression=false;
26603928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentLength=-1;
26703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26803928aee4356845252ac6b662d5c72c29903813eJake Slack
26903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
27103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#resetBuffer()
27203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
27303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
27403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void resetBuffer()
27503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27603928aee4356845252ac6b662d5c72c29903813eJake Slack        super.resetBuffer();
27703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_compressedStream!=null)
27803928aee4356845252ac6b662d5c72c29903813eJake Slack            _compressedStream.resetBuffer();
27903928aee4356845252ac6b662d5c72c29903813eJake Slack        _writer=null;
28003928aee4356845252ac6b662d5c72c29903813eJake Slack        _compressedStream=null;
28103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
28203928aee4356845252ac6b662d5c72c29903813eJake Slack
28303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
28403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
28503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendError(int, java.lang.String)
28603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
28703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
28803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void sendError(int sc, String msg) throws IOException
28903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
29003928aee4356845252ac6b662d5c72c29903813eJake Slack        resetBuffer();
29103928aee4356845252ac6b662d5c72c29903813eJake Slack        super.sendError(sc,msg);
29203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29303928aee4356845252ac6b662d5c72c29903813eJake Slack
29403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
29503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
29603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendError(int)
29703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
29803928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
29903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void sendError(int sc) throws IOException
30003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30103928aee4356845252ac6b662d5c72c29903813eJake Slack        resetBuffer();
30203928aee4356845252ac6b662d5c72c29903813eJake Slack        super.sendError(sc);
30303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
30403928aee4356845252ac6b662d5c72c29903813eJake Slack
30503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
30703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendRedirect(java.lang.String)
30803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
30903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
31003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void sendRedirect(String location) throws IOException
31103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
31203928aee4356845252ac6b662d5c72c29903813eJake Slack        resetBuffer();
31303928aee4356845252ac6b662d5c72c29903813eJake Slack        super.sendRedirect(location);
31403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
31503928aee4356845252ac6b662d5c72c29903813eJake Slack
31603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
31703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
31803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#noCompression()
31903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
32003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void noCompression()
32103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
32203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!_noCompression)
32303928aee4356845252ac6b662d5c72c29903813eJake Slack            setDeferredHeaders();
32403928aee4356845252ac6b662d5c72c29903813eJake Slack        _noCompression=true;
32503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_compressedStream!=null)
32603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
32703928aee4356845252ac6b662d5c72c29903813eJake Slack            try
32803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
32903928aee4356845252ac6b662d5c72c29903813eJake Slack                _compressedStream.doNotCompress(false);
33003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
33103928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IOException e)
33203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
33303928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalStateException(e);
33403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
33503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
33603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
33703928aee4356845252ac6b662d5c72c29903813eJake Slack
33803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
33903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
34003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#finish()
34103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
34203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void finish() throws IOException
34303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
34403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_writer!=null && !_compressedStream.isClosed())
34503928aee4356845252ac6b662d5c72c29903813eJake Slack            _writer.flush();
34603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_compressedStream!=null)
34703928aee4356845252ac6b662d5c72c29903813eJake Slack            _compressedStream.finish();
34803928aee4356845252ac6b662d5c72c29903813eJake Slack        else
34903928aee4356845252ac6b662d5c72c29903813eJake Slack            setDeferredHeaders();
35003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
35103928aee4356845252ac6b662d5c72c29903813eJake Slack
35203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
35303928aee4356845252ac6b662d5c72c29903813eJake Slack    private void setDeferredHeaders()
35403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
35503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!isCommitted())
35603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
35703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contentLength>=0)
35803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
35903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_contentLength < Integer.MAX_VALUE)
36003928aee4356845252ac6b662d5c72c29903813eJake Slack                    super.setContentLength((int)_contentLength);
36103928aee4356845252ac6b662d5c72c29903813eJake Slack                else
36203928aee4356845252ac6b662d5c72c29903813eJake Slack                    super.setHeader("Content-Length",Long.toString(_contentLength));
36303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
36403928aee4356845252ac6b662d5c72c29903813eJake Slack            if(_etag!=null)
36503928aee4356845252ac6b662d5c72c29903813eJake Slack                super.setHeader("ETag",_etag);
36603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
36703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36803928aee4356845252ac6b662d5c72c29903813eJake Slack
36903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
37003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
37103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setHeader(java.lang.String, java.lang.String)
37203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
37303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
37403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setHeader(String name, String value)
37503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
37603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_noCompression)
37703928aee4356845252ac6b662d5c72c29903813eJake Slack            super.setHeader(name,value);
37803928aee4356845252ac6b662d5c72c29903813eJake Slack        else if ("content-length".equalsIgnoreCase(name))
37903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38003928aee4356845252ac6b662d5c72c29903813eJake Slack            setContentLength(Long.parseLong(value));
38103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
38203928aee4356845252ac6b662d5c72c29903813eJake Slack        else if ("content-type".equalsIgnoreCase(name))
38303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38403928aee4356845252ac6b662d5c72c29903813eJake Slack            setContentType(value);
38503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
38603928aee4356845252ac6b662d5c72c29903813eJake Slack        else if ("content-encoding".equalsIgnoreCase(name))
38703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38803928aee4356845252ac6b662d5c72c29903813eJake Slack            super.setHeader(name,value);
38903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!isCommitted())
39003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
39103928aee4356845252ac6b662d5c72c29903813eJake Slack                noCompression();
39203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
39303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
39403928aee4356845252ac6b662d5c72c29903813eJake Slack        else if ("etag".equalsIgnoreCase(name))
39503928aee4356845252ac6b662d5c72c29903813eJake Slack            _etag=value;
39603928aee4356845252ac6b662d5c72c29903813eJake Slack        else
39703928aee4356845252ac6b662d5c72c29903813eJake Slack            super.setHeader(name,value);
39803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
39903928aee4356845252ac6b662d5c72c29903813eJake Slack
40003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
40103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
40203928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean containsHeader(String name)
40303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
40403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!_noCompression && "etag".equalsIgnoreCase(name) && _etag!=null)
40503928aee4356845252ac6b662d5c72c29903813eJake Slack            return true;
40603928aee4356845252ac6b662d5c72c29903813eJake Slack        return super.containsHeader(name);
40703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
40803928aee4356845252ac6b662d5c72c29903813eJake Slack
40903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
41003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
41103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getOutputStream()
41203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
41303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
41403928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletOutputStream getOutputStream() throws IOException
41503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
41603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_compressedStream==null)
41703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
41803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (getResponse().isCommitted() || _noCompression)
41903928aee4356845252ac6b662d5c72c29903813eJake Slack                return getResponse().getOutputStream();
42003928aee4356845252ac6b662d5c72c29903813eJake Slack
42103928aee4356845252ac6b662d5c72c29903813eJake Slack            _compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
42203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
42303928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (_writer!=null)
42403928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("getWriter() called");
42503928aee4356845252ac6b662d5c72c29903813eJake Slack
42603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _compressedStream;
42703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
42803928aee4356845252ac6b662d5c72c29903813eJake Slack
42903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
43003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
43103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getWriter()
43203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
43303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
43403928aee4356845252ac6b662d5c72c29903813eJake Slack    public PrintWriter getWriter() throws IOException
43503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
43603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_writer==null)
43703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
43803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_compressedStream!=null)
43903928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalStateException("getOutputStream() called");
44003928aee4356845252ac6b662d5c72c29903813eJake Slack
44103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (getResponse().isCommitted() || _noCompression)
44203928aee4356845252ac6b662d5c72c29903813eJake Slack                return getResponse().getWriter();
44303928aee4356845252ac6b662d5c72c29903813eJake Slack
44403928aee4356845252ac6b662d5c72c29903813eJake Slack            _compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
44503928aee4356845252ac6b662d5c72c29903813eJake Slack            _writer=newWriter(_compressedStream,getCharacterEncoding());
44603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
44703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _writer;
44803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
44903928aee4356845252ac6b662d5c72c29903813eJake Slack
45003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
45103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
45203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setIntHeader(java.lang.String, int)
45303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
45403928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
45503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setIntHeader(String name, int value)
45603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
45703928aee4356845252ac6b662d5c72c29903813eJake Slack        if ("content-length".equalsIgnoreCase(name))
45803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
45903928aee4356845252ac6b662d5c72c29903813eJake Slack            _contentLength=value;
46003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_compressedStream!=null)
46103928aee4356845252ac6b662d5c72c29903813eJake Slack                _compressedStream.setContentLength();
46203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
46303928aee4356845252ac6b662d5c72c29903813eJake Slack        else
46403928aee4356845252ac6b662d5c72c29903813eJake Slack            super.setIntHeader(name,value);
46503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
46603928aee4356845252ac6b662d5c72c29903813eJake Slack
46703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
46803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
46903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Allows derived implementations to replace PrintWriter implementation.
47003928aee4356845252ac6b662d5c72c29903813eJake Slack     *
47103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param out the out
47203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param encoding the encoding
47303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return the prints the writer
47403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws UnsupportedEncodingException the unsupported encoding exception
47503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
47603928aee4356845252ac6b662d5c72c29903813eJake Slack    protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
47703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
47803928aee4356845252ac6b662d5c72c29903813eJake Slack        return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
47903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
48003928aee4356845252ac6b662d5c72c29903813eJake Slack
48103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
48203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
48303928aee4356845252ac6b662d5c72c29903813eJake Slack     *@return the underlying CompressedStream implementation
48403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
48503928aee4356845252ac6b662d5c72c29903813eJake Slack    protected abstract AbstractCompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response) throws IOException;
48603928aee4356845252ac6b662d5c72c29903813eJake Slack
48703928aee4356845252ac6b662d5c72c29903813eJake Slack}
488