Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java')
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java482
1 files changed, 187 insertions, 295 deletions
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 520822637b..0c1787b9f5 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
@@ -21,7 +21,6 @@ package org.eclipse.jetty.http;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@@ -32,28 +31,26 @@ import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
-/* ------------------------------------------------------------ */
/**
* HttpGenerator. Builds HTTP Messages.
- *
+ * <p>
* If the system property "org.eclipse.jetty.http.HttpGenerator.STRICT" is set to true,
* then the generator will strictly pass on the exact strings received from methods and header
* fields. Otherwise a fast case insensitive string lookup is used that may alter the
* case and white space of some methods/headers
- * </p>
*/
public class HttpGenerator
{
private final static Logger LOG = Log.getLogger(HttpGenerator.class);
- public final static boolean __STRICT=Boolean.getBoolean("org.eclipse.jetty.http.HttpGenerator.STRICT");
+ public final static boolean __STRICT=Boolean.getBoolean("org.eclipse.jetty.http.HttpGenerator.STRICT");
private final static byte[] __colon_space = new byte[] {':',' '};
private final static HttpHeaderValue[] CLOSE = {HttpHeaderValue.CLOSE};
- public static final ResponseInfo CONTINUE_100_INFO = new ResponseInfo(HttpVersion.HTTP_1_1,null,-1,100,null,false);
- public static final ResponseInfo PROGRESS_102_INFO = new ResponseInfo(HttpVersion.HTTP_1_1,null,-1,102,null,false);
- public final static ResponseInfo RESPONSE_500_INFO =
- new ResponseInfo(HttpVersion.HTTP_1_1,new HttpFields(){{put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);}},0,HttpStatus.INTERNAL_SERVER_ERROR_500,null,false);
+ public static final MetaData.Response CONTINUE_100_INFO = new MetaData.Response(HttpVersion.HTTP_1_1,100,null,null,-1);
+ public static final MetaData.Response PROGRESS_102_INFO = new MetaData.Response(HttpVersion.HTTP_1_1,102,null,null,-1);
+ public final static MetaData.Response RESPONSE_500_INFO =
+ new MetaData.Response(HttpVersion.HTTP_1_1,HttpStatus.INTERNAL_SERVER_ERROR_500,null,new HttpFields(){{put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);}},0);
// states
public enum State { START, COMMITTED, COMPLETING, COMPLETING_1XX, END }
@@ -92,7 +89,7 @@ public class HttpGenerator
{
this(false,false);
}
-
+
/* ------------------------------------------------------------------------------- */
public HttpGenerator(boolean sendServerVersion,boolean sendXPoweredBy)
{
@@ -165,7 +162,7 @@ public class HttpGenerator
{
return _noContent;
}
-
+
/* ------------------------------------------------------------ */
public void setPersistent(boolean persistent)
{
@@ -202,7 +199,7 @@ public class HttpGenerator
}
/* ------------------------------------------------------------ */
- public Result generateRequest(RequestInfo info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last) throws IOException
+ public Result generateRequest(MetaData.Request info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last) throws IOException
{
switch(_state)
{
@@ -211,13 +208,16 @@ public class HttpGenerator
if (info==null)
return Result.NEED_INFO;
- // Do we need a request header
if (header==null)
return Result.NEED_HEADER;
// If we have not been told our persistence, set the default
if (_persistent==null)
- _persistent=(info.getHttpVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal());
+ {
+ _persistent=info.getVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal();
+ if (!_persistent && HttpMethod.CONNECT.is(info.getMethod()))
+ _persistent=true;
+ }
// prepare the header
int pos=BufferUtil.flipToFill(header);
@@ -226,12 +226,12 @@ public class HttpGenerator
// generate ResponseLine
generateRequestLine(info,header);
- if (info.getHttpVersion()==HttpVersion.HTTP_0_9)
- _noContent=true;
- else
- generateHeaders(info,header,content,last);
+ if (info.getVersion()==HttpVersion.HTTP_0_9)
+ throw new IllegalArgumentException("HTTP/0.9 not supported");
+
+ generateHeaders(info,header,content,last);
- boolean expect100 = info.getHttpFields().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString());
+ boolean expect100 = info.getFields().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString());
if (expect100)
{
@@ -254,7 +254,7 @@ public class HttpGenerator
}
catch(Exception e)
{
- String message= (e instanceof BufferOverflowException)?"Response header too large":e.getMessage();
+ String message= (e instanceof BufferOverflowException)?"Request header too large":e.getMessage();
throw new IOException(message,e);
}
finally
@@ -283,12 +283,9 @@ public class HttpGenerator
}
if (last)
- {
_state=State.COMPLETING;
- return len>0?Result.FLUSH:Result.CONTINUE;
- }
- return Result.FLUSH;
+ return len>0?Result.FLUSH:Result.CONTINUE;
}
case COMPLETING:
@@ -331,7 +328,13 @@ public class HttpGenerator
}
/* ------------------------------------------------------------ */
- public Result generateResponse(ResponseInfo info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last) throws IOException
+ public Result generateResponse(MetaData.Response info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last) throws IOException
+ {
+ return generateResponse(info,false,header,chunk,content,last);
+ }
+
+ /* ------------------------------------------------------------ */
+ public Result generateResponse(MetaData.Response info, boolean head, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last) throws IOException
{
switch(_state)
{
@@ -339,26 +342,27 @@ public class HttpGenerator
{
if (info==null)
return Result.NEED_INFO;
-
- // Handle 0.9
- if (info.getHttpVersion() == HttpVersion.HTTP_0_9)
+
+ switch(info.getVersion())
{
- _persistent = false;
- _endOfContent=EndOfContent.EOF_CONTENT;
- if (BufferUtil.hasContent(content))
- _contentPrepared+=content.remaining();
- _state = last?State.COMPLETING:State.COMMITTED;
- return Result.FLUSH;
+ case HTTP_1_0:
+ if (_persistent==null)
+ _persistent=Boolean.FALSE;
+ break;
+
+ case HTTP_1_1:
+ if (_persistent==null)
+ _persistent=Boolean.TRUE;
+ break;
+
+ default:
+ throw new IllegalArgumentException(info.getVersion()+" not supported");
}
-
+
// Do we need a response header
if (header==null)
return Result.NEED_HEADER;
- // If we have not been told our persistence, set the default
- if (_persistent==null)
- _persistent=(info.getHttpVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal());
-
// prepare the header
int pos=BufferUtil.flipToFill(header);
try
@@ -391,7 +395,7 @@ public class HttpGenerator
if (len>0)
{
_contentPrepared+=len;
- if (isChunking() && !info.isHead())
+ if (isChunking() && !head)
prepareChunk(header,len);
}
_state = last?State.COMPLETING:State.COMMITTED;
@@ -506,26 +510,18 @@ public class HttpGenerator
}
/* ------------------------------------------------------------ */
- private void generateRequestLine(RequestInfo request,ByteBuffer header)
+ private void generateRequestLine(MetaData.Request request,ByteBuffer header)
{
header.put(StringUtil.getBytes(request.getMethod()));
header.put((byte)' ');
- header.put(StringUtil.getBytes(request.getUri()));
- switch(request.getHttpVersion())
- {
- case HTTP_1_0:
- case HTTP_1_1:
- header.put((byte)' ');
- header.put(request.getHttpVersion().toBytes());
- break;
- default:
- throw new IllegalStateException();
- }
+ header.put(StringUtil.getBytes(request.getURIString()));
+ header.put((byte)' ');
+ header.put(request.getVersion().toBytes());
header.put(HttpTokens.CRLF);
}
/* ------------------------------------------------------------ */
- private void generateResponseLine(ResponseInfo response, ByteBuffer header)
+ private void generateResponseLine(MetaData.Response response, ByteBuffer header)
{
// Look for prepared response line
int status=response.getStatus();
@@ -575,10 +571,10 @@ public class HttpGenerator
}
/* ------------------------------------------------------------ */
- private void generateHeaders(Info _info,ByteBuffer header,ByteBuffer content,boolean last)
+ private void generateHeaders(MetaData _info,ByteBuffer header,ByteBuffer content,boolean last)
{
- final RequestInfo request=(_info instanceof RequestInfo)?(RequestInfo)_info:null;
- final ResponseInfo response=(_info instanceof ResponseInfo)?(ResponseInfo)_info:null;
+ final MetaData.Request request=(_info instanceof MetaData.Request)?(MetaData.Request)_info:null;
+ final MetaData.Response response=(_info instanceof MetaData.Response)?(MetaData.Response)_info:null;
// default field values
int send=_send;
@@ -587,122 +583,132 @@ public class HttpGenerator
boolean close=false;
boolean content_type=false;
StringBuilder connection = null;
+ long content_length = _info.getContentLength();
// Generate fields
- if (_info.getHttpFields() != null)
+ HttpFields fields = _info.getFields();
+ if (fields != null)
{
- for (HttpField field : _info.getHttpFields())
+ int n=fields.size();
+ for (int f=0;f<n;f++)
{
- HttpHeader h = field.getHeader();
+ HttpField field = fields.getField(f);
+ String v = field.getValue();
+ if (v==null || v.length()==0)
+ continue; // rfc7230 does not allow no value
- switch (h==null?HttpHeader.UNKNOWN:h)
+ HttpHeader h = field.getHeader();
+ if (h==null)
+ putTo(field,header);
+ else
{
- case CONTENT_LENGTH:
- // handle specially below
- if (_info.getContentLength()>=0)
- _endOfContent=EndOfContent.CONTENT_LENGTH;
- break;
-
- case CONTENT_TYPE:
- {
- if (field.getValue().startsWith(MimeTypes.Type.MULTIPART_BYTERANGES.toString()))
- _endOfContent=EndOfContent.SELF_DEFINING_CONTENT;
-
- // write the field to the header
- content_type=true;
- putTo(field,header);
- break;
- }
-
- case TRANSFER_ENCODING:
+ switch (h)
{
- if (_info.getHttpVersion() == HttpVersion.HTTP_1_1)
- transfer_encoding = field;
- // Do NOT add yet!
- break;
- }
+ case CONTENT_LENGTH:
+ _endOfContent=EndOfContent.CONTENT_LENGTH;
+ if (content_length<0)
+ content_length=Long.valueOf(field.getValue());
+ // handle setting the field specially below
+ break;
- case CONNECTION:
- {
- if (request!=null)
+ case CONTENT_TYPE:
+ {
+ // write the field to the header
+ content_type=true;
putTo(field,header);
+ break;
+ }
- // Lookup and/or split connection value field
- HttpHeaderValue[] values = HttpHeaderValue.CLOSE.is(field.getValue())?CLOSE:new HttpHeaderValue[]{HttpHeaderValue.CACHE.get(field.getValue())};
- String[] split = null;
-
- if (values[0]==null)
+ case TRANSFER_ENCODING:
{
- split = field.getValue().split("\\s*,\\s*");
- if (split.length>0)
- {
- values=new HttpHeaderValue[split.length];
- for (int i=0;i<split.length;i++)
- values[i]=HttpHeaderValue.CACHE.get(split[i]);
- }
+ if (_info.getVersion() == HttpVersion.HTTP_1_1)
+ transfer_encoding = field;
+ // Do NOT add yet!
+ break;
}
- // Handle connection values
- for (int i=0;i<values.length;i++)
+ case CONNECTION:
{
- HttpHeaderValue value=values[i];
- switch (value==null?HttpHeaderValue.UNKNOWN:value)
+ if (request!=null)
+ putTo(field,header);
+
+ // Lookup and/or split connection value field
+ HttpHeaderValue[] values = HttpHeaderValue.CLOSE.is(field.getValue())?CLOSE:new HttpHeaderValue[]{HttpHeaderValue.CACHE.get(field.getValue())};
+ String[] split = null;
+
+ if (values[0]==null)
{
- case UPGRADE:
+ split = StringUtil.csvSplit(field.getValue());
+ if (split.length>0)
{
- // special case for websocket connection ordering
- header.put(HttpHeader.CONNECTION.getBytesColonSpace()).put(HttpHeader.UPGRADE.getBytes());
- header.put(CRLF);
- break;
+ values=new HttpHeaderValue[split.length];
+ for (int i=0;i<split.length;i++)
+ values[i]=HttpHeaderValue.CACHE.get(split[i]);
}
+ }
- case CLOSE:
+ // Handle connection values
+ for (int i=0;i<values.length;i++)
+ {
+ HttpHeaderValue value=values[i];
+ switch (value==null?HttpHeaderValue.UNKNOWN:value)
{
- close=true;
- if (response!=null)
+ case UPGRADE:
{
- _persistent=false;
- if (_endOfContent == EndOfContent.UNKNOWN_CONTENT)
- _endOfContent=EndOfContent.EOF_CONTENT;
+ // special case for websocket connection ordering
+ header.put(HttpHeader.CONNECTION.getBytesColonSpace()).put(HttpHeader.UPGRADE.getBytes());
+ header.put(CRLF);
+ break;
}
- break;
- }
- case KEEP_ALIVE:
- {
- if (_info.getHttpVersion() == HttpVersion.HTTP_1_0)
+ case CLOSE:
{
- keep_alive = true;
+ close=true;
+ _persistent=false;
if (response!=null)
- _persistent=true;
+ {
+ if (_endOfContent == EndOfContent.UNKNOWN_CONTENT)
+ _endOfContent=EndOfContent.EOF_CONTENT;
+ }
+ break;
}
- break;
- }
- default:
- {
- if (connection==null)
- connection=new StringBuilder();
- else
- connection.append(',');
- connection.append(split==null?field.getValue():split[i]);
+ case KEEP_ALIVE:
+ {
+ if (_info.getVersion() == HttpVersion.HTTP_1_0)
+ {
+ keep_alive = true;
+ if (response!=null)
+ _persistent=true;
+ }
+ break;
+ }
+
+ default:
+ {
+ if (connection==null)
+ connection=new StringBuilder();
+ else
+ connection.append(',');
+ connection.append(split==null?field.getValue():split[i]);
+ }
}
}
+
+ // Do NOT add yet!
+ break;
}
- // Do NOT add yet!
- break;
- }
+ case SERVER:
+ {
+ send=send&~SEND_SERVER;
+ putTo(field,header);
+ break;
+ }
- case SERVER:
- {
- send=send&~SEND_SERVER;
- putTo(field,header);
- break;
+ default:
+ putTo(field,header);
}
-
- default:
- putTo(field,header);
}
}
}
@@ -710,13 +716,15 @@ public class HttpGenerator
// Calculate how to end _content and connection, _content length and transfer encoding
// settings.
+ // From http://tools.ietf.org/html/rfc7230#section-3.3.3
// From RFC 2616 4.4:
// 1. No body for 1xx, 204, 304 & HEAD response
- // 2. Force _content-length?
- // 3. If Transfer-Encoding!=identity && HTTP/1.1 && !HttpConnection==close then chunk
- // 4. Content-Length
- // 5. multipart/byteranges
- // 6. close
+ // 3. If Transfer-Encoding==(.*,)?chunked && HTTP/1.1 && !HttpConnection==close then chunk
+ // 5. Content-Length without Transfer-Encoding
+ // 6. Request and none over the above, then Content-Length=0 if POST/PUT
+ // 7. close
+
+
int status=response!=null?response.getStatus():-1;
switch (_endOfContent)
{
@@ -725,13 +733,12 @@ public class HttpGenerator
// written yet?
// Response known not to have a body
- if (_contentPrepared == 0 && response!=null && (status < 200 || status == 204 || status == 304))
+ if (_contentPrepared == 0 && response!=null && _noContent)
_endOfContent=EndOfContent.NO_CONTENT;
else if (_info.getContentLength()>0)
{
// we have been given a content length
_endOfContent=EndOfContent.CONTENT_LENGTH;
- long content_length = _info.getContentLength();
if ((response!=null || content_length>0 || content_type ) && !_noContent)
{
// known length but not actually set.
@@ -744,20 +751,13 @@ public class HttpGenerator
{
// we have seen all the _content there is, so we can be content-length limited.
_endOfContent=EndOfContent.CONTENT_LENGTH;
- long content_length = _contentPrepared+BufferUtil.length(content);
+ long actual_length = _contentPrepared+BufferUtil.length(content);
+ if (content_length>=0 && content_length!=actual_length)
+ throw new IllegalArgumentException("Content-Length header("+content_length+") != actual("+actual_length+")");
+
// Do we need to tell the headers about it
- if (content_length>0)
- {
- header.put(HttpHeader.CONTENT_LENGTH.getBytesColonSpace());
- BufferUtil.putDecLong(header, content_length);
- header.put(HttpTokens.CRLF);
- }
- else if (!_noContent)
- {
- if (content_type || response!=null || (request!=null && __assumedContentMethods.contains(request.getMethod())))
- header.put(CONTENT_LENGTH_0);
- }
+ putContentLength(header,actual_length,content_type,request,response);
}
else
{
@@ -767,25 +767,16 @@ public class HttpGenerator
// For a request with HTTP 1.0 & Connection: keep-alive
// we *must* close the connection, otherwise the client
// has no way to detect the end of the content.
- if (!isPersistent() || _info.getHttpVersion().ordinal() < HttpVersion.HTTP_1_1.ordinal())
+ if (!isPersistent() || _info.getVersion().ordinal() < HttpVersion.HTTP_1_1.ordinal())
_endOfContent = EndOfContent.EOF_CONTENT;
}
break;
case CONTENT_LENGTH:
- long content_length = _info.getContentLength();
- if (content_length>0)
- {
- header.put(HttpHeader.CONTENT_LENGTH.getBytesColonSpace());
- BufferUtil.putDecLong(header, content_length);
- header.put(HttpTokens.CRLF);
- }
- else if (!_noContent)
- {
- if (content_type || response!=null || (request!=null && __assumedContentMethods.contains(request.getMethod())))
- header.put(CONTENT_LENGTH_0);
- }
+ {
+ putContentLength(header,content_length,content_type,request,response);
break;
+ }
case NO_CONTENT:
throw new IllegalStateException();
@@ -827,7 +818,7 @@ public class HttpGenerator
// If this is a response, work out persistence
if (response!=null)
{
- if (!isPersistent() && (close || _info.getHttpVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal()))
+ if (!isPersistent() && (close || _info.getVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal()))
{
if (connection==null)
header.put(CONNECTION_CLOSE);
@@ -867,6 +858,22 @@ public class HttpGenerator
}
/* ------------------------------------------------------------------------------- */
+ private void putContentLength(ByteBuffer header, long contentLength, boolean contentType, MetaData.Request request, MetaData.Response response)
+ {
+ if (contentLength>0)
+ {
+ header.put(HttpHeader.CONTENT_LENGTH.getBytesColonSpace());
+ BufferUtil.putDecLong(header, contentLength);
+ header.put(HttpTokens.CRLF);
+ }
+ else if (!_noContent)
+ {
+ if (contentType || response!=null || (request!=null && __assumedContentMethods.contains(request.getMethod())))
+ header.put(CONTENT_LENGTH_0);
+ }
+ }
+
+ /* ------------------------------------------------------------------------------- */
public static byte[] getReasonBuffer(int code)
{
PreparedResponse status = code<__preprepared.length?__preprepared[code]:null;
@@ -879,8 +886,9 @@ public class HttpGenerator
@Override
public String toString()
{
- return String.format("%s{s=%s}",
+ return String.format("%s@%x{s=%s}",
getClass().getSimpleName(),
+ hashCode(),
_state);
}
@@ -942,110 +950,13 @@ public class HttpGenerator
}
}
- public static class Info
- {
- final HttpVersion _httpVersion;
- final HttpFields _httpFields;
- final long _contentLength;
-
- private Info(HttpVersion httpVersion, HttpFields httpFields, long contentLength)
- {
- _httpVersion = httpVersion;
- _httpFields = httpFields;
- _contentLength = contentLength;
- }
-
- public HttpVersion getHttpVersion()
- {
- return _httpVersion;
- }
- public HttpFields getHttpFields()
- {
- return _httpFields;
- }
- public long getContentLength()
- {
- return _contentLength;
- }
- }
-
- public static class RequestInfo extends Info
- {
- private final String _method;
- private final String _uri;
-
- public RequestInfo(HttpVersion httpVersion, HttpFields httpFields, long contentLength, String method, String uri)
- {
- super(httpVersion,httpFields,contentLength);
- _method = method;
- _uri = uri;
- }
-
- public String getMethod()
- {
- return _method;
- }
-
- public String getUri()
- {
- return _uri;
- }
-
- @Override
- public String toString()
- {
- return String.format("RequestInfo{%s %s %s,%d}",_method,_uri,_httpVersion,_contentLength);
- }
- }
-
- public static class ResponseInfo extends Info
- {
- private final int _status;
- private final String _reason;
- private final boolean _head;
-
- public ResponseInfo(HttpVersion httpVersion, HttpFields httpFields, long contentLength, int status, String reason, boolean head)
- {
- super(httpVersion,httpFields,contentLength);
- _status = status;
- _reason = reason;
- _head = head;
- }
-
- public boolean isInformational()
- {
- return _status>=100 && _status<200;
- }
-
- public int getStatus()
- {
- return _status;
- }
-
- public String getReason()
- {
- return _reason;
- }
-
- public boolean isHead()
- {
- return _head;
- }
-
- @Override
- public String toString()
- {
- return String.format("ResponseInfo{%s %s %s,%d,%b}",_httpVersion,_status,_reason,_contentLength,_head);
- }
- }
-
private static void putSanitisedName(String s,ByteBuffer buffer)
{
int l=s.length();
for (int i=0;i<l;i++)
{
char c=s.charAt(i);
-
+
if (c<0 || c>0xff || c=='\r' || c=='\n'|| c==':')
buffer.put((byte)'?');
else
@@ -1059,7 +970,7 @@ public class HttpGenerator
for (int i=0;i<l;i++)
{
char c=s.charAt(i);
-
+
if (c<0 || c>0xff || c=='\r' || c=='\n')
buffer.put((byte)' ');
else
@@ -1069,9 +980,9 @@ public class HttpGenerator
public static void putTo(HttpField field, ByteBuffer bufferInFillMode)
{
- if (field instanceof CachedHttpField)
+ if (field instanceof PreEncodedHttpField)
{
- ((CachedHttpField)field).putTo(bufferInFillMode);
+ ((PreEncodedHttpField)field).putTo(bufferInFillMode,HttpVersion.HTTP_1_0);
}
else
{
@@ -1092,7 +1003,7 @@ public class HttpGenerator
}
}
- public static void putTo(HttpFields fields, ByteBuffer bufferInFillMode)
+ public static void putTo(HttpFields fields, ByteBuffer bufferInFillMode)
{
for (HttpField field : fields)
{
@@ -1101,23 +1012,4 @@ public class HttpGenerator
}
BufferUtil.putCRLF(bufferInFillMode);
}
-
- public static class CachedHttpField extends HttpField
- {
- private final byte[] _bytes;
- public CachedHttpField(HttpHeader header,String value)
- {
- super(header,value);
- int cbl=header.getBytesColonSpace().length;
- _bytes=Arrays.copyOf(header.getBytesColonSpace(), cbl+value.length()+2);
- System.arraycopy(value.getBytes(StandardCharsets.ISO_8859_1),0,_bytes,cbl,value.length());
- _bytes[_bytes.length-2]=(byte)'\r';
- _bytes[_bytes.length-1]=(byte)'\n';
- }
-
- public void putTo(ByteBuffer bufferInFillMode)
- {
- bufferInFillMode.put(_bytes);
- }
- }
}

Back to the top