JETTY-1086 Added UncheckedPrintWriter to avoid ignored EOFs

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@753 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-08-24 05:00:38 +00:00
parent 347ea58a28
commit 463bf87ebf
11 changed files with 746 additions and 16 deletions

View File

@ -1,6 +1,7 @@
jetty-7.0.0-SNAPSHOT jetty-7.0.0-SNAPSHOT
+ 286911 Clean out cache when recycling HTTP fields + 286911 Clean out cache when recycling HTTP fields
+ JETTY-1081 Handle null content type in GzipFilter + JETTY-1081 Handle null content type in GzipFilter
+ JETTY-1086 Added UncheckedPrintWriter to avoid ignored EOFs
jetty-7.0.0.RC4 18 August 2009 jetty-7.0.0.RC4 18 August 2009
+ 286185 Implement ability for JSON implementation to automatically register convertors + 286185 Implement ability for JSON implementation to automatically register convertors

View File

@ -0,0 +1,43 @@
// ========================================================================
// Copyright (c) 2009-2009 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.io;
/* ------------------------------------------------------------ */
/**
* Subclass of {@link java.lang.RuntimeException} used to signal that there
* was an {@link java.io.IOException} thrown by underlying {@link java.io.Writer}
*/
public class RuntimeIOException extends RuntimeException
{
public RuntimeIOException()
{
super();
}
public RuntimeIOException(String message)
{
super(message);
}
public RuntimeIOException(Throwable cause)
{
super(cause);
}
public RuntimeIOException(String message, Throwable cause)
{
super(message,cause);
}
}

View File

