View Javadoc

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  
19  package org.eclipse.jetty.servlets;
20  
21  import java.io.IOException;
22  import java.io.OutputStream;
23  import java.io.OutputStreamWriter;
24  import java.io.PrintWriter;
25  import java.io.UnsupportedEncodingException;
26  import java.util.zip.Deflater;
27  import java.util.zip.DeflaterOutputStream;
28  import java.util.zip.GZIPOutputStream;
29  
30  import javax.servlet.FilterConfig;
31  import javax.servlet.ServletException;
32  import javax.servlet.http.HttpServletRequest;
33  import javax.servlet.http.HttpServletResponse;
34  
35  import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
36  import org.eclipse.jetty.http.gzip.AbstractCompressedStream;
37  import 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   */
51  public 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 }