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

View File

@ -591,14 +591,24 @@ public class ResponseTest
session_handler.start(); session_handler.start();
request.setSessionHandler(session_handler); request.setSessionHandler(session_handler);
HttpSession session = request.getSession(true); HttpSession session = request.getSession(true);
response.setCharacterEncoding(UTF_8.name());
assertThat(session,not(nullValue())); assertThat(session,not(nullValue()));
assertTrue(session.isNew()); assertTrue(session.isNew());
response.getOutputStream().println("ABC"); String expected = "";
response.getOutputStream().print("ABC");
expected += "ABC";
response.getOutputStream().println("XYZ"); 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(); response.getOutputStream().close();
assertEquals("ABC\r\nXYZ\r\n",BufferUtil.toString(_content)); assertEquals(expected,BufferUtil.toString(_content, UTF_8));
} }