# HG changeset patch # User Jie Kang # Date 1406744263 14400 # Node ID 5fff68c9a9ecaa742b3f51abda863a4b80b3069f # Parent 8e9179035018d0125ef1a508bf4b025cd125470c Fixed TeeOutputStream to accept multi-byte encodings. Fixed TeeOutputStream to accept multi-byte encodings. * netx/net/sourceforge/jnlp/util/logging/TeeOutputStream.java: Now uses ByteArrayOutputStream instead of StringBuffer * tests/netx/unit/net/sourceforge/jnlp/util/logging/TeeOutputStreamTest.java: diff -r 8e9179035018 -r 5fff68c9a9ec ChangeLog --- a/ChangeLog Wed Jul 30 14:13:51 2014 -0400 +++ b/ChangeLog Wed Jul 30 14:17:43 2014 -0400 @@ -1,3 +1,10 @@ +2014-07-30 Jie Kang + + Fixed TeeOutputStream to accept multi-byte encodings. + * netx/net/sourceforge/jnlp/util/logging/TeeOutputStream.java: Now uses + ByteArrayOutputStream instead of StringBuffer + * tests/netx/unit/net/sourceforge/jnlp/util/logging/TeeOutputStreamTest.java: + 2014-07-30 Jie Kang Fix to Java ConsoleOutputPane for lower resolutions. Addresses bug diff -r 8e9179035018 -r 5fff68c9a9ec netx/net/sourceforge/jnlp/util/logging/TeeOutputStream.java --- a/netx/net/sourceforge/jnlp/util/logging/TeeOutputStream.java Wed Jul 30 14:13:51 2014 -0400 +++ b/netx/net/sourceforge/jnlp/util/logging/TeeOutputStream.java Wed Jul 30 14:17:43 2014 -0400 @@ -38,14 +38,13 @@ package net.sourceforge.jnlp.util.logging; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.PrintStream; -import net.sourceforge.jnlp.util.logging.JavaConsole; -import net.sourceforge.jnlp.util.logging.OutputController; + import net.sourceforge.jnlp.util.logging.OutputController.Level; -import net.sourceforge.jnlp.util.logging.SingleStreamLogger; import net.sourceforge.jnlp.util.logging.headers.Header; import net.sourceforge.jnlp.util.logging.headers.JavaMessage; -import net.sourceforge.jnlp.util.logging.headers.MessageWithHeader; /** * Behaves like the 'tee' command, sends output to both actual std stream and a @@ -55,15 +54,15 @@ // Everthing written to TeeOutputStream is written to our log too - private final StringBuffer string = new StringBuffer(); + private final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); private final boolean isError; + private final String lineSeparator = System.getProperty("line.separator"); public TeeOutputStream(PrintStream stdStream, boolean isError) { super(stdStream); this.isError = isError; } - @Override public void close() { flushLog(); @@ -82,32 +81,25 @@ @Override public synchronized void write(byte[] b, int off, int len) { - if (b == null) { - throw new NullPointerException(); - } else if ((off < 0) || (off > b.length) || (len < 0) - || ((off + len) > b.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + if (len == 0) { return; } - for (int i = 0; i < len; i++) { - appendChar(b[off + i]); - } + appendByteArray(b, off, len); super.write(b, off, len); } @Override public synchronized void write(int b) { - appendChar(b); + appendByte(b); super.write(b); } private void flushLog() { - if (string.length() <= 0 ){ - return; + String s = byteArrayOutputStream.toString(); + if (s.length() > 0) { + log(s); + byteArrayOutputStream.reset(); } - log(string.toString()); - string.setLength(0); } @Override @@ -121,21 +113,34 @@ return isError; } - private void appendChar(int b) { - if ( b <= 0 || b == '\n'){ + private void appendByte(int b) { + byteArrayOutputStream.write(b); + String s = byteArrayOutputStream.toString(); + if (s.endsWith(lineSeparator)) { flushLog(); - } else { - string.append((char)b); + } + } + + private void appendByteArray(byte[] b, int off, int len) { + byteArrayOutputStream.write(b, off, len); + String s = new String(b, off, len); + if (s.endsWith(lineSeparator)) { + flushLog(); } } private Level getlevel() { - if (isError()){ + if (isError()) { return OutputController.Level.ERROR_ALL; } else { return OutputController.Level.MESSAGE_ALL; } } - - + + //For unit testing + protected ByteArrayOutputStream getByteArrayOutputStream() throws IOException { + ByteArrayOutputStream copy = new ByteArrayOutputStream(); + copy.write(this.byteArrayOutputStream.toByteArray()); + return copy; + } } diff -r 8e9179035018 -r 5fff68c9a9ec tests/netx/unit/net/sourceforge/jnlp/util/logging/TeeOutputStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/netx/unit/net/sourceforge/jnlp/util/logging/TeeOutputStreamTest.java Wed Jul 30 14:17:43 2014 -0400 @@ -0,0 +1,70 @@ +package net.sourceforge.jnlp.util.logging; + +import org.junit.Before; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; + +import static org.junit.Assert.assertTrue; + +/** + * Created by jkang on 15/07/14. + */ +public class TeeOutputStreamTest { + + private PrintStream teePrintStream; + private TeeOutputStream tos; + + + @Before + public void setup() { + teePrintStream = new PrintStream(new ByteArrayOutputStream(), true); + tos = new TeeOutputStream(teePrintStream, false); + } + @Test + public void testPrintLn() throws IOException { + String s = "Hel你好lo \n World!"; + tos.println(s); //println should be immediately flushed + assertTrue(tos.getByteArrayOutputStream().toString().isEmpty()); + } + + @Test + public void testPrint() throws IOException { + String s = "नमस्तHello!\r"; + tos.print(s); + assertTrue(tos.getByteArrayOutputStream().toString().equals(s)); + } + + @Test + public void testWriteByteArrayString() throws IOException { + String s = "He\n\n\\llo chào"; + tos.write(s.getBytes(), 0, s.getBytes().length); + assertTrue(tos.getByteArrayOutputStream().toString().equals(s.toString())); + } + @Test + public void testWriteByte() throws IOException { + byte b = 5; + tos.write(b); + assertTrue(byteArrayEquals(b, tos.getByteArrayOutputStream().toByteArray())); + } + + @Test + public void testFlush() throws IOException { + String s = "Hello"; + tos.print(s); + assertTrue(!tos.getByteArrayOutputStream().toString().isEmpty()); + tos.flush(); + assertTrue(tos.getByteArrayOutputStream().toString().isEmpty()); + } + + private boolean byteArrayEquals(byte b, byte[] arr) { + for (byte i : arr) { + if (b != i) { + return false; + } + } + return true; + } +}