@ -0,0 +1,536 @@
// ========================================================================
// Copyright (c) 2009-2009 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.io;
import java.io.BufferedWriter;
import java.io.InterruptedIOException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
/**
* A wrapper for the {@link java.io.PrintWriter} that re-throws the instances of
* {@link java.io.IOException} thrown by the underlying implementation of
* {@link java.io.Writer} as {@link RunimeIOException} instances.
*/
public class UncheckedPrintWriter extends PrintWriter
{
private boolean autoFlush = false;
/* ------------------------------------------------------------ */
/**
* Line separator string. This is the value of the line.separator
* property at the moment that the stream was created.
*/
private String lineSeparator;
public UncheckedPrintWriter (Writer out)
{
this(out, false);
}
/* ------------------------------------------------------------ */
/**
* Create a new PrintWriter.
*
* @param out A character-output stream
* @param autoFlush A boolean; if true, the println() methods will flush
* the output buffer
*/
public UncheckedPrintWriter(Writer out, boolean autoFlush)
{
super(out, autoFlush);
this.autoFlush = autoFlush;
this.lineSeparator = System.getProperty("line.separator");
}
/* ------------------------------------------------------------ */
/**
* Create a new PrintWriter, without automatic line flushing, from an
* existing OutputStream. This convenience constructor creates the
* necessary intermediate OutputStreamWriter, which will convert characters
* into bytes using the default character encoding.
*
* @param out An output stream
*
* @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
*/
public UncheckedPrintWriter(OutputStream out)
{
this(out, false);
}
/* ------------------------------------------------------------ */
/**
* Create a new PrintWriter from an existing OutputStream. This
* convenience constructor creates the necessary intermediate
* OutputStreamWriter, which will convert characters into bytes using the
* default character encoding.
*
* @param out An output stream
* @param autoFlush A boolean; if true, the println() methods will flush
* the output buffer
*
* @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
*/
public UncheckedPrintWriter(OutputStream out, boolean autoFlush)
{
this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);
}
/* ------------------------------------------------------------ */
/** Check to make sure that the stream has not been closed */
private void isOpen() throws IOException
{
if (super.out == null)
throw new IOException("Stream closed");
}
/* ------------------------------------------------------------ */
/**
* Flush the stream.
*/
public void flush() {
try {
synchronized (lock) {
isOpen();
out.flush();
}
}
catch (IOException ex) {
Log.debug(ex);
setError();
throw new RuntimeIOException(ex);
}
}
/* ------------------------------------------------------------ */
/**
* Close the stream.
*/
public void close() {
try {
synchronized (lock) {
out.close();
}
}
catch (IOException ex) {
Log.debug(ex);
setError();
throw new RuntimeIOException(ex);
}
}
/* ------------------------------------------------------------ */
/**
* Write a single character.
* @param c int specifying a character to be written.
*/
public void write(int c) {
try {
synchronized (lock) {
isOpen();
out.write(c);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException ex) {
Log.debug(ex);
setError();
throw new RuntimeIOException(ex);
}
}
/* ------------------------------------------------------------ */
/**
* Write a portion of an array of characters.
* @param buf Array of characters
* @param off Offset from which to start writing characters
* @param len Number of characters to write
*/
public void write(char buf[], int off, int len) {
try {
synchronized (lock) {
isOpen();
out.write(buf, off, len);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException ex) {
Log.debug(ex);
setError();
throw new RuntimeIOException(ex);
}
}
/* ------------------------------------------------------------ */
/**
* Write an array of characters. This method cannot be inherited from the
* Writer class because it must suppress I/O exceptions.
* @param buf Array of characters to be written
*/
public void write(char buf[]) {
this.write(buf, 0, buf.length);
}
/* ------------------------------------------------------------ */
/**
* Write a portion of a string.
* @param s A String
* @param off Offset from which to start writing characters
* @param len Number of characters to write
*/
public void write(String s, int off, int len) {
try {
synchronized (lock) {
isOpen();
out.write(s, off, len);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException ex) {
Log.debug(ex);
setError();
throw new RuntimeIOException(ex);
}
}
/* ------------------------------------------------------------ */
/**
* Write a string. This method cannot be inherited from the Writer class
* because it must suppress I/O exceptions.
* @param s String to be written
*/
public void write(String s) {
this.write(s, 0, s.length());
}
private void newLine() {
try {
synchronized (lock) {
isOpen();
out.write(lineSeparator);
if (autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException ex) {
Log.debug(ex);
setError();
throw new RuntimeIOException(ex);
}
}
/* Methods that do not terminate lines */
/* ------------------------------------------------------------ */
/**
* Print a boolean value. The string produced by <code>{@link
* java.lang.String#valueOf(boolean)}</code> is translated into bytes
* according to the platform's default character encoding, and these bytes
* are written in exactly the manner of the <code>{@link
* #write(int)}</code> method.
*
* @param b The <code>boolean</code> to be printed
*/
public void print(boolean b) {
this.write(b ? "true" : "false");
}
/* ------------------------------------------------------------ */
/**
* Print a character. The character is translated into one or more bytes
* according to the platform's default character encoding, and these bytes
* are written in exactly the manner of the <code>{@link
* #write(int)}</code> method.
*
* @param c The <code>char</code> to be printed
*/
public void print(char c) {
this.write(c);
}
/* ------------------------------------------------------------ */
/**
* Print an integer. The string produced by <code>{@link
* java.lang.String#valueOf(int)}</code> is translated into bytes according
* to the platform's default character encoding, and these bytes are
* written in exactly the manner of the <code>{@link #write(int)}</code>
* method.
*
* @param i The <code>int</code> to be printed
* @see java.lang.Integer#toString(int)
*/
public void print(int i) {
this.write(String.valueOf(i));
}
/* ------------------------------------------------------------ */
/**
* Print a long integer. The string produced by <code>{@link
* java.lang.String#valueOf(long)}</code> is translated into bytes
* according to the platform's default character encoding, and these bytes
* are written in exactly the manner of the <code>{@link #write(int)}</code>
* method.
*
* @param l The <code>long</code> to be printed
* @see java.lang.Long#toString(long)
*/
public void print(long l) {
this.write(String.valueOf(l));
}
/* ------------------------------------------------------------ */
/**
* Print a floating-point number. The string produced by <code>{@link
* java.lang.String#valueOf(float)}</code> is translated into bytes
* according to the platform's default character encoding, and these bytes
* are written in exactly the manner of the <code>{@link #write(int)}</code>
* method.
*
* @param f The <code>float</code> to be printed
* @see java.lang.Float#toString(float)
*/
public void print(float f) {
this.write(String.valueOf(f));
}
/* ------------------------------------------------------------ */
/**
* Print a double-precision floating-point number. The string produced by
* <code>{@link java.lang.String#valueOf(double)}</code> is translated into
* bytes according to the platform's default character encoding, and these
* bytes are written in exactly the manner of the <code>{@link
* #write(int)}</code> method.
*
* @param d The <code>double</code> to be printed
* @see java.lang.Double#toString(double)
*/
public void print(double d) {
this.write(String.valueOf(d));
}
/* ------------------------------------------------------------ */
/**
* Print an array of characters. The characters are converted into bytes
* according to the platform's default character encoding, and these bytes
* are written in exactly the manner of the <code>{@link #write(int)}</code>
* method.
*
* @param s The array of chars to be printed
*
* @throws NullPointerException If <code>s</code> is <code>null</code>
*/
public void print(char s[]) {
this.write(s);
}
/* ------------------------------------------------------------ */
/**
* Print a string. If the argument is <code>null</code> then the string
* <code>"null"</code> is printed. Otherwise, the string's characters are
* converted into bytes according to the platform's default character
* encoding, and these bytes are written in exactly the manner of the
* <code>{@link #write(int)}</code> method.
*
* @param s The <code>String</code> to be printed
*/
public void print(String s) {
if (s == null) {
s = "null";
}
this.write(s);
}
/* ------------------------------------------------------------ */
/**
* Print an object. The string produced by the <code>{@link
* java.lang.String#valueOf(Object)}</code> method is translated into bytes
* according to the platform's default character encoding, and these bytes
* are written in exactly the manner of the <code>{@link #write(int)}</code>
* method.
*
* @param obj The <code>Object</code> to be printed
* @see java.lang.Object#toString()
*/
public void print(Object obj) {
this.write(String.valueOf(obj));
}
/* Methods that do terminate lines */
/* ------------------------------------------------------------ */
/**
* Terminate the current line by writing the line separator string. The
* line separator string is defined by the system property
* <code>line.separator</code>, and is not necessarily a single newline
* character (<code>'\n'</code>).
*/
public void println() {
this.newLine();
}
/* ------------------------------------------------------------ */
/**
* Print a boolean value and then terminate the line. This method behaves
* as though it invokes <code>{@link #print(boolean)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x the <code>boolean</code> value to be printed
*/
public void println(boolean x) {
synchronized (lock) {
this.print(x);
this.println();
}
}
/* ------------------------------------------------------------ */
/**
* Print a character and then terminate the line. This method behaves as
* though it invokes <code>{@link #print(char)}</code> and then <code>{@link
* #println()}</code>.
*
* @param x the <code>char</code> value to be printed
*/
public void println(char x) {
synchronized (lock) {
this.print(x);
this.println();
}
}
/* ------------------------------------------------------------ */
/**
* Print an integer and then terminate the line. This method behaves as
* though it invokes <code>{@link #print(int)}</code> and then <code>{@link
* #println()}</code>.
*
* @param x the <code>int</code> value to be printed
*/
public void println(int x) {
synchronized (lock) {
this.print(x);
this.println();
}
}
/* ------------------------------------------------------------ */
/**
* Print a long integer and then terminate the line. This method behaves
* as though it invokes <code>{@link #print(long)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x the <code>long</code> value to be printed
*/
public void println(long x) {
synchronized (lock) {
this.print(x);
this.println();
}
}
/* ------------------------------------------------------------ */
/**
* Print a floating-point number and then terminate the line. This method
* behaves as though it invokes <code>{@link #print(float)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x the <code>float</code> value to be printed
*/
public void println(float x) {
synchronized (lock) {
this.print(x);
this.println();
}
}
/* ------------------------------------------------------------ */
/**
* Print a double-precision floating-point number and then terminate the
* line. This method behaves as though it invokes <code>{@link
* #print(double)}</code> and then <code>{@link #println()}</code>.
*
* @param x the <code>double</code> value to be printed
*/
/* ------------------------------------------------------------ */
public void println(double x) {
synchronized (lock) {
this.print(x);
this.println();
}
}
/* ------------------------------------------------------------ */
/**
* Print an array of characters and then terminate the line. This method
* behaves as though it invokes <code>{@link #print(char[])}</code> and then
* <code>{@link #println()}</code>.
*
* @param x the array of <code>char</code> values to be printed
*/
public void println(char x[]) {
synchronized (lock) {
this.print(x);
this.println();
}
}
/* ------------------------------------------------------------ */
/**
* Print a String and then terminate the line. This method behaves as
* though it invokes <code>{@link #print(String)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x the <code>String</code> value to be printed
*/
public void println(String x) {
synchronized (lock) {
this.print(x);
this.println();
}
}
/* ------------------------------------------------------------ */
/**
* Print an Object and then terminate the line. This method behaves as
* though it invokes <code>{@link #print(Object)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x the <code>Object</code> value to be printed
*/
public void println(Object x) {
synchronized (lock) {
this.print(x);
this.println();
}
}
}

View File

@ -43,6 +43,7 @@ import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint; import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.QuotedStringTokenizer;
@ -575,6 +576,11 @@ public class HttpConnection implements Connection
Log.debug(e); Log.debug(e);
error=true; error=true;
} }
catch (RuntimeIOException e)
{
Log.debug(e);
error=true;
}
catch (HttpException e) catch (HttpException e)
{ {
Log.debug(e); Log.debug(e);

View File

@ -61,6 +61,7 @@ public class DebugHandler extends HandlerWrapper
else else
retry=true; retry=true;
String ex=null;
try try
{ {
final String d=_date.now(); final String d=_date.now();
@ -74,6 +75,26 @@ public class DebugHandler extends HandlerWrapper
getHandler().handle(target,baseRequest,request,response); getHandler().handle(target,baseRequest,request,response);
} }
catch(IOException ioe)
{
ex=ioe.toString();
throw ioe;
}
catch(ServletException se)
{
ex=se.toString()+":"+se.getCause();
throw se;
}
catch(RuntimeException rte)
{
ex=rte.toString();
throw rte;
}
catch(Error e)
{
ex=e.toString();
throw e;
}
finally finally
{ {
thread.setName(old_name); thread.setName(old_name);
@ -86,7 +107,9 @@ public class DebugHandler extends HandlerWrapper
_print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" SUSPEND"); _print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" SUSPEND");
} }
else else
_print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" "+base_response.getStatus()+" "+base_response.getContentType()+" "+base_response.getContentCount()); _print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" "+base_response.getStatus()+
(ex==null?"":("/"+ex))+
" "+base_response.getContentType()+" "+base_response.getContentCount());
} }
} }

View File

@ -38,6 +38,7 @@ import org.eclipse.jetty.continuation.ContinuationThrowable;
import org.eclipse.jetty.http.HttpException; import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.PathMap; import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Dispatcher; import org.eclipse.jetty.server.Dispatcher;
@ -439,6 +440,10 @@ public class ServletHandler extends ScopedHandler
{ {
throw e; throw e;
} }
catch(ContinuationThrowable e)
{
throw e;
}
catch(Exception e) catch(Exception e)
{ {
if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type))) if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
@ -461,7 +466,14 @@ public class ServletHandler extends ScopedHandler
{ {
Log.debug(th); Log.debug(th);
Throwable cause=((ServletException)th).getRootCause(); Throwable cause=((ServletException)th).getRootCause();
if (cause!=th && cause!=null) if (cause!=null)
th=cause;
}
else if (th instanceof RuntimeIOException)
{
Log.debug(th);
Throwable cause=(IOException)((RuntimeIOException)th).getCause();
if (cause!=null)
th=cause; th=cause;
} }
@ -477,7 +489,7 @@ public class ServletHandler extends ScopedHandler
} }
else if (th instanceof IOException || th instanceof UnavailableException) else if (th instanceof IOException || th instanceof UnavailableException)
{ {
Log.warn(request.getRequestURI()+": "+th); Log.debug(request.getRequestURI(),th);
} }
else else
{ {
@ -502,10 +514,9 @@ public class ServletHandler extends ScopedHandler
} }
else else
if(Log.isDebugEnabled())Log.debug("Response already committed for handling "+th); if(Log.isDebugEnabled())Log.debug("Response already committed for handling "+th);
}
catch(ContinuationThrowable e) if (th instanceof IOException)
{ throw (IOException)th;
throw e;
} }
catch(Error e) catch(Error e)
{ {

View File

@ -16,6 +16,7 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -172,7 +173,15 @@ public class GzipFilter extends UserAgentFilter
{ {
return new GZIPResponseWrapper(request,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 public class GZIPResponseWrapper extends HttpServletResponseWrapper
{ {
HttpServletRequest _request; HttpServletRequest _request;
@ -361,8 +370,7 @@ public class GzipFilter extends UserAgentFilter
return getResponse().getWriter(); return getResponse().getWriter();
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize); _gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
String encoding = getCharacterEncoding(); _writer=newWriter(_gzStream,getCharacterEncoding());
_writer=encoding==null?new PrintWriter(_gzStream):new PrintWriter(new OutputStreamWriter(_gzStream,encoding));
} }
return _writer; return _writer;
} }
@ -385,7 +393,7 @@ public class GzipFilter extends UserAgentFilter
void finish() throws IOException void finish() throws IOException
{ {
if (_writer!=null) if (_writer!=null && !_gzStream._closed)
_writer.flush(); _writer.flush();
if (_gzStream!=null) if (_gzStream!=null)
_gzStream.finish(); _gzStream.finish();

View File

@ -14,9 +14,16 @@
package org.eclipse.jetty.servlets; package org.eclipse.jetty.servlets;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.UncheckedPrintWriter;
@ -28,12 +35,25 @@ import javax.servlet.http.HttpServletResponse;
* This allows the gzip filter to function correct during includes and to make a decision to gzip or not * This allows the gzip filter to function correct during includes and to make a decision to gzip or not
* at the time the buffer fills and on the basis of all response headers. * at the time the buffer fills and on the basis of all response headers.
* *
* * If the init parameter "uncheckedPrintWriter" is set to "true", then the PrintWriter used by
* the wrapped getWriter will be {@link UncheckedPrintWriter}.
* *
*/ */
public class IncludableGzipFilter extends GzipFilter public class IncludableGzipFilter extends GzipFilter
{ {
boolean _uncheckedPrintWriter=false;
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
super.init(filterConfig);
String tmp=filterConfig.getInitParameter("uncheckedPrintWriter");
if (tmp!=null)
_uncheckedPrintWriter=Boolean.valueOf(tmp).booleanValue();
}
@Override
protected GZIPResponseWrapper newGZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response) protected GZIPResponseWrapper newGZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response)
{ {
return new IncludableResponseWrapper(request,response); return new IncludableResponseWrapper(request,response);
@ -45,7 +65,8 @@ public class IncludableGzipFilter extends GzipFilter
{ {
super(request,response); super(request,response);
} }
@Override
protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
{ {
return new IncludableGzipStream(request,response,contentLength,bufferSize,minGzipSize); return new IncludableGzipStream(request,response,contentLength,bufferSize,minGzipSize);
@ -60,6 +81,7 @@ public class IncludableGzipFilter extends GzipFilter
super(request,response,contentLength,bufferSize,minGzipSize); super(request,response,contentLength,bufferSize,minGzipSize);
} }
@Override
protected boolean setContentEncodingGzip() protected boolean setContentEncodingGzip()
{ {
if (_request.getAttribute("javax.servlet.include.request_uri")!=null) if (_request.getAttribute("javax.servlet.include.request_uri")!=null)
@ -69,7 +91,13 @@ public class IncludableGzipFilter extends GzipFilter
return _response.containsHeader("Content-Encoding"); return _response.containsHeader("Content-Encoding");
} }
} }
@Override
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
{
if (_uncheckedPrintWriter)
return encoding==null?new UncheckedPrintWriter(out):new UncheckedPrintWriter(new OutputStreamWriter(out,encoding));
return super.newWriter(out,encoding);
}
} }

View File

@ -200,7 +200,7 @@ public class Dump extends HttpServlet
boolean flush= request.getParameter("flush")!=null?Boolean.parseBoolean(request.getParameter("flush")):false; boolean flush= request.getParameter("flush")!=null?Boolean.parseBoolean(request.getParameter("flush")):false;
if (data != null && data.length() > 0) if (data != null && data.length() > 0)
{ {
int d=Integer.parseInt(data); long d=Long.parseLong(data);
int b=(block!=null&&block.length()>0)?Integer.parseInt(block):50; int b=(block!=null&&block.length()>0)?Integer.parseInt(block):50;
byte[] buf=new byte[b]; byte[] buf=new byte[b];
for (int i=0;i<b;i++) for (int i=0;i<b;i++)
@ -227,7 +227,7 @@ public class Dump extends HttpServlet
} }
else else
{ {
out.write(buf,0,d); out.write(buf,0,(int)d);
d=0; d=0;
} }
@ -252,6 +252,44 @@ public class Dump extends HttpServlet
return; return;
} }
// Handle a dump of data
String chars= request.getParameter("chars");
if (chars != null && chars.length() > 0)
{
long d=Long.parseLong(chars);
int b=(block!=null&&block.length()>0)?Integer.parseInt(block):50;
char[] buf=new char[b];
for (int i=0;i<b;i++)
{
buf[i]=(char)('0'+(i%10));
if (i%10==9)
buf[i]='\n';
}
buf[0]='o';
response.setContentType("text/plain");
PrintWriter out=response.getWriter();
while (d > 0 && !out.checkError())
{
if (b==1)
{
out.write(d%80==0?'\n':'.');
d--;
}
else if (d>=b)
{
out.write(buf);
d=d-b;
}
else
{
out.write(buf,0,(int)d);
d=0;
}
}
return;
}
// handle an exception // handle an exception

View File

@ -67,6 +67,10 @@
<param-name>excludedAgents</param-name> <param-name>excludedAgents</param-name>
<param-value>MSIE 6.0</param-value> <param-value>MSIE 6.0</param-value>
</init-param> </init-param>
<init-param>
<param-name>uncheckedPrintWriter</param-name>
<param-value>true</param-value>
</init-param>
</filter> </filter>
<filter-mapping> <filter-mapping>
<filter-name>GzipFilter</filter-name> <filter-name>GzipFilter</filter-name>

View File

@ -0,0 +1,32 @@
package org.eclipse.jetty;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DebugHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlets.IncludableGzipFilter;
import com.acme.Dump;
public class DumpServer
{
public static void main(String[] args)
throws Exception
{
Server server = new Server(8080);
DebugHandler debug = new DebugHandler();
debug.setOutputStream(System.err);
server.setHandler(debug);
ServletContextHandler context = new ServletContextHandler(debug,"/",ServletContextHandler.SESSIONS);
FilterHolder gzip=context.addFilter(IncludableGzipFilter.class,"/*",0);
gzip.setInitParameter("uncheckedPrintWriter","true");
context.addServlet(new ServletHolder(new Dump()), "/*");
server.start();
server.join();
}
}