From 2659d87868c0eec22ec20f0709337de5c141839f Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 9 Feb 2012 23:27:49 +1100 Subject: [PATCH] jetty-9 HttpParser tests passing --- .../org/eclipse/jetty/http/HttpFields.java | 10 +- .../org/eclipse/jetty/http/HttpParser.java | 372 +++++++++--------- .../java/org/eclipse/jetty/http/Parser.java | 7 +- .../java/org/eclipse/jetty/http/PathMap.java | 93 ++--- .../eclipse/jetty/http/HttpParserTest.java | 305 ++++++-------- .../org/eclipse/jetty/util/BufferUtil.java | 77 +++- .../org/eclipse/jetty/util/StringMap.java | 47 +-- 7 files changed, 432 insertions(+), 479 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java index 86a471a00a8..3cd6d6d6d6c 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java @@ -927,7 +927,7 @@ public class HttpFields private static final StringMap __qualities = new StringMap<>(); static { - __qualities.put(null, __one); + __qualities.put("*", __one); __qualities.put("1.0", __one); __qualities.put("1", __one); __qualities.put("0.9", new Float("0.9")); @@ -956,14 +956,16 @@ public class HttpFields if (value.charAt(qe++) == 'q') { qe++; - Map.Entry entry = __qualities.getEntry(value, qe, value.length() - qe); - if (entry != null) - return (Float) entry.getValue(); + Float q = __qualities.get(value, qe, value.length() - qe); + if (q != null) + return q; } Map params = new HashMap(4); valueParameters(value, params); String qs = (String) params.get("q"); + if (qs==null) + qs="*"; Float q = (Float) __qualities.get(qs); if (q == null) { diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index d6e714ef358..b14cbc32905 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -27,28 +27,31 @@ public class HttpParser implements Parser private static final Logger LOG = Log.getLogger(HttpParser.class); // States - public static final int STATE_START=-14; - public static final int STATE_METHOD=-13; - public static final int STATE_RESPONSE_VERSION=-12; - public static final int STATE_SPACE1=-11; - public static final int STATE_STATUS=-10; - public static final int STATE_URI=-9; - public static final int STATE_SPACE2=-8; - public static final int STATE_REQUEST_VERSION=-7; - public static final int STATE_REASON=-6; - public static final int STATE_HEADER=-5; - public static final int STATE_HEADER_NAME=-4; - public static final int STATE_HEADER_IN_NAME=-3; - public static final int STATE_HEADER_VALUE=-2; - public static final int STATE_HEADER_IN_VALUE=-1; - public static final int STATE_END=0; - public static final int STATE_EOF_CONTENT=1; - public static final int STATE_CONTENT=2; - public static final int STATE_CHUNKED_CONTENT=3; - public static final int STATE_CHUNK_SIZE=4; - public static final int STATE_CHUNK_PARAMS=5; - public static final int STATE_CHUNK=6; - public static final int STATE_SEEKING_EOF=7; + public enum State + { + START, + METHOD, + RESPONSE_VERSION, + SPACE1, + STATUS, + URI, + SPACE2, + REQUEST_VERSION, + REASON, + HEADER, + HEADER_NAME, + HEADER_IN_NAME, + HEADER_VALUE, + HEADER_IN_VALUE, + END, + EOF_CONTENT, + CONTENT, + CHUNKED_CONTENT, + CHUNK_SIZE, + CHUNK_PARAMS, + CHUNK, + SEEKING_EOF + }; private final EventHandler _handler; private final RequestHandler _requestHandler; @@ -59,7 +62,7 @@ public class HttpParser implements Parser private boolean _persistent; /* ------------------------------------------------------------------------------- */ - private int _state=STATE_START; + private State _state=State.START; private String _field0; private String _field1; private byte _eol; @@ -113,7 +116,7 @@ public class HttpParser implements Parser } /* ------------------------------------------------------------------------------- */ - public int getState() + public State getState() { return _state; } @@ -121,13 +124,13 @@ public class HttpParser implements Parser /* ------------------------------------------------------------------------------- */ public boolean inContentState() { - return _state > 0; + return _state.ordinal() > State.END.ordinal(); } /* ------------------------------------------------------------------------------- */ public boolean inHeaderState() { - return _state < 0; + return _state.ordinal() < State.END.ordinal(); } /* ------------------------------------------------------------------------------- */ @@ -139,17 +142,17 @@ public class HttpParser implements Parser /* ------------------------------------------------------------ */ public boolean isIdle() { - return isState(STATE_START); + return isState(State.START); } /* ------------------------------------------------------------ */ public boolean isComplete() { - return isState(STATE_END); + return isState(State.END); } /* ------------------------------------------------------------------------------- */ - public boolean isState(int state) + public boolean isState(State state) { return _state == state; } @@ -164,49 +167,34 @@ public class HttpParser implements Parser public void setPersistent(boolean persistent) { _persistent = persistent; - if (!_persistent &&(_state==STATE_END || _state==STATE_START)) - _state=STATE_SEEKING_EOF; + if (!_persistent &&(_state==State.END || _state==State.START)) + _state=State.SEEKING_EOF; } /* ------------------------------------------------------------------------------- */ /** - * Parse until {@link #STATE_END END} state. + * Parse until {@link #END END} state. * If the parser is already in the END state, then it is {@link #reset reset} and re-parsed. * @throws IllegalStateException If the buffers have already been partially parsed. */ - public void parse(ByteBuffer buffer) throws IOException + public void parseAll(ByteBuffer buffer) throws IOException { - if (_state==STATE_END) + if (_state==State.END) reset(); - if (_state!=STATE_START) + if (_state!=State.START) throw new IllegalStateException("!START"); // continue parsing - while (_state != STATE_END && buffer.hasRemaining()) - if (!parseNext(buffer)) - return; - } - - /* ------------------------------------------------------------------------------- */ - /** - * Parse until END state. - * This method will parse any remaining content in the current buffer. It does not care about the - * {@link #getState current state} of the parser. - * @see #parse - * @see #parseNext - */ - public boolean parseAvailable(ByteBuffer buffer) throws IOException - { - boolean progress=parseNext(buffer); - - // continue parsing - while (!isComplete() && buffer.hasRemaining()) + while (_state != State.END && buffer.hasRemaining()) { - progress |= parseNext(buffer); + int remaining=buffer.remaining(); + parseNext(buffer); + if (remaining==buffer.remaining()) + break; } - return progress; } + /* ------------------------------------------------------------------------------- */ /** * Parse until next Event. @@ -214,35 +202,28 @@ public class HttpParser implements Parser */ public boolean parseNext(ByteBuffer buffer) throws IOException { + int start=-1; + State startState=null; + try { - int progress=0; - - if (_state == STATE_END) + if (_state == State.END) return false; - if (_state == STATE_CONTENT && _contentPosition == _contentLength) + if (_state == State.CONTENT && _contentPosition == _contentLength) { - _state=STATE_END; - _handler.messageComplete(_contentPosition); - return true; + _state=State.END; + if(_handler.messageComplete(_contentPosition)) + return true; } - // Handle header states byte ch; - int last=_state; - int start=-1; int length=-1; + boolean at_next=false; - while (_state HttpTokens.SPACE || ch<0) { start=buffer.position()-1; - _state=_requestHandler!=null?STATE_METHOD:STATE_RESPONSE_VERSION; + startState=_state; + _state=_requestHandler!=null?State.METHOD:State.RESPONSE_VERSION; } break; - case STATE_METHOD: + case METHOD: if (ch == HttpTokens.SPACE) { HttpMethods method=HttpMethods.CACHE.get(buffer,start,buffer.position()-start-1); _field0=method==null?BufferUtil.toString(buffer,start,buffer.position()-start-1,StringUtil.__ISO_8859_1_CHARSET):method.toString(); - _state=STATE_SPACE1; + _state=State.SPACE1; } else if (ch < HttpTokens.SPACE && ch>=0) { @@ -277,15 +259,14 @@ public class HttpParser implements Parser } break; - case STATE_RESPONSE_VERSION: + case RESPONSE_VERSION: if (ch == HttpTokens.SPACE) { - int l=buffer.position()-start; - HttpVersions v=HttpVersions.CACHE.get(buffer,start,l); - _field0=v==null?BufferUtil.toString(buffer,start,l,StringUtil.__ISO_8859_1_CHARSET):v.toString(); + HttpVersions v=HttpVersions.CACHE.get(buffer,start,buffer.position()-start-1); + _field0=v==null?BufferUtil.toString(buffer,start,buffer.position()-start-1,StringUtil.__ISO_8859_1_CHARSET):v.toString(); start=-1; _persistent=HttpVersions.HTTP_1_1==v; - _state=STATE_SPACE1; + _state=State.SPACE1; } else if (ch < HttpTokens.SPACE && ch>=0) { @@ -293,18 +274,19 @@ public class HttpParser implements Parser } break; - case STATE_SPACE1: + case SPACE1: if (ch > HttpTokens.SPACE || ch<0) { if (_responseHandler!=null) { - _state=STATE_STATUS; + _state=State.STATUS; _responseStatus=ch-'0'; } else { - _state=STATE_URI; start=buffer.position()-1; + startState=_state; + _state=State.URI; } } else if (ch < HttpTokens.SPACE) @@ -313,10 +295,10 @@ public class HttpParser implements Parser } break; - case STATE_STATUS: + case STATUS: if (ch == HttpTokens.SPACE) { - _state=STATE_SPACE2; + _state=State.SPACE2; } else if (ch>='0' && ch<='9') { @@ -324,10 +306,10 @@ public class HttpParser implements Parser } else if (ch < HttpTokens.SPACE && ch>=0) { - _responseHandler.startResponse(_field0, _responseStatus, null); + at_next|=_responseHandler.startResponse(_field0, _responseStatus, null); _eol=ch; - _state=STATE_HEADER; + _state=State.HEADER; _field0=_field1=null; } else @@ -336,84 +318,85 @@ public class HttpParser implements Parser } break; - case STATE_URI: + case URI: if (ch == HttpTokens.SPACE) { _field1=BufferUtil.toString(buffer,start,buffer.position()-start-1,StringUtil.__UTF8_CHARSET); start=-1; - _state=STATE_SPACE2; + _state=State.SPACE2; } else if (ch < HttpTokens.SPACE && ch>=0) { // HTTP/0.9 _field1=BufferUtil.toString(buffer,start,buffer.position()-start-1,StringUtil.__UTF8_CHARSET); start=-1; - _requestHandler.startRequest(_field0,_field1,null); + at_next|=_requestHandler.startRequest(_field0,_field1,null); _persistent=false; - _state=STATE_SEEKING_EOF; - _handler.headerComplete(); - _handler.messageComplete(_contentPosition); + _state=State.SEEKING_EOF; + at_next|=_handler.headerComplete(); + at_next|=_handler.messageComplete(_contentPosition); } break; - case STATE_SPACE2: + case SPACE2: if (ch > HttpTokens.SPACE || ch<0) { - _state=_requestHandler!=null?STATE_REQUEST_VERSION:STATE_REASON; start=buffer.position()-1; + startState=_state; + _state=_requestHandler!=null?State.REQUEST_VERSION:State.REASON; } else if (ch < HttpTokens.SPACE) { if (_responseHandler!=null) { - _responseHandler.startResponse(_field0, _responseStatus, null); + at_next|=_responseHandler.startResponse(_field0, _responseStatus, null); _eol=ch; - _state=STATE_HEADER; + _state=State.HEADER; _field0=_field1=null; } else { // HTTP/0.9 - _requestHandler.startRequest(_field0, _field1, null); + at_next|=_requestHandler.startRequest(_field0, _field1, null); _persistent=false; - _state=STATE_SEEKING_EOF; - _handler.headerComplete(); - _handler.messageComplete(_contentPosition); + _state=State.SEEKING_EOF; + at_next|=_handler.headerComplete(); + at_next|=_handler.messageComplete(_contentPosition); } } break; - case STATE_REQUEST_VERSION: + case REQUEST_VERSION: if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { HttpVersions v=HttpVersions.CACHE.get(buffer,start,buffer.position()-start-1); String version=v==null?BufferUtil.toString(buffer,start,buffer.position()-start-1,StringUtil.__ISO_8859_1_CHARSET):v.toString(); start=-1; - _requestHandler.startRequest(_field0, _field1, version); + at_next|=_requestHandler.startRequest(_field0, _field1, version); _eol=ch; _persistent=HttpVersions.HTTP_1_1==v; - _state=STATE_HEADER; + _state=State.HEADER; _field0=_field1=null; continue; } break; - case STATE_REASON: + case REASON: if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { - String reason=BufferUtil.toString(buffer,start,buffer.position()-start,StringUtil.__ISO_8859_1_CHARSET); + String reason=BufferUtil.toString(buffer,start,buffer.position()-start-1,StringUtil.__ISO_8859_1_CHARSET); start=-1; - _responseHandler.startResponse(_field0, _responseStatus, reason); + at_next|=_responseHandler.startResponse(_field0, _responseStatus, reason); _eol=ch; - _state=STATE_HEADER; + _state=State.HEADER; _field0=_field1=null; continue; } break; - case STATE_HEADER: + case HEADER: switch(ch) { case HttpTokens.COLON: @@ -422,7 +405,7 @@ public class HttpParser implements Parser { // header value without name - continuation? length=-1; - _state=STATE_HEADER_VALUE; + _state=State.HEADER_VALUE; break; } @@ -497,7 +480,7 @@ public class HttpParser implements Parser } } - _handler.parsedHeader(_field0, _field1); + at_next|=_handler.parsedHeader(_field0, _field1); } _field0=_field1=null; _header=null; @@ -528,24 +511,24 @@ public class HttpParser implements Parser switch (_contentLength > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) _contentLength) { case HttpTokens.EOF_CONTENT: - _state=STATE_EOF_CONTENT; - _handler.headerComplete(); // May recurse here ! + _state=State.EOF_CONTENT; + at_next|=_handler.headerComplete(); // May recurse here ! break; case HttpTokens.CHUNKED_CONTENT: - _state=STATE_CHUNKED_CONTENT; - _handler.headerComplete(); // May recurse here ! + _state=State.CHUNKED_CONTENT; + at_next|=_handler.headerComplete(); // May recurse here ! break; case HttpTokens.NO_CONTENT: - _handler.headerComplete(); - _state=_persistent||(_responseStatus>=100&&_responseStatus<200)?STATE_END:STATE_SEEKING_EOF; - _handler.messageComplete(_contentPosition); + at_next|=_handler.headerComplete(); + _state=_persistent||(_responseStatus>=100&&_responseStatus<200)?State.END:State.SEEKING_EOF; + at_next|=_handler.messageComplete(_contentPosition); break; default: - _state=STATE_CONTENT; - _handler.headerComplete(); // May recurse here ! + _state=State.CONTENT; + at_next|=_handler.headerComplete(); // May recurse here ! break; } } @@ -553,15 +536,16 @@ public class HttpParser implements Parser { // New header start=buffer.position()-1; + startState=_state; length=1; - _state=STATE_HEADER_NAME; + _state=State.HEADER_NAME; } } } break; - case STATE_HEADER_NAME: + case HEADER_NAME: switch(ch) { case HttpTokens.CARRIAGE_RETURN: @@ -570,14 +554,14 @@ public class HttpParser implements Parser _header=HttpHeaders.CACHE.get(buffer,start,length); _field0=_header==null?BufferUtil.toString(buffer,start,length,StringUtil.__ISO_8859_1_CHARSET):_header.toString(); start=length=-1; - _state=STATE_HEADER; + _state=State.HEADER; break; case HttpTokens.COLON: _header=HttpHeaders.CACHE.get(buffer,start,length); _field0=_header==null?BufferUtil.toString(buffer,start,length,StringUtil.__ISO_8859_1_CHARSET):_header.toString(); start=length=-1; - _state=STATE_HEADER_VALUE; + _state=State.HEADER_VALUE; break; case HttpTokens.SPACE: case HttpTokens.TAB: @@ -585,13 +569,13 @@ public class HttpParser implements Parser default: { length=buffer.position()-start; - _state=STATE_HEADER_IN_NAME; + _state=State.HEADER_IN_NAME; } } break; - case STATE_HEADER_IN_NAME: + case HEADER_IN_NAME: switch(ch) { case HttpTokens.CARRIAGE_RETURN: @@ -600,25 +584,25 @@ public class HttpParser implements Parser _header=HttpHeaders.CACHE.get(buffer,start,length); _field0=_header==null?BufferUtil.toString(buffer,start,length,StringUtil.__ISO_8859_1_CHARSET):_header.toString(); start=length=-1; - _state=STATE_HEADER; + _state=State.HEADER; break; case HttpTokens.COLON: _header=HttpHeaders.CACHE.get(buffer,start,length); _field0=_header==null?BufferUtil.toString(buffer,start,length,StringUtil.__ISO_8859_1_CHARSET):_header.toString(); start=length=-1; - _state=STATE_HEADER_VALUE; + _state=State.HEADER_VALUE; break; case HttpTokens.SPACE: case HttpTokens.TAB: - _state=STATE_HEADER_NAME; + _state=State.HEADER_NAME; break; default: length++; } break; - case STATE_HEADER_VALUE: + case HEADER_VALUE: switch(ch) { case HttpTokens.CARRIAGE_RETURN: @@ -643,7 +627,7 @@ public class HttpParser implements Parser } start=length=-1; } - _state=STATE_HEADER; + _state=State.HEADER; break; case HttpTokens.SPACE: case HttpTokens.TAB: @@ -651,14 +635,17 @@ public class HttpParser implements Parser default: { if (start==-1) + { start=buffer.position()-1; + startState=_state; + } length=buffer.position()-start; - _state=STATE_HEADER_IN_VALUE; + _state=State.HEADER_IN_VALUE; } } break; - case STATE_HEADER_IN_VALUE: + case HEADER_IN_VALUE: switch(ch) { case HttpTokens.CARRIAGE_RETURN: @@ -683,11 +670,11 @@ public class HttpParser implements Parser } start=length=-1; } - _state=STATE_HEADER; + _state=State.HEADER; break; case HttpTokens.SPACE: case HttpTokens.TAB: - _state=STATE_HEADER_VALUE; + _state=State.HEADER_VALUE; break; default: length++; @@ -701,24 +688,17 @@ public class HttpParser implements Parser // Handle HEAD response if (_responseStatus>0 && _headResponse) { - _state=_persistent||(_responseStatus>=100&&_responseStatus<200)?STATE_END:STATE_SEEKING_EOF; - _handler.messageComplete(_contentLength); + _state=_persistent||(_responseStatus>=100&&_responseStatus<200)?State.END:State.SEEKING_EOF; + at_next|=_handler.messageComplete(_contentLength); } // ========================== // Handle _content - last=_state; ByteBuffer chunk; - while (_state > STATE_END && buffer.hasRemaining()) + while (_state.ordinal() > State.END.ordinal() && buffer.hasRemaining()) { - if (last!=_state) - { - progress++; - last=_state; - } - if (_eol == HttpTokens.CARRIAGE_RETURN && buffer.get(buffer.position()) == HttpTokens.LINE_FEED) { _eol=buffer.get(); @@ -728,20 +708,20 @@ public class HttpParser implements Parser switch (_state) { - case STATE_EOF_CONTENT: + case EOF_CONTENT: chunk=buffer.asReadOnlyBuffer(); _contentPosition += chunk.remaining(); buffer.position(buffer.position()+chunk.remaining()); - _handler.content(chunk); // May recurse here + at_next|=_handler.content(chunk); // May recurse here break; - case STATE_CONTENT: + case CONTENT: { long remaining=_contentLength - _contentPosition; if (remaining == 0) { - _state=_persistent?STATE_END:STATE_SEEKING_EOF; - _handler.messageComplete(_contentPosition); + _state=_persistent?State.END:State.SEEKING_EOF; + at_next|=_handler.messageComplete(_contentPosition); } else { @@ -757,18 +737,18 @@ public class HttpParser implements Parser _contentPosition += chunk.remaining(); buffer.position(buffer.position()+chunk.remaining()); - _handler.content(chunk); // May recurse here + at_next|=_handler.content(chunk); // May recurse here if(_contentPosition == _contentLength) { - _state=_persistent?STATE_END:STATE_SEEKING_EOF; - _handler.messageComplete(_contentPosition); + _state=_persistent?State.END:State.SEEKING_EOF; + at_next|=_handler.messageComplete(_contentPosition); } } break; } - case STATE_CHUNKED_CONTENT: + case CHUNKED_CONTENT: { ch=buffer.get(buffer.position()); if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) @@ -779,12 +759,12 @@ public class HttpParser implements Parser { _chunkLength=0; _chunkPosition=0; - _state=STATE_CHUNK_SIZE; + _state=State.CHUNK_SIZE; } break; } - case STATE_CHUNK_SIZE: + case CHUNK_SIZE: { ch=buffer.get(); if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) @@ -795,14 +775,14 @@ public class HttpParser implements Parser { if (_eol==HttpTokens.CARRIAGE_RETURN && buffer.hasRemaining() && buffer.get(buffer.position())==HttpTokens.LINE_FEED) _eol=buffer.get(); - _state=_persistent?STATE_END:STATE_SEEKING_EOF; - _handler.messageComplete(_contentPosition); + _state=_persistent?State.END:State.SEEKING_EOF; + at_next|=_handler.messageComplete(_contentPosition); } else - _state=STATE_CHUNK; + _state=State.CHUNK; } else if (ch <= HttpTokens.SPACE || ch == HttpTokens.SEMI_COLON) - _state=STATE_CHUNK_PARAMS; + _state=State.CHUNK_PARAMS; else if (ch >= '0' && ch <= '9') _chunkLength=_chunkLength * 16 + (ch - '0'); else if (ch >= 'a' && ch <= 'f') @@ -814,7 +794,7 @@ public class HttpParser implements Parser break; } - case STATE_CHUNK_PARAMS: + case CHUNK_PARAMS: { ch=buffer.get(); if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) @@ -824,21 +804,21 @@ public class HttpParser implements Parser { if (_eol==HttpTokens.CARRIAGE_RETURN && buffer.hasRemaining() && buffer.get(buffer.position())==HttpTokens.LINE_FEED) _eol=buffer.get(); - _state=_persistent?STATE_END:STATE_SEEKING_EOF; - _handler.messageComplete(_contentPosition); + _state=_persistent?State.END:State.SEEKING_EOF; + at_next|=_handler.messageComplete(_contentPosition); } else - _state=STATE_CHUNK; + _state=State.CHUNK; } break; } - case STATE_CHUNK: + case CHUNK: { int remaining=_chunkLength - _chunkPosition; if (remaining == 0) { - _state=STATE_CHUNKED_CONTENT; + _state=State.CHUNKED_CONTENT; } else { @@ -851,13 +831,12 @@ public class HttpParser implements Parser _contentPosition += remaining; _chunkPosition += remaining; buffer.position(buffer.position()+remaining); - _handler.content(chunk); // May recurse here - - _handler.content(chunk); + at_next|=_handler.content(chunk); // May recurse here } + break; } - case STATE_SEEKING_EOF: + case SEEKING_EOF: { buffer.clear().limit(0); break; @@ -866,14 +845,23 @@ public class HttpParser implements Parser } - return progress>0; + return at_next; } catch(HttpException e) { _persistent=false; - _state=STATE_SEEKING_EOF; + _state=State.SEEKING_EOF; throw e; } + finally + { + if (start>=0) + { + buffer.position(start); + _state=startState; + } + + } } @@ -885,18 +873,18 @@ public class HttpParser implements Parser // was this unexpected? switch(_state) { - case STATE_END: - case STATE_SEEKING_EOF: - _state=STATE_END; + case END: + case SEEKING_EOF: + _state=State.END; break; - case STATE_EOF_CONTENT: - _state=STATE_END; + case EOF_CONTENT: + _state=State.END; _handler.messageComplete(_contentPosition); break; default: - _state=STATE_END; + _state=State.END; if (!_headResponse) _handler.earlyEOF(); _handler.messageComplete(_contentPosition); @@ -914,7 +902,7 @@ public class HttpParser implements Parser public void reset() { // reset state - _state=_persistent?STATE_START:_state==STATE_END?STATE_END:STATE_SEEKING_EOF; + _state=_persistent?State.START:_state==State.END?State.END:State.SEEKING_EOF; _contentLength=HttpTokens.UNKNOWN_CONTENT; _contentPosition=0; _responseStatus=0; @@ -925,7 +913,7 @@ public class HttpParser implements Parser /* ------------------------------------------------------------------------------- */ - public void setState(int state) + public void setState(State state) { this._state=state; _contentLength=HttpTokens.UNKNOWN_CONTENT; @@ -946,20 +934,24 @@ public class HttpParser implements Parser /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ + /* Event Handler interface + * These methods return true if they want parsing to return to + * the caller. + */ public interface EventHandler { - public void content(ByteBuffer ref) throws IOException; + public boolean content(ByteBuffer ref) throws IOException; - public void headerComplete() throws IOException; + public boolean headerComplete() throws IOException; - public void messageComplete(long contentLength) throws IOException; + public boolean messageComplete(long contentLength) throws IOException; /** * This is the method called by parser when a HTTP Header name and value is found */ - public void parsedHeader(String name, String value) throws IOException; + public boolean parsedHeader(String name, String value) throws IOException; - public void earlyEOF(); + public boolean earlyEOF(); } public interface RequestHandler extends EventHandler @@ -967,7 +959,7 @@ public class HttpParser implements Parser /** * This is the method called by parser when the HTTP request line is parsed */ - public abstract void startRequest(String method, String uri, String version) + public abstract boolean startRequest(String method, String uri, String version) throws IOException; } @@ -976,7 +968,7 @@ public class HttpParser implements Parser /** * This is the method called by parser when the HTTP request line is parsed */ - public abstract void startResponse(String version, int status, String reason) + public abstract boolean startResponse(String version, int status, String reason) throws IOException; } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/Parser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/Parser.java index 9aff2c6c4ba..883b99d9333 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/Parser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/Parser.java @@ -25,11 +25,14 @@ public interface Parser boolean isComplete(); + + /* ------------------------------------------------------------ */ /** - * @return True if progress made + * @param buffer + * @return True if parsed to the next unit * @throws IOException */ - boolean parseAvailable(ByteBuffer buffer) throws IOException; + boolean parseNext(ByteBuffer buffer) throws IOException; boolean onEOF()throws IOException; diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java b/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java index 12abbfee5b5..8c0111d2cb5 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java @@ -56,7 +56,7 @@ import org.eclipse.jetty.util.URIUtil; * * */ -public class PathMap extends HashMap implements Externalizable +public class PathMap extends HashMap { /* ------------------------------------------------------------ */ private static String __pathSpecSeparators = ":,"; @@ -74,13 +74,13 @@ public class PathMap extends HashMap implements Externalizable } /* --------------------------------------------------------------- */ - final StringMap _prefixMap=new StringMap(); - final StringMap _suffixMap=new StringMap(); - final StringMap _exactMap=new StringMap(); + final StringMap> _prefixMap=new StringMap<>(); + final StringMap> _suffixMap=new StringMap<>(); + final StringMap> _exactMap=new StringMap<>(); List _defaultSingletonList=null; - Entry _prefixDefault=null; - Entry _default=null; + MappedEntry _prefixDefault=null; + MappedEntry _default=null; final Set _entrySet; boolean _nodefault=false; @@ -121,22 +121,6 @@ public class PathMap extends HashMap implements Externalizable _entrySet=entrySet(); } - /* ------------------------------------------------------------ */ - public void writeExternal(java.io.ObjectOutput out) - throws java.io.IOException - { - HashMap map = new HashMap(this); - out.writeObject(map); - } - - /* ------------------------------------------------------------ */ - public void readExternal(java.io.ObjectInput in) - throws java.io.IOException, ClassNotFoundException - { - HashMap map = (HashMap)in.readObject(); - this.putAll(map); - } - /* --------------------------------------------------------------- */ /** Add a single path match to the PathMap. * @param pathSpec The path specification, or comma separated list of @@ -144,19 +128,19 @@ public class PathMap extends HashMap implements Externalizable * @param object The object the path maps to */ @Override - public Object put(Object pathSpec, Object object) + public O put(String pathSpec, O object) { String str = pathSpec.toString(); if ("".equals(str.trim())) { - Entry entry = new Entry("",object); + MappedEntry entry = new MappedEntry("",object); entry.setMapped(""); _exactMap.put("", entry); return super.put("", object); } StringTokenizer tok = new StringTokenizer(str,__pathSpecSeparators); - Object old =null; + O old =null; while (tok.hasMoreTokens()) { @@ -168,7 +152,7 @@ public class PathMap extends HashMap implements Externalizable old = super.put(spec,object); // Make entry that was just created. - Entry entry = new Entry(spec,object); + MappedEntry entry = new MappedEntry(spec,object); if (entry.getKey().equals(spec)) { @@ -225,9 +209,9 @@ public class PathMap extends HashMap implements Externalizable * @param path the path. * @return Map.Entry of the best matched or null. */ - public Entry getMatch(String path) + public MappedEntry getMatch(String path) { - Map.Entry entry=null; + MappedEntry entry=null; if (path==null) return null; @@ -237,23 +221,23 @@ public class PathMap extends HashMap implements Externalizable //special case if (l == 1 && path.charAt(0)=='/') { - entry = (Map.Entry)_exactMap.get(""); + entry = _exactMap.get(""); if (entry != null) - return (Entry)entry; + return (MappedEntry)entry; } // try exact match - entry=_exactMap.getEntry(path,0,l); + entry=_exactMap.get(path,0,l); if (entry!=null) - return (Entry) entry.getValue(); + return entry; // prefix search int i=l; while((i=path.lastIndexOf('/',i-1))>=0) { - entry=_prefixMap.getEntry(path,0,i); + entry=_prefixMap.get(path,0,i); if (entry!=null) - return (Entry) entry.getValue(); + return entry; } // Prefix Default @@ -264,9 +248,9 @@ public class PathMap extends HashMap implements Externalizable i=0; while ((i=path.indexOf('.',i+1))>0) { - entry=_suffixMap.getEntry(path,i+1,l-i-1); + entry=_suffixMap.get(path,i+1,l-i-1); if (entry!=null) - return (Entry) entry.getValue(); + return entry; } // Default @@ -281,7 +265,7 @@ public class PathMap extends HashMap implements Externalizable */ public Object getLazyMatches(String path) { - Map.Entry entry; + MappedEntry entry; Object entries=null; if (path==null) @@ -290,17 +274,17 @@ public class PathMap extends HashMap implements Externalizable int l=path.length(); // try exact match - entry=_exactMap.getEntry(path,0,l); + entry=_exactMap.get(path,0,l); if (entry!=null) - entries=LazyList.add(entries,entry.getValue()); + entries=LazyList.add(entries,entry); // prefix search int i=l-1; while((i=path.lastIndexOf('/',i-1))>=0) { - entry=_prefixMap.getEntry(path,0,i); + entry=_prefixMap.get(path,0,i); if (entry!=null) - entries=LazyList.add(entries,entry.getValue()); + entries=LazyList.add(entries,entry); } // Prefix Default @@ -311,9 +295,9 @@ public class PathMap extends HashMap implements Externalizable i=0; while ((i=path.indexOf('.',i+1))>0) { - entry=_suffixMap.getEntry(path,i+1,l-i-1); + entry=_suffixMap.get(path,i+1,l-i-1); if (entry!=null) - entries=LazyList.add(entries,entry.getValue()); + entries=LazyList.add(entries,entry); } // Default @@ -348,13 +332,13 @@ public class PathMap extends HashMap implements Externalizable */ public boolean containsMatch(String path) { - Entry match = getMatch(path); + MappedEntry match = getMatch(path); return match!=null && !match.equals(_default); } /* --------------------------------------------------------------- */ @Override - public Object remove(Object pathSpec) + public O remove(Object pathSpec) { if (pathSpec!=null) { @@ -532,30 +516,29 @@ public class PathMap extends HashMap implements Externalizable /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ - public static class Entry implements Map.Entry + public static class MappedEntry implements Map.Entry { - private final Object key; - private final Object value; + private final String key; + private final O value; private String mapped; - private transient String string; - Entry(Object key, Object value) + MappedEntry(String key, O value) { this.key=key; this.value=value; } - public Object getKey() + public String getKey() { return key; } - public Object getValue() + public O getValue() { return value; } - public Object setValue(Object o) + public O setValue(O o) { throw new UnsupportedOperationException(); } @@ -563,9 +546,7 @@ public class PathMap extends HashMap implements Externalizable @Override public String toString() { - if (string==null) - string=key+"="+value; - return string; + return key+"="+value; } public String getMapped() diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java index b4e46a398c3..652bb0e48b6 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java @@ -37,7 +37,7 @@ public class HttpParserTest Handler handler = new Handler(); HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler); - parser.parse(buffer); + parser.parseAll(buffer); assertEquals("POST", f0); assertEquals("/foo", f1); assertEquals("HTTP/1.0", f2); @@ -52,7 +52,7 @@ public class HttpParserTest f2= null; Handler handler = new Handler(); HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler); - parser.parse(buffer); + parser.parseAll(buffer); assertEquals("GET", f0); assertEquals("/999", f1); assertEquals(null, f2); @@ -67,7 +67,7 @@ public class HttpParserTest f2= null; Handler handler = new Handler(); HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler); - parser.parse(buffer); + parser.parseAll(buffer); assertEquals("POST", f0); assertEquals("/222", f1); assertEquals(null, f2); @@ -81,7 +81,7 @@ public class HttpParserTest Handler handler = new Handler(); HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler); - parser.parse(buffer); + parser.parseAll(buffer); assertEquals("POST", f0); assertEquals("/fo\u0690", f1); assertEquals("HTTP/1.0", f2); @@ -95,7 +95,7 @@ public class HttpParserTest Handler handler = new Handler(); HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler); - parser.parse(buffer); + parser.parseAll(buffer); assertEquals("POST", f0); assertEquals("/foo?param=\u0690", f1); assertEquals("HTTP/1.0", f2); @@ -108,7 +108,7 @@ public class HttpParserTest ByteBuffer buffer= BufferUtil.toBuffer("CONNECT 192.168.1.2:80 HTTP/1.1\015\012" + "\015\012"); Handler handler = new Handler(); HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler); - parser.parse(buffer); + parser.parseAll(buffer); assertTrue(handler.request); assertEquals("CONNECT", f0); assertEquals("192.168.1.2:80", f1); @@ -120,19 +120,19 @@ public class HttpParserTest public void testHeaderParse() throws Exception { ByteBuffer buffer= BufferUtil.toBuffer( - "GET / 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\012"); + "GET / 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\012"); Handler handler = new Handler(); HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler); - parser.parse(buffer); + parser.parseAll(buffer); assertEquals("GET", f0); assertEquals("/", f1); @@ -151,14 +151,58 @@ public class HttpParserTest assertEquals("notServer", val[5]); assertEquals(5, h); } - + @Test - public void testHttpHeaders() throws Exception + public void testSplitHeaderParse() throws Exception { - ByteBuffer buffer= BufferUtil.toBuffer("Transfer-Encoding"); - assertEquals(HttpHeaders.TRANSFER_ENCODING,HttpHeaders.CACHE.get(buffer)); + 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"); + buffer.position(2); + buffer.limit(buffer.capacity()-2); + buffer=buffer.slice(); + for (int i=0;i=0); - } - } - } - @Test public void testResponseParse0() throws Exception { - StringEndPoint io=new StringEndPoint(); - io.setInput( + ByteBuffer buffer= BufferUtil.toBuffer( "HTTP/1.1 200 Correct\015\012" + "Content-Length: 10\015\012" + "Content-Type: text/plain\015\012" + "\015\012" + "0123456789\015\012"); - ByteBuffer buffer= BufferUtil.allocate(4096); - SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); - HttpParser parser= new HttpParser(buffers,io, handler); - parser.parse(); + HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler); + parser.parseNext(buffer); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals("Correct", f2); @@ -369,17 +314,14 @@ public class HttpParserTest @Test public void testResponseParse1() throws Exception { - StringEndPoint io=new StringEndPoint(); - io.setInput( + ByteBuffer buffer= BufferUtil.toBuffer( "HTTP/1.1 304 Not-Modified\015\012" + "Connection: close\015\012" + "\015\012"); - ByteBuffer buffer= BufferUtil.allocate(4096); - SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); - HttpParser parser= new HttpParser(buffers,io, handler); - parser.parse(); + HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler); + parser.parseNext(buffer); assertEquals("HTTP/1.1", f0); assertEquals("304", f1); assertEquals("Not-Modified", f2); @@ -390,8 +332,7 @@ public class HttpParserTest @Test public void testResponseParse2() throws Exception { - StringEndPoint io=new StringEndPoint(); - io.setInput( + ByteBuffer buffer= BufferUtil.toBuffer( "HTTP/1.1 204 No-Content\015\012" + "Header: value\015\012" + "\015\012" @@ -400,19 +341,21 @@ public class HttpParserTest + "Content-Type: text/plain\015\012" + "\015\012" + "0123456789\015\012"); - ByteBuffer buffer= BufferUtil.allocate(4096); - SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); - HttpParser parser= new HttpParser(buffers,io, handler); - parser.parse(); + HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler); + parser.parseNext(buffer); assertEquals("HTTP/1.1", f0); assertEquals("204", f1); assertEquals("No-Content", f2); assertTrue(headerCompleted); assertTrue(messageCompleted); - parser.parse(); + + parser.setPersistent(true); + parser.reset(); + parser.parseNext(buffer); + parser.onEOF(); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals("Correct", f2); @@ -425,19 +368,16 @@ public class HttpParserTest @Test public void testResponseParse3() throws Exception { - StringEndPoint io=new StringEndPoint(); - io.setInput( + ByteBuffer buffer= BufferUtil.toBuffer( "HTTP/1.1 200\015\012" + "Content-Length: 10\015\012" + "Content-Type: text/plain\015\012" + "\015\012" + "0123456789\015\012"); - ByteBuffer buffer= BufferUtil.allocate(4096); - SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); - HttpParser parser= new HttpParser(buffers,io, handler); - parser.parse(); + HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler); + parser.parseNext(buffer); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals(null, f2); @@ -449,19 +389,16 @@ public class HttpParserTest @Test public void testResponseParse4() throws Exception { - StringEndPoint io=new StringEndPoint(); - io.setInput( + ByteBuffer buffer= BufferUtil.toBuffer( "HTTP/1.1 200 \015\012" + "Content-Length: 10\015\012" + "Content-Type: text/plain\015\012" + "\015\012" + "0123456789\015\012"); - ByteBuffer buffer= BufferUtil.allocate(4096); - SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); - HttpParser parser= new HttpParser(buffers,io, handler); - parser.parse(); + HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler); + parser.parseNext(buffer); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals(null, f2); @@ -473,17 +410,14 @@ public class HttpParserTest @Test public void testResponse304WithContentLength() throws Exception { - StringEndPoint io=new StringEndPoint(); - io.setInput( + ByteBuffer buffer= BufferUtil.toBuffer( "HTTP/1.1 304 found\015\012" + "Content-Length: 10\015\012" + "\015\012"); - ByteBuffer buffer= BufferUtil.allocate(4096); - SimpleBuffers buffers=new SimpleBuffers(buffer,null); - + Handler handler = new Handler(); - HttpParser parser= new HttpParser(buffers,io, handler); - parser.parse(); + HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler); + parser.parseNext(buffer); assertEquals("HTTP/1.1", f0); assertEquals("304", f1); assertEquals("found", f2); @@ -495,8 +429,7 @@ public class HttpParserTest @Test public void testSeekEOF() throws Exception { - StringEndPoint io=new StringEndPoint(); - io.setInput( + ByteBuffer buffer= BufferUtil.toBuffer( "HTTP/1.1 200 OK\015\012" + "Content-Length: 0\015\012" + "Connection: close\015\012" @@ -504,14 +437,11 @@ public class HttpParserTest + "\015\012" // extra CRLF ignored + "HTTP/1.1 400 OK\015\012"); // extra data causes close - - ByteBuffer buffer= BufferUtil.allocate(4096); - SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); - HttpParser parser= new HttpParser(buffers,io, handler); + HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler); - parser.parse(); + parser.parseNext(buffer); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals("OK", f2); @@ -538,15 +468,19 @@ public class HttpParserTest private HttpFields fields; private boolean request; - public void content(ByteBuffer ref) + public boolean content(ByteBuffer ref) { if (_content==null) _content=""; - _content= _content + BufferUtil.toString(ref,StringUtil.__UTF8_CHARSET); + String c = BufferUtil.toString(ref,StringUtil.__UTF8_CHARSET); + //System.err.println("content '"+c+"'"); + _content= _content + c; + return false; } - public void startRequest(String tok0, String tok1, String tok2) + public boolean startRequest(String tok0, String tok1, String tok2) { + //System.err.println("request "+tok0+" "+tok1+" "+tok2); request=true; h= -1; hdr= new String[9]; @@ -558,16 +492,20 @@ public class HttpParserTest fields=new HttpFields(); messageCompleted = false; headerCompleted = false; + return false; } - public void parsedHeader(String name, String value) + public boolean parsedHeader(String name, String value) { + //System.err.println("header "+name+": "+value); hdr[++h]= name; val[h]= value; + return false; } - public void headerComplete() + public boolean headerComplete() { + //System.err.println("headerComplete"); _content= null; String s0=fields.toString(); String s1=fields.toString(); @@ -579,14 +517,17 @@ public class HttpParserTest } headerCompleted = true; + return false; } - public void messageComplete(long contentLength) + public boolean messageComplete(long contentLength) { + //System.err.println("messageComplete"); messageCompleted = true; + return true; } - public void startResponse(String version, int status, String reason) + public boolean startResponse(String version, int status, String reason) { request=false; f0 = version.toString(); @@ -599,11 +540,13 @@ public class HttpParserTest messageCompleted = false; headerCompleted = false; + return false; } @Override - public void earlyEOF() + public boolean earlyEOF() { + return true; } } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java index eb94e4152d4..6fc848de1c0 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java @@ -16,6 +16,8 @@ package org.eclipse.jetty.util; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import javax.swing.text.Position; + /* ------------------------------------------------------------------------------- */ /** @@ -179,11 +181,11 @@ public class BufferUtil byte[] array = buffer.hasArray()?buffer.array():null; if (array == null) { - ByteBuffer slice=buffer.slice(); - slice.position(position); - slice.limit(position+length); + ByteBuffer ro=buffer.asReadOnlyBuffer(); + ro.position(position); + ro.limit(position+length); byte[] to = new byte[length]; - slice.get(to); + ro.get(to); return new String(to,0,to.length,charset); } return new String(array,buffer.arrayOffset()+position,length,charset); @@ -461,6 +463,73 @@ public class BufferUtil return ByteBuffer.wrap(s.getBytes(charset)); } + public static String toDetailString(ByteBuffer buffer) + { + StringBuilder buf = new StringBuilder(); + buf.append("[p="); + buf.append(buffer.position()); + buf.append(",l="); + buf.append(buffer.limit()); + buf.append(",c="); + buf.append(buffer.capacity()); + buf.append("]={"); + + for (int i=0;i=' ') + buf.append(c); + else if (c=='\r'||c=='\n') + buf.append('|'); + else + buf.append('?'); + if (i==16&&buffer.position()>32) + { + buf.append("..."); + i=buffer.position()-16; + } + } + buf.append("}{"); + for (int i=buffer.position();i=' ') + buf.append(c); + else if (c=='\r'||c=='\n') + buf.append('|'); + else + buf.append('?'); + if (i==buffer.position()+16&&buffer.limit()>buffer.position()+32) + { + buf.append("..."); + i=buffer.limit()-16; + } + } + buf.append("}{"); + int limit=buffer.limit(); + buffer.limit(buffer.capacity()); + for (int i=limit;i=' ') + buf.append(c); + else if (c=='\r'||c=='\n') + buf.append('|'); + else + buf.append('?'); + if (i==limit+16&&buffer.capacity()>limit+32) + { + buf.append("..."); + i=buffer.capacity()-16; + } + } + buffer.limit(limit); + buf.append("}"); + + return buf.toString(); + } + + private final static int[] decDivisors = { 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 }; diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java index 7e2477bb02b..61909882e57 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java @@ -111,44 +111,6 @@ public class StringMap extends AbstractMap return _caseInsensitive; } - /* ------------------------------------------------------------ */ - public static void main(String[] arg) - { - StringMap map = new StringMap<>(); - - System.err.println("null="+map.get("nothing")); - - map.put("foo","1"); - System.err.println("null="+map.get("nothing")); - System.err.println("null="+map.get("foobar")); - System.err.println("1="+map.get("foo")); - System.err.println("null="+map.get("fo")); - - map.put("foobar","2"); - System.err.println("null="+map.get("nothing")); - System.err.println("2="+map.get("foobar")); - System.err.println("1="+map.get("foo")); - System.err.println("null="+map.get("fo")); - System.err.println("null="+map.get("foob")); - - map.put("foob","3"); - System.err.println("null="+map.get("nothing")); - System.err.println("2="+map.get("foobar")); - System.err.println("3="+map.get("foob")); - System.err.println("1="+map.get("foo")); - - map.put("fool","4"); - map.put("fop","5"); - map.put("fred","6"); - - - System.err.println("2="+map.get(BufferUtil.toBuffer("foobar"))); - System.err.println("3="+map.get(BufferUtil.toBuffer("foob"))); - System.err.println("1="+map.get(BufferUtil.toBuffer("foo"))); - - - } - /* ------------------------------------------------------------ */ @Override public O put(String key, O value) @@ -178,10 +140,11 @@ public class StringMap extends AbstractMap /* ------------------------------------------------------------ */ public O get(ByteBuffer buffer, int position, int length) { - ByteBuffer slice=buffer.slice(); - slice.position(position); - slice.limit(position+length); - return _map.get(slice); + ByteBuffer ro=buffer.asReadOnlyBuffer(); + ro.limit(ro.capacity()); + ro.position(position); + ro.limit(position+length); + return _map.get(ro); }