jetty-9 work in progress. developing ServerConnection abstraction

This commit is contained in:
Greg Wilkins 2012-03-21 14:42:33 +11:00
parent c04a195256
commit dc29d73d0b
21 changed files with 1073 additions and 1535 deletions

View File

@ -1,178 +0,0 @@
// ========================================================================
// Copyright (c) 2008-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.http;
import java.io.UnsupportedEncodingException;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.util.Utf8StringBuffer;
public class EncodedHttpURI extends HttpURI
{
private final String _encoding;
public EncodedHttpURI(String encoding)
{
super();
_encoding = encoding;
}
@Override
public String getScheme()
{
if (_scheme==_authority)
return null;
int l=_authority-_scheme;
if (l==5 &&
_raw[_scheme]=='h' &&
_raw[_scheme+1]=='t' &&
_raw[_scheme+2]=='t' &&
_raw[_scheme+3]=='p' )
return HttpScheme.HTTP.toString();
if (l==6 &&
_raw[_scheme]=='h' &&
_raw[_scheme+1]=='t' &&
_raw[_scheme+2]=='t' &&
_raw[_scheme+3]=='p' &&
_raw[_scheme+4]=='s' )
return HttpScheme.HTTPS.toString();
return StringUtil.toString(_raw,_scheme,_authority-_scheme-1,_encoding);
}
@Override
public String getAuthority()
{
if (_authority==_path)
return null;
return StringUtil.toString(_raw,_authority,_path-_authority,_encoding);
}
@Override
public String getHost()
{
if (_host==_port)
return null;
return StringUtil.toString(_raw,_host,_port-_host,_encoding);
}
@Override
public int getPort()
{
if (_port==_path)
return -1;
return TypeUtil.parseInt(_raw, _port+1, _path-_port-1,10);
}
@Override
public String getPath()
{
if (_path==_param)
return null;
return StringUtil.toString(_raw,_path,_param-_path,_encoding);
}
@Override
public String getDecodedPath()
{
if (_path==_param)
return null;
return URIUtil.decodePath(_raw,_path,_param-_path);
}
@Override
public String getPathAndParam()
{
if (_path==_query)
return null;
return StringUtil.toString(_raw,_path,_query-_path,_encoding);
}
@Override
public String getCompletePath()
{
if (_path==_end)
return null;
return StringUtil.toString(_raw,_path,_end-_path,_encoding);
}
@Override
public String getParam()
{
if (_param==_query)
return null;
return StringUtil.toString(_raw,_param+1,_query-_param-1,_encoding);
}
@Override
public String getQuery()
{
if (_query==_fragment)
return null;
return StringUtil.toString(_raw,_query+1,_fragment-_query-1,_encoding);
}
@Override
public boolean hasQuery()
{
return (_fragment>_query);
}
@Override
public String getFragment()
{
if (_fragment==_end)
return null;
return StringUtil.toString(_raw,_fragment+1,_end-_fragment-1,_encoding);
}
@Override
public void decodeQueryTo(MultiMap parameters)
{
if (_query==_fragment)
return;
UrlEncoded.decodeTo(StringUtil.toString(_raw,_query+1,_fragment-_query-1,_encoding),parameters,_encoding);
}
@Override
public void decodeQueryTo(MultiMap parameters, String encoding)
throws UnsupportedEncodingException
{
if (_query==_fragment)
return;
if (encoding==null)
encoding=_encoding;
UrlEncoded.decodeTo(StringUtil.toString(_raw,_query+1,_fragment-_query-1,encoding),parameters,encoding);
}
@Override
public String toString()
{
if (_rawString==null)
_rawString= StringUtil.toString(_raw,_scheme,_end-_scheme,_encoding);
return _rawString;
}
public void writeTo(Utf8StringBuffer buf)
{
buf.getStringBuffer().append(toString());
}
}

View File

@ -26,8 +26,8 @@ import org.eclipse.jetty.util.resource.Resource;
*/
public interface HttpContent
{
ByteBuffer getContentType();
ByteBuffer getLastModified();
String getContentType();
String getLastModified();
ByteBuffer getIndirectBuffer();
ByteBuffer getDirectBuffer();
Resource getResource();
@ -41,17 +41,17 @@ public interface HttpContent
public class ResourceAsHttpContent implements HttpContent
{
final Resource _resource;
final ByteBuffer _mimeType;
final String _mimeType;
final int _maxBuffer;
public ResourceAsHttpContent(final Resource resource, final ByteBuffer mimeType)
public ResourceAsHttpContent(final Resource resource, final String mimeType)
{
_resource=resource;
_mimeType=mimeType;
_maxBuffer=-1;
}
public ResourceAsHttpContent(final Resource resource, final ByteBuffer mimeType, int maxBuffer)
public ResourceAsHttpContent(final Resource resource, final String mimeType, int maxBuffer)
{
_resource=resource;
_mimeType=mimeType;
@ -60,14 +60,14 @@ public interface HttpContent
/* ------------------------------------------------------------ */
@Override
public ByteBuffer getContentType()
public String getContentType()
{
return _mimeType;
}
/* ------------------------------------------------------------ */
@Override
public ByteBuffer getLastModified()
public String getLastModified()
{
return null;
}

View File

@ -534,6 +534,12 @@ public class HttpFields implements Iterable<HttpFields.Field>
_names.put(name, field);
}
/* -------------------------------------------------------------- */
public void put(HttpHeader header, HttpHeaderValue value)
{
put(header,value.toString());
}
/* -------------------------------------------------------------- */
/**
* Set a field.
@ -601,6 +607,12 @@ public class HttpFields implements Iterable<HttpFields.Field>
_names.put(name, field);
}
/* -------------------------------------------------------------- */
public void add(HttpHeader header, HttpHeaderValue value) throws IllegalArgumentException
{
add(header,value.toString());
}
/* -------------------------------------------------------------- */
/**
* Add to or set a field. If the field is allowed to have multiple values, add will add multiple
@ -699,6 +711,19 @@ public class HttpFields implements Iterable<HttpFields.Field>
}
/* -------------------------------------------------------------- */
/**
* Sets the value of an long field.
*
* @param name the field name
* @param value the field long value
*/
public void putLongField(HttpHeader name, long value)
{
String v = Long.toString(value);
put(name, v);
}
/* -------------------------------------------------------------- */
/**
* Sets the value of an long field.
@ -713,6 +738,19 @@ public class HttpFields implements Iterable<HttpFields.Field>
}
/* -------------------------------------------------------------- */
/**
* Sets the value of a date field.
*
* @param name the field name
* @param date the field date value
*/
public void putDateField(HttpHeader name, long date)
{
String d=formatDate(date);
put(name, d);
}
/* -------------------------------------------------------------- */
/**
* Sets the value of a date field.

View File

@ -15,6 +15,7 @@ package org.eclipse.jetty.http;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.Charset;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
@ -55,6 +56,7 @@ public class HttpURI
QUERY=9,
ASTERISK=10;
final Charset _charset;
boolean _partial=false;
byte[] _raw=__empty;
String _rawString;
@ -70,11 +72,14 @@ public class HttpURI
int _end;
boolean _encoded=false;
final Utf8StringBuilder _utf8b = new Utf8StringBuilder(64);
public HttpURI()
{
_charset = URIUtil.__CHARSET;
}
public HttpURI(Charset charset)
{
_charset = charset;
}
/* ------------------------------------------------------------ */
@ -84,6 +89,7 @@ public class HttpURI
public HttpURI(boolean parsePartialAuth)
{
_partial=parsePartialAuth;
_charset = URIUtil.__CHARSET;
}
public HttpURI(String raw)
@ -91,25 +97,35 @@ public class HttpURI
_rawString=raw;
byte[] b = raw.getBytes();
parse(b,0,b.length);
_charset = URIUtil.__CHARSET;
}
public HttpURI(byte[] raw,int offset, int length)
{
parse2(raw,offset,length);
_charset = URIUtil.__CHARSET;
}
public HttpURI(URI uri)
{
parse(uri.toASCIIString());
_charset = URIUtil.__CHARSET;
}
public void parse(String raw)
{
byte[] b = raw.getBytes();
byte[] b = StringUtil.getBytes(raw);
parse2(b,0,b.length);
_rawString=raw;
}
public void parseConnect(String raw)
{
byte[] b = StringUtil.getBytes(raw);
parseConnect(b,0,b.length);
_rawString=raw;
}
public void parse(byte[] raw,int offset, int length)
{
_rawString=null;
@ -167,7 +183,7 @@ public class HttpURI
{
case '/':
{
throw new IllegalArgumentException("No closing ']' for " + StringUtil.toString(_raw,offset,length,URIUtil.__CHARSET));
throw new IllegalArgumentException("No closing ']' for " + new String(_raw,offset,length,_charset));
}
case ']':
{
@ -386,7 +402,7 @@ public class HttpURI
{
case '/':
{
throw new IllegalArgumentException("No closing ']' for " + StringUtil.toString(_raw,offset,length,URIUtil.__CHARSET));
throw new IllegalArgumentException("No closing ']' for " + new String(_raw,offset,length,_charset));
}
case ']':
{
@ -484,13 +500,6 @@ public class HttpURI
_portValue=TypeUtil.parseInt(_raw, _port+1, _path-_port-1,10);
}
private String toUtf8String(int offset,int length)
{
_utf8b.reset();
_utf8b.append(_raw,offset,length);
return _utf8b.toString();
}
public String getScheme()
{
if (_scheme==_authority)
@ -510,21 +519,21 @@ public class HttpURI
_raw[_scheme+4]=='s' )
return HttpScheme.HTTPS.toString();
return toUtf8String(_scheme,_authority-_scheme-1);
return new String(_raw,_scheme,_authority-_scheme-1,_charset);
}
public String getAuthority()
{
if (_authority==_path)
return null;
return toUtf8String(_authority,_path-_authority);
return new String(_raw,_authority,_path-_authority,_charset);
}
public String getHost()
{
if (_host==_port)
return null;
return toUtf8String(_host,_port-_host);
return new String(_raw,_host,_port-_host,_charset);
}
public int getPort()
@ -536,7 +545,7 @@ public class HttpURI
{
if (_path==_param)
return null;
return toUtf8String(_path,_param-_path);
return new String(_raw,_path,_param-_path,_charset);
}
public String getDecodedPath()
@ -575,39 +584,36 @@ public class HttpURI
}
if (bytes==null)
return toUtf8String(_path,length);
_utf8b.reset();
_utf8b.append(bytes,0,n);
return _utf8b.toString();
return new String(_raw,_path,length,_charset);
return new String(bytes,0,n,_charset);
}
public String getPathAndParam()
{
if (_path==_query)
return null;
return toUtf8String(_path,_query-_path);
return new String(_raw,_path,_query-_path,_charset);
}
public String getCompletePath()
{
if (_path==_end)
return null;
return toUtf8String(_path,_end-_path);
return new String(_raw,_path,_end-_path,_charset);
}
public String getParam()
{
if (_param==_query)
return null;
return toUtf8String(_param+1,_query-_param-1);
return new String(_raw,_param+1,_query-_param-1,_charset);
}
public String getQuery()
{
if (_query==_fragment)
return null;
return toUtf8String(_query+1,_fragment-_query-1);
return new String(_raw,_query+1,_fragment-_query-1,_charset);
}
public String getQuery(String encoding)
@ -626,15 +632,14 @@ public class HttpURI
{
if (_fragment==_end)
return null;
return toUtf8String(_fragment+1,_end-_fragment-1);
return new String(_raw,_fragment+1,_end-_fragment-1,_charset);
}
public void decodeQueryTo(MultiMap parameters)
{
if (_query==_fragment)
return;
_utf8b.reset();
UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters,_utf8b);
UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters);
}
public void decodeQueryTo(MultiMap parameters, String encoding)
@ -646,7 +651,7 @@ public class HttpURI
if (encoding==null || StringUtil.isUTF8(encoding))
UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters);
else
UrlEncoded.decodeTo(toUtf8String(_query+1,_fragment-_query-1),parameters,encoding);
UrlEncoded.decodeTo(new String(_raw,_query+1,_fragment-_query-1,_charset),parameters,encoding);
}
public void clear()
@ -661,7 +666,7 @@ public class HttpURI
public String toString()
{
if (_rawString==null)
_rawString=toUtf8String(_scheme,_end-_scheme);
_rawString=new String(_raw,_scheme,_end-_scheme,_charset);
return _rawString;
}

View File

@ -66,6 +66,12 @@ public enum HttpVersion
return _version;
}
/* ------------------------------------------------------------ */
public boolean is(String s)
{
return _string.equalsIgnoreCase(s);
}
/* ------------------------------------------------------------ */
@Override
public String toString()

View File

@ -14,6 +14,7 @@
package org.eclipse.jetty.http;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@ -56,12 +57,16 @@ public class MimeTypes
/* ------------------------------------------------------------ */
private final String _string;
private final ByteBuffer _buffer;
private final Charset _charset;
/* ------------------------------------------------------------ */
Type(String s)
{
_string=s;
_buffer=BufferUtil.toBuffer(s);
int i=s.toLowerCase().indexOf("charset=");
_charset=(i>0)?Charset.forName(s.substring(i+8)):null;
}
/* ------------------------------------------------------------ */
@ -70,6 +75,12 @@ public class MimeTypes
return _buffer.asReadOnlyBuffer();
}
/* ------------------------------------------------------------ */
public Charset getCharset()
{
return _charset;
}
/* ------------------------------------------------------------ */
public boolean is(String s)
{
@ -86,7 +97,7 @@ public class MimeTypes
/* ------------------------------------------------------------ */
private static final Logger LOG = Log.getLogger(MimeTypes.class);
private final static StringMap<MimeTypes.Type> CACHE= new StringMap<MimeTypes.Type>(true);
public final static StringMap<MimeTypes.Type> CACHE= new StringMap<MimeTypes.Type>(true);
private final static StringMap<ByteBuffer> TYPES= new StringMap<ByteBuffer>(true);
private final static Map<String,ByteBuffer> __dftMimeMap = new HashMap<String,ByteBuffer>();
private final static Map<String,String> __encodings = new HashMap<String,String>();
@ -234,16 +245,16 @@ public class MimeTypes
}
/* ------------------------------------------------------------ */
public static String getCharsetFromContentType(ByteBuffer value)
public static String getCharsetFromContentType(String value)
{
int i=value.position();
int end=value.limit();
int end=value.length();
int state=0;
int start=0;
boolean quote=false;
int i=0;
for (;i<end;i++)
{
byte b = value.get(i);
char b = value.charAt(i);
if (quote && state!=10)
{
@ -300,4 +311,96 @@ public class MimeTypes
return __encodings.get(value);
}
public static String getContentTypeWithoutCharset(String value)
{
int end=value.length();
int state=0;
int start=0;
boolean quote=false;
int i=0;
StringBuilder builder=null;
for (;i<end;i++)
{
char b = value.charAt(i);
if ('"'==b)
{
if (quote)
{
quote=false;
}
else
{
quote=true;
}
switch(state)
{
case 11:
builder.append(b);break;
case 10:
break;
case 9:
builder=new StringBuilder();
builder.append(value,0,start+1);
state=10;
break;
default:
start=i;
state=0;
}
continue;
}
if (quote)
{
if (builder!=null && state!=10)
builder.append(b);
continue;
}
switch(state)
{
case 0:
if (';'==b)
state=1;
else if (' '!=b)
start=i;
break;
case 1: if ('c'==b) state=2; else if (' '!=b) state=0; break;
case 2: if ('h'==b) state=3; else state=0;break;
case 3: if ('a'==b) state=4; else state=0;break;
case 4: if ('r'==b) state=5; else state=0;break;
case 5: if ('s'==b) state=6; else state=0;break;
case 6: if ('e'==b) state=7; else state=0;break;
case 7: if ('t'==b) state=8; else state=0;break;
case 8: if ('='==b) state=9; else if (' '!=b) state=0; break;
case 9:
if (' '==b)
break;
builder=new StringBuilder();
builder.append(value,0,start+1);
state=10;
break;
case 10:
if (';'==b)
{
builder.append(b);
state=11;
}
break;
case 11:
if (' '!=b)
builder.append(b);
}
}
if (builder==null)
return value;
return builder.toString();
}
}

View File

@ -1,5 +1,8 @@
package org.eclipse.jetty.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
@ -46,7 +49,46 @@ public class MimeTypesTest
MimeTypes mimetypes = new MimeTypes();
ByteBuffer contentType = mimetypes.getMimeByExtension(filename);
String prefix = "MimeTypes.getMimeByExtension(" + filename + ")";
Assert.assertNotNull(prefix,contentType);
Assert.assertEquals(prefix,expectedMimeType,BufferUtil.toString(contentType));
assertNotNull(prefix,contentType);
assertEquals(prefix,expectedMimeType,BufferUtil.toString(contentType));
}
@Test
public void testCharsetFromContentType()
{
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar;charset=abc;some=else"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar;charset=abc"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar ; charset = abc"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar ; charset = abc ; some=else"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar;other=param;charset=abc;some=else"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar;other=param;charset=abc"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar other = param ; charset = abc"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar other = param ; charset = abc ; some=else"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar other = param ; charset = abc"));
assertEquals("abc",MimeTypes.getCharsetFromContentType("foo/bar other = param ; charset = \"abc\" ; some=else"));
assertEquals(null,MimeTypes.getCharsetFromContentType("foo/bar"));
assertEquals("UTF-8",MimeTypes.getCharsetFromContentType("foo/bar;charset=uTf8"));
assertEquals("UTF-8",MimeTypes.getCharsetFromContentType("foo/bar;other=\"charset=abc\";charset=uTf8"));
assertEquals("UTF-8",MimeTypes.getCharsetFromContentType("text/html;charset=utf-8"));
}
@Test
public void testContentTypeWithoutCharset()
{
assertEquals("foo/bar;some=else",MimeTypes.getContentTypeWithoutCharset("foo/bar;charset=abc;some=else"));
assertEquals("foo/bar",MimeTypes.getContentTypeWithoutCharset("foo/bar;charset=abc"));
assertEquals("foo/bar",MimeTypes.getContentTypeWithoutCharset("foo/bar ; charset = abc"));
assertEquals("foo/bar;some=else",MimeTypes.getContentTypeWithoutCharset("foo/bar ; charset = abc ; some=else"));
assertEquals("foo/bar;other=param;some=else",MimeTypes.getContentTypeWithoutCharset("foo/bar;other=param;charset=abc;some=else"));
assertEquals("foo/bar;other=param",MimeTypes.getContentTypeWithoutCharset("foo/bar;other=param;charset=abc"));
assertEquals("foo/bar ; other = param",MimeTypes.getContentTypeWithoutCharset("foo/bar ; other = param ; charset = abc"));
assertEquals("foo/bar ; other = param;some=else",MimeTypes.getContentTypeWithoutCharset("foo/bar ; other = param ; charset = abc ; some=else"));
assertEquals("foo/bar ; other = param",MimeTypes.getContentTypeWithoutCharset("foo/bar ; other = param ; charset = abc"));
assertEquals("foo/bar ; other = param;some=else",MimeTypes.getContentTypeWithoutCharset("foo/bar ; other = param ; charset = \"abc\" ; some=else"));
assertEquals("foo/bar",MimeTypes.getContentTypeWithoutCharset("foo/bar"));
assertEquals("foo/bar",MimeTypes.getContentTypeWithoutCharset("foo/bar;charset=uTf8"));
assertEquals("foo/bar;other=\"charset=abc\"",MimeTypes.getContentTypeWithoutCharset("foo/bar;other=\"charset=abc\";charset=uTf8"));
assertEquals("text/html",MimeTypes.getContentTypeWithoutCharset("text/html;charset=utf-8"));
}
}

View File

@ -756,7 +756,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
if (version==null)
{
_request.setProtocol(HttpVersion.HTTP_0_9);
_request.setHttpVersion(HttpVersion.HTTP_0_9);
_version=HttpVersion.HTTP_0_9_ORDINAL;
}
else
@ -766,7 +766,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
throw new HttpException(HttpStatus.BAD_REQUEST_400,null);
_version = HttpVersion.CACHE.getOrdinal(version);
if (_version <= 0) _version = HttpVersion.HTTP_1_0_ORDINAL;
_request.setProtocol(version.toString());
_request.setHttpVersion(version.toString());
}
}
catch (Exception e)

View File

@ -62,25 +62,28 @@ public class AsyncContinuation implements AsyncContext, Continuation
// COMPLETING UNCOMPLETED UNCOMPLETED
// UNCOMPLETED COMPLETED
// COMPLETED
private static final int __IDLE=0; // Idle request
private static final int __DISPATCHED=1; // Request dispatched to filter/servlet
private static final int __ASYNCSTARTED=2; // Suspend called, but not yet returned to container
private static final int __REDISPATCHING=3;// resumed while dispatched
private static final int __ASYNCWAIT=4; // Suspended and parked
private static final int __REDISPATCH=5; // Has been scheduled
private static final int __REDISPATCHED=6; // Request redispatched to filter/servlet
private static final int __COMPLETING=7; // complete while dispatched
private static final int __UNCOMPLETED=8; // Request is completable
private static final int __COMPLETED=9; // Request is complete
public enum State {
IDLE, // Idle request
DISPATCHED, // Request dispatched to filter/servlet
ASYNCSTARTED, // Suspend called, but not yet returned to container
REDISPATCHING,// resumed while dispatched
ASYNCWAIT, // Suspended and parked
REDISPATCH, // Has been scheduled
REDISPATCHED, // Request redispatched to filter/servlet
COMPLETING, // complete while dispatched
UNCOMPLETED, // Request is completable
COMPLETED // Request is complete
};
/* ------------------------------------------------------------ */
protected AbstractHttpConnection _connection;
protected ServerConnection _connection;
private List<AsyncListener> _lastAsyncListeners;
private List<AsyncListener> _asyncListeners;
private List<ContinuationListener> _continuationListeners;
/* ------------------------------------------------------------ */
private int _state;
private State _state;
private boolean _initial;
private boolean _resumed;
private boolean _expired;
@ -93,12 +96,12 @@ public class AsyncContinuation implements AsyncContext, Continuation
/* ------------------------------------------------------------ */
protected AsyncContinuation()
{
_state=__IDLE;
_state=State.IDLE;
_initial=true;
}
/* ------------------------------------------------------------ */
protected void setConnection(final AbstractHttpConnection connection)
protected void setConnection(final ServerConnection connection)
{
synchronized(this)
{
@ -203,10 +206,10 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __ASYNCSTARTED:
case __REDISPATCHING:
case __COMPLETING:
case __ASYNCWAIT:
case ASYNCSTARTED:
case REDISPATCHING:
case COMPLETING:
case ASYNCWAIT:
return true;
default:
@ -222,8 +225,8 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __ASYNCSTARTED:
case __ASYNCWAIT:
case ASYNCSTARTED:
case ASYNCWAIT:
return true;
default:
@ -239,10 +242,10 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __REDISPATCH:
case __REDISPATCHED:
case __REDISPATCHING:
case __COMPLETING:
case REDISPATCH:
case REDISPATCHED:
case REDISPATCHING:
case COMPLETING:
return true;
default:
@ -266,18 +269,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
return
((_state==__IDLE)?"IDLE":
(_state==__DISPATCHED)?"DISPATCHED":
(_state==__ASYNCSTARTED)?"ASYNCSTARTED":
(_state==__ASYNCWAIT)?"ASYNCWAIT":
(_state==__REDISPATCHING)?"REDISPATCHING":
(_state==__REDISPATCH)?"REDISPATCH":
(_state==__REDISPATCHED)?"REDISPATCHED":
(_state==__COMPLETING)?"COMPLETING":
(_state==__UNCOMPLETED)?"UNCOMPLETED":
(_state==__COMPLETED)?"COMPLETE":
("UNKNOWN?"+_state))+
return _state+
(_initial?",initial":"")+
(_resumed?",resumed":"")+
(_expired?",expired":"");
@ -297,9 +289,9 @@ public class AsyncContinuation implements AsyncContext, Continuation
switch(_state)
{
case __IDLE:
case IDLE:
_initial=true;
_state=__DISPATCHED;
_state=State.DISPATCHED;
if (_lastAsyncListeners!=null)
_lastAsyncListeners.clear();
if (_asyncListeners!=null)
@ -311,15 +303,15 @@ public class AsyncContinuation implements AsyncContext, Continuation
}
return true;
case __COMPLETING:
_state=__UNCOMPLETED;
case COMPLETING:
_state=State.UNCOMPLETED;
return false;
case __ASYNCWAIT:
case ASYNCWAIT:
return false;
case __REDISPATCH:
_state=__REDISPATCHED;
case REDISPATCH:
_state=State.REDISPATCHED;
return true;
default:
@ -340,8 +332,8 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __DISPATCHED:
case __REDISPATCHED:
case DISPATCHED:
case REDISPATCHED:
_resumed=false;
_expired=false;
@ -353,7 +345,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
_event._path=null;
}
_state=__ASYNCSTARTED;
_state=State.ASYNCSTARTED;
List<AsyncListener> recycle=_lastAsyncListeners;
_lastAsyncListeners=_asyncListeners;
_asyncListeners=recycle;
@ -397,37 +389,37 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __REDISPATCHED:
case __DISPATCHED:
_state=__UNCOMPLETED;
case REDISPATCHED:
case DISPATCHED:
_state=State.UNCOMPLETED;
return true;
case __IDLE:
case IDLE:
throw new IllegalStateException(this.getStatusString());
case __ASYNCSTARTED:
case ASYNCSTARTED:
_initial=false;
_state=__ASYNCWAIT;
_state=State.ASYNCWAIT;
scheduleTimeout(); // could block and change state.
if (_state==__ASYNCWAIT)
if (_state==State.ASYNCWAIT)
return true;
else if (_state==__COMPLETING)
else if (_state==State.COMPLETING)
{
_state=__UNCOMPLETED;
_state=State.UNCOMPLETED;
return true;
}
_initial=false;
_state=__REDISPATCHED;
_state=State.REDISPATCHED;
return false;
case __REDISPATCHING:
case REDISPATCHING:
_initial=false;
_state=__REDISPATCHED;
_state=State.REDISPATCHED;
return false;
case __COMPLETING:
case COMPLETING:
_initial=false;
_state=__UNCOMPLETED;
_state=State.UNCOMPLETED;
return true;
default:
@ -444,18 +436,18 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __ASYNCSTARTED:
_state=__REDISPATCHING;
case ASYNCSTARTED:
_state=State.REDISPATCHING;
_resumed=true;
return;
case __ASYNCWAIT:
case ASYNCWAIT:
dispatch=!_expired;
_state=__REDISPATCH;
_state=State.REDISPATCH;
_resumed=true;
break;
case __REDISPATCH:
case REDISPATCH:
return;
default:
@ -479,8 +471,8 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __ASYNCSTARTED:
case __ASYNCWAIT:
case ASYNCSTARTED:
case ASYNCWAIT:
cListeners=_continuationListeners;
aListeners=_asyncListeners;
break;
@ -527,8 +519,8 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __ASYNCSTARTED:
case __ASYNCWAIT:
case ASYNCSTARTED:
case ASYNCWAIT:
if (_continuation)
dispatch();
else
@ -552,16 +544,16 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __DISPATCHED:
case __REDISPATCHED:
case DISPATCHED:
case REDISPATCHED:
throw new IllegalStateException(this.getStatusString());
case __ASYNCSTARTED:
_state=__COMPLETING;
case ASYNCSTARTED:
_state=State.COMPLETING;
return;
case __ASYNCWAIT:
_state=__COMPLETING;
case ASYNCWAIT:
_state=State.COMPLETING;
dispatch=!_expired;
break;
@ -604,8 +596,8 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __UNCOMPLETED:
_state=__COMPLETED;
case UNCOMPLETED:
_state=State.COMPLETED;
cListeners=_continuationListeners;
aListeners=_asyncListeners;
break;
@ -661,11 +653,11 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __DISPATCHED:
case __REDISPATCHED:
case DISPATCHED:
case REDISPATCHED:
throw new IllegalStateException(getStatusString());
default:
_state=__IDLE;
_state=State.IDLE;
}
_initial = true;
_resumed=false;
@ -690,71 +682,19 @@ public class AsyncContinuation implements AsyncContext, Continuation
/* ------------------------------------------------------------ */
protected void scheduleDispatch()
{
EndPoint endp=_connection.getEndPoint();
if (!endp.isBlocking())
{
((AsyncEndPoint)endp).asyncDispatch();
}
_connection.asyncDispatch();
}
/* ------------------------------------------------------------ */
protected void scheduleTimeout()
{
EndPoint endp=_connection.getEndPoint();
if (_timeoutMs>0)
{
if (endp.isBlocking())
{
synchronized(this)
{
_expireAt = System.currentTimeMillis()+_timeoutMs;
long wait=_timeoutMs;
while (_expireAt>0 && wait>0 && _connection.getServer().isRunning())
{
try
{
this.wait(wait);
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
wait=_expireAt-System.currentTimeMillis();
}
if (_expireAt>0 && wait<=0 && _connection.getServer().isRunning())
{
expired();
}
}
}
else
{
((AsyncEndPoint)endp).scheduleTimeout(_event._timeout,_timeoutMs);
}
}
_connection.scheduleTimeout(_event._timeout,_timeoutMs);
}
/* ------------------------------------------------------------ */
protected void cancelTimeout()
{
EndPoint endp=_connection.getEndPoint();
if (endp.isBlocking())
{
synchronized(this)
{
_expireAt=0;
this.notifyAll();
}
}
else
{
final AsyncEventState event=_event;
if (event!=null)
{
((AsyncEndPoint)endp).cancelTimeout(event._timeout);
}
}
_connection.cancelTimeout(_event._timeout);
}
/* ------------------------------------------------------------ */
@ -762,7 +702,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
return _state==__COMPLETING;
return _state==State.COMPLETING;
}
}
@ -771,7 +711,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
return _state==__UNCOMPLETED;
return _state==State.UNCOMPLETED;
}
}
@ -780,7 +720,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
return _state==__COMPLETED;
return _state==State.COMPLETED;
}
}
@ -792,10 +732,10 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __ASYNCSTARTED:
case __REDISPATCHING:
case __REDISPATCH:
case __ASYNCWAIT:
case ASYNCSTARTED:
case REDISPATCHING:
case REDISPATCH:
case ASYNCWAIT:
return true;
default:
@ -812,10 +752,10 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
switch(_state)
{
case __IDLE:
case __DISPATCHED:
case __UNCOMPLETED:
case __COMPLETED:
case IDLE:
case DISPATCHED:
case UNCOMPLETED:
case COMPLETED:
return false;
default:

View File

@ -14,14 +14,24 @@
package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpGenerator.Action;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -183,4 +193,104 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
_parser.setPersistent(false);
}
ByteBuffer header=null;
ByteBuffer chunk=null;
ByteBuffer buffer=null;
/* ------------------------------------------------------------ */
private void write(ByteBuffer content) throws IOException
{
if (!_generator.isComplete())
throw new EofException();
try
{
while(BufferUtil.hasContent(content))
{
// Generate
Action action=BufferUtil.hasContent(content)?null:Action.COMPLETE;
/* System.err.printf("generate(%s,%s,%s,%s,%s)@%s%n",
BufferUtil.toSummaryString(header),
BufferUtil.toSummaryString(chunk),
BufferUtil.toSummaryString(buffer),
BufferUtil.toSummaryString(content),
action,gen.getState());*/
HttpGenerator.Result result=_generator.generate(header,chunk,buffer,content,action);
/*System.err.printf("%s (%s,%s,%s,%s,%s)@%s%n",
result,
BufferUtil.toSummaryString(header),
BufferUtil.toSummaryString(chunk),
BufferUtil.toSummaryString(buffer),
BufferUtil.toSummaryString(content),
action,gen.getState());*/
switch(result)
{
case NEED_HEADER:
header=BufferUtil.allocate(2048);
break;
case NEED_BUFFER:
buffer=BufferUtil.allocate(8192);
break;
case NEED_CHUNK:
header=null;
chunk=BufferUtil.allocate(HttpGenerator.CHUNK_SIZE);
break;
case FLUSH:
{
Future<Integer> future = getEndPoint().flush(header,chunk,buffer);
future.get(getMaxIdleTime(),TimeUnit.MILLISECONDS);
break;
}
case FLUSH_CONTENT:
{
Future<Integer> future = getEndPoint().flush(header,chunk,content);
future.get(getMaxIdleTime(),TimeUnit.MILLISECONDS);
break;
}
case OK:
break;
case SHUTDOWN_OUT:
getEndPoint().shutdownOutput();
break;
}
}
}
catch(final TimeoutException e)
{
throw new InterruptedIOException(e.toString())
{
{
this.initCause(e);
}
};
}
catch (final InterruptedException e)
{
throw new InterruptedIOException(e.toString())
{
{
this.initCause(e);
}
};
}
catch (final ExecutionException e)
{
throw new IOException(e.toString())
{
{
this.initCause(e);
}
};
}
}
}

View File

@ -14,22 +14,23 @@
package org.eclipse.jetty.server;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.servlet.ServletInputStream;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.util.BufferUtil;
public class HttpInput extends ServletInputStream
{
protected final AbstractHttpConnection _connection;
protected final HttpParser _parser;
protected final ServerConnection _connection;
private ByteBuffer _content;
/* ------------------------------------------------------------ */
public HttpInput(AbstractHttpConnection connection)
public HttpInput(ServerConnection connection)
{
_connection=connection;
_parser=(HttpParser)connection.getParser();
}
/* ------------------------------------------------------------ */
@ -40,9 +41,10 @@ public class HttpInput extends ServletInputStream
public int read() throws IOException
{
int c=-1;
ByteBuffer content=_parser.blockForContent(_connection.getMaxIdleTime());
if (content!=null)
c= 0xff & content.get();
if (BufferUtil.isEmpty(_content))
_content=_connection.blockForContent();
if (BufferUtil.hasContent(_content))
c= 0xff & _content.get();
return c;
}
@ -54,9 +56,13 @@ public class HttpInput extends ServletInputStream
public int read(byte[] b, int off, int len) throws IOException
{
int l=-1;
ByteBuffer content=_parser.blockForContent(_connection.getMaxIdleTime());
if (content!=null)
l= content.get(b, off, len);
if (BufferUtil.isEmpty(_content))
_content=_connection.blockForContent();
if (BufferUtil.hasContent(_content))
{
l=Math.min(len,_content.remaining());
_content.get(b,off,l);
}
return l;
}
@ -64,7 +70,11 @@ public class HttpInput extends ServletInputStream
@Override
public int available() throws IOException
{
return _parser.available();
if (BufferUtil.isEmpty(_content))
_content=_connection.getContent();
if (BufferUtil.hasContent(_content))
return _content.remaining();
return 0;
}

View File

@ -44,12 +44,8 @@ import org.eclipse.jetty.util.ByteArrayOutputStream2;
*/
public class HttpOutput extends ServletOutputStream
{
protected final AbstractHttpConnection _connection;
protected final HttpGenerator _generator;
private final ServerConnection _connection;
private boolean _closed;
ByteBuffer header=null;
ByteBuffer chunk=null;
ByteBuffer buffer=null;
// These are held here for reuse by Writer
String _characterEncoding;
@ -58,22 +54,15 @@ public class HttpOutput extends ServletOutputStream
ByteArrayOutputStream2 _bytes;
/* ------------------------------------------------------------ */
public HttpOutput(AbstractHttpConnection connection)
public HttpOutput(ServerConnection connection)
{
_connection=connection;
_generator=(HttpGenerator)connection.getGenerator();
}
/* ------------------------------------------------------------ */
public int getMaxIdleTime()
{
return _connection.getMaxIdleTime();
}
/* ------------------------------------------------------------ */
public boolean isWritten()
{
return _generator.getContentWritten()>0;
return _connection.getContentWritten()>0;
}
/* ------------------------------------------------------------ */
@ -109,7 +98,10 @@ public class HttpOutput extends ServletOutputStream
@Override
public void write(byte[] b, int off, int len) throws IOException
{
write(ByteBuffer.wrap(b,off,len));
if (_closed)
throw new IOException("Closed");
_connection.write(ByteBuffer.wrap(b,off,len));
}
/* ------------------------------------------------------------ */
@ -119,7 +111,10 @@ public class HttpOutput extends ServletOutputStream
@Override
public void write(byte[] b) throws IOException
{
write(ByteBuffer.wrap(b));
if (_closed)
throw new IOException("Closed");
_connection.write(ByteBuffer.wrap(b));
}
/* ------------------------------------------------------------ */
@ -128,106 +123,12 @@ public class HttpOutput extends ServletOutputStream
*/
@Override
public void write(int b) throws IOException
{
write(ByteBuffer.wrap(new byte[]{(byte)b}));
}
/* ------------------------------------------------------------ */
private void write(ByteBuffer content) throws IOException
{
if (_closed)
throw new IOException("Closed");
if (!_generator.isComplete())
throw new EofException();
try
{
while(BufferUtil.hasContent(content))
{
// Generate
Action action=BufferUtil.hasContent(content)?null:Action.COMPLETE;
/* System.err.printf("generate(%s,%s,%s,%s,%s)@%s%n",
BufferUtil.toSummaryString(header),
BufferUtil.toSummaryString(chunk),
BufferUtil.toSummaryString(buffer),
BufferUtil.toSummaryString(content),
action,gen.getState());*/
HttpGenerator.Result result=_generator.generate(header,chunk,buffer,content,action);
/*System.err.printf("%s (%s,%s,%s,%s,%s)@%s%n",
result,
BufferUtil.toSummaryString(header),
BufferUtil.toSummaryString(chunk),
BufferUtil.toSummaryString(buffer),
BufferUtil.toSummaryString(content),
action,gen.getState());*/
switch(result)
{
case NEED_HEADER:
header=BufferUtil.allocate(2048);
break;
case NEED_BUFFER:
buffer=BufferUtil.allocate(8192);
break;
case NEED_CHUNK:
header=null;
chunk=BufferUtil.allocate(HttpGenerator.CHUNK_SIZE);
break;
case FLUSH:
{
Future<Integer> future = _connection.getEndPoint().flush(header,chunk,buffer);
future.get(getMaxIdleTime(),TimeUnit.MILLISECONDS);
break;
_connection.write(ByteBuffer.wrap(new byte[]{(byte)b}));
}
case FLUSH_CONTENT:
{
Future<Integer> future = _connection.getEndPoint().flush(header,chunk,content);
future.get(getMaxIdleTime(),TimeUnit.MILLISECONDS);
break;
}
case OK:
break;
case SHUTDOWN_OUT:
_connection.getEndPoint().shutdownOutput();
break;
}
}
}
catch(final TimeoutException e)
{
throw new InterruptedIOException(e.toString())
{
{
this.initCause(e);
}
};
}
catch (final InterruptedException e)
{
throw new InterruptedIOException(e.toString())
{
{
this.initCause(e);
}
};
}
catch (final ExecutionException e)
{
throw new IOException(e.toString())
{
{
this.initCause(e);
}
};
}
}
/* ------------------------------------------------------------ */
/*

View File

@ -17,7 +17,6 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import org.eclipse.jetty.http.AbstractGenerator;
import org.eclipse.jetty.util.ByteArrayOutputStream2;
import org.eclipse.jetty.util.StringUtil;
@ -38,7 +37,6 @@ public class HttpWriter extends Writer
private static final int WRITE_UTF8 = 2;
final HttpOutput _out;
final AbstractGenerator _generator;
int _writeMode;
int _surrogate;
@ -46,7 +44,6 @@ public class HttpWriter extends Writer
public HttpWriter(HttpOutput out)
{
_out=out;
_generator=_out._generator;
_surrogate=0; // AS lastUTF16CodePoint
}

View File

@ -20,7 +20,10 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
@ -114,52 +117,44 @@ import org.eclipse.jetty.util.log.Logger;
*
*
*/
public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
public class Request implements HttpServletRequest
{
public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.multipartConfig";
private static final Logger LOG = Log.getLogger(Request.class);
private static final String __ASYNC_FWD = "org.eclipse.asyncfwd";
private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault());
private static final Collection<Locale> __defaultLocale = Collections.singleton(Locale.getDefault());
private static final int __NONE = 0, _STREAM = 1, __READER = 2;
/* ------------------------------------------------------------ */
public static Request getRequest(HttpServletRequest request)
{
if (request instanceof Request)
return (Request)request;
private ServerConnection _connection;
private HttpFields _fields;
private final AsyncContinuation _async = new AsyncContinuation();
return AbstractHttpConnection.getCurrentConnection().getRequest();
}
protected final AsyncContinuation _async = new AsyncContinuation();
private boolean _asyncSupported = true;
private volatile Attributes _attributes;
private Authentication _authentication;
private MultiMap<String> _baseParameters;
private String _characterEncoding;
protected AbstractHttpConnection _connection;
private ContextHandler.Context _context;
private boolean _newContext;
private String _contextPath;
private CookieCutter _cookies;
private boolean _cookiesExtracted = false;
private DispatcherType _dispatcherType;
private boolean _dns = false;
private EndPoint _endp;
private boolean _handled = false;
private int _inputState = __NONE;
private HttpMethod _httpMethod;
private String _method;
private MultiMap<String> _parameters;
private boolean _paramsExtracted;
private String _pathInfo;
private int _port;
private String _protocol = HttpVersion.HTTP_1_1.toString();
private HttpVersion _httpVersion = HttpVersion.HTTP_1_1;
private String _queryEncoding;
private String _queryString;
private BufferedReader _reader;
private String _readerEncoding;
private String _remoteAddr;
private String _remoteHost;
private InetSocketAddress _remote;
private Object _requestAttributeListeners;
private String _requestedSessionId;
private boolean _requestedSessionIdFromCookie = false;
@ -179,15 +174,13 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
private MultiPartInputStream _multiPartInputStream; //if the request is a multi-part mime
/* ------------------------------------------------------------ */
public Request()
{
}
/* ------------------------------------------------------------ */
public Request(AbstractHttpConnection connection)
public Request(ServerConnection connection)
{
setConnection(connection);
_connection = connection;
_fields=_connection.getRequestFields();
_async.setConnection(connection);
}
/* ------------------------------------------------------------ */
@ -208,7 +201,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
public void extractParameters()
{
if (_baseParameters == null)
_baseParameters = new MultiMap(16);
_baseParameters = new MultiMap<String>(16);
if (_paramsExtracted)
{
@ -267,10 +260,10 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
}
else
{
Number size = (Number)_connection.getConnector().getServer()
Number size = (Number)_connection.getServer()
.getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize");
maxFormContentSize = size == null?200000:size.intValue();
Number keys = (Number)_connection.getConnector().getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys");
Number keys = (Number)_connection.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys");
maxFormKeys = keys == null?1000:keys.intValue();
}
@ -339,7 +332,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
public Object getAttribute(String name)
{
if ("org.eclipse.jetty.io.EndPoint.maxIdleTime".equalsIgnoreCase(name))
return new Long(getConnection().getEndPoint().getMaxIdleTime());
return new Long(_connection.getMaxIdleTime());
Object attr = (_attributes == null)?null:_attributes.getAttribute(name);
if (attr == null && Continuation.ATTRIBUTE.equals(name))
@ -407,7 +400,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
/**
* @return Returns the connection.
*/
public AbstractHttpConnection getConnection()
public ServerConnection getConnection()
{
return _connection;
}
@ -418,16 +411,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public int getContentLength()
{
return (int)_connection.getRequestFields().getLongField(HttpHeader.CONTENT_LENGTH.toString());
}
/* ------------------------------------------------------------ */
public long getContentRead()
{
if (_connection == null || _connection.getParser() == null)
return -1;
return ((HttpParser)_connection.getParser()).getContentRead();
return (int)_fields.getLongField(HttpHeader.CONTENT_LENGTH.toString());
}
/* ------------------------------------------------------------ */
@ -436,7 +420,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public String getContentType()
{
return _connection.getRequestFields().getStringField(HttpHeader.CONTENT_TYPE);
return _fields.getStringField(HttpHeader.CONTENT_TYPE);
}
/* ------------------------------------------------------------ */
@ -468,7 +452,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
_cookiesExtracted = true;
Enumeration enm = _connection.getRequestFields().getValues(HttpHeader.COOKIE.toString());
Enumeration enm = _fields.getValues(HttpHeader.COOKIE.toString());
// Handle no cookies
if (enm != null)
@ -492,7 +476,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public long getDateHeader(String name)
{
return _connection.getRequestFields().getDateField(name);
return _fields.getDateField(name);
}
/* ------------------------------------------------------------ */
@ -507,7 +491,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public String getHeader(String name)
{
return _connection.getRequestFields().getStringField(name);
return _fields.getStringField(name);
}
/* ------------------------------------------------------------ */
@ -516,7 +500,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public Enumeration getHeaderNames()
{
return _connection.getRequestFields().getFieldNames();
return _fields.getFieldNames();
}
/* ------------------------------------------------------------ */
@ -525,7 +509,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public Enumeration getHeaders(String name)
{
Enumeration e = _connection.getRequestFields().getValues(name);
Enumeration e = _fields.getValues(name);
if (e == null)
return Collections.enumeration(Collections.EMPTY_LIST);
return e;
@ -558,17 +542,9 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public int getIntHeader(String name)
{
return (int)_connection.getRequestFields().getLongField(name);
return (int)_fields.getLongField(name);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getLocalAddr()
*/
public String getLocalAddr()
{
return _endp == null?null:_endp.getLocalAddr();
}
/* ------------------------------------------------------------ */
/*
@ -576,7 +552,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public Locale getLocale()
{
Enumeration enm = _connection.getRequestFields().getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators);
Enumeration<String> enm = _fields.getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators);
// handle no locale
if (enm == null || !enm.hasMoreElements())
@ -613,14 +589,14 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
public Enumeration getLocales()
{
Enumeration enm = _connection.getRequestFields().getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators);
Enumeration<String> enm = _fields.getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators);
// handle no locale
if (enm == null || !enm.hasMoreElements())
return Collections.enumeration(__defaultLocale);
// sort the list in quality order
List acceptLanguage = HttpFields.qualityList(enm);
List<String> acceptLanguage = HttpFields.qualityList(enm);
if (acceptLanguage.size() == 0)
return Collections.enumeration(__defaultLocale);
@ -650,21 +626,24 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
return Collections.enumeration(LazyList.getList(langs));
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getLocalAddr()
*/
public String getLocalAddr()
{
InetSocketAddress local=_connection.getLocalAddress();
return local.getAddress().getHostAddress();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getLocalName()
*/
public String getLocalName()
{
if (_endp == null)
return null;
if (_dns)
return _endp.getLocalHost();
String local = _endp.getLocalAddr();
if (local != null && local.indexOf(':') >= 0)
local = "[" + local + "]";
return local;
InetSocketAddress local=_connection.getLocalAddress();
return local.getHostString();
}
/* ------------------------------------------------------------ */
@ -673,7 +652,8 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public int getLocalPort()
{
return _endp == null?0:_endp.getLocalPort();
InetSocketAddress local=_connection.getLocalAddress();
return local.getPort();
}
/* ------------------------------------------------------------ */
@ -712,7 +692,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
/*
* @see javax.servlet.ServletRequest#getParameterNames()
*/
public Enumeration getParameterNames()
public Enumeration<String> getParameterNames()
{
if (!_paramsExtracted)
extractParameters();
@ -768,7 +748,16 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public String getProtocol()
{
return _protocol;
return _httpVersion.toString();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getProtocol()
*/
public HttpVersion getHttpVersion()
{
return _httpVersion;
}
/* ------------------------------------------------------------ */
@ -843,9 +832,10 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public String getRemoteAddr()
{
if (_remoteAddr != null)
return _remoteAddr;
return _endp == null?null:_endp.getRemoteAddr();
InetSocketAddress remote=_remote;
if (remote==null)
remote=_connection.getRemoteAddress();
return remote==null?"":remote.getAddress().getHostAddress();
}
/* ------------------------------------------------------------ */
@ -854,15 +844,10 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public String getRemoteHost()
{
if (_dns)
{
if (_remoteHost != null)
{
return _remoteHost;
}
return _endp == null?null:_endp.getRemoteHost();
}
return getRemoteAddr();
InetSocketAddress remote=_remote;
if (remote==null)
remote=_connection.getRemoteAddress();
return remote==null?"":remote.getHostString();
}
/* ------------------------------------------------------------ */
@ -871,7 +856,10 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public int getRemotePort()
{
return _endp == null?0:_endp.getRemotePort();
InetSocketAddress remote=_remote;
if (remote==null)
remote=_connection.getRemoteAddress();
return remote==null?0:remote.getPort();
}
/* ------------------------------------------------------------ */
@ -1020,7 +1008,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
return _serverName;
// Return host from header field
String hostPort = _connection.getRequestFields().getStringField(HttpHeader.HOST);
String hostPort = _fields.getStringField(HttpHeader.HOST);
if (hostPort != null)
{
loop: for (int i = hostPort.length(); i-- > 0;)
@ -1042,7 +1030,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
try
{
if (_connection != null)
_connection._generator.sendError(HttpStatus.BAD_REQUEST_400,"Bad Host header",null,true);
_connection.sendError(HttpStatus.BAD_REQUEST_400,"Bad Host header",null,true);
}
catch (IOException e1)
{
@ -1099,7 +1087,10 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
if (_serverName != null && _uri != null)
_port = _uri.getPort();
else
_port = _endp == null?0:_endp.getLocalPort();
{
InetSocketAddress local = _connection.getLocalAddress();
_port = local == null?0:local.getPort();
}
}
}
@ -1202,19 +1193,6 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
return _timeStamp;
}
/* ------------------------------------------------------------ */
/**
* Get Request TimeStamp
*
* @return The time that the request was received.
*/
public ByteBuffer getTimeStampBuffer()
{
if (_timeStampBuffer == null && _timeStamp > 0)
_timeStampBuffer = HttpFields.__dateCache.formatBuffer(_timeStamp);
return _timeStampBuffer;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the uri.
@ -1405,7 +1383,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
_method = null;
_pathInfo = null;
_port = 0;
_protocol = HttpVersion.HTTP_1_1.toString();
_httpVersion = HttpVersion.HTTP_1_1;
_queryEncoding = null;
_queryString = null;
_requestedSessionId = null;
@ -1429,6 +1407,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
_savedNewSessions.clear();
_savedNewSessions=null;
_multiPartInputStream = null;
_remote=null;
}
/* ------------------------------------------------------------ */
@ -1524,17 +1503,6 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
throw new RuntimeException(e);
}
}
else if ("org.eclipse.jetty.io.EndPoint.maxIdleTime".equalsIgnoreCase(name))
{
try
{
getConnection().getEndPoint().setMaxIdleTime(Integer.valueOf(value.toString()));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
if (_attributes == null)
@ -1598,8 +1566,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
// check encoding is supported
if (!StringUtil.isUTF8(encoding))
// noinspection ResultOfMethodCallIgnored
"".getBytes(encoding);
Charset.forName(encoding);
}
/* ------------------------------------------------------------ */
@ -1615,10 +1582,6 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
// final so we can safely call this from constructor
protected final void setConnection(AbstractHttpConnection connection)
{
_connection = connection;
_async.setConnection(connection);
_endp = connection.getEndPoint();
_dns = connection.getResolveNames();
}
/* ------------------------------------------------------------ */
@ -1627,7 +1590,7 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
*/
public void setContentType(String contentType)
{
_connection.getRequestFields().put(HttpHeader.CONTENT_TYPE,contentType);
_fields.put(HttpHeader.CONTENT_TYPE,contentType);
}
@ -1696,11 +1659,18 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
* @param method
* The method to set.
*/
public void setMethod(String method)
public void setMethod(HttpMethod httpMethod, String method)
{
_httpMethod=httpMethod;
_method = method;
}
/* ------------------------------------------------------------ */
public boolean isHead()
{
return HttpMethod.HEAD==_httpMethod;
}
/* ------------------------------------------------------------ */
/**
* @param parameters
@ -1725,12 +1695,12 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
/* ------------------------------------------------------------ */
/**
* @param protocol
* @param version
* The protocol to set.
*/
public void setProtocol(String protocol)
public void setHttpVersion(HttpVersion version)
{
_protocol = protocol;
_httpVersion = version;
}
/* ------------------------------------------------------------ */
@ -1763,19 +1733,9 @@ public class Request implements HttpServletRequest, HttpGenerator.RequestInfo
* @param addr
* The address to set.
*/
public void setRemoteAddr(String addr)
public void setRemoteAddr(InetSocketAddress addr)
{
_remoteAddr = addr;
}
/* ------------------------------------------------------------ */
/**
* @param host
* The host to set.
*/
public void setRemoteHost(String host)
{
_remoteHost = host;
_remote = addr;
}
/* ------------------------------------------------------------ */

View File

@ -53,11 +53,7 @@ public class Response implements HttpServletResponse
{
private static final Logger LOG = Log.getLogger(Response.class);
public static final int
NONE=0,
STREAM=1,
WRITER=2;
public enum Output {NONE,STREAM,WRITER}
/**
* If a header name starts with this string, the header (stripped of the prefix)
@ -72,24 +68,68 @@ public class Response implements HttpServletResponse
*/
public final static String HTTP_ONLY_COMMENT="__HTTP_ONLY__";
private final AbstractHttpConnection _connection;
private final ServerConnection _connection;
private final HttpFields _fields;
private int _status=SC_OK;
private String _reason;
private Locale _locale;
private String _mimeType;
private MimeTypes.Type _mimeType;
private String _characterEncoding;
private boolean _explicitEncoding;
private String _contentType;
private volatile int _outputState;
private Output _outputState;
private PrintWriter _writer;
private long _contentLength;
private final HttpGenerator.ResponseInfo _info = new HttpGenerator.ResponseInfo()
{
@Override
public HttpVersion getHttpVersion()
{
return _connection.getRequest().getHttpVersion();
}
@Override
public HttpFields getHttpFields()
{
return _fields;
}
@Override
public long getContentLength()
{
return _contentLength;
}
@Override
public boolean isHead()
{
return _connection.getRequest().isHead();
}
@Override
public int getStatus()
{
return _status;
}
@Override
public String getReason()
{
return _reason;
}
};
/* ------------------------------------------------------------ */
/**
*
*/
public Response(AbstractHttpConnection connection)
public Response(ServerConnection connection)
{
_connection=connection;
_fields=connection.getResponseFields();
}
@ -104,10 +144,9 @@ public class Response implements HttpServletResponse
_locale=null;
_mimeType=null;
_characterEncoding=null;
_explicitEncoding=false;
_contentType=null;
_writer=null;
_outputState=NONE;
_outputState=Output.NONE;
}
/* ------------------------------------------------------------ */
@ -116,7 +155,7 @@ public class Response implements HttpServletResponse
*/
public void addCookie(HttpCookie cookie)
{
_connection.getResponseFields().addSetCookie(cookie);
_fields.addSetCookie(cookie);
}
/* ------------------------------------------------------------ */
@ -139,7 +178,7 @@ public class Response implements HttpServletResponse
comment=null;
}
}
_connection.getResponseFields().addSetCookie(cookie.getName(),
_fields.addSetCookie(cookie.getName(),
cookie.getValue(),
cookie.getDomain(),
cookie.getPath(),
@ -156,7 +195,7 @@ public class Response implements HttpServletResponse
*/
public boolean containsHeader(String name)
{
return _connection.getResponseFields().containsKey(name);
return _fields.containsKey(name);
}
/* ------------------------------------------------------------ */
@ -300,7 +339,7 @@ public class Response implements HttpServletResponse
setHeader(HttpHeader.CONTENT_TYPE,null);
setHeader(HttpHeader.CONTENT_LENGTH,null);
_outputState=NONE;
_outputState=Output.NONE;
setStatus(code,message);
if (message==null)
@ -319,7 +358,7 @@ public class Response implements HttpServletResponse
if (context!=null)
error_handler=context.getContextHandler().getErrorHandler();
if (error_handler==null)
error_handler = _connection.getConnector().getServer().getBean(ErrorHandler.class);
error_handler = _connection.getServer().getBean(ErrorHandler.class);
if (error_handler!=null)
{
request.setAttribute(Dispatcher.ERROR_STATUS_CODE,new Integer(code));
@ -407,7 +446,7 @@ public class Response implements HttpServletResponse
public void sendProcessing() throws IOException
{
if (_connection.isExpecting102Processing() && !isCommitted())
((HttpGenerator)_connection.getGenerator()).send1xx(HttpStatus.PROCESSING_102);
_connection.send1xx(HttpStatus.PROCESSING_102);
}
/* ------------------------------------------------------------ */
@ -477,7 +516,7 @@ public class Response implements HttpServletResponse
public void setDateHeader(String name, long date)
{
if (!_connection.isIncluding())
_connection.getResponseFields().putDateField(name, date);
_fields.putDateField(name, date);
}
/* ------------------------------------------------------------ */
@ -487,7 +526,7 @@ public class Response implements HttpServletResponse
public void addDateHeader(String name, long date)
{
if (!_connection.isIncluding())
_connection.getResponseFields().addDateField(name, date);
_fields.addDateField(name, date);
}
/* ------------------------------------------------------------ */
@ -503,14 +542,14 @@ public class Response implements HttpServletResponse
if (_connection.isIncluding())
return;
_connection.getResponseFields().put(name, value);
_fields.put(name, value);
if (HttpHeader.CONTENT_LENGTH==name)
{
if (value==null)
_connection._generator.setContentLength(-1);
_contentLength=-1l;
else
_connection._generator.setContentLength(Long.parseLong(value));
_contentLength=Long.parseLong(value);
}
}
}
@ -531,13 +570,13 @@ public class Response implements HttpServletResponse
else
return;
}
_connection.getResponseFields().put(name, value);
_fields.put(name, value);
if (HttpHeader.CONTENT_LENGTH.is(name))
{
if (value==null)
_connection._generator.setContentLength(-1);
_contentLength=-1l;
else
_connection._generator.setContentLength(Long.parseLong(value));
_contentLength=Long.parseLong(value);
}
}
}
@ -546,7 +585,7 @@ public class Response implements HttpServletResponse
/* ------------------------------------------------------------ */
public Collection<String> getHeaderNames()
{
final HttpFields fields=_connection.getResponseFields();
final HttpFields fields=_fields;
return fields.getFieldNamesCollection();
}
@ -555,7 +594,7 @@ public class Response implements HttpServletResponse
*/
public String getHeader(String name)
{
return _connection.getResponseFields().getStringField(name);
return _fields.getStringField(name);
}
/* ------------------------------------------------------------ */
@ -563,7 +602,7 @@ public class Response implements HttpServletResponse
*/
public Collection<String> getHeaders(String name)
{
final HttpFields fields=_connection.getResponseFields();
final HttpFields fields=_fields;
Collection<String> i = fields.getValuesCollection(name);
if (i==null)
return Collections.EMPTY_LIST;
@ -584,9 +623,14 @@ public class Response implements HttpServletResponse
return;
}
_connection.getResponseFields().add(name, value);
_fields.add(name, value);
if (HttpHeader.CONTENT_LENGTH.is(name))
_connection._generator.setContentLength(Long.parseLong(value));
{
if (value==null)
_contentLength=-1l;
else
_contentLength=Long.parseLong(value);
}
}
/* ------------------------------------------------------------ */
@ -597,9 +641,9 @@ public class Response implements HttpServletResponse
{
if (!_connection.isIncluding())
{
_connection.getResponseFields().putLongField(name, value);
_fields.putLongField(name, value);
if (HttpHeader.CONTENT_LENGTH.is(name))
_connection._generator.setContentLength(value);
_contentLength=value;
}
}
@ -611,9 +655,9 @@ public class Response implements HttpServletResponse
{
if (!_connection.isIncluding())
{
_connection.getResponseFields().addLongField(name, value);
_fields.add(name, Integer.toString(value));
if (HttpHeader.CONTENT_LENGTH.is(name))
_connection._generator.setContentLength(value);
_contentLength=value;
}
}
@ -673,24 +717,24 @@ public class Response implements HttpServletResponse
*/
public ServletOutputStream getOutputStream() throws IOException
{
if (_outputState!=NONE && _outputState!=STREAM)
if (_outputState==Output.WRITER)
throw new IllegalStateException("WRITER");
ServletOutputStream out = _connection.getOutputStream();
_outputState=STREAM;
_outputState=Output.STREAM;
return out;
}
/* ------------------------------------------------------------ */
public boolean isWriting()
{
return _outputState==WRITER;
return _outputState==Output.WRITER;
}
/* ------------------------------------------------------------ */
public boolean isOutputing()
{
return _outputState!=NONE;
return _outputState!=Output.NONE;
}
/* ------------------------------------------------------------ */
@ -699,7 +743,7 @@ public class Response implements HttpServletResponse
*/
public PrintWriter getWriter() throws IOException
{
if (_outputState!=NONE && _outputState!=WRITER)
if (_outputState==Output.STREAM)
throw new IllegalStateException("STREAM");
/* if there is no writer yet */
@ -719,71 +763,10 @@ public class Response implements HttpServletResponse
/* construct Writer using correct encoding */
_writer = _connection.getPrintWriter(encoding);
}
_outputState=WRITER;
_outputState=Output.WRITER;
return _writer;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletResponse#setCharacterEncoding(java.lang.String)
*/
public void setCharacterEncoding(String encoding)
{
if (_connection.isIncluding())
return;
if (this._outputState==0 && !isCommitted())
{
_explicitEncoding=true;
if (encoding==null)
{
// Clear any encoding.
if (_characterEncoding!=null)
{
_characterEncoding=null;
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_mimeType);
}
}
else
{
// No, so just add this one to the mimetype
_characterEncoding=encoding;
if (_contentType!=null)
{
int i0=_contentType.indexOf(';');
if (i0<0)
{
_contentType=null;
if (_contentType==null)
{
_contentType = _mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else
{
int i1=_contentType.indexOf("charset=",i0);
if (i1<0)
{
_contentType = _contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
}
else
{
int i8=i1+8;
int i2=_contentType.indexOf(" ",i8);
if (i2<0)
_contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
else
_contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ")+_contentType.substring(i2);
}
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
}
}
}
/* ------------------------------------------------------------ */
/*
@ -796,16 +779,18 @@ public class Response implements HttpServletResponse
// if the getHandling committed the response!
if (isCommitted() || _connection.isIncluding())
return;
_connection._generator.setContentLength(len);
_contentLength=len;
if (len>=0)
{
_connection.getResponseFields().putLongField(HttpHeader.CONTENT_LENGTH, len);
if (_connection._generator.isAllContentWritten())
_fields.putLongField(HttpHeader.CONTENT_LENGTH.toString(), (long)len);
if (_connection.isAllContentWritten())
{
if (_outputState==WRITER)
switch(_outputState)
{
case WRITER:
_writer.close();
else if (_outputState==STREAM)
{
break;
case STREAM:
try
{
getOutputStream().close();
@ -830,8 +815,45 @@ public class Response implements HttpServletResponse
// if the getHandling committed the response!
if (isCommitted() || _connection.isIncluding())
return;
_connection._generator.setContentLength(len);
_connection.getResponseFields().putLongField(HttpHeader.CONTENT_LENGTH, len);
_contentLength=len;
_fields.putLongField(HttpHeader.CONTENT_LENGTH.toString(), len);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletResponse#setCharacterEncoding(java.lang.String)
*/
public void setCharacterEncoding(String encoding)
{
if (_connection.isIncluding())
return;
if (_outputState==Output.NONE && !isCommitted())
{
if (encoding==null)
{
// Clear any encoding.
if (_characterEncoding!=null)
{
_characterEncoding=null;
if (_contentType!=null)
{
_contentType=MimeTypes.getContentTypeWithoutCharset(_contentType);
_fields.put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
}
else
{
// No, so just add this one to the mimetype
_characterEncoding=encoding;
if (_contentType!=null)
{
_contentType=MimeTypes.getContentTypeWithoutCharset(_contentType)+";charset="+encoding;
_fields.put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
}
}
/* ------------------------------------------------------------ */
@ -843,159 +865,29 @@ public class Response implements HttpServletResponse
if (isCommitted() || _connection.isIncluding())
return;
// Yes this method is horribly complex.... but there are lots of special cases and
// as this method is called on every request, it is worth trying to save string creation.
//
if (contentType==null)
{
if (_locale==null)
_characterEncoding=null;
_mimeType=null;
_contentType=null;
_connection.getResponseFields().remove(HttpHeader.CONTENT_TYPE);
}
else
{
// Look for encoding in contentType
int i0=contentType.indexOf(';');
if (i0>0)
{
// we have content type parameters
// Extract params off mimetype
_mimeType=contentType.substring(0,i0).trim();
MimeTypes.Type mime_type=MimeTypes.CACHE.get(_mimeType);
// Look for charset
int i1=contentType.indexOf("charset=",i0+1);
if (i1>=0)
{
_explicitEncoding=true;
int i8=i1+8;
int i2 = contentType.indexOf(' ',i8);
if (_outputState==WRITER)
{
// strip the charset and ignore;
if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
{
if (mime_type!=null)
{
CachedBuffer content_type = mime_type.getAssociate(_characterEncoding);
if (content_type!=null)
{
_contentType=content_type.toString();
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,content_type);
}
else
{
_contentType=_mimeType+";charset="+_characterEncoding;
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else
{
_contentType=_mimeType+";charset="+_characterEncoding;
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else if (i2<0)
{
_contentType=contentType.substring(0,i1)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
else
{
_contentType=contentType.substring(0,i1)+contentType.substring(i2)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
{
// The params are just the char encoding
mime_type=MimeTypes.CACHE.get(_mimeType);
_characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
if (mime_type!=null)
{
CachedBuffer content_type = mime_type.getAssociate(_characterEncoding);
if (content_type!=null)
{
_contentType=content_type.toString();
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,content_type);
_fields.remove(HttpHeader.CONTENT_TYPE);
}
else
{
_contentType=contentType;
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else
{
_contentType=contentType;
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else if (i2>0)
{
_characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8,i2));
_contentType=contentType;
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
else
{
_characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
_contentType=contentType;
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else // No encoding in the params.
{
mime_type=null;
_contentType=_characterEncoding==null?contentType:contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else // No params at all
{
_mimeType=contentType;
_cachedMimeType=MimeTypes.CACHE.get(_mimeType);
_mimeType=MimeTypes.CACHE.get(contentType);
String charset=_mimeType==null?MimeTypes.getCharsetFromContentType(contentType):_mimeType.getCharset().toString();
if (_characterEncoding!=null)
if (charset!=null)
_characterEncoding=charset;
else if (_characterEncoding!=null)
{
if (_cachedMimeType!=null)
{
CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
if (content_type!=null)
{
_contentType=content_type.toString();
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,content_type);
}
else
{
_contentType=_mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else
{
_contentType=contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
else if (_cachedMimeType!=null)
{
_contentType=_cachedMimeType.toString();
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_cachedMimeType);
}
else
{
_contentType=contentType;
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
_contentType=contentType+";charset="+_characterEncoding;
_mimeType=null;
}
_fields.put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
@ -1005,9 +897,9 @@ public class Response implements HttpServletResponse
*/
public void setBufferSize(int size)
{
if (isCommitted() || getContentCount()>0)
if (isCommitted())
throw new IllegalStateException("Committed or content written");
_connection.getGenerator().increaseContentBufferSize(size);
_connection.increaseContentBufferSize(size);
}
/* ------------------------------------------------------------ */
@ -1016,7 +908,7 @@ public class Response implements HttpServletResponse
*/
public int getBufferSize()
{
return _connection.getGenerator().getContentBufferSize();
return _connection.getContentBufferSize();
}
/* ------------------------------------------------------------ */
@ -1039,7 +931,7 @@ public class Response implements HttpServletResponse
_status=200;
_reason=null;
HttpFields response_fields=_connection.getResponseFields();
HttpFields response_fields=_fields;
response_fields.clear();
String connection=_connection.getRequestFields().getStringField(HttpHeader.CONNECTION);
@ -1048,22 +940,22 @@ public class Response implements HttpServletResponse
String[] values = connection.split(",");
for (int i=0;values!=null && i<values.length;i++)
{
CachedBuffer cb = HttpHeaderValue.CACHE.get(values[0].trim());
HttpHeaderValue cb = HttpHeaderValue.CACHE.get(values[0].trim());
if (cb!=null)
{
switch(cb.getOrdinal())
switch(cb)
{
case HttpHeaderValue.CLOSE_ORDINAL:
response_fields.put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
case CLOSE:
response_fields.put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE.toString());
break;
case HttpHeaderValue.KEEP_ALIVE_ORDINAL:
if (HttpVersion.HTTP_1_0.equalsIgnoreCase(_connection.getRequest().getProtocol()))
response_fields.put(HttpHeader.CONNECTION,HttpHeaderValue.KEEP_ALIVE);
case KEEP_ALIVE:
if (HttpVersion.HTTP_1_0.is(_connection.getRequest().getProtocol()))
response_fields.put(HttpHeader.CONNECTION,HttpHeaderValue.KEEP_ALIVE.toString());
break;
case HttpHeaderValue.TE_ORDINAL:
response_fields.put(HttpHeader.CONNECTION,HttpHeaderValue.TE);
case TE:
response_fields.put(HttpHeader.CONNECTION,HttpHeaderValue.TE.toString());
break;
}
}
@ -1080,7 +972,7 @@ public class Response implements HttpServletResponse
resetBuffer();
_writer=null;
_outputState=NONE;
_outputState=Output.NONE;
}
/* ------------------------------------------------------------ */
@ -1091,7 +983,7 @@ public class Response implements HttpServletResponse
{
if (isCommitted())
throw new IllegalStateException("Committed");
_connection.getGenerator().resetBuffer();
_connection.resetBuffer();
}
/* ------------------------------------------------------------ */
@ -1114,9 +1006,9 @@ public class Response implements HttpServletResponse
return;
_locale = locale;
_connection.getResponseFields().put(HttpHeader.CONTENT_LANGUAGE,locale.toString().replace('_','-'));
_fields.put(HttpHeader.CONTENT_LANGUAGE,locale.toString().replace('_','-'));
if (_explicitEncoding || _outputState!=0 )
if (_outputState!=Output.NONE )
return;
if (_connection.getRequest().getContext()==null)
@ -1124,31 +1016,8 @@ public class Response implements HttpServletResponse
String charset = _connection.getRequest().getContext().getContextHandler().getLocaleEncoding(locale);
if (charset!=null && charset.length()>0)
{
_characterEncoding=charset;
/* get current MIME type from Content-Type header */
String type=getContentType();
if (type!=null)
{
_characterEncoding=charset;
int semi=type.indexOf(';');
if (semi<0)
{
_mimeType=type;
_contentType= type += ";charset="+charset;
}
else
{
_mimeType=type.substring(0,semi);
_contentType= _mimeType += ";charset="+charset;
}
_cachedMimeType=MimeTypes.CACHE.get(_mimeType);
_connection.getResponseFields().put(HttpHeader.CONTENT_TYPE,_contentType);
}
}
if (charset!=null && charset.length()>0 && _characterEncoding==null)
setCharacterEncoding(charset);
}
/* ------------------------------------------------------------ */
@ -1191,21 +1060,10 @@ public class Response implements HttpServletResponse
_connection.completeResponse();
}
/* ------------------------------------------------------------- */
/**
* @return the number of bytes actually written in response body
*/
public long getContentCount()
{
if (_connection==null || _connection.getGenerator()==null)
return -1;
return _connection.getGenerator().getContentWritten();
}
/* ------------------------------------------------------------ */
public HttpFields getHttpFields()
{
return _connection.getResponseFields();
return _fields;
}
/* ------------------------------------------------------------ */
@ -1213,7 +1071,7 @@ public class Response implements HttpServletResponse
public String toString()
{
return "HTTP/1.1 "+_status+" "+ (_reason==null?"":_reason) +System.getProperty("line.separator")+
_connection.getResponseFields().toString();
_fields.toString();
}
/* ------------------------------------------------------------ */

View File

@ -335,7 +335,7 @@ public class Server extends HandlerWrapper implements Attributes
* or after the entire request has been received (for short requests of known length), or
* on the dispatch of an async request.
*/
public void handle(AbstractHttpConnection connection) throws IOException, ServletException
public void handle(ServerConnection connection) throws IOException, ServletException
{
final String target=connection.getRequest().getPathInfo();
final Request request=connection.getRequest();
@ -357,7 +357,7 @@ public class Server extends HandlerWrapper implements Attributes
* or after the entire request has been received (for short requests of known length), or
* on the dispatch of an async request.
*/
public void handleAsync(AbstractHttpConnection connection) throws IOException, ServletException
public void handleAsync(ServerConnection connection) throws IOException, ServletException
{
final AsyncContinuation async = connection.getRequest().getAsyncContinuation();
final AsyncContinuation.AsyncEventState state = async.getAsyncEventState();

View File

@ -1,45 +0,0 @@
// ========================================================================
// Copyright (c) 2008-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.server;
import static org.junit.Assert.assertEquals;
import java.net.URLDecoder;
import java.net.URLEncoder;
import org.eclipse.jetty.http.EncodedHttpURI;
import org.junit.Test;
public class EncodedHttpURITest
{
@Test
public void testNonURIAscii() throws Exception
{
String url = "http://www.foo.com/ma\u00F1ana";
byte[] asISO = url.getBytes("ISO-8859-1");
new String(asISO, "ISO-8859-1");
//use a non UTF-8 charset as the encoding and url-escape as per
//http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars
String s = URLEncoder.encode(url, "ISO-8859-1");
EncodedHttpURI uri = new EncodedHttpURI("ISO-8859-1");
//parse it, using the same encoding
uri.parse(s);
//decode the url encoding
String d = URLDecoder.decode(uri.getCompletePath(), "ISO-8859-1");
assertEquals(url, d);
}
}

View File

@ -21,12 +21,13 @@ import static org.junit.Assert.fail;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import junit.framework.Assert;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
import org.junit.Test;
public class HttpURITest
@ -270,8 +271,9 @@ public class HttpURITest
{
try
{
ByteArrayBuffer buf = new ByteArrayBuffer(connect_tests[i][0]);
uri.parseConnect(buf.array(),2,buf.length()-4);
byte[] buf = connect_tests[i][0].getBytes(StringUtil.__UTF8);
uri.parseConnect(buf,2,buf.length-4);
assertEquals("path"+i,connect_tests[i][1]+":"+connect_tests[i][2],uri.getPath());
assertEquals("host"+i,connect_tests[i][1],uri.getHost());
assertEquals("port"+i,Integer.parseInt(connect_tests[i][2]),uri.getPort());
@ -282,4 +284,24 @@ public class HttpURITest
}
}
}
@Test
public void testNonURIAscii() throws Exception
{
String url = "http://www.foo.com/ma\u00F1ana";
byte[] asISO = url.getBytes("ISO-8859-1");
new String(asISO, "ISO-8859-1");
//use a non UTF-8 charset as the encoding and url-escape as per
//http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars
String s = URLEncoder.encode(url, "ISO-8859-1");
HttpURI uri = new HttpURI(Charset.forName("ISO-8859-1"));
//parse it, using the same encoding
uri.parse(s);
//decode the url encoding
String d = URLDecoder.decode(uri.getCompletePath(), "ISO-8859-1");
assertEquals(url, d);
}
}

View File

@ -14,6 +14,7 @@
package org.eclipse.jetty.util;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
@ -38,7 +39,7 @@ public class URIUtil
public static final String HTTPS_COLON="https:";
// Use UTF-8 as per http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars
public static final String __CHARSET=System.getProperty("org.eclipse.jetty.util.URI.charset",StringUtil.__UTF8);
public static final Charset __CHARSET=Charset.forName(System.getProperty("org.eclipse.jetty.util.URI.charset",StringUtil.__UTF8));
private URIUtil()
{}
@ -221,15 +222,7 @@ public class URIUtil
if (b>0)
{
String s;
try
{
s=new String(bytes,0,b,__CHARSET);
}
catch (UnsupportedEncodingException e)
{
s=new String(bytes,0,b);
}
String s=new String(bytes,0,b,__CHARSET);
s.getChars(0,s.length(),chars,n);
n+=s.length();
b=0;
@ -243,15 +236,7 @@ public class URIUtil
if (b>0)
{
String s;
try
{
s=new String(bytes,0,b,__CHARSET);
}
catch (UnsupportedEncodingException e)
{
s=new String(bytes,0,b);
}
String s=new String(bytes,0,b,__CHARSET);
s.getChars(0,s.length(),chars,n);
n+=s.length();
}
@ -295,8 +280,8 @@ public class URIUtil
}
if (bytes==null)
return StringUtil.toString(buf,offset,length,__CHARSET);
return StringUtil.toString(bytes,0,n,__CHARSET);
return new String(buf,offset,length,__CHARSET);
return new String(bytes,0,n,__CHARSET);
}

View File

@ -265,22 +265,11 @@ public class UrlEncoded extends MultiMap implements Cloneable
* @param offset the offset within raw to decode from
* @param length the length of the section to decode
* @param map the {@link MultiMap} to populate
* @param buffer the buffer to decode into
*/
public static void decodeUtf8To(byte[] raw,int offset, int length, MultiMap map)
{
decodeUtf8To(raw,offset,length,map,new Utf8StringBuilder());
}
/* -------------------------------------------------------------- */
/** Decoded parameters to Map.
* @param raw the byte[] containing the encoded parameters
* @param offset the offset within raw to decode from
* @param length the length of the section to decode
* @param map the {@link MultiMap} to populate
* @param buffer the buffer to decode into
*/
public static void decodeUtf8To(byte[] raw,int offset, int length, MultiMap map,Utf8StringBuilder buffer)
{
Utf8StringBuilder buffer = new Utf8StringBuilder();
synchronized(map)
{
String key = null;