Fix for bug #283357: org.eclipse.jetty.server.HttpConnectionTest exceptions.

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@848 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Simone Bordet 2009-09-09 12:43:06 +00:00
parent ffa43e89a9
commit 2bbf944a20
2 changed files with 94 additions and 95 deletions

View File

@ -18,6 +18,7 @@ jetty-7.0.0.RC6-SNAPSHOT
+ 288466 LocalConnector is not thread safe
+ 288772 Failure to connect does not set status to EXCEPTED
+ 280723 Add non blocking statistics handler
+ 283357 org.eclipse.jetty.server.HttpConnectionTest exceptions
jetty-6.1.20 27 August 2009
+ JETTY-838 Don't log and throw

View File

@ -4,11 +4,11 @@
// 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
// 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.
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
@ -16,7 +16,6 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
@ -40,12 +39,12 @@ import org.eclipse.jetty.http.HttpVersions;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.Parser;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.UncheckedPrintWriter;
import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
@ -56,7 +55,7 @@ import org.eclipse.jetty.util.thread.Timeout;
/**
* <p>A HttpConnection represents the connection of a HTTP client to the server
* and is created by an instance of a {@link Connector}. It's prime function is
* and is created by an instance of a {@link Connector}. It's prime function is
* to associate {@link Request} and {@link Response} instances with a {@link EndPoint}.
* </p>
* <p>
@ -66,7 +65,7 @@ import org.eclipse.jetty.util.thread.Timeout;
* a connection. Where appropriate, allocated buffers are also kept associated
* with the connection via the parser and/or generator.
* </p>
*
*
*/
public class HttpConnection implements Connection
{
@ -95,11 +94,11 @@ public class HttpConnection implements Connection
protected PrintWriter _printWriter;
int _include;
private Object _associatedObject; // associated object
private int _version = UNKNOWN;
private boolean _expect = false;
private boolean _expect100Continue = false;
private boolean _expect102Processing = false;
@ -112,7 +111,7 @@ public class HttpConnection implements Connection
{
return __currentConnection.get();
}
/* ------------------------------------------------------------ */
protected static void setCurrentConnection(HttpConnection connection)
{
@ -121,7 +120,7 @@ public class HttpConnection implements Connection
/* ------------------------------------------------------------ */
/** Constructor
*
*
*/
public HttpConnection(Connector connector, EndPoint endpoint, Server server)
{
@ -155,16 +154,16 @@ public class HttpConnection implements Connection
_generator.setSendServerVersion(server.getSendServerVersion());
_server = server;
}
/* ------------------------------------------------------------ */
/**
* @return the parser used by this connection
*/
*/
public Parser getParser()
{
return _parser;
}
/* ------------------------------------------------------------ */
/**
* @return the number of requests handled by this connection
@ -182,7 +181,7 @@ public class HttpConnection implements Connection
{
return _timeStamp;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the associatedObject.
@ -239,7 +238,7 @@ public class HttpConnection implements Connection
return _connector.isConfidential(request);
return false;
}
/* ------------------------------------------------------------ */
/**
* Find out if the request is INTEGRAL security.
@ -297,8 +296,8 @@ public class HttpConnection implements Connection
* If the associated response has the Expect header set to 100 Continue,
* then accessing the input stream indicates that the handler/servlet
* is ready for the request body and thus a 100 Continue response is sent.
*
* @return The input stream for this connection.
*
* @return The input stream for this connection.
* The stream will be created if it does not already exist.
*/
public ServletInputStream getInputStream() throws IOException
@ -311,13 +310,13 @@ public class HttpConnection implements Connection
{
if (_generator.isCommitted())
throw new IllegalStateException("Committed before 100 Continues");
((HttpGenerator)_generator).send1xx(HttpStatus.CONTINUE_100);
}
_expect100Continue=false;
}
if (_in == null)
if (_in == null)
_in = new HttpInput(((HttpParser)_parser),_connector.getMaxIdleTime());
return _in;
}
@ -328,7 +327,7 @@ public class HttpConnection implements Connection
*/
public ServletOutputStream getOutputStream()
{
if (_out == null)
if (_out == null)
_out = new Output();
return _out;
}
@ -349,7 +348,7 @@ public class HttpConnection implements Connection
_writer.setCharacterEncoding(encoding);
return _printWriter;
}
/* ------------------------------------------------------------ */
public boolean isResponseCommitted()
{
@ -362,9 +361,9 @@ public class HttpConnection implements Connection
// Loop while more in buffer
boolean more_in_buffer =true; // assume true until proven otherwise
boolean progress=true;
try
{
{
assert getCurrentConnection()==null;
assert _handling==false;
_handling=true;
@ -379,12 +378,12 @@ public class HttpConnection implements Connection
Log.debug("async request",_request);
if (!_request._async.isComplete())
handleRequest();
else if (!_parser.isComplete())
else if (!_parser.isComplete())
{
long parsed=_parser.parseAvailable();
progress|=parsed>0;
}
if (_generator.isCommitted() && !_generator.isComplete())
progress|=_generator.flushBuffer()>0;
if (_endp.isBufferingOutput())
@ -393,7 +392,7 @@ public class HttpConnection implements Connection
else
{
// If we are not ended then parse available
if (!_parser.isComplete())
if (!_parser.isComplete())
progress|=_parser.parseAvailable()>0;
// Do we have more generating to do?
@ -418,7 +417,7 @@ public class HttpConnection implements Connection
progress=true;
}
if (!progress)
if (!progress)
return;
progress=false;
}
@ -439,10 +438,10 @@ public class HttpConnection implements Connection
}
finally
{
more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
if (_parser.isComplete() && _generator.isComplete() && !_endp.isBufferingOutput())
{
{
if (!_generator.isPersistent())
{
_parser.reset(true);
@ -469,33 +468,33 @@ public class HttpConnection implements Connection
_handling=false;
}
}
/* ------------------------------------------------------------ */
public void scheduleTimeout(Timeout.Task task, long timeoutMs)
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
public void cancelTimeout(Timeout.Task task)
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
public void reset(boolean returnBuffers)
{
_parser.reset(returnBuffers); // TODO maybe only release when low on resources
_requestFields.clear();
_request.recycle();
_generator.reset(returnBuffers); // TODO maybe only release when low on resources
_responseFields.clear();
_response.recycle();
_uri.clear();
_uri.clear();
}
/* ------------------------------------------------------------ */
protected void handleRequest() throws IOException
{
@ -509,9 +508,9 @@ public class HttpConnection implements Connection
threadName=Thread.currentThread().getName();
Thread.currentThread().setName(threadName+" - "+_uri);
}
// Loop here to handle async request redispatches.
// Loop here to handle async request redispatches.
// The loop is controlled by the call to async.unhandle in the
// finally block below. If call is from a non-blocking connector,
// then the unhandle will return false only if an async dispatch has
@ -543,7 +542,7 @@ public class HttpConnection implements Connection
_connector.customize(_endp, _request);
server.handle(this);
}
else
else
{
_request.setDispatcherType(DispatcherType.ASYNC);
server.handleAsync(this);
@ -576,23 +575,23 @@ public class HttpConnection implements Connection
{
if (e instanceof ThreadDeath)
throw (ThreadDeath)e;
error=true;
if (info==null)
{
Log.warn(_uri+": "+e);
Log.debug(_uri+": "+e);
_request.setHandled(true);
_generator.sendError(400, null, null, true);
}
else
{
Log.warn(""+_uri,e);
Log.debug(""+_uri,e);
_request.setHandled(true);
_generator.sendError(500, null, null, true);
}
}
finally
{
{
handling = !_request._async.unhandle() && server.isRunning() && _server!=null;
}
}
@ -603,12 +602,12 @@ public class HttpConnection implements Connection
Thread.currentThread().setName(threadName);
if (_request._async.isUncompleted())
{
{
_request._async.doComplete();
if (_expect100Continue)
{
// Continue not sent so don't parse any content
// Continue not sent so don't parse any content
_expect100Continue = false;
if (_parser instanceof HttpParser)
((HttpParser)_parser).setState(HttpParser.STATE_END);
@ -619,7 +618,7 @@ public class HttpConnection implements Connection
if (_generator.isPersistent())
_connector.persist(_endp);
if (error)
if (error)
_endp.close();
else
{
@ -630,11 +629,11 @@ public class HttpConnection implements Connection
}
else
{
_response.complete();
_response.complete();
}
_request.setHandled(true);
}
}
}
}
@ -656,16 +655,16 @@ public class HttpConnection implements Connection
{
Log.warn("header full: "+e);
Log.debug(e);
_response.reset();
_generator.reset(true);
_generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500,null);
_generator.completeHeader(_responseFields,HttpGenerator.LAST);
throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
}
if (last)
if (last)
_generator.complete();
}
@ -687,7 +686,7 @@ public class HttpConnection implements Connection
{
Log.warn("header full: "+e);
Log.debug(e);
_response.reset();
_generator.reset(true);
_generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500,null);
@ -744,7 +743,7 @@ public class HttpConnection implements Connection
{
return _generator.isIdle() && (_parser.isIdle() || _delayedHandling);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.io.Connection#isSuspended()
@ -772,9 +771,9 @@ public class HttpConnection implements Connection
private class RequestHandler extends HttpParser.EventHandler
{
private String _charset;
/*
*
*
* @see org.eclipse.jetty.server.server.HttpParser.EventHandler#startRequest(org.eclipse.io.Buffer,
* org.eclipse.io.Buffer, org.eclipse.io.Buffer)
*/
@ -813,7 +812,6 @@ public class HttpConnection implements Connection
}
catch (Exception e)
{
Log.warn(method+" "+uri+" "+version+": "+e);
Log.debug(e);
throw new HttpException(HttpStatus.BAD_REQUEST_400,null,e);
}
@ -831,7 +829,7 @@ public class HttpConnection implements Connection
// TODO check if host matched a host in the URI.
_host = true;
break;
case HttpHeaders.EXPECT_ORDINAL:
value = HttpHeaderValues.CACHE.lookup(value);
switch(HttpHeaderValues.CACHE.getOrdinal(value))
@ -843,7 +841,7 @@ public class HttpConnection implements Connection
case HttpHeaderValues.PROCESSING_ORDINAL:
_expect102Processing=_generator instanceof HttpGenerator;
break;
default:
String[] values = value.toString().split(",");
for (int i=0;values!=null && i<values.length;i++)
@ -868,12 +866,12 @@ public class HttpConnection implements Connection
}
}
break;
case HttpHeaders.ACCEPT_ENCODING_ORDINAL:
case HttpHeaders.USER_AGENT_ORDINAL:
value = HttpHeaderValues.CACHE.lookup(value);
break;
case HttpHeaders.CONTENT_TYPE_ORDINAL:
value = MimeTypes.CACHE.lookup(value);
_charset=MimeTypes.getCharsetFromContentType(value);
@ -884,7 +882,7 @@ public class HttpConnection implements Connection
switch(HttpHeaderValues.CACHE.getOrdinal(value))
{
case -1:
{
{
String[] values = value.toString().split(",");
for (int i=0;values!=null && i<values.length;i++)
{
@ -917,7 +915,7 @@ public class HttpConnection implements Connection
if (_version==HttpVersions.HTTP_1_0_ORDINAL)
_responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
break;
}
}
}
_requestFields.add(name, value);
@ -939,10 +937,10 @@ public class HttpConnection implements Connection
break;
case HttpVersions.HTTP_1_1_ORDINAL:
_generator.setHead(_head);
if (_server.getSendDateHeader())
_responseFields.put(HttpHeaders.DATE_BUFFER, _request.getTimeStampBuffer(),_request.getTimeStamp());
if (!_host)
{
_generator.setResponse(HttpStatus.BAD_REQUEST_400, null);
@ -957,16 +955,16 @@ public class HttpConnection implements Connection
_generator.sendError(HttpStatus.EXPECTATION_FAILED_417, null, null, true);
return;
}
break;
default:
}
if(_charset!=null)
_request.setCharacterEncodingUnchecked(_charset);
// Either handle now or wait for first content
if ((((HttpParser)_parser).getContentLength()<=0 && !((HttpParser)_parser).isChunking())||_expect100Continue)
if ((((HttpParser)_parser).getContentLength()<=0 && !((HttpParser)_parser).isChunking())||_expect100Continue)
handleRequest();
else
_delayedHandling=true;
@ -988,7 +986,7 @@ public class HttpConnection implements Connection
/* ------------------------------------------------------------ */
/*
* (non-Javadoc)
*
*
* @see org.eclipse.jetty.server.server.HttpParser.EventHandler#messageComplete(int)
*/
public void messageComplete(long contentLength) throws IOException
@ -1003,7 +1001,7 @@ public class HttpConnection implements Connection
/* ------------------------------------------------------------ */
/*
* (non-Javadoc)
*
*
* @see org.eclipse.jetty.server.server.HttpParser.EventHandler#startResponse(org.eclipse.io.Buffer, int,
* org.eclipse.io.Buffer)
*/
@ -1013,18 +1011,18 @@ public class HttpConnection implements Connection
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public class Output extends HttpOutput
public class Output extends HttpOutput
{
Output()
{
super((AbstractGenerator)HttpConnection.this._generator,
_connector.isLowResources()?_connector.getLowResourceMaxIdleTime():_connector.getMaxIdleTime());
}
/* ------------------------------------------------------------ */
/*
* @see java.io.OutputStream#close()
@ -1033,16 +1031,16 @@ public class HttpConnection implements Connection
{
if (_closed)
return;
if (!isIncluding() && !super._generator.isCommitted())
commitResponse(HttpGenerator.LAST);
else
flushResponse();
super.close();
}
/* ------------------------------------------------------------ */
/*
* @see java.io.OutputStream#flush()
@ -1055,7 +1053,7 @@ public class HttpConnection implements Connection
}
/* ------------------------------------------------------------ */
/*
/*
* @see javax.servlet.ServletOutputStream#print(java.lang.String)
*/
public void print(String s) throws IOException
@ -1071,16 +1069,16 @@ public class HttpConnection implements Connection
{
((HttpGenerator)super._generator).sendResponse(response);
}
/* ------------------------------------------------------------ */
public void sendContent(Object content) throws IOException
{
Resource resource=null;
if (_closed)
throw new IOException("Closed");
if (super._generator.getContentWritten() > 0)
if (super._generator.getContentWritten() > 0)
throw new IllegalStateException("!empty");
if (content instanceof HttpContent)
@ -1101,29 +1099,29 @@ public class HttpConnection implements Connection
_responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER, content_type);
else
{
_responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
_responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
}
}
else
{
_responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
_responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
}
}
}
if (c.getContentLength() > 0)
if (c.getContentLength() > 0)
_responseFields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER, c.getContentLength());
Buffer lm = c.getLastModified();
long lml=c.getResource().lastModified();
if (lm != null)
if (lm != null)
_responseFields.put(HttpHeaders.LAST_MODIFIED_BUFFER, lm,lml);
else if (c.getResource()!=null)
{
if (lml!=-1)
_responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, lml);
}
content = c.getBuffer();
if (content==null)
content=c.getInputStream();
@ -1134,8 +1132,8 @@ public class HttpConnection implements Connection
_responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, resource.lastModified());
content=resource.getInputStream();
}
if (content instanceof Buffer)
{
super._generator.addContent((Buffer) content, HttpGenerator.LAST);
@ -1144,7 +1142,7 @@ public class HttpConnection implements Connection
else if (content instanceof InputStream)
{
InputStream in = (InputStream)content;
try
{
int max = super._generator.prepareUncheckedAddContent();
@ -1162,7 +1160,7 @@ public class HttpConnection implements Connection
len=buffer.readFrom(in,max);
}
super._generator.completeUncheckedAddContent();
_out.flush();
_out.flush();
}
finally
{
@ -1170,14 +1168,14 @@ public class HttpConnection implements Connection
resource.release();
else
in.close();
}
}
else
throw new IllegalArgumentException("unknown content type?");
}
}
}
/* ------------------------------------------------------------ */