jetty-9 moved more fields out of HttpChannel

This commit is contained in:
Greg Wilkins 2012-08-17 16:32:36 +10:00
parent 2a66567a5b
commit 78a529fc9d
10 changed files with 116 additions and 231 deletions

View File

@ -129,7 +129,7 @@ public class Dispatcher implements RequestDispatcher
try
{
baseRequest.setDispatcherType(DispatcherType.INCLUDE);
baseRequest.getHttpChannel().include();
baseRequest.getResponse().include();
if (_named!=null)
_contextHandler.handle(_named,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
else
@ -171,7 +171,7 @@ public class Dispatcher implements RequestDispatcher
finally
{
baseRequest.setAttributes(old_attr);
baseRequest.getHttpChannel().included();
baseRequest.getResponse().included();
baseRequest.setParameters(old_params);
baseRequest.setDispatcherType(old_type);
}

View File

@ -72,18 +72,12 @@ public abstract class HttpChannel
private final ChannelEventHandler _handler = new ChannelEventHandler();
private final HttpChannelState _state;
private final HttpFields _requestFields;
private final Request _request;
private final HttpInput _in;
private final HttpFields _responseFields;
private final Response _response;
private final Output _out;
private HttpWriter _writer;
private PrintWriter _printWriter;
private int _requests;
private int _include;
private HttpVersion _version = HttpVersion.HTTP_1_1;
@ -99,13 +93,10 @@ public abstract class HttpChannel
_server = server;
_connection = connection;
_uri = new HttpURI(URIUtil.__CHARSET);
_requestFields = new HttpFields();
_responseFields = new HttpFields();
_state = new HttpChannelState(this);
_request = new Request(this);
_response = new Response(this);
_response = new Response(this,new Output());
_in=input;
_out=new Output();
}
/* ------------------------------------------------------------ */
@ -146,25 +137,7 @@ public abstract class HttpChannel
{
return _server;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the requestFields.
*/
public HttpFields getRequestFields()
{
return _requestFields;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the responseFields.
*/
public HttpFields getResponseFields()
{
return _responseFields;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the request.
@ -232,52 +205,6 @@ public abstract class HttpChannel
}
/* ------------------------------------------------------------ */
/**
* @return The output stream for this connection. The stream will be created if it does not already exist.
*/
public HttpOutput getOutputStream()
{
return _out;
}
/* ------------------------------------------------------------ */
/**
* @param charset the character set for the PrintWriter
* @return A {@link PrintWriter} wrapping the {@link #getOutputStream output stream}. The writer is created if it
* does not already exist.
*/
public PrintWriter getPrintWriter(String charset)
{
getOutputStream();
if (_writer==null)
{
_writer=new HttpWriter(_out);
if (_server.isUncheckedPrintWriter())
_printWriter=new UncheckedPrintWriter(_writer);
else
_printWriter = new PrintWriter(_writer)
{
public void close()
{
synchronized (lock)
{
try
{
out.close();
}
catch (IOException e)
{
setError();
}
}
}
};
}
_writer.setCharacterEncoding(charset);
return _printWriter;
}
/* ------------------------------------------------------------ */
public void reset()
@ -285,12 +212,9 @@ public abstract class HttpChannel
_expect=false;
_expect100Continue=false;
_expect102Processing=false;
_requestFields.clear();
_request.recycle();
_responseFields.clear();
_response.recycle();
_uri.clear();
_out.reset();
_in.recycle(); // TODO done here or in connection?
}
@ -320,7 +244,7 @@ public abstract class HttpChannel
try
{
_request.setHandled(false);
_out.reopen();
_response.getHttpOutput().reopen();
if (_state.isInitial())
{
@ -429,7 +353,7 @@ public abstract class HttpChannel
try
{
_response.setStatus(status,reason);
_responseFields.add(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
_response.getHttpFields().add(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
ByteBuffer buffer=null;
if (content!=null)
@ -456,25 +380,6 @@ public abstract class HttpChannel
return false;
}
/* ------------------------------------------------------------ */
public boolean isIncluding()
{
return _include>0;
}
/* ------------------------------------------------------------ */
public void include()
{
_include++;
}
/* ------------------------------------------------------------ */
public void included()
{
_include--;
_out.reopen();
}
/* ------------------------------------------------------------ */
public boolean isSuspended()
{
@ -599,7 +504,7 @@ public abstract class HttpChannel
}
}
if (name!=null)
_requestFields.add(name, value);
_request.getHttpFields().add(name, value);
return false;
}
@ -613,19 +518,19 @@ public abstract class HttpChannel
break;
case HTTP_1_0:
if (persistent)
_responseFields.add(HttpHeader.CONNECTION,HttpHeaderValue.KEEP_ALIVE);
_response.getHttpFields().add(HttpHeader.CONNECTION,HttpHeaderValue.KEEP_ALIVE);
if (_server.getSendDateHeader())
_responseFields.putDateField(HttpHeader.DATE.toString(),_request.getTimeStamp());
_response.getHttpFields().putDateField(HttpHeader.DATE.toString(),_request.getTimeStamp());
break;
case HTTP_1_1:
if (!persistent)
_responseFields.add(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
_response.getHttpFields().add(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
if (_server.getSendDateHeader())
_responseFields.putDateField(HttpHeader.DATE.toString(),_request.getTimeStamp());
_response.getHttpFields().putDateField(HttpHeader.DATE.toString(),_request.getTimeStamp());
if (!_host)
{
@ -690,7 +595,7 @@ public abstract class HttpChannel
if (_expect100Continue)
{
_expect100Continue=false;
getResponseFields().put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
_response.getHttpFields().put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
}
return _response.commit();
}
@ -723,8 +628,7 @@ public abstract class HttpChannel
{
if (isClosed())
throw new IOException("Closed");
PrintWriter writer=getPrintWriter(null);
writer.print(s);
write(s.getBytes(_response.getCharacterEncoding()));
}
@ -743,19 +647,19 @@ public abstract class HttpChannel
HttpContent httpContent = (HttpContent) content;
String contentType = httpContent.getContentType();
if (contentType != null)
_responseFields.put(HttpHeader.CONTENT_TYPE, contentType);
_response.getHttpFields().put(HttpHeader.CONTENT_TYPE, contentType);
if (httpContent.getContentLength() > 0)
_responseFields.putLongField(HttpHeader.CONTENT_LENGTH, httpContent.getContentLength());
_response.getHttpFields().putLongField(HttpHeader.CONTENT_LENGTH, httpContent.getContentLength());
String lm = httpContent.getLastModified();
if (lm != null)
_responseFields.put(HttpHeader.LAST_MODIFIED, lm);
_response.getHttpFields().put(HttpHeader.LAST_MODIFIED, lm);
else if (httpContent.getResource()!=null)
{
long lml=httpContent.getResource().lastModified();
if (lml!=-1)
_responseFields.putDateField(HttpHeader.LAST_MODIFIED, lml);
_response.getHttpFields().putDateField(HttpHeader.LAST_MODIFIED, lml);
}
content = httpContent.getDirectBuffer();
@ -767,7 +671,7 @@ public abstract class HttpChannel
else if (content instanceof Resource)
{
resource=(Resource)content;
_responseFields.putDateField(HttpHeader.LAST_MODIFIED, resource.lastModified());
_response.getHttpFields().putDateField(HttpHeader.LAST_MODIFIED, resource.lastModified());
content=resource.getInputStream();
}

View File

@ -139,7 +139,7 @@ public class HttpConfiguration extends AggregateLifeCycle
/* ------------------------------------------------------------ */
protected void checkForwardedHeaders(Request request) throws IOException
{
HttpFields httpFields = request.getHttpChannel().getRequestFields();
HttpFields httpFields = request.getHttpFields();
// Do SSL first
if (getForwardedCipherSuiteHeader()!=null)

View File

@ -41,10 +41,11 @@ public class HttpWriter extends Writer
int _surrogate;
/* ------------------------------------------------------------ */
public HttpWriter(HttpOutput out)
public HttpWriter(HttpOutput out, String encoding)
{
_out=out;
_surrogate=0; // AS lastUTF16CodePoint
setCharacterEncoding(encoding);
}
/* ------------------------------------------------------------ */

View File

@ -115,7 +115,7 @@ public class Request implements HttpServletRequest
private static final int __NONE = 0, _STREAM = 1, __READER = 2;
private final HttpChannel _channel;
private HttpFields _fields;
private final HttpFields _fields=new HttpFields();
private final HttpChannelState _state;
private final List<ServletRequestAttributeListener> _requestAttributeListeners=new ArrayList<>();
@ -168,9 +168,14 @@ public class Request implements HttpServletRequest
{
_channel = channel;
_state=channel.getState();
_fields=_channel.getRequestFields();
}
/* ------------------------------------------------------------ */
public HttpFields getHttpFields()
{
return _fields;
}
/* ------------------------------------------------------------ */
public void addEventListener(final EventListener listener)
{
@ -1434,6 +1439,7 @@ public class Request implements HttpServletRequest
_savedNewSessions=null;
_multiPartInputStream = null;
_remote=null;
_fields.clear();
}
/* ------------------------------------------------------------ */

View File

@ -20,6 +20,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream;
@ -71,8 +72,10 @@ public class Response implements HttpServletResponse
public final static String HTTP_ONLY_COMMENT="__HTTP_ONLY__";
private final HttpChannel _channel;
private final HttpFields _fields;
private final HttpOutput _out;
private final HttpFields _fields=new HttpFields();
private final AtomicBoolean _committed = new AtomicBoolean(false);
private final AtomicInteger _include = new AtomicInteger();
private int _status=HttpStatus.NOT_SET_000;
private String _reason;
private Locale _locale;
@ -87,10 +90,10 @@ public class Response implements HttpServletResponse
/**
*
*/
public Response(HttpChannel channel)
public Response(HttpChannel channel, HttpOutput out)
{
_channel=channel;
_fields=channel.getResponseFields();
_out=out;
}
/* ------------------------------------------------------------ */
@ -115,8 +118,35 @@ public class Response implements HttpServletResponse
_outputState=OutputState.NONE;
_contentLength=-1;
_committed.set(false);
_out.reset();
_fields.clear();
}
/* ------------------------------------------------------------ */
public HttpOutput getHttpOutput()
{
return _out;
}
/* ------------------------------------------------------------ */
public boolean isIncluding()
{
return _include.get()>0;
}
/* ------------------------------------------------------------ */
public void include()
{
_include.incrementAndGet();
}
/* ------------------------------------------------------------ */
public void included()
{
_include.decrementAndGet();
_out.reopen();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletResponse#addCookie(javax.servlet.http.Cookie)
@ -300,8 +330,8 @@ public class Response implements HttpServletResponse
@Override
public void sendError(int code, String message) throws IOException
{
if (_channel.isIncluding())
return;
if (isIncluding())
return;
if (isCommitted())
LOG.warn("Committed before "+code+" "+message);
@ -386,8 +416,8 @@ public class Response implements HttpServletResponse
}
else if (code!=SC_PARTIAL_CONTENT)
{
_channel.getRequestFields().remove(HttpHeader.CONTENT_TYPE);
_channel.getRequestFields().remove(HttpHeader.CONTENT_LENGTH);
_channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_TYPE);
_channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_LENGTH);
_characterEncoding=null;
_mimeType=null;
}
@ -429,7 +459,7 @@ public class Response implements HttpServletResponse
@Override
public void sendRedirect(String location) throws IOException
{
if (_channel.isIncluding())
if (isIncluding())
return;
if (location==null)
@ -490,7 +520,7 @@ public class Response implements HttpServletResponse
@Override
public void setDateHeader(String name, long date)
{
if (!_channel.isIncluding())
if (!isIncluding())
_fields.putDateField(name, date);
}
@ -501,7 +531,7 @@ public class Response implements HttpServletResponse
@Override
public void addDateHeader(String name, long date)
{
if (!_channel.isIncluding())
if (!isIncluding())
_fields.addDateField(name, date);
}
@ -515,7 +545,7 @@ public class Response implements HttpServletResponse
setContentType(value);
else
{
if (_channel.isIncluding())
if (isIncluding())
return;
_fields.put(name, value);
@ -540,7 +570,7 @@ public class Response implements HttpServletResponse
setContentType(value);
else
{
if (_channel.isIncluding())
if (isIncluding())
{
if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
name=name.substring(SET_INCLUDE_HEADER_PREFIX.length());
@ -595,7 +625,7 @@ public class Response implements HttpServletResponse
*/
public void addHeader(HttpHeader name, String value)
{
if (_channel.isIncluding())
if (isIncluding())
return;
_fields.add(name, value);
@ -615,7 +645,7 @@ public class Response implements HttpServletResponse
@Override
public void addHeader(String name, String value)
{
if (_channel.isIncluding())
if (isIncluding())
{
if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
name=name.substring(SET_INCLUDE_HEADER_PREFIX.length());
@ -640,7 +670,7 @@ public class Response implements HttpServletResponse
@Override
public void setIntHeader(String name, int value)
{
if (!_channel.isIncluding())
if (!isIncluding())
{
_fields.putLongField(name, value);
if (HttpHeader.CONTENT_LENGTH.is(name))
@ -655,7 +685,7 @@ public class Response implements HttpServletResponse
@Override
public void addIntHeader(String name, int value)
{
if (!_channel.isIncluding())
if (!isIncluding())
{
_fields.add(name, Integer.toString(value));
if (HttpHeader.CONTENT_LENGTH.is(name))
@ -682,7 +712,7 @@ public class Response implements HttpServletResponse
{
if (sc<=0)
throw new IllegalArgumentException();
if (!_channel.isIncluding())
if (!isIncluding())
{
_status=sc;
_reason=sm;
@ -726,10 +756,8 @@ public class Response implements HttpServletResponse
{
if (_outputState==OutputState.WRITER)
throw new IllegalStateException("WRITER");
ServletOutputStream out = _channel.getOutputStream();
_outputState=OutputState.STREAM;
return out;
return _out;
}
/* ------------------------------------------------------------ */
@ -770,7 +798,24 @@ public class Response implements HttpServletResponse
}
/* construct Writer using correct encoding */
_writer = _channel.getPrintWriter(encoding);
// TODO switch on encoding here
_writer = new PrintWriter(new HttpWriter(_out,encoding))
{
public void close()
{
synchronized (lock)
{
try
{
out.close();
}
catch (IOException e)
{
setError();
}
}
}
};
}
_outputState=OutputState.WRITER;
return _writer;
@ -788,10 +833,10 @@ public class Response implements HttpServletResponse
// Protect from setting after committed as default handling
// of a servlet HEAD request ALWAYS sets _content length, even
// if the getHandling committed the response!
if (isCommitted() || _channel.isIncluding())
if (isCommitted() || isIncluding())
return;
long written=_channel.getOutputStream().getWritten();
long written=_out.getWritten();
if (written>len)
throw new IllegalArgumentException("setContent("+len+") when already written "+written);
@ -841,7 +886,7 @@ public class Response implements HttpServletResponse
// Protect from setting after committed as default handling
// of a servlet HEAD request ALWAYS sets _content length, even
// if the getHandling committed the response!
if (isCommitted() || _channel.isIncluding())
if (isCommitted() || isIncluding())
return;
_contentLength=len;
_fields.putLongField(HttpHeader.CONTENT_LENGTH.toString(), len);
@ -854,7 +899,7 @@ public class Response implements HttpServletResponse
@Override
public void setCharacterEncoding(String encoding)
{
if (_channel.isIncluding())
if (isIncluding())
return;
if (_outputState==OutputState.NONE && !isCommitted())
@ -905,7 +950,7 @@ public class Response implements HttpServletResponse
@Override
public void setContentType(String contentType)
{
if (isCommitted() || _channel.isIncluding())
if (isCommitted() || isIncluding())
return;
if (contentType==null)
@ -1002,7 +1047,7 @@ public class Response implements HttpServletResponse
HttpFields response_fields=_fields;
response_fields.clear();
String connection=_channel.getRequestFields().getStringField(HttpHeader.CONNECTION);
String connection=_channel.getRequest().getHttpFields().getStringField(HttpHeader.CONNECTION);
if (connection!=null)
{
String[] values = connection.split(",");
@ -1057,7 +1102,7 @@ public class Response implements HttpServletResponse
{
case STREAM:
case WRITER:
_channel.getOutputStream().reset();
_out.reset();
}
_channel.resetBuffer();
@ -1092,7 +1137,7 @@ public class Response implements HttpServletResponse
@Override
public void setLocale(Locale locale)
{
if (locale == null || isCommitted() ||_channel.isIncluding())
if (locale == null || isCommitted() ||isIncluding())
return;
_locale = locale;
@ -1161,7 +1206,7 @@ public class Response implements HttpServletResponse
/* ------------------------------------------------------------ */
public long getContentCount()
{
return _channel.getOutputStream().getWritten();
return _out.getWritten();
}
/* ------------------------------------------------------------ */
@ -1171,31 +1216,4 @@ public class Response implements HttpServletResponse
return "HTTP/1.1 "+_status+" "+ (_reason==null?"":_reason) +System.getProperty("line.separator")+
_fields.toString();
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private static class NullOutput extends ServletOutputStream
{
@Override
public void write(int b) throws IOException
{
}
@Override
public void print(String s) throws IOException
{
}
@Override
public void println(String s) throws IOException
{
}
@Override
public void write(byte[] b, int off, int len) throws IOException
{
}
}
}

View File

@ -78,7 +78,6 @@ public class Server extends HandlerWrapper implements Attributes
private boolean _stopAtShutdown;
private boolean _dumpAfterStart=false;
private boolean _dumpBeforeStop=false;
private boolean _uncheckedPrintWriter=false;
/* ------------------------------------------------------------ */
@ -627,18 +626,6 @@ public class Server extends HandlerWrapper implements Attributes
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),_connectors);
}
/* ------------------------------------------------------------ */
public boolean isUncheckedPrintWriter()
{
return _uncheckedPrintWriter;
}
/* ------------------------------------------------------------ */
public void setUncheckedPrintWriter(boolean unchecked)
{
_uncheckedPrintWriter=unchecked;
}
/* ------------------------------------------------------------ */
/* A handler that can be gracefully shutdown.
* Called by doStop if a {@link #setGracefulShutdown} period is set.

View File

@ -28,7 +28,7 @@ import org.junit.Test;
public class HttpWriterTest
{
private HttpWriter _writer;
private HttpOutput _httpOut;
private ByteBuffer _bytes;
@Before
@ -107,14 +107,13 @@ public class HttpWriterTest
};
HttpOutput httpOut = new HttpOutput(channel);
_writer = new HttpWriter(httpOut);
_httpOut = new HttpOutput(channel);
}
@Test
public void testSimpleUTF8() throws Exception
{
_writer.setCharacterEncoding(StringUtil.__UTF8);
HttpWriter _writer = new HttpWriter(_httpOut,StringUtil.__UTF8);
_writer.write("Now is the time");
assertArrayEquals("Now is the time".getBytes(StringUtil.__UTF8),BufferUtil.toArray(_bytes));
}
@ -122,7 +121,7 @@ public class HttpWriterTest
@Test
public void testUTF8() throws Exception
{
_writer.setCharacterEncoding(StringUtil.__UTF8);
HttpWriter _writer = new HttpWriter(_httpOut,StringUtil.__UTF8);
_writer.write("How now \uFF22rown cow");
assertArrayEquals("How now \uFF22rown cow".getBytes(StringUtil.__UTF8),BufferUtil.toArray(_bytes));
}
@ -130,7 +129,7 @@ public class HttpWriterTest
@Test
public void testNotCESU8() throws Exception
{
_writer.setCharacterEncoding(StringUtil.__UTF8);
HttpWriter _writer = new HttpWriter(_httpOut,StringUtil.__UTF8);
String data="xxx\uD801\uDC00xxx";
_writer.write(data);
assertEquals("787878F0909080787878",TypeUtil.toHexString(BufferUtil.toArray(_bytes)));
@ -146,7 +145,7 @@ public class HttpWriterTest
@Test
public void testMultiByteOverflowUTF8() throws Exception
{
_writer.setCharacterEncoding(StringUtil.__UTF8);
HttpWriter _writer = new HttpWriter(_httpOut,StringUtil.__UTF8);
final String singleByteStr = "a";
final String multiByteDuplicateStr = "\uFF22";
int remainSize = 1;
@ -173,7 +172,7 @@ public class HttpWriterTest
@Test
public void testISO8859() throws Exception
{
_writer.setCharacterEncoding(StringUtil.__ISO_8859_1);
HttpWriter _writer = new HttpWriter(_httpOut,StringUtil.__ISO_8859_1);
_writer.write("How now \uFF22rown cow");
assertEquals("How now ?rown cow",new String(BufferUtil.toArray(_bytes),StringUtil.__ISO_8859_1));
}
@ -182,7 +181,7 @@ public class HttpWriterTest
@Test
public void testUTF16x2() throws Exception
{
_writer.setCharacterEncoding(StringUtil.__UTF8);
HttpWriter _writer = new HttpWriter(_httpOut,StringUtil.__UTF8);
String source = "\uD842\uDF9F";
@ -205,7 +204,7 @@ public class HttpWriterTest
@Test
public void testMultiByteOverflowUTF16x2() throws Exception
{
_writer.setCharacterEncoding(StringUtil.__UTF8);
HttpWriter _writer = new HttpWriter(_httpOut,StringUtil.__UTF8);
final String singleByteStr = "a";
int remainSize = 1;
@ -243,7 +242,7 @@ public class HttpWriterTest
@Test
public void testMultiByteOverflowUTF16x2_2() throws Exception
{
_writer.setCharacterEncoding(StringUtil.__UTF8);
HttpWriter _writer = new HttpWriter(_httpOut,StringUtil.__UTF8);
final String singleByteStr = "a";
int remainSize = 1;

View File

@ -651,8 +651,8 @@ public class ResponseTest
private Response newResponse()
{
_channel.getOutputStream().reset();
Response response = new Response(_channel);
_channel.getResponse().getHttpOutput().reset();
Response response = new Response(_channel,_channel.getResponse().getHttpOutput());
return response;
}

View File

@ -360,36 +360,6 @@ public class ContextHandlerTest
return root;
}
@Test
public void testUncheckedPrintWriter() throws Exception
{
Server server = new Server();
server.setUncheckedPrintWriter(true);
LocalConnector connector = new LocalConnector(server);
server.setConnectors(new Connector[] { connector });
ContextHandler context = new ContextHandler("/");
WriterHandler handler = new WriterHandler();
context.setHandler(handler);
server.setHandler(context);
try
{
server.start();
String response = connector.getResponses("GET / HTTP/1.1\n" + "Host: www.example.com.\nConnection:close\n\n");
Assert.assertTrue(response.indexOf("Goodbye")>0);
Assert.assertTrue(response.indexOf("dead")<0);
Thread.sleep(100);
Assert.assertTrue(handler.error);
Assert.assertTrue(handler.throwable!=null);
}
finally
{
server.stop();
}
}
private void checkWildcardHost(boolean succeed, Server server, String[] contextHosts, String[] requestHosts) throws Exception
{
LocalConnector connector = (LocalConnector)server.getConnectors()[0];