updates after review

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2018-12-20 08:53:16 +11:00
parent 225760c2de
commit 8f06fa8083
2 changed files with 29 additions and 11 deletions

View File

@ -27,6 +27,7 @@ import java.nio.channels.WritePendingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@ -127,6 +128,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
}
private static Logger LOG = Log.getLogger(HttpOutput.class);
private final static ThreadLocal<CharsetEncoder> _encoder = new ThreadLocal<>();
private final HttpChannel _channel;
private final SharedBlockingCallback _writeBlocker;
@ -138,7 +140,6 @@ public class HttpOutput extends ServletOutputStream implements Runnable
private int _bufferSize;
private int _commitSize;
private WriteListener _writeListener;
private CharsetEncoder _encoder;
private volatile Throwable _onError;
/*
ACTION OPEN ASYNC READY PENDING UNREADY CLOSED
@ -699,16 +700,23 @@ public class HttpOutput extends ServletOutputStream implements Runnable
if (isClosed())
throw new IOException("Closed");
// TODO would a Threadlocal pool be better?
String charset = _channel.getResponse().getCharacterEncoding();
if (_encoder==null || !_encoder.charset().name().equals(charset))
_encoder = Charset.forName(charset).newEncoder();
CharsetEncoder encoder = _encoder.get();
if (encoder==null || !encoder.charset().name().equalsIgnoreCase(charset))
{
encoder = Charset.forName(charset).newEncoder();
encoder.onMalformedInput(CodingErrorAction.REPLACE);
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
_encoder.set(encoder);
}
else
_encoder.reset();
{
encoder.reset();
}
CharBuffer in = CharBuffer.wrap(s);
CharBuffer crlf = eoln?CharBuffer.wrap("\r\n"):null;
ByteBuffer out = getHttpChannel().getByteBufferPool().acquire((int)(1+(s.length()+2)*_encoder.averageBytesPerChar()),false);
ByteBuffer out = getHttpChannel().getByteBufferPool().acquire((int)(1+(s.length()+2)*encoder.averageBytesPerChar()),false);
BufferUtil.flipToFill(out);
for(;;)
@ -716,7 +724,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
CoderResult result;
if (in.hasRemaining())
{
result = _encoder.encode(in, out, false);
result = encoder.encode(in, out, crlf==null);
if (result.isUnderflow())
if (crlf==null)
break;
@ -725,10 +733,10 @@ public class HttpOutput extends ServletOutputStream implements Runnable
}
else if (crlf.hasRemaining())
{
result = _encoder.encode(crlf, out, true);
result = encoder.encode(crlf, out, true);
if (result.isUnderflow())
{
if (!_encoder.flush(out).isUnderflow())
if (!encoder.flush(out).isUnderflow())
result.throwException();
break;
}

View File

@ -591,14 +591,24 @@ public class ResponseTest
session_handler.start();
request.setSessionHandler(session_handler);
HttpSession session = request.getSession(true);
response.setCharacterEncoding(UTF_8.name());
assertThat(session,not(nullValue()));
assertTrue(session.isNew());
response.getOutputStream().println("ABC");
String expected = "";
response.getOutputStream().print("ABC");
expected += "ABC";
response.getOutputStream().println("XYZ");
expected += "XYZ\r\n";
String s="";
for (int i=0; i<100; i++)
s += "\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC\u20AC";
response.getOutputStream().println(s);
expected += s +"\r\n";
response.getOutputStream().close();
assertEquals("ABC\r\nXYZ\r\n",BufferUtil.toString(_content));
assertEquals(expected,BufferUtil.toString(_content, UTF_8));
}