diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java
deleted file mode 100644
index 9ddb356eb76..00000000000
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java
+++ /dev/null
@@ -1,522 +0,0 @@
-// ========================================================================
-// Copyright (c) 2004-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.IOException;
-import java.nio.ByteBuffer;
-
-import javax.swing.text.View;
-
-import org.eclipse.jetty.io.Buffers;
-import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.io.EofException;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-/* ------------------------------------------------------------ */
-/**
- * Abstract Generator. Builds HTTP Messages.
- *
- * Currently this class uses a system parameter "jetty.direct.writers" to control
- * two optional writer to byte conversions. buffer.writers=true will probably be
- * faster, but will consume more memory. This option is just for testing and tuning.
- *
- */
-public abstract class AbstractGenerator implements Generator
-{
- private static final Logger LOG = Log.getLogger(AbstractGenerator.class);
-
- // states
- public final static int STATE_HEADER = 0;
- public final static int STATE_CONTENT = 2;
- public final static int STATE_FLUSHING = 3;
- public final static int STATE_END = 4;
-
- public static final byte[] NO_BYTES = {};
-
- // data
-
- protected final Buffers _buffers; // source of buffers
- protected final EndPoint _endp;
-
- protected int _state = STATE_HEADER;
-
- protected int _status = 0;
- protected HttpVersion _version = HttpVersion.HTTP_1_1;
- protected ByteBuffer _reason;
- protected ByteBuffer _method;
- protected String _uri;
-
- protected long _contentWritten = 0;
- protected long _contentLength = HttpTokens.UNKNOWN_CONTENT;
- protected boolean _last = false;
- protected boolean _head = false;
- protected boolean _noContent = false;
- protected Boolean _persistent = null;
-
- protected ByteBuffer _header; // Buffer for HTTP header (and maybe small _content)
- protected ByteBuffer _buffer; // Buffer for copy of passed _content
- protected ByteBuffer _content; // Buffer passed to addContent
-
- protected ByteBuffer _date;
-
- private boolean _sendServerVersion;
-
-
- /* ------------------------------------------------------------------------------- */
- /**
- * Constructor.
- *
- * @param buffers buffer pool
- * @param io the end point
- */
- public AbstractGenerator(Buffers buffers, EndPoint io)
- {
- this._buffers = buffers;
- this._endp = io;
- }
-
- /* ------------------------------------------------------------------------------- */
- public abstract boolean isRequest();
-
- /* ------------------------------------------------------------------------------- */
- public abstract boolean isResponse();
-
- /* ------------------------------------------------------------------------------- */
- public boolean isOpen()
- {
- return _endp.isOpen();
- }
-
- /* ------------------------------------------------------------------------------- */
- public void reset()
- {
- _state = STATE_HEADER;
- _status = 0;
- _version = HttpVersion.HTTP_1_1;
- _reason = null;
- _last = false;
- _head = false;
- _noContent=false;
- _persistent = null;
- _contentWritten = 0;
- _contentLength = HttpTokens.UNKNOWN_CONTENT;
- _date = null;
-
- _content = null;
- _method=null;
- }
-
- /* ------------------------------------------------------------------------------- */
- public void returnBuffers()
- {
- if (_buffer!=null && _buffer.length()==0)
- {
- _buffers.returnBuffer(_buffer);
- _buffer=null;
- }
-
- if (_header!=null && _header.length()==0)
- {
- _buffers.returnBuffer(_header);
- _header=null;
- }
- }
-
- /* ------------------------------------------------------------------------------- */
- public void resetBuffer()
- {
- if(_state>=STATE_FLUSHING)
- throw new IllegalStateException("Flushed");
-
- _last = false;
- _persistent=null;
- _contentWritten = 0;
- _contentLength = HttpTokens.UNKNOWN_CONTENT;
- _content=null;
- if (_buffer!=null)
- _buffer.clear();
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @return Returns the contentBufferSize.
- */
- public int getContentBufferSize()
- {
- if (_buffer==null)
- _buffer=_buffers.getBuffer();
- return _buffer.capacity();
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @param contentBufferSize The contentBufferSize to set.
- */
- public void increaseContentBufferSize(int contentBufferSize)
- {
- if (_buffer==null)
- _buffer=_buffers.getBuffer();
- if (contentBufferSize > _buffer.capacity())
- {
- ByteBuffer nb = _buffers.getBuffer(contentBufferSize);
- nb.put(_buffer);
- _buffers.returnBuffer(_buffer);
- _buffer = nb;
- }
- }
-
- /* ------------------------------------------------------------ */
- public ByteBuffer getUncheckedBuffer()
- {
- return _buffer;
- }
-
- /* ------------------------------------------------------------ */
- public boolean getSendServerVersion ()
- {
- return _sendServerVersion;
- }
-
- /* ------------------------------------------------------------ */
- public void setSendServerVersion (boolean sendServerVersion)
- {
- _sendServerVersion = sendServerVersion;
- }
-
- /* ------------------------------------------------------------ */
- public int getState()
- {
- return _state;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isState(int state)
- {
- return _state == state;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isComplete()
- {
- return _state == STATE_END;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isIdle()
- {
- return _state == STATE_HEADER && _method==null && _status==0;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isCommitted()
- {
- return _state != STATE_HEADER;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @return Returns the head.
- */
- public boolean isHead()
- {
- return _head;
- }
-
- /* ------------------------------------------------------------ */
- public void setContentLength(long value)
- {
- if (value<0)
- _contentLength=HttpTokens.UNKNOWN_CONTENT;
- else
- _contentLength=value;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @param head The head to set.
- */
- public void setHead(boolean head)
- {
- _head = head;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @return false
if the connection should be closed after a request has been read,
- * true
if it should be used for additional requests.
- */
- public boolean isPersistent()
- {
- return _persistent!=null
- ?_persistent.booleanValue()
- :(isRequest()?true:_version>HttpVersion.HTTP_1_0_ORDINAL);
- }
-
- /* ------------------------------------------------------------ */
- public void setPersistent(boolean persistent)
- {
- _persistent=persistent;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @param version The version of the client the response is being sent to (NB. Not the version
- * in the response, which is the version of the server).
- */
- public void setVersion(int version)
- {
- if (_state != STATE_HEADER)
- throw new IllegalStateException("STATE!=START "+_state);
- _version = version;
- if (_version==HttpVersion.HTTP_0_9_ORDINAL && _method!=null)
- _noContent=true;
- }
-
- /* ------------------------------------------------------------ */
- public int getVersion()
- {
- return _version;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.ByteBuffer)
- */
- public void setDate(ByteBuffer timeStampBuffer)
- {
- _date=timeStampBuffer;
- }
-
- /* ------------------------------------------------------------ */
- /**
- */
- public void setRequest(String method, String uri)
- {
- if (method==null || HttpMethod.GET.equals(method) )
- _method=HttpMethod.GET_BUFFER;
- else
- _method=HttpMethod.CACHE.lookup(method);
- _uri=uri;
- if (_version==HttpVersion.HTTP_0_9_ORDINAL)
- _noContent=true;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @param status The status code to send.
- * @param reason the status message to send.
- */
- public void setResponse(int status, String reason)
- {
- if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START");
- _method=null;
- _status = status;
- if (reason!=null)
- {
- int len=reason.length();
-
- // TODO don't hard code
- if (len>1024)
- len=1024;
- _reason=BufferUtil.allocate(len);
- for (int i=0;i0;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isWritten()
- {
- return _contentWritten>0;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isAllContentWritten()
- {
- return _contentLength>=0 && _contentWritten>=_contentLength;
- }
-
- /* ------------------------------------------------------------ */
- public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException;
-
- /* ------------------------------------------------------------ */
- /**
- * Complete the message.
- *
- * @throws IOException
- */
- public void complete() throws IOException
- {
- if (_state == STATE_HEADER)
- {
- throw new IllegalStateException("State==HEADER");
- }
-
- if (_contentLength >= 0 && _contentLength != _contentWritten && !_head)
- {
- if (LOG.isDebugEnabled())
- LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength);
- _persistent = false;
- }
- }
-
- /* ------------------------------------------------------------ */
- public abstract int flushBuffer() throws IOException;
-
-
- /* ------------------------------------------------------------ */
- public void flush(long maxIdleTime) throws IOException
- {
- // block until everything is flushed
- long now=System.currentTimeMillis();
- long end=now+maxIdleTime;
- ByteBuffer content = _content;
- ByteBuffer buffer = _buffer;
- if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull())
- {
- flushBuffer();
-
- while (now0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown())
- {
- blockForOutput(end-now);
- now=System.currentTimeMillis();
- }
- }
- }
-
- /* ------------------------------------------------------------ */
- /**
- * Utility method to send an error response. If the builder is not committed, this call is
- * equivalent to a setResponse, addContent and complete call.
- *
- * @param code The error code
- * @param reason The error reason
- * @param content Contents of the error page
- * @param close True if the connection should be closed
- * @throws IOException if there is a problem flushing the response
- */
- public void sendError(int code, String reason, String content, boolean close) throws IOException
- {
- if (close)
- _persistent=false;
- if (isCommitted())
- {
- LOG.debug("sendError on committed: {} {}",code,reason);
- }
- else
- {
- LOG.debug("sendError: {} {}",code,reason);
- setResponse(code, reason);
- if (content != null)
- {
- completeHeader(null, false);
- addContent(new View(BufferUtil.allocate(content)), Generator.LAST);
- }
- else
- {
- completeHeader(null, true);
- }
- complete();
- }
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @return Returns the contentWritten.
- */
- public long getContentWritten()
- {
- return _contentWritten;
- }
-
-
-
- /* ------------------------------------------------------------ */
- public void blockForOutput(long maxIdleTime) throws IOException
- {
- if (_endp.isBlocking())
- {
- try
- {
- flushBuffer();
- }
- catch(IOException e)
- {
- _endp.close();
- throw e;
- }
- }
- else
- {
- if (!_endp.blockWritable(maxIdleTime))
- {
- _endp.close();
- throw new EofException("timeout");
- }
-
- flushBuffer();
- }
- }
-
-}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java
deleted file mode 100644
index 503bba6c391..00000000000
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// ========================================================================
-// Copyright (c) 2006-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.IOException;
-import java.nio.ByteBuffer;
-
-
-public interface Generator
-{
- public static final boolean LAST=true;
- public static final boolean MORE=false;
-
- /* ------------------------------------------------------------ */
- /**
- * Add content.
- *
- * @param content
- * @param last
- * @throws IllegalArgumentException if content
is {@link ByteBuffer#isImmutable immutable}.
- * @throws IllegalStateException If the request is not expecting any more content,
- * or if the buffers are full and cannot be flushed.
- * @throws IOException if there is a problem flushing the buffers.
- */
- void addContent(ByteBuffer content, boolean last) throws IOException;
-
- /* ------------------------------------------------------------ */
- /**
- * Add content.
- *
- * @param b byte
- * @return true if the buffers are full
- * @throws IOException
- */
- boolean addContent(byte b) throws IOException;
-
- void complete() throws IOException;
-
- void completeHeader(HttpFields responseFields, boolean last) throws IOException;
-
- int flushBuffer() throws IOException;
-
- int getContentBufferSize();
-
- long getContentWritten();
-
- boolean isWritten();
-
- boolean isAllContentWritten();
-
- void increaseContentBufferSize(int size);
-
- boolean isBufferFull();
-
- boolean isCommitted();
-
- boolean isComplete();
-
- boolean isPersistent();
-
- void reset();
-
- void resetBuffer();
-
- void returnBuffers();
-
- void sendError(int code, String reason, String content, boolean close) throws IOException;
-
- void setHead(boolean head);
-
- void setRequest(String method, String uri);
-
- void setResponse(int status, String reason);
-
-
- void setSendServerVersion(boolean sendServerVersion);
-
- void setVersion(int version);
-
- boolean isIdle();
-
- void setContentLength(long length);
-
- void setPersistent(boolean persistent);
-
- void setDate(ByteBuffer timeStampBuffer);
-
-
-}
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 131ad3ea8e7..f09f272d290 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
@@ -1048,6 +1048,7 @@ public class HttpFields
_next = null;
}
+ /* ------------------------------------------------------------ */
private byte[] toSanitisedBytes(String s)
{
byte[] bytes = s.getBytes(StringUtil.__ISO_8859_1_CHARSET);
@@ -1091,6 +1092,12 @@ public class HttpFields
BufferUtil.putCRLF(buffer);
}
+
+ /* ------------------------------------------------------------ */
+ public void putValueTo(ByteBuffer buffer) throws IOException
+ {
+ buffer.put(toSanitisedBytes(_value));
+ }
/* ------------------------------------------------------------ */
public String getName()
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
index aa2e0ae7240..9b1415ec934 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
@@ -17,6 +17,8 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
+import javax.swing.text.View;
+
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
@@ -32,9 +34,8 @@ import org.eclipse.jetty.util.log.Logger;
*
*
*/
-public class HttpGenerator extends AbstractGenerator
+public class HttpGenerator
{
- private static final Logger LOG = Log.getLogger(HttpGenerator.class);
// Build cache of response lines for status
private static class Status
@@ -75,14 +76,37 @@ public class HttpGenerator extends AbstractGenerator
}
}
- /* ------------------------------------------------------------------------------- */
- public static byte[] getReasonBuffer(int code)
- {
- Status status = code<__status.length?__status[code]:null;
- if (status!=null)
- return status._reason;
- return null;
- }
+
+ private static final Logger LOG = Log.getLogger(HttpGenerator.class);
+
+ // states
+
+ enum State { HEADER, CONTENT, FLUSHING, END };
+
+ public static final byte[] NO_BYTES = {};
+
+ // data
+
+ protected State _state = State.HEADER;
+
+ protected int _status = 0;
+ protected HttpVersion _version = HttpVersion.HTTP_1_1;
+ protected String _reason;
+ protected String _method;
+ protected String _uri;
+
+ protected long _contentWritten = 0;
+ protected long _contentLength = HttpTokens.UNKNOWN_CONTENT;
+ protected boolean _last = false;
+ protected boolean _head = false;
+ protected boolean _noContent = false;
+ protected Boolean _persistent = null;
+
+
+ protected ByteBuffer _date;
+
+ private boolean _sendServerVersion;
+
// common _content
@@ -92,6 +116,7 @@ public class HttpGenerator extends AbstractGenerator
private static final byte[] CONNECTION_KEEP_ALIVE = StringUtil.getBytes("Connection: keep-alive\015\012");
private static final byte[] CONNECTION_CLOSE = StringUtil.getBytes("Connection: close\015\012");
private static final byte[] CONNECTION_ = StringUtil.getBytes("Connection: ");
+ private static final byte[] HTTP_1_1_SPACE = StringUtil.getBytes(HttpVersion.HTTP_1_1+" ");
private static final byte[] CRLF = StringUtil.getBytes("\015\012");
private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\015\012");
private static byte[] SERVER = StringUtil.getBytes("Server: Jetty(7.0.x)\015\012");
@@ -111,41 +136,26 @@ public class HttpGenerator extends AbstractGenerator
private boolean _bufferChunked = false;
+
+
+
/* ------------------------------------------------------------------------------- */
- /**
- * Constructor.
- *
- * @param buffers buffer pool
- * @param io the end point to use
- */
- public HttpGenerator(Buffers buffers, EndPoint io)
- {
- super(buffers,io);
- }
-
- /* ------------------------------------------------------------------------------- */
- @Override
public void reset()
{
- if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown())
- {
- try
- {
- _endp.shutdownOutput();
- }
- catch(IOException e)
- {
- LOG.ignore(e);
- }
- }
- super.reset();
- if (_buffer!=null)
- _buffer.clear();
- if (_header!=null)
- _header.clear();
- if (_content!=null)
- _content=null;
- _bypass = false;
+ _state = State.HEADER;
+ _status = 0;
+ _version = HttpVersion.HTTP_1_1;
+ _reason = null;
+ _last = false;
+ _head = false;
+ _noContent=false;
+ _persistent = null;
+ _contentWritten = 0;
+ _contentLength = HttpTokens.UNKNOWN_CONTENT;
+ _date = null;
+
+ _method=null;
+
_needCRLF = false;
_needEOC = false;
_bufferChunked=false;
@@ -153,6 +163,264 @@ public class HttpGenerator extends AbstractGenerator
_uri=null;
_noContent=false;
}
+
+ /* ------------------------------------------------------------------------------- */
+ public void resetBuffer()
+ {
+ if(_state.ordinal()>=State.FLUSHING.ordinal())
+ throw new IllegalStateException("Flushed");
+
+ _last = false;
+ _persistent=null;
+ _contentWritten = 0;
+ _contentLength = HttpTokens.UNKNOWN_CONTENT;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean getSendServerVersion ()
+ {
+ return _sendServerVersion;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setSendServerVersion (boolean sendServerVersion)
+ {
+ _sendServerVersion = sendServerVersion;
+ }
+
+ /* ------------------------------------------------------------ */
+ public State getState()
+ {
+ return _state;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean isState(State state)
+ {
+ return _state == state;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean isComplete()
+ {
+ return _state == State.END;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean isIdle()
+ {
+ return _state == State.HEADER && _method==null && _status==0;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean isCommitted()
+ {
+ return _state != State.HEADER;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return Returns the head.
+ */
+ public boolean isHead()
+ {
+ return _head;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setContentLength(long value)
+ {
+ if (value<0)
+ _contentLength=HttpTokens.UNKNOWN_CONTENT;
+ else
+ _contentLength=value;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param head The head to set.
+ */
+ public void setHead(boolean head)
+ {
+ _head = head;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return false
if the connection should be closed after a request has been read,
+ * true
if it should be used for additional requests.
+ */
+ public boolean isPersistent()
+ {
+ return _persistent!=null
+ ?_persistent.booleanValue()
+ :(isRequest()?true:_version.ordinal()>HttpVersion.HTTP_1_0.ordinal());
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setPersistent(boolean persistent)
+ {
+ _persistent=persistent;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param version The version of the client the response is being sent to (NB. Not the version
+ * in the response, which is the version of the server).
+ */
+ public void setVersion(HttpVersion version)
+ {
+ if (_state != State.HEADER)
+ throw new IllegalStateException("STATE!=START "+_state);
+ _version = version;
+ if (_version==HttpVersion.HTTP_0_9 && _method!=null)
+ _noContent=true;
+ }
+
+ /* ------------------------------------------------------------ */
+ public HttpVersion getVersion()
+ {
+ return _version;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.ByteBuffer)
+ */
+ public void setDate(ByteBuffer timeStampBuffer)
+ {
+ _date=timeStampBuffer;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ */
+ public void setRequest(String method, String uri)
+ {
+ _method=method;
+ _uri=uri;
+ if (_version==HttpVersion.HTTP_0_9)
+ _noContent=true;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param status The status code to send.
+ * @param reason the status message to send.
+ */
+ public void setResponse(int status, String reason)
+ {
+ if (_state != State.HEADER) throw new IllegalStateException("STATE!=START");
+ _method=null;
+ _status = status;
+ _reason=reason;
+ if (_reason!=null)
+ {
+ if (_reason.length()>1024)
+ _reason=reason.substring(0,1024);
+ _reason=_reason.replace('\r','?').replace('\n','?');
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean isWritten()
+ {
+ return _contentWritten>0;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean isAllContentWritten()
+ {
+ return _contentLength>=0 && _contentWritten>=_contentLength;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Complete the message.
+ *
+ * @throws IOException
+ */
+ public void complete() throws IOException
+ {
+ if (_state == State.END)
+ return;
+
+ if (_state == State.HEADER)
+ {
+ throw new IllegalStateException("State==HEADER");
+ }
+
+ if (_contentLength >= 0 && _contentLength != _contentWritten && !_head)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength);
+ _persistent = false;
+ }
+
+ if (_state.ordinal() < State.FLUSHING.ordinal())
+ {
+ _state = State.FLUSHING;
+ if (_contentLength == HttpTokens.CHUNKED_CONTENT)
+ _needEOC = true;
+ }
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Utility method to send an error response. If the builder is not committed, this call is
+ * equivalent to a setResponse, addContent and complete call.
+ *
+ * @param code The error code
+ * @param reason The error reason
+ * @param content Contents of the error page
+ * @param close True if the connection should be closed
+ * @throws IOException if there is a problem flushing the response
+ */
+ public void sendError(int code, String reason, String content, boolean close) throws IOException
+ {
+ if (close)
+ _persistent=false;
+ if (isCommitted())
+ {
+ LOG.debug("sendError on committed: {} {}",code,reason);
+ }
+ else
+ {
+ LOG.debug("sendError: {} {}",code,reason);
+ setResponse(code, reason);
+ if (content != null)
+ {
+ completeHeader(null, false);
+ addContent(new View(BufferUtil.allocate(content)), Generator.LAST);
+ }
+ else
+ {
+ completeHeader(null, true);
+ }
+ complete();
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return Returns the contentWritten.
+ */
+ public long getContentWritten()
+ {
+ return _contentWritten;
+ }
+
+
+ /* ------------------------------------------------------------------------------- */
+ public static byte[] getReasonBuffer(int code)
+ {
+ Status status = code<__status.length?__status[code]:null;
+ if (status!=null)
+ return status._reason;
+ return null;
+ }
+
/* ------------------------------------------------------------ */
/**
@@ -170,7 +438,7 @@ public class HttpGenerator extends AbstractGenerator
if (_noContent)
throw new IllegalStateException("NO CONTENT");
- if (_last || _state==STATE_END)
+ if (_last || _state==State.END)
{
LOG.warn("Ignoring extra content {}",content);
content.clear();
@@ -186,7 +454,7 @@ public class HttpGenerator extends AbstractGenerator
flushBuffer();
if (_content != null && _content.hasRemaining())
{
- ByteBuffer nc=_buffers.getBuffer(_content.remaining()+content.length());
+ ByteBuffer nc=_buffers.getBuffer(_content.remaining()+content.remaining());
nc.put(_content);
nc.put(content);
content=nc;
@@ -194,7 +462,7 @@ public class HttpGenerator extends AbstractGenerator
}
_content = content;
- _contentWritten += content.length();
+ _contentWritten += content.remaining();
// Handle the _content
if (_head)
@@ -228,14 +496,14 @@ public class HttpGenerator extends AbstractGenerator
*/
public void sendResponse(ByteBuffer response) throws IOException
{
- if (_noContent || _state!=STATE_HEADER || _content!=null && _content.hasRemaining() || _bufferChunked || _head )
+ if (_noContent || _state!=State.HEADER || _content!=null && _content.hasRemaining() || _bufferChunked || _head )
throw new IllegalStateException();
_last = true;
_content = response;
_bypass = true;
- _state = STATE_FLUSHING;
+ _state = State.FLUSHING;
// TODO this is not exactly right, but should do.
_contentLength =_contentWritten = response.length();
@@ -255,7 +523,7 @@ public class HttpGenerator extends AbstractGenerator
if (_noContent)
throw new IllegalStateException("NO CONTENT");
- if (_last || _state==STATE_END)
+ if (_last || _state==State.END)
{
LOG.warn("Ignoring extra content {}",Byte.valueOf(b));
return false;
@@ -285,55 +553,10 @@ public class HttpGenerator extends AbstractGenerator
return _buffer.space()<=(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0);
}
- /* ------------------------------------------------------------ */
- /** Prepare buffer for unchecked writes.
- * Prepare the generator buffer to receive unchecked writes
- * @return the available space in the buffer.
- * @throws IOException
- */
- @Override
- public int prepareUncheckedAddContent() throws IOException
- {
- if (_noContent)
- return -1;
-
- if (_last || _state==STATE_END)
- return -1;
-
- // Handle any unfinished business?
- ByteBuffer content = _content;
- if (content != null && content.length()>0 || _bufferChunked)
- {
- flushBuffer();
- if (content != null && content.length()>0 || _bufferChunked)
- throw new IllegalStateException("FULL");
- }
-
- // we better check we have a buffer
- if (_buffer == null)
- _buffer = _buffers.getBuffer();
-
- _contentWritten-=_buffer.remaining();
-
- // Handle the _content
- if (_head)
- return Integer.MAX_VALUE;
-
- return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public boolean isBufferFull()
- {
- // Should we flush the buffers?
- return super.isBufferFull() || _bufferChunked || _bypass || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE);
- }
-
/* ------------------------------------------------------------ */
public void send1xx(int code) throws IOException
{
- if (_state != STATE_HEADER)
+ if (_state != State.HEADER)
return;
if (code<100||code>199)
@@ -369,24 +592,21 @@ public class HttpGenerator extends AbstractGenerator
}
/* ------------------------------------------------------------ */
- @Override
public boolean isRequest()
{
return _method!=null;
}
/* ------------------------------------------------------------ */
- @Override
public boolean isResponse()
{
return _method==null;
}
/* ------------------------------------------------------------ */
- @Override
- public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
+ public void completeHeader(ByteBuffer buffer, HttpFields fields, boolean allContentAdded) throws IOException
{
- if (_state != STATE_HEADER)
+ if (_state != State.HEADER)
return;
// handle a reset
@@ -397,9 +617,6 @@ public class HttpGenerator extends AbstractGenerator
throw new IllegalStateException("last?");
_last = _last | allContentAdded;
- // get a header buffer
- if (_header == null)
- _header = _buffers.getHeader();
boolean has_server = false;
@@ -409,72 +626,71 @@ public class HttpGenerator extends AbstractGenerator
{
_persistent=true;
- if (_version == HttpVersion.HTTP_0_9_ORDINAL)
+ if (_version == HttpVersion.HTTP_0_9)
{
_contentLength = HttpTokens.NO_CONTENT;
- _header.put(_method);
- _header.put((byte)' ');
- _header.put(_uri.getBytes("UTF-8")); // TODO check
- _header.put(HttpTokens.CRLF);
- _state = STATE_FLUSHING;
+ buffer.put(_method);
+ buffer.put((byte)' ');
+ buffer.put(_uri.getBytes("UTF-8")); // TODO check
+ buffer.put(HttpTokens.CRLF);
+ _state = State.FLUSHING;
_noContent=true;
return;
}
else
{
- _header.put(_method);
- _header.put((byte)' ');
- _header.put(_uri.getBytes("UTF-8")); // TODO check
- _header.put((byte)' ');
- _header.put(_version==HttpVersion.HTTP_1_0_ORDINAL?HttpVersion.HTTP_1_0_BUFFER:HttpVersion.HTTP_1_1_BUFFER);
- _header.put(HttpTokens.CRLF);
+ buffer.put(_method);
+ buffer.put((byte)' ');
+ buffer.put(_uri.getBytes("UTF-8")); // TODO check
+ buffer.put((byte)' ');
+ buffer.put((_version==HttpVersion.HTTP_1_0?HttpVersion.HTTP_1_0:HttpVersion.HTTP_1_1).toBytes());
+ buffer.put(HttpTokens.CRLF);
}
}
else
{
// Responses
- if (_version == HttpVersion.HTTP_0_9_ORDINAL)
+ if (_version == HttpVersion.HTTP_0_9)
{
_persistent = false;
_contentLength = HttpTokens.EOF_CONTENT;
- _state = STATE_CONTENT;
+ _state = State.CONTENT;
return;
}
else
{
if (_persistent==null)
- _persistent= (_version > HttpVersion.HTTP_1_0_ORDINAL);
+ _persistent= (_version.ordinal() > HttpVersion.HTTP_1_0.ordinal());
// add response line
Status status = _status<__status.length?__status[_status]:null;
if (status==null)
{
- _header.put(HttpVersion.HTTP_1_1_BUFFER);
- _header.put((byte) ' ');
- _header.put((byte) ('0' + _status / 100));
- _header.put((byte) ('0' + (_status % 100) / 10));
- _header.put((byte) ('0' + (_status % 10)));
- _header.put((byte) ' ');
+ buffer.put(HTTP_1_1_SPACE);
+ buffer.put((byte) ('0' + _status / 100));
+ buffer.put((byte) ('0' + (_status % 100) / 10));
+ buffer.put((byte) ('0' + (_status % 10)));
+ buffer.put((byte) ' ');
if (_reason==null)
{
- _header.put((byte) ('0' + _status / 100));
- _header.put((byte) ('0' + (_status % 100) / 10));
- _header.put((byte) ('0' + (_status % 10)));
+ buffer.put((byte) ('0' + _status / 100));
+ buffer.put((byte) ('0' + (_status % 100) / 10));
+ buffer.put((byte) ('0' + (_status % 10)));
}
else
- _header.put(_reason);
- _header.put(HttpTokens.CRLF);
+ buffer.put(_reason);
+ buffer.put(HttpTokens.CRLF);
}
else
{
if (_reason==null)
- _header.put(status._responseLine);
+ buffer.put(status._responseLine);
else
{
- _header.put(status._schemeCode);
- _header.put(_reason);
- _header.put(HttpTokens.CRLF);
+ buffer.put(status._schemeCode);
+ buffer.put(_reason);
+ buffer.put(HttpTokens.CRLF);
}
}
@@ -488,8 +704,8 @@ public class HttpGenerator extends AbstractGenerator
if (_status!=101 )
{
- _header.put(HttpTokens.CRLF);
- _state = STATE_CONTENT;
+ buffer.put(HttpTokens.CRLF);
+ _state = State.CONTENT;
return;
}
}
@@ -506,11 +722,9 @@ public class HttpGenerator extends AbstractGenerator
// Add headers
if (_status>=200 && _date!=null)
{
- _header.put(HttpHeader.DATE_BUFFER);
- _header.put((byte)':');
- _header.put((byte)' ');
- _header.put(_date);
- _header.put(CRLF);
+ buffer.put(HttpHeader.DATE.toBytesColonSpace());
+ buffer.put(_date);
+ buffer.put(CRLF);
}
// key field values
@@ -530,9 +744,12 @@ public class HttpGenerator extends AbstractGenerator
if (field==null)
continue;
- switch (field.getNameOrdinal())
- {
- case HttpHeader.CONTENT_LENGTH_ORDINAL:
+ HttpHeader header = HttpHeader.CACHE.get(field.getName());
+ HttpHeaderValue value = null;
+
+ switch (header==null?HttpHeader.UNKNOWN:header)
+ {
+ case CONTENT_LENGTH:
content_length = field;
_contentLength = field.getLongValue();
@@ -540,42 +757,72 @@ public class HttpGenerator extends AbstractGenerator
content_length = null;
// write the field to the header buffer
- field.putTo(_header);
+ field.putTo(buffer);
break;
- case HttpHeader.CONTENT_TYPE_ORDINAL:
- if (BufferUtil.isPrefix(MimeTypes.MULTIPART_BYTERANGES_BUFFER, field.getValueBuffer())) _contentLength = HttpTokens.SELF_DEFINING_CONTENT;
+ case CONTENT_TYPE:
+ if (field.getValue().startsWith(MimeTypes.Type.MULTIPART_BYTERANGES.toString()))
+ _contentLength = HttpTokens.SELF_DEFINING_CONTENT;
// write the field to the header buffer
content_type=true;
- field.putTo(_header);
+ field.putTo(buffer);
break;
- case HttpHeader.TRANSFER_ENCODING_ORDINAL:
- if (_version == HttpVersion.HTTP_1_1_ORDINAL)
+ case TRANSFER_ENCODING:
+ if (_version == HttpVersion.HTTP_1_1)
transfer_encoding = field;
// Do NOT add yet!
break;
- case HttpHeader.CONNECTION_ORDINAL:
+ case CONNECTION:
if (isRequest())
- field.putTo(_header);
+ field.putTo(buffer);
- int connection_value = field.getValueOrdinal();
- switch (connection_value)
+ value = HttpHeaderValue.CACHE.get(field.getValue());
+
+ switch (value==null?HttpHeaderValue.UNKNOWN:value)
{
- case -1:
+ case UPGRADE:
+ {
+ // special case for websocket connection ordering
+ if (isResponse())
+ {
+ field.putTo(buffer);
+ continue;
+ }
+ }
+ case CLOSE:
+ {
+ close=true;
+ if (isResponse())
+ _persistent=false;
+ if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT)
+ _contentLength = HttpTokens.EOF_CONTENT;
+ break;
+ }
+ case KEEP_ALIVE:
+ {
+ if (_version == HttpVersion.HTTP_1_0)
+ {
+ keep_alive = true;
+ if (isResponse())
+ _persistent=true;
+ }
+ break;
+ }
+
+ default:
{
String[] values = field.getValue().split(",");
for (int i=0;values!=null && i0 || content_type ) && !_noContent)
{
// known length but not actually set.
- _header.put(HttpHeader.CONTENT_LENGTH_BUFFER);
- _header.put(HttpTokens.COLON);
- _header.put((byte) ' ');
- BufferUtil.putDecLong(_header, _contentLength);
- _header.put(HttpTokens.CRLF);
+ buffer.put(HttpHeader.CONTENT_LENGTH.toBytes());
+ buffer.put(HttpTokens.COLON);
+ buffer.put((byte) ' ');
+ BufferUtil.putDecLong(buffer, _contentLength);
+ buffer.put(HttpTokens.CRLF);
}
}
else
@@ -715,7 +933,7 @@ public class HttpGenerator extends AbstractGenerator
case HttpTokens.NO_CONTENT:
if (content_length == null && isResponse() && _status >= 200 && _status != 204 && _status != 304)
- _header.put(CONTENT_LENGTH_0);
+ buffer.put(CONTENT_LENGTH_0);
break;
case HttpTokens.EOF_CONTENT:
@@ -738,12 +956,12 @@ public class HttpGenerator extends AbstractGenerator
{
String c = transfer_encoding.getValue();
if (c.endsWith(HttpHeaderValue.CHUNKED))
- transfer_encoding.putTo(_header);
+ transfer_encoding.putTo(buffer);
else
throw new IllegalArgumentException("BAD TE");
}
else
- _header.put(TRANSFER_ENCODING_CHUNKED);
+ buffer.put(TRANSFER_ENCODING_CHUNKED);
}
// Handle connection if need be
@@ -757,197 +975,47 @@ public class HttpGenerator extends AbstractGenerator
{
if (!_persistent && (close || _version > HttpVersion.HTTP_1_0_ORDINAL))
{
- _header.put(CONNECTION_CLOSE);
+ buffer.put(CONNECTION_CLOSE);
if (connection!=null)
{
- _header.setPutIndex(_header.putIndex()-2);
- _header.put((byte)',');
- _header.put(connection.toString().getBytes());
- _header.put(CRLF);
+ buffer.setPutIndex(buffer.putIndex()-2);
+ buffer.put((byte)',');
+ buffer.put(connection.toString().getBytes());
+ buffer.put(CRLF);
}
}
else if (keep_alive)
{
- _header.put(CONNECTION_KEEP_ALIVE);
+ buffer.put(CONNECTION_KEEP_ALIVE);
if (connection!=null)
{
- _header.setPutIndex(_header.putIndex()-2);
- _header.put((byte)',');
- _header.put(connection.toString().getBytes());
- _header.put(CRLF);
+ buffer.setPutIndex(buffer.putIndex()-2);
+ buffer.put((byte)',');
+ buffer.put(connection.toString().getBytes());
+ buffer.put(CRLF);
}
}
else if (connection!=null)
{
- _header.put(CONNECTION_);
- _header.put(connection.toString().getBytes());
- _header.put(CRLF);
+ buffer.put(CONNECTION_);
+ buffer.put(connection.toString().getBytes());
+ buffer.put(CRLF);
}
}
if (!has_server && _status>199 && getSendServerVersion())
- _header.put(SERVER);
+ buffer.put(SERVER);
// end the header.
- _header.put(HttpTokens.CRLF);
- _state = STATE_CONTENT;
+ buffer.put(HttpTokens.CRLF);
+ _state = State.CONTENT;
}
catch(ArrayIndexOutOfBoundsException e)
{
- throw new RuntimeException("Header>"+_header.capacity(),e);
+ throw new RuntimeException("Header>"+buffer.capacity(),e);
}
}
-
- /* ------------------------------------------------------------ */
- /**
- * Complete the message.
- *
- * @throws IOException
- */
- @Override
- public void complete() throws IOException
- {
- if (_state == STATE_END)
- return;
-
- super.complete();
-
- if (_state < STATE_FLUSHING)
- {
- _state = STATE_FLUSHING;
- if (_contentLength == HttpTokens.CHUNKED_CONTENT)
- _needEOC = true;
- }
-
- flushBuffer();
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public int flushBuffer() throws IOException
- {
- try
- {
-
- if (_state == STATE_HEADER)
- throw new IllegalStateException("State==HEADER");
-
- prepareBuffers();
-
- if (_endp == null)
- {
- if (_needCRLF && _buffer!=null)
- _buffer.put(HttpTokens.CRLF);
- if (_needEOC && _buffer!=null && !_head)
- _buffer.put(LAST_CHUNK);
- _needCRLF=false;
- _needEOC=false;
- return 0;
- }
-
- int total= 0;
-
- int len = -1;
- int to_flush = flushMask();
- int last_flush;
-
- do
- {
- last_flush=to_flush;
- switch (to_flush)
- {
- case 7:
- throw new IllegalStateException(); // should never happen!
- case 6:
- len = _endp.flush(_header, _buffer, null);
- break;
- case 5:
- len = _endp.flush(_header, _content, null);
- break;
- case 4:
- len = _endp.flush(_header);
- break;
- case 3:
- len = _endp.flush(_buffer, _content, null);
- break;
- case 2:
- len = _endp.flush(_buffer);
- break;
- case 1:
- len = _endp.flush(_content);
- break;
- case 0:
- {
- len=0;
- // Nothing more we can write now.
- if (_header != null)
- _header.clear();
-
- _bypass = false;
- _bufferChunked = false;
-
- if (_buffer != null)
- {
- _buffer.clear();
- if (_contentLength == HttpTokens.CHUNKED_CONTENT)
- {
- // reserve some space for the chunk header
- _buffer.setPutIndex(CHUNK_SPACE);
- _buffer.setGetIndex(CHUNK_SPACE);
-
- // Special case handling for small left over buffer from
- // an addContent that caused a buffer flush.
- if (_content != null && _content.remaining() < _buffer.space() && _state != STATE_FLUSHING)
- {
- _buffer.put(_content);
- _content.clear();
- _content=null;
- }
- }
- }
-
- // Are we completely finished for now?
- if (!_needCRLF && !_needEOC && (_content==null || _content.remaining()==0))
- {
- if (_state == STATE_FLUSHING)
- _state = STATE_END;
-
- if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null)
- _endp.shutdownOutput();
- }
- else
- // Try to prepare more to write.
- prepareBuffers();
- }
-
- }
-
- if (len > 0)
- total+=len;
-
- to_flush = flushMask();
- }
- // loop while progress is being made (OR we have prepared some buffers that might make progress)
- while (len>0 || (to_flush!=0 && last_flush==0));
-
- return total;
- }
- catch (IOException e)
- {
- LOG.ignore(e);
- throw (e instanceof EofException) ? e:new EofException(e);
- }
- }
-
- /* ------------------------------------------------------------ */
- private int flushMask()
- {
- return ((_header != null && _header.remaining() > 0)?4:0)
- | ((_buffer != null && _buffer.remaining() > 0)?2:0)
- | ((_bypass && _content != null && _content.remaining() > 0)?1:0);
- }
-
/* ------------------------------------------------------------ */
private void prepareBuffers()
{
@@ -1084,28 +1152,11 @@ public class HttpGenerator extends AbstractGenerator
}
- public int getBytesBuffered()
- {
- return(_header==null?0:_header.remaining())+
- (_buffer==null?0:_buffer.remaining())+
- (_content==null?0:_content.remaining());
- }
-
- public boolean isEmpty()
- {
- return (_header==null||_header.remaining()==0) &&
- (_buffer==null||_buffer.remaining()==0) &&
- (_content==null||_content.remaining()==0);
- }
-
@Override
public String toString()
{
- return String.format("%s{s=%d,h=%d,b=%d,c=%d}",
+ return String.format("%s{s=%d}",
getClass().getSimpleName(),
- _state,
- _header == null ? -1 : _header.remaining(),
- _buffer == null ? -1 : _buffer.remaining(),
- _content == null ? -1 : _content.remaining());
+ _state);
}
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeader.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeader.java
index b8d92c6ba1b..ad81252a403 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeader.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeader.java
@@ -17,6 +17,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringMap;
+import org.eclipse.jetty.util.StringUtil;
public enum HttpHeader
@@ -101,7 +102,9 @@ public enum HttpHeader
SET_COOKIE("Set-Cookie"),
SET_COOKIE2("Set-Cookie2"),
MIME_VERSION("MIME-Version"),
- IDENTITY("identity");
+ IDENTITY("identity"),
+
+ UNKNOWN("::UNKNOWN::");
/* ------------------------------------------------------------ */
@@ -109,17 +112,22 @@ public enum HttpHeader
static
{
for (HttpHeader header : HttpHeader.values())
- CACHE.put(header.toString(),header);
+ if (header!=UNKNOWN)
+ CACHE.put(header.toString(),header);
}
private final String _string;
+ private final byte[] _bytes;
+ private final byte[] _bytesColonSpace;
private final ByteBuffer _buffer;
/* ------------------------------------------------------------ */
HttpHeader(String s)
{
_string=s;
- _buffer=BufferUtil.toBuffer(s);
+ _bytes=StringUtil.getBytes(s);
+ _bytesColonSpace=StringUtil.getBytes(s+": ");
+ _buffer=ByteBuffer.wrap(_bytes);
}
/* ------------------------------------------------------------ */
@@ -128,6 +136,18 @@ public enum HttpHeader
return _buffer.asReadOnlyBuffer();
}
+ /* ------------------------------------------------------------ */
+ public byte[] toBytes()
+ {
+ return _bytes;
+ }
+
+ /* ------------------------------------------------------------ */
+ public byte[] toBytesColonSpace()
+ {
+ return _bytesColonSpace;
+ }
+
/* ------------------------------------------------------------ */
public String toString()
{
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValue.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValue.java
index 8e68cdbe335..d502d9c9b41 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValue.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValue.java
@@ -35,14 +35,16 @@ public enum HttpHeaderValue
TE("TE"),
BYTES("bytes"),
NO_CACHE("no-cache"),
- UPGRADE("Upgrade");
+ UPGRADE("Upgrade"),
+ UNKNOWN("::UNKNOWN::");
/* ------------------------------------------------------------ */
public final static StringMap CACHE= new StringMap(true);
static
{
for (HttpHeaderValue value : HttpHeaderValue.values())
- CACHE.put(value.toString(),value);
+ if (value!=UNKNOWN)
+ CACHE.put(value.toString(),value);
}
private final String _string;
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpVersion.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpVersion.java
index 97f6b7f779f..4a809deea45 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpVersion.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpVersion.java
@@ -17,6 +17,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringMap;
+import org.eclipse.jetty.util.StringUtil;
/* ------------------------------------------------------------------------------- */
@@ -35,6 +36,7 @@ public enum HttpVersion
}
private final String _string;
+ private final byte[] _bytes;
private final ByteBuffer _buffer;
private final int _version;
@@ -42,10 +44,17 @@ public enum HttpVersion
HttpVersion(String s,int version)
{
_string=s;
- _buffer=BufferUtil.toBuffer(s);
+ _bytes=StringUtil.getBytes(s);
+ _buffer=ByteBuffer.wrap(_bytes);
_version=version;
}
+ /* ------------------------------------------------------------ */
+ public byte[] toBytes()
+ {
+ return _bytes;
+ }
+
/* ------------------------------------------------------------ */
public ByteBuffer toBuffer()
{
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java
index de79ee258c9..75fec91a823 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java
@@ -352,14 +352,7 @@ public class StringUtil
/* ------------------------------------------------------------ */
public static String toUTF8String(byte[] b,int offset,int length)
{
- try
- {
- return new String(b,offset,length,__UTF8);
- }
- catch (UnsupportedEncodingException e)
- {
- throw new IllegalArgumentException(e);
- }
+ return new String(b,offset,length,__UTF8_CHARSET);
}
/* ------------------------------------------------------------ */
@@ -418,15 +411,7 @@ public class StringUtil
public static byte[] getBytes(String s)
{
- try
- {
- return s.getBytes(__ISO_8859_1);
- }
- catch(Exception e)
- {
- LOG.warn(e);
- return s.getBytes();
- }
+ return s.getBytes(__ISO_8859_1_CHARSET);
}
public static byte[] getBytes(String s,String charset)