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:
parent
347ea58a28
commit
463bf87ebf
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue