1// 2// ======================================================================== 3// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 4// ------------------------------------------------------------------------ 5// All rights reserved. This program and the accompanying materials 6// are made available under the terms of the Eclipse Public License v1.0 7// and Apache License v2.0 which accompanies this distribution. 8// 9// The Eclipse Public License is available at 10// http://www.eclipse.org/legal/epl-v10.html 11// 12// The Apache License v2.0 is available at 13// http://www.opensource.org/licenses/apache2.0.php 14// 15// You may elect to redistribute this code under either of these licenses. 16// ======================================================================== 17// 18 19package org.eclipse.jetty.servlets; 20 21import java.io.IOException; 22import java.io.OutputStream; 23import java.io.OutputStreamWriter; 24import java.io.PrintWriter; 25import java.io.UnsupportedEncodingException; 26import java.util.zip.Deflater; 27import java.util.zip.DeflaterOutputStream; 28import java.util.zip.GZIPOutputStream; 29 30import javax.servlet.FilterConfig; 31import javax.servlet.ServletException; 32import javax.servlet.http.HttpServletRequest; 33import javax.servlet.http.HttpServletResponse; 34 35import org.eclipse.jetty.http.gzip.CompressedResponseWrapper; 36import org.eclipse.jetty.http.gzip.AbstractCompressedStream; 37import org.eclipse.jetty.io.UncheckedPrintWriter; 38 39/* ------------------------------------------------------------ */ 40/** Includable GZip Filter. 41 * This extension to the {@link GzipFilter} that uses Jetty features to allow 42 * headers to be set during calls to 43 * {@link javax.servlet.RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse)}. 44 * This allows the gzip filter to function correct during includes and to make a decision to gzip or not 45 * at the time the buffer fills and on the basis of all response headers. 46 * 47 * If the init parameter "uncheckedPrintWriter" is set to "true", then the PrintWriter used by 48 * the wrapped getWriter will be {@link UncheckedPrintWriter}. 49 * 50 */ 51public class IncludableGzipFilter extends GzipFilter 52{ 53 boolean _uncheckedPrintWriter=false; 54 55 @Override 56 public void init(FilterConfig filterConfig) throws ServletException 57 { 58 super.init(filterConfig); 59 60 String tmp=filterConfig.getInitParameter("uncheckedPrintWriter"); 61 if (tmp!=null) 62 _uncheckedPrintWriter=Boolean.valueOf(tmp).booleanValue(); 63 } 64 65 /* ------------------------------------------------------------ */ 66 /** 67 * @see org.eclipse.jetty.servlets.GzipFilter#createWrappedResponse(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String) 68 */ 69 @Override 70 protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType) 71 { 72 CompressedResponseWrapper wrappedResponse = null; 73 if (compressionType==null) 74 { 75 wrappedResponse = new IncludableResponseWrapper(request,response) 76 { 77 @Override 78 protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException 79 { 80 return new AbstractCompressedStream(null,request,this,_vary) 81 { 82 @Override 83 protected DeflaterOutputStream createStream() throws IOException 84 { 85 return null; 86 } 87 }; 88 } 89 }; 90 } 91 else if (compressionType.equals(GZIP)) 92 { 93 wrappedResponse = new IncludableResponseWrapper(request,response) 94 { 95 @Override 96 protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException 97 { 98 return new AbstractCompressedStream(compressionType,request,this,_vary) 99 { 100 @Override 101 protected DeflaterOutputStream createStream() throws IOException 102 { 103 return new GZIPOutputStream(_response.getOutputStream(),_bufferSize); 104 } 105 }; 106 } 107 }; 108 } 109 else if (compressionType.equals(DEFLATE)) 110 { 111 wrappedResponse = new IncludableResponseWrapper(request,response) 112 { 113 @Override 114 protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException 115 { 116 return new AbstractCompressedStream(compressionType,request,this,_vary) 117 { 118 @Override 119 protected DeflaterOutputStream createStream() throws IOException 120 { 121 return new DeflaterOutputStream(_response.getOutputStream(),new Deflater(_deflateCompressionLevel, _deflateNoWrap)); 122 } 123 }; 124 } 125 }; 126 } 127 else 128 { 129 throw new IllegalStateException(compressionType + " not supported"); 130 } 131 configureWrappedResponse(wrappedResponse); 132 return wrappedResponse; 133 } 134 135 136 // Extend CompressedResponseWrapper to be able to set headers during include and to create unchecked printwriters 137 private abstract class IncludableResponseWrapper extends CompressedResponseWrapper 138 { 139 public IncludableResponseWrapper(HttpServletRequest request, HttpServletResponse response) 140 { 141 super(request,response); 142 } 143 144 @Override 145 public void setHeader(String name,String value) 146 { 147 super.setHeader(name,value); 148 HttpServletResponse response = (HttpServletResponse)getResponse(); 149 if (!response.containsHeader(name)) 150 response.setHeader("org.eclipse.jetty.server.include."+name,value); 151 } 152 153 @Override 154 public void addHeader(String name, String value) 155 { 156 super.addHeader(name, value); 157 HttpServletResponse response = (HttpServletResponse)getResponse(); 158 if (!response.containsHeader(name)) 159 setHeader(name,value); 160 } 161 162 @Override 163 protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException 164 { 165 if (_uncheckedPrintWriter) 166 return encoding == null?new UncheckedPrintWriter(out):new UncheckedPrintWriter(new OutputStreamWriter(out,encoding)); 167 return super.newWriter(out,encoding); 168 } 169 } 170 171} 172