All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mortbay.servlet.GzipFilter Maven / Gradle / Ivy

There is a newer version: 7.0.0.pre5
Show newest version
//========================================================================
//Copyright 2007 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================
package org.mortbay.servlet;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.zip.GZIPOutputStream;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.mortbay.util.ByteArrayOutputStream2;
import org.mortbay.util.StringUtil;

/* ------------------------------------------------------------ */
/** GZIP Filter
 * This filter will gzip the content of a response iff: 
    *
  • The filter is mapped to a matching path
  • *
  • The response status code is >=200 and <300 *
  • The content length is unknown or more than the minGzipSize initParameter or the minGzipSize is 0(default)
  • *
  • The content-type is in the comma separated list of mimeTypes set in the mimeTypes initParameter or * if no mimeTypes are defined the content-type is not "application/gzip"
  • *
  • No content-encoding is specified by the resource
  • *
* *

* Compressing the content can greatly improve the network bandwidth usage, but at a cost of memory and * CPU cycles. If this filter is mapped for static content, then use of efficient direct NIO may be * prevented, thus use of the gzip mechanism of the {@link org.mortbay.jetty.servlet.DefaultServlet} is * advised instead. *

*

* This filter extends {@link UserAgentFilter} and if the the initParameter excludedAgents * is set to a comma separated list of user agents, then these agents will be excluded from gzip content. *

* * @author gregw * */ public class GzipFilter extends UserAgentFilter { protected Set _mimeTypes; protected int _bufferSize=8192; protected int _minGzipSize=0; protected Set _excluded; public void init(FilterConfig filterConfig) throws ServletException { super.init(filterConfig); String tmp=filterConfig.getInitParameter("bufferSize"); if (tmp!=null) _bufferSize=Integer.parseInt(tmp); tmp=filterConfig.getInitParameter("minGzipSize"); if (tmp!=null) _minGzipSize=Integer.parseInt(tmp); tmp=filterConfig.getInitParameter("mimeTypes"); if (tmp!=null) { _mimeTypes=new HashSet(); StringTokenizer tok = new StringTokenizer(tmp,",",false); while (tok.hasMoreTokens()) _mimeTypes.add(tok.nextToken()); } tmp=filterConfig.getInitParameter("excludedAgents"); if (tmp!=null) { _excluded=new HashSet(); StringTokenizer tok = new StringTokenizer(tmp,",",false); while (tok.hasMoreTokens()) _excluded.add(tok.nextToken()); } } public void destroy() { } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest)req; HttpServletResponse response=(HttpServletResponse)res; String ae = request.getHeader("accept-encoding"); Boolean gzip=(Boolean)request.getAttribute("GzipFilter"); if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding") && (gzip==null || gzip.booleanValue()) && !"HEAD".equalsIgnoreCase(request.getMethod())) { if (_excluded!=null) { String ua=getUserAgent(request); if (_excluded.contains(ua)) { super.doFilter(request,response,chain); return; } } GZIPResponseWrapper wrappedResponse=newGZIPResponseWrapper(request,response); boolean exceptional=true; try { super.doFilter(request,wrappedResponse,chain); exceptional=false; } catch(RuntimeException e) { request.setAttribute("GzipFilter",Boolean.FALSE); if (!response.isCommitted()) response.reset(); throw e; } finally { if (exceptional && !response.isCommitted()) { wrappedResponse.resetBuffer(); wrappedResponse.noGzip(); } else wrappedResponse.finish(); } } else { super.doFilter(request,response,chain); } } protected GZIPResponseWrapper newGZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response) { return new GZIPResponseWrapper(request,response); } /* * Allows derived implementations to replace PrintWriter implementation */ protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException { return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding)); } public class GZIPResponseWrapper extends HttpServletResponseWrapper { HttpServletRequest _request; boolean _noGzip; PrintWriter _writer; GzipStream _gzStream; long _contentLength=-1; public GZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response) { super(response); _request=request; } public void setContentType(String ct) { super.setContentType(ct); if (ct!=null) { int colon=ct.indexOf(";"); if (colon>0) ct=ct.substring(0,colon); } if ((_gzStream==null || _gzStream._out==null) && (_mimeTypes==null && "application/gzip".equalsIgnoreCase(ct) || _mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct))))) { noGzip(); } } public void setStatus(int sc, String sm) { super.setStatus(sc,sm); if (sc<200||sc>=300) noGzip(); } public void setStatus(int sc) { super.setStatus(sc); if (sc<200||sc>=300) noGzip(); } public void setContentLength(int length) { _contentLength=length; if (_gzStream!=null) _gzStream.setContentLength(length); } public void addHeader(String name, String value) { if ("content-length".equalsIgnoreCase(name)) { _contentLength=Long.parseLong(value); if (_gzStream!=null) _gzStream.setContentLength(_contentLength); } else if ("content-type".equalsIgnoreCase(name)) { setContentType(value); } else if ("content-encoding".equalsIgnoreCase(name)) { super.addHeader(name,value); if (!isCommitted()) { noGzip(); } } else super.addHeader(name,value); } public void setHeader(String name, String value) { if ("content-length".equalsIgnoreCase(name)) { _contentLength=Long.parseLong(value); if (_gzStream!=null) _gzStream.setContentLength(_contentLength); } else if ("content-type".equalsIgnoreCase(name)) { setContentType(value); } else if ("content-encoding".equalsIgnoreCase(name)) { super.setHeader(name,value); if (!isCommitted()) { noGzip(); } } else super.setHeader(name,value); } public void setIntHeader(String name, int value) { if ("content-length".equalsIgnoreCase(name)) { _contentLength=value; if (_gzStream!=null) _gzStream.setContentLength(_contentLength); } else super.setIntHeader(name,value); } public void flushBuffer() throws IOException { if (_writer!=null) _writer.flush(); if (_gzStream!=null) _gzStream.finish(); else getResponse().flushBuffer(); } public void reset() { super.reset(); if (_gzStream!=null) _gzStream.resetBuffer(); _writer=null; _gzStream=null; _noGzip=false; _contentLength=-1; } public void resetBuffer() { super.resetBuffer(); if (_gzStream!=null) _gzStream.resetBuffer(); _writer=null; _gzStream=null; } public void sendError(int sc, String msg) throws IOException { resetBuffer(); super.sendError(sc,msg); } public void sendError(int sc) throws IOException { resetBuffer(); super.sendError(sc); } public void sendRedirect(String location) throws IOException { resetBuffer(); super.sendRedirect(location); } public ServletOutputStream getOutputStream() throws IOException { if (_gzStream==null) { if (getResponse().isCommitted() || _noGzip) return getResponse().getOutputStream(); _gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize); } else if (_writer!=null) throw new IllegalStateException("getWriter() called"); return _gzStream; } public PrintWriter getWriter() throws IOException { if (_writer==null) { if (_gzStream!=null) throw new IllegalStateException("getOutputStream() called"); if (getResponse().isCommitted() || _noGzip) return getResponse().getWriter(); _gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize); _writer=newWriter(_gzStream,getCharacterEncoding()); } return _writer; } void noGzip() { _noGzip=true; if (_gzStream!=null) { try { _gzStream.doNotGzip(); } catch (IOException e) { throw new IllegalStateException(); } } } void finish() throws IOException { if (_writer!=null && !_gzStream._closed) _writer.flush(); if (_gzStream!=null) _gzStream.finish(); } protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException { return new GzipStream(request,response,contentLength,bufferSize,minGzipSize); } } public static class GzipStream extends ServletOutputStream { protected HttpServletRequest _request; protected HttpServletResponse _response; protected OutputStream _out; protected ByteArrayOutputStream2 _bOut; protected GZIPOutputStream _gzOut; protected boolean _closed; protected int _bufferSize; protected int _minGzipSize; protected long _contentLength; public GzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException { _request=request; _response=response; _contentLength=contentLength; _bufferSize=bufferSize; _minGzipSize=minGzipSize; if (minGzipSize==0) doGzip(); } public void resetBuffer() { _closed=false; _out=null; _bOut=null; if (_gzOut!=null && !_response.isCommitted()) _response.setHeader("Content-Encoding",null); _gzOut=null; } public void setContentLength(long length) { _contentLength=length; } public void flush() throws IOException { if (_out==null || _bOut!=null) { if (_contentLength>0 && _contentLength<_minGzipSize) doNotGzip(); else doGzip(); } _out.flush(); } public void close() throws IOException { if (_request.getAttribute("javax.servlet.include.request_uri")!=null) flush(); else { if (_bOut!=null) { if (_contentLength<0) _contentLength=_bOut.getCount(); if (_contentLength<_minGzipSize) doNotGzip(); else doGzip(); } else if (_out==null) { doNotGzip(); } if (_gzOut!=null) _gzOut.close(); else _out.close(); _closed=true; } } public void finish() throws IOException { if (!_closed) { if (_out==null || _bOut!=null) { if (_contentLength>0 && _contentLength<_minGzipSize) doNotGzip(); else doGzip(); } if (_gzOut!=null && !_closed) { _closed=true; _gzOut.close(); } } } public void write(int b) throws IOException { checkOut(1); _out.write(b); } public void write(byte b[]) throws IOException { checkOut(b.length); _out.write(b); } public void write(byte b[], int off, int len) throws IOException { checkOut(len); _out.write(b,off,len); } protected boolean setContentEncodingGzip() { _response.setHeader("Content-Encoding", "gzip"); return _response.containsHeader("Content-Encoding"); } public void doGzip() throws IOException { if (_gzOut==null) { if (_response.isCommitted()) throw new IllegalStateException(); if (setContentEncodingGzip()) { _out=_gzOut=new GZIPOutputStream(_response.getOutputStream(),_bufferSize); if (_bOut!=null) { _out.write(_bOut.getBuf(),0,_bOut.getCount()); _bOut=null; } } else doNotGzip(); } } public void doNotGzip() throws IOException { if (_gzOut!=null) throw new IllegalStateException(); if (_out==null || _bOut!=null ) { _out=_response.getOutputStream(); if (_contentLength>=0) { if(_contentLength=0 && _contentLength<_minGzipSize)) doNotGzip(); else if (length>_minGzipSize) doGzip(); else _out=_bOut=new ByteArrayOutputStream2(_bufferSize); } else if (_bOut!=null) { if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize)) doNotGzip(); else if (length>=(_bOut.getBuf().length-_bOut.getCount())) doGzip(); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy