jetty-9 converted parser to consume all
This commit is contained in:
parent
68f8e073db
commit
1c319703b9
|
@ -14,6 +14,10 @@
|
|||
package org.eclipse.jetty.http;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.util.StringMap;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
@ -114,7 +118,72 @@ public enum HttpHeader
|
|||
if (header!=UNKNOWN)
|
||||
CACHE.put(header.toString(),header);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private final static HttpHeader[] __hashed= new HttpHeader[4096];
|
||||
private final static int __maxHashed;
|
||||
static
|
||||
{
|
||||
// This hash function has been picked to have no collisions for
|
||||
// the known header values. This allows a very quick lookup.
|
||||
int max=0;
|
||||
Map<Integer,HttpHeader> hashes=new HashMap<>();
|
||||
for (HttpHeader header : HttpHeader.values())
|
||||
{
|
||||
String s=header.asString();
|
||||
max=Math.max(max,s.length());
|
||||
int h=0;
|
||||
for (char c:s.toCharArray())
|
||||
h = 31*h + ((c>='a')?(c-'a'+'A'):c);
|
||||
int hash=h%__hashed.length;
|
||||
if (hash<0)hash=-hash;
|
||||
if (hashes.containsKey(hash))
|
||||
{
|
||||
// This should not happen with known headers.
|
||||
System.err.println("Duplicate hash "+header+" "+hashes.get(hash));
|
||||
System.exit(1);
|
||||
}
|
||||
hashes.put(hash,header);
|
||||
__hashed[hash]=header;
|
||||
}
|
||||
__maxHashed=max;
|
||||
}
|
||||
|
||||
public static HttpHeader lookAheadGet(byte[] bytes, int position, int limit)
|
||||
{
|
||||
int h=0;
|
||||
byte b=0;
|
||||
limit=Math.min(position+__maxHashed,limit);
|
||||
for (int i=position;i<limit;i++)
|
||||
{
|
||||
b=bytes[i];
|
||||
if (b==':'||b==' ')
|
||||
break;
|
||||
h= 31*h+ ((b>='a')?(b-'a'+'A'):b);
|
||||
}
|
||||
if (b!=':'&&b!=' ')
|
||||
return null;
|
||||
|
||||
int hash=h%__hashed.length;
|
||||
if (hash<0)hash=-hash;
|
||||
HttpHeader header=__hashed[hash];
|
||||
|
||||
if (header!=null)
|
||||
{
|
||||
String s=header.asString();
|
||||
for (int i=s.length();i-->0;)
|
||||
{
|
||||
b=bytes[position+i];
|
||||
char c=s.charAt(i);
|
||||
if (c!=b && Character.toUpperCase(c)!=(b>='a'?(b-'a'+'A'):b))
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
private final String _string;
|
||||
private final byte[] _bytes;
|
||||
private final byte[] _bytesColonSpace;
|
||||
|
|
|
@ -63,6 +63,12 @@ public enum HttpHeaderValue
|
|||
return _buffer.asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String asString()
|
||||
{
|
||||
return _string;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
|
|
|
@ -34,6 +34,81 @@ public enum HttpMethod
|
|||
CONNECT,
|
||||
MOVE;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Optimised lookup to find a method name and trailing space in a byte array.
|
||||
* @param bytes Array containing ISO-8859-1 characters
|
||||
* @param position The first valid index
|
||||
* @param limit The first non valid index
|
||||
* @return A HttpMethod if a match or null if no easy match.
|
||||
*/
|
||||
public static HttpMethod lookAheadGet(byte[] bytes, int position, int limit)
|
||||
{
|
||||
int length=limit-position;
|
||||
if (length<4)
|
||||
return null;
|
||||
switch(bytes[position])
|
||||
{
|
||||
case 'G':
|
||||
if (bytes[position+1]=='E' && bytes[position+2]=='T' && bytes[position+3]==' ')
|
||||
return GET;
|
||||
break;
|
||||
case 'P':
|
||||
if (bytes[position+1]=='O' && bytes[position+2]=='S' && bytes[position+3]=='T' && length>=5 && bytes[position+4]==' ')
|
||||
return POST;
|
||||
if (bytes[position+1]=='U' && bytes[position+2]=='T' && bytes[position+3]==' ')
|
||||
return PUT;
|
||||
break;
|
||||
case 'H':
|
||||
if (bytes[position+1]=='E' && bytes[position+2]=='A' && bytes[position+3]=='D' && length>=5 && bytes[position+4]==' ')
|
||||
return HEAD;
|
||||
break;
|
||||
case 'O':
|
||||
if (bytes[position+1]=='O' && bytes[position+2]=='T' && bytes[position+3]=='I' && length>=8 &&
|
||||
bytes[position+4]=='O' && bytes[position+5]=='N' && bytes[position+6]=='S' && bytes[position+7]==' ' )
|
||||
return OPTIONS;
|
||||
break;
|
||||
case 'D':
|
||||
if (bytes[position+1]=='E' && bytes[position+2]=='L' && bytes[position+3]=='E' && length>=7 &&
|
||||
bytes[position+4]=='T' && bytes[position+5]=='E' && bytes[position+6]==' ' )
|
||||
return DELETE;
|
||||
break;
|
||||
case 'T':
|
||||
if (bytes[position+1]=='R' && bytes[position+2]=='A' && bytes[position+3]=='C' && length>=6 &&
|
||||
bytes[position+4]=='E' && bytes[position+5]==' ' )
|
||||
return TRACE;
|
||||
break;
|
||||
case 'C':
|
||||
if (bytes[position+1]=='O' && bytes[position+2]=='N' && bytes[position+3]=='N' && length>=8 &&
|
||||
bytes[position+4]=='E' && bytes[position+5]=='C' && bytes[position+6]=='T' && bytes[position+7]==' ' )
|
||||
return CONNECT;
|
||||
break;
|
||||
case 'M':
|
||||
if (bytes[position+1]=='O' && bytes[position+2]=='V' && bytes[position+3]=='E' && bytes[position+4]==' ')
|
||||
return MOVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Optimised lookup to find a method name and trailing space in a byte array.
|
||||
* @param bytes Array containing ISO-8859-1 characters
|
||||
* @param position The first valid index
|
||||
* @param limit The first non valid index
|
||||
* @return A HttpMethod if a match or null if no easy match.
|
||||
*/
|
||||
public static HttpMethod lookAheadGet(ByteBuffer buffer)
|
||||
{
|
||||
if (buffer.hasArray())
|
||||
return lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position(),buffer.arrayOffset()+buffer.limit());
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public final static StringMap<HttpMethod> CACHE= new StringMap<HttpMethod>(true);
|
||||
static
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,7 +24,8 @@ public enum HttpVersion
|
|||
{
|
||||
HTTP_0_9("HTTP/0.9",9),
|
||||
HTTP_1_0("HTTP/1.0",10),
|
||||
HTTP_1_1("HTTP/1.1",11);
|
||||
HTTP_1_1("HTTP/1.1",11),
|
||||
HTTP_2_0("HTTP/2.0",20);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public final static StringMap<HttpVersion> CACHE= new StringMap<HttpVersion>(true);
|
||||
|
@ -34,6 +35,64 @@ public enum HttpVersion
|
|||
CACHE.put(version.toString(),version);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Optimised lookup to find a Http Version and whitespace in a byte array.
|
||||
* @param bytes Array containing ISO-8859-1 characters
|
||||
* @param position The first valid index
|
||||
* @param limit The first non valid index
|
||||
* @return A HttpMethod if a match or null if no easy match.
|
||||
*/
|
||||
public static HttpVersion lookAheadGet(byte[] bytes, int position, int limit)
|
||||
{
|
||||
int length=limit-position;
|
||||
if (length<9)
|
||||
return null;
|
||||
|
||||
if (bytes[position+4]=='/' && bytes[position+6]=='.' && Character.isWhitespace((char)bytes[position+8]) &&
|
||||
((bytes[position]=='H' && bytes[position+1]=='T' && bytes[position+2]=='T' && bytes[position+3]=='P') ||
|
||||
(bytes[position]=='h' && bytes[position+1]=='t' && bytes[position+2]=='t' && bytes[position+3]=='p')))
|
||||
{
|
||||
switch(bytes[position+5])
|
||||
{
|
||||
case '1':
|
||||
switch(bytes[position+7])
|
||||
{
|
||||
case '0':
|
||||
return HTTP_1_0;
|
||||
case '1':
|
||||
return HTTP_1_1;
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
switch(bytes[position+7])
|
||||
{
|
||||
case '0':
|
||||
return HTTP_2_0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Optimised lookup to find a HTTP Version and trailing white space in a byte array.
|
||||
* @param bytes Array containing ISO-8859-1 characters
|
||||
* @param position The first valid index
|
||||
* @param limit The first non valid index
|
||||
* @return A HttpVersion if a match or null if no easy match.
|
||||
*/
|
||||
public static HttpVersion lookAheadGet(ByteBuffer buffer)
|
||||
{
|
||||
if (buffer.hasArray())
|
||||
return lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position(),buffer.arrayOffset()+buffer.limit());
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private final String _string;
|
||||
private final byte[] _bytes;
|
||||
private final ByteBuffer _buffer;
|
||||
|
@ -72,6 +131,12 @@ public enum HttpVersion
|
|||
return _string.equalsIgnoreCase(s);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String asString()
|
||||
{
|
||||
return _string;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
|
|
|
@ -23,7 +23,6 @@ import static org.junit.matchers.JUnitMatchers.containsString;
|
|||
import static org.junit.matchers.JUnitMatchers.either;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -81,7 +80,7 @@ public class HttpGeneratorServerTest
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean startResponse(String version, int status, String reason) throws IOException
|
||||
public boolean startResponse(HttpVersion version, int status, String reason) throws IOException
|
||||
{
|
||||
_version=version;
|
||||
_status=status;
|
||||
|
@ -273,7 +272,7 @@ public class HttpGeneratorServerTest
|
|||
private int _status;
|
||||
|
||||
private final List<String> _val=new ArrayList<>();
|
||||
private String _version;
|
||||
private HttpVersion _version;
|
||||
|
||||
private final TR[] tr =
|
||||
{
|
||||
|
@ -309,15 +308,15 @@ public class HttpGeneratorServerTest
|
|||
for (int c=0;c<(v==11?connect.length:(connect.length-1));c++)
|
||||
{
|
||||
String t="v="+v+",chunks="+chunks+",connect="+connect[c]+",tr="+r+"="+tr[r];
|
||||
System.err.println("\n==========================================");
|
||||
System.err.println(t);
|
||||
// System.err.println("\n==========================================");
|
||||
// System.err.println(t);
|
||||
|
||||
gen.reset();
|
||||
tr[r].getHttpFields().clear();
|
||||
|
||||
String response=tr[r].build(v,gen,"OK\r\nTest",connect[c],null,chunks);
|
||||
|
||||
System.err.println("---\n"+t+"\n"+response+(gen.isPersistent()?"...":"==="));
|
||||
// System.err.println("---\n"+t+"\n"+response+(gen.isPersistent()?"...":"==="));
|
||||
|
||||
if (v==9)
|
||||
{
|
||||
|
|
|
@ -120,12 +120,13 @@ public class HttpParserTest
|
|||
"GET / HTTP/1.0\015\012" +
|
||||
"Host: localhost\015\012" +
|
||||
"Header1: value1\015\012" +
|
||||
"Header2 : value 2a \015\012" +
|
||||
"Header 2 : value 2a \015\012" +
|
||||
" value 2b \015\012" +
|
||||
"Header3: \015\012" +
|
||||
"Header4 \015\012" +
|
||||
" value4\015\012" +
|
||||
"Server5: notServer\015\012" +
|
||||
"Server5 : notServer\015\012" +
|
||||
"Host Header: notHost\015\012" +
|
||||
"\015\012");
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
|
@ -138,7 +139,7 @@ public class HttpParserTest
|
|||
assertEquals("localhost", val[0]);
|
||||
assertEquals("Header1", hdr[1]);
|
||||
assertEquals("value1", val[1]);
|
||||
assertEquals("Header2", hdr[2]);
|
||||
assertEquals("Header 2", hdr[2]);
|
||||
assertEquals("value 2a value 2b", val[2]);
|
||||
assertEquals("Header3", hdr[3]);
|
||||
assertEquals(null, val[3]);
|
||||
|
@ -146,23 +147,25 @@ public class HttpParserTest
|
|||
assertEquals("value4", val[4]);
|
||||
assertEquals("Server5", hdr[5]);
|
||||
assertEquals("notServer", val[5]);
|
||||
assertEquals(5, h);
|
||||
assertEquals("Host Header", hdr[6]);
|
||||
assertEquals("notHost", val[6]);
|
||||
assertEquals(6, h);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitHeaderParse() throws Exception
|
||||
{
|
||||
ByteBuffer buffer= BufferUtil.toBuffer(
|
||||
"XXXXGET / HTTP/1.0\015\012" +
|
||||
"Host: localhost\015\012" +
|
||||
"Header1: value1\015\012" +
|
||||
"Header2 : value 2a \015\012" +
|
||||
" value 2b \015\012" +
|
||||
"Header3: \015\012" +
|
||||
"Header4 \015\012" +
|
||||
" value4\015\012" +
|
||||
"Server5: notServer\015\012" +
|
||||
"\015\012ZZZZ");
|
||||
"XXXXSPLIT / HTTP/1.0\015\012" +
|
||||
"Host: localhost\015\012" +
|
||||
"Header1: value1\015\012" +
|
||||
"Header2 : value 2a \015\012" +
|
||||
" value 2b \015\012" +
|
||||
"Header3: \015\012" +
|
||||
"Header4 \015\012" +
|
||||
" value4\015\012" +
|
||||
"Server5: notServer\015\012" +
|
||||
"\015\012ZZZZ");
|
||||
buffer.position(2);
|
||||
buffer.limit(buffer.capacity()-2);
|
||||
buffer=buffer.slice();
|
||||
|
@ -177,11 +180,15 @@ public class HttpParserTest
|
|||
|
||||
if (!parser.parseNext(buffer))
|
||||
{
|
||||
// consumed all
|
||||
assertEquals(0,buffer.remaining());
|
||||
|
||||
// parse the rest
|
||||
buffer.limit(buffer.capacity()-2);
|
||||
parser.parseNext(buffer);
|
||||
}
|
||||
|
||||
assertEquals("GET", f0);
|
||||
assertEquals("SPLIT", f0);
|
||||
assertEquals("/", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals("Host", hdr[0]);
|
||||
|
@ -478,7 +485,7 @@ public class HttpParserTest
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean startRequest(String method, String uri, String version)
|
||||
public boolean startRequest(HttpMethod httpMethod, String method, String uri, HttpVersion version)
|
||||
{
|
||||
request=true;
|
||||
h= -1;
|
||||
|
@ -486,7 +493,7 @@ public class HttpParserTest
|
|||
val= new String[9];
|
||||
f0= method;
|
||||
f1= uri;
|
||||
f2= version;
|
||||
f2= version==null?null:version.asString();
|
||||
|
||||
fields=new HttpFields();
|
||||
messageCompleted = false;
|
||||
|
@ -530,10 +537,10 @@ public class HttpParserTest
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean startResponse(String version, int status, String reason)
|
||||
public boolean startResponse(HttpVersion version, int status, String reason)
|
||||
{
|
||||
request=false;
|
||||
f0 = version.toString();
|
||||
f0 = version.asString();
|
||||
f1 = Integer.toString(status);
|
||||
f2 = reason==null?null:reason.toString();
|
||||
|
||||
|
|
|
@ -297,6 +297,8 @@ public abstract class HttpChannel
|
|||
_responseFields.clear();
|
||||
_response.recycle();
|
||||
_uri.clear();
|
||||
if (_out!=null)
|
||||
_out.reset();
|
||||
synchronized (_inputQ)
|
||||
{
|
||||
_inputEOF=false;
|
||||
|
@ -437,8 +439,13 @@ public abstract class HttpChannel
|
|||
_response.setStatus(status,reason);
|
||||
if (close)
|
||||
_responseFields.add(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
|
||||
ByteBuffer buffer=BufferUtil.toBuffer(content,StringUtil.__UTF8_CHARSET);
|
||||
_response.setContentLength(buffer.remaining());
|
||||
|
||||
ByteBuffer buffer=null;
|
||||
if (content!=null)
|
||||
{
|
||||
buffer=BufferUtil.toBuffer(content,StringUtil.__UTF8_CHARSET);
|
||||
_response.setContentLength(buffer.remaining());
|
||||
}
|
||||
|
||||
HttpGenerator.ResponseInfo info = _handler.commit();
|
||||
commit(info,buffer);
|
||||
|
@ -555,7 +562,7 @@ public abstract class HttpChannel
|
|||
private class RequestHandler implements EventHandler
|
||||
{
|
||||
@Override
|
||||
public boolean startRequest(String method, String uri, String version) throws IOException
|
||||
public boolean startRequest(HttpMethod httpMethod,String method, String uri, HttpVersion version) throws IOException
|
||||
{
|
||||
_host = false;
|
||||
_expect = false;
|
||||
|
@ -564,30 +571,18 @@ public abstract class HttpChannel
|
|||
|
||||
if(_request.getTimeStamp()==0)
|
||||
_request.setTimeStamp(System.currentTimeMillis());
|
||||
HttpMethod m = HttpMethod.CACHE.get(method);
|
||||
_request.setMethod(m,method);
|
||||
_request.setMethod(httpMethod,method);
|
||||
|
||||
try
|
||||
{
|
||||
if (m==HttpMethod.CONNECT)
|
||||
if (httpMethod==HttpMethod.CONNECT)
|
||||
_uri.parseConnect(uri);
|
||||
else
|
||||
_uri.parse(uri);
|
||||
|
||||
_request.setUri(_uri);
|
||||
|
||||
if (version==null)
|
||||
{
|
||||
_request.setHttpVersion(HttpVersion.HTTP_0_9);
|
||||
_version=HttpVersion.HTTP_0_9;
|
||||
}
|
||||
else
|
||||
{
|
||||
_version= HttpVersion.CACHE.get(version);
|
||||
if (_version==null)
|
||||
throw new HttpException(HttpStatus.BAD_REQUEST_400,null);
|
||||
_request.setHttpVersion(_version);
|
||||
}
|
||||
_version=version==null?HttpVersion.HTTP_0_9:version;
|
||||
_request.setHttpVersion(_version);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -713,7 +708,10 @@ public abstract class HttpChannel
|
|||
@Override
|
||||
public boolean content(ByteBuffer ref) throws IOException
|
||||
{
|
||||
_inputQ.add(ref);
|
||||
synchronized (_inputQ.lock())
|
||||
{
|
||||
_inputQ.add(ref);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -826,9 +824,7 @@ public abstract class HttpChannel
|
|||
public abstract HttpConnector getHttpConnector();
|
||||
|
||||
protected abstract void blockForContent() throws IOException;
|
||||
|
||||
protected abstract void contentConsumed();
|
||||
|
||||
|
||||
protected abstract int write(ByteBuffer content) throws IOException;
|
||||
|
||||
protected abstract void commit(ResponseInfo info, ByteBuffer content) throws IOException;
|
||||
|
|
|
@ -200,8 +200,15 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
?_bufferPool.acquire(_connector.getRequestBufferSize(),false)
|
||||
:_bufferPool.acquire(_connector.getRequestHeaderSize(),false);
|
||||
|
||||
int filled=getEndPoint().fill(_requestBuffer);
|
||||
LOG.debug("{} filled {}",this,filled);
|
||||
// Only fill if buffer is fully consumed
|
||||
if (BufferUtil.isEmpty(_requestBuffer))
|
||||
{
|
||||
// TODO this is still dangerous as a suspended request might have references
|
||||
// to the buffer still for unconsumed input. We need a callback to say
|
||||
// all content is consumed and we can read again.
|
||||
int filled=getEndPoint().fill(_requestBuffer);
|
||||
LOG.debug("{} filled {}",this,filled);
|
||||
}
|
||||
|
||||
// If we parse to an event, call the connection
|
||||
if (BufferUtil.hasContent(_requestBuffer) && _parser.parseNext(_requestBuffer))
|
||||
|
@ -220,6 +227,9 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
getEndPoint().setCheckForIdle(true);
|
||||
}
|
||||
}
|
||||
else if (BufferUtil.hasContent(_requestBuffer))
|
||||
throw new IllegalStateException("parser should consume all content OR return true");
|
||||
|
||||
|
||||
}
|
||||
catch (HttpException e)
|
||||
|
@ -565,6 +575,7 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
protected void blockForContent() throws IOException
|
||||
{
|
||||
// While progress and the connection has not changed
|
||||
boolean parsed_event=false;
|
||||
while (getEndPoint().isOpen())
|
||||
{
|
||||
try
|
||||
|
@ -578,8 +589,13 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
if (_requestBuffer==null)
|
||||
_requestBuffer=_bufferPool.acquire(_connector.getRequestBufferSize(),false);
|
||||
|
||||
int filled=getEndPoint().fill(_requestBuffer);
|
||||
LOG.debug("{} filled {}",this,filled);
|
||||
|
||||
// If we parse to an event, return
|
||||
if (BufferUtil.hasContent(_requestBuffer) && _parser.parseNext(_requestBuffer))
|
||||
while (BufferUtil.hasContent(_requestBuffer) && _parser.inContentState())
|
||||
parsed_event|=_parser.parseNext(_requestBuffer);
|
||||
if (parsed_event)
|
||||
return;
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
|
@ -603,13 +619,6 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contentConsumed()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void commit(ResponseInfo info, ByteBuffer content) throws IOException
|
||||
{
|
||||
|
|
|
@ -71,7 +71,6 @@ public class StringMap<O> extends AbstractMap<String,O>
|
|||
s1=o1.toString();
|
||||
String s2=(String)o2;
|
||||
|
||||
|
||||
int n1 = s1==null?b1.remaining():s1.length();
|
||||
int n2 = s2.length();
|
||||
int min = Math.min(n1, n2);
|
||||
|
@ -79,7 +78,6 @@ public class StringMap<O> extends AbstractMap<String,O>
|
|||
char c1 = s1==null?(char)b1.get(b1.position()+i):s1.charAt(i);
|
||||
char c2 = s2.charAt(i);
|
||||
if (c1 != c2) {
|
||||
|
||||
if (ignoreCase)
|
||||
{
|
||||
c1 = Character.toUpperCase(c1);
|
||||
|
@ -98,11 +96,8 @@ public class StringMap<O> extends AbstractMap<String,O>
|
|||
}
|
||||
}
|
||||
return n1 - n2;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -138,17 +133,11 @@ public class StringMap<O> extends AbstractMap<String,O>
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public O get(ByteBuffer buffer, int position, int length)
|
||||
public O get(ByteBuffer buffer)
|
||||
{
|
||||
ByteBuffer ro=buffer.asReadOnlyBuffer();
|
||||
ro.limit(ro.capacity());
|
||||
ro.position(position);
|
||||
ro.limit(position+length);
|
||||
return _map.get(ro);
|
||||
return _map.get(buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public O remove(Object key)
|
||||
|
@ -156,7 +145,6 @@ public class StringMap<O> extends AbstractMap<String,O>
|
|||
return _map.remove(key);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public O remove(String key)
|
||||
{
|
||||
|
|
|
@ -88,7 +88,11 @@ public class StringUtil
|
|||
*/
|
||||
public static String normalizeCharset(ByteBuffer b,int position,int length)
|
||||
{
|
||||
String n=CHARSETS.get(b,position,length);
|
||||
ByteBuffer ro=b.asReadOnlyBuffer();
|
||||
ro.limit(ro.capacity());
|
||||
ro.position(position);
|
||||
ro.limit(position+length);
|
||||
String n=CHARSETS.get(ro);
|
||||
if (n!=null)
|
||||
return n;
|
||||
ByteBuffer slice = b.slice();
|
||||
|
|
Loading…
Reference in New Issue