diff --git a/src/main/java/org/jboss/netty/buffer/AbstractChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/AbstractChannelBuffer.java index 2cb5ba3f92..cdd118aa65 100644 --- a/src/main/java/org/jboss/netty/buffer/AbstractChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/AbstractChannelBuffer.java @@ -40,7 +40,6 @@ import java.util.NoSuchElementException; */ public abstract class AbstractChannelBuffer implements ChannelBuffer { - private int hashCode; private int readerIndex; private int writerIndex; private int markedReaderIndex; @@ -406,6 +405,10 @@ public abstract class AbstractChannelBuffer implements ChannelBuffer { return new ByteBuffer[] { toByteBuffer(index, length) }; } + public String toString(String charsetName) { + return toString(readerIndex, readableBytes(), charsetName); + } + public int indexOf(int fromIndex, int toIndex, byte value) { return ChannelBuffers.indexOf(this, fromIndex, toIndex, value); } @@ -416,14 +419,7 @@ public abstract class AbstractChannelBuffer implements ChannelBuffer { @Override public int hashCode() { - if (hashCode != 0) { - return hashCode; - } - return hashCode = ChannelBuffers.hashCode(this); - } - - protected void clearHashCode() { - hashCode = 0; + return ChannelBuffers.hashCode(this); } @Override diff --git a/src/main/java/org/jboss/netty/buffer/ByteBufferBackedChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/ByteBufferBackedChannelBuffer.java index cbc9060ae9..22794f8e86 100644 --- a/src/main/java/org/jboss/netty/buffer/ByteBufferBackedChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/ByteBufferBackedChannelBuffer.java @@ -26,10 +26,12 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; +import java.nio.charset.UnsupportedCharsetException; public class ByteBufferBackedChannelBuffer extends AbstractChannelBuffer { @@ -234,6 +236,26 @@ public class ByteBufferBackedChannelBuffer extends AbstractChannelBuffer { } } + public String toString(int index, int length, String charsetName) { + if (!buffer.isReadOnly() && buffer.hasArray()) { + try { + return new String( + buffer.array(), index + buffer.arrayOffset(), length, + charsetName); + } catch (UnsupportedEncodingException e) { + throw new UnsupportedCharsetException(charsetName); + } + } else { + byte[] tmp = new byte[length]; + ((ByteBuffer) buffer.duplicate().position(index)).get(tmp); + try { + return new String(tmp, charsetName); + } catch (UnsupportedEncodingException e) { + throw new UnsupportedCharsetException(charsetName); + } + } + } + public ChannelBuffer slice(int index, int length) { if (index == 0 && length == capacity()) { return duplicate(); diff --git a/src/main/java/org/jboss/netty/buffer/ChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/ChannelBuffer.java index 41677dabea..d5355ecf4a 100644 --- a/src/main/java/org/jboss/netty/buffer/ChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/ChannelBuffer.java @@ -648,6 +648,9 @@ public interface ChannelBuffer extends Comparable { ByteBuffer[] toByteBuffers(); ByteBuffer[] toByteBuffers(int index, int length); + String toString(String charsetName); + String toString(int index, int length, String charsetName); + /** * Returns a hash code which was calculated from the content of this * buffer. If there's a byte array which is diff --git a/src/main/java/org/jboss/netty/buffer/ChannelBuffers.java b/src/main/java/org/jboss/netty/buffer/ChannelBuffers.java index 08a747a704..ab524c2f1b 100644 --- a/src/main/java/org/jboss/netty/buffer/ChannelBuffers.java +++ b/src/main/java/org/jboss/netty/buffer/ChannelBuffers.java @@ -22,8 +22,10 @@ */ package org.jboss.netty.buffer; +import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.charset.UnsupportedCharsetException; /** @@ -241,6 +243,14 @@ public class ChannelBuffers { return wrappedBuffer(wrappedBuffers); } + public static ChannelBuffer wrappedBuffer(String string, String charsetName) { + try { + return wrappedBuffer(string.getBytes(charsetName)); + } catch (UnsupportedEncodingException e) { + throw new UnsupportedCharsetException(charsetName); + } + } + public static ChannelBuffer copiedBuffer(byte[] array) { return copiedBuffer(BIG_ENDIAN, array); } diff --git a/src/main/java/org/jboss/netty/buffer/CompositeChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/CompositeChannelBuffer.java index 800ea9e00c..0c0ac09f56 100644 --- a/src/main/java/org/jboss/netty/buffer/CompositeChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/CompositeChannelBuffer.java @@ -25,10 +25,12 @@ package org.jboss.netty.buffer; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; +import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; import java.util.List; @@ -418,6 +420,10 @@ public class CompositeChannelBuffer extends AbstractChannelBuffer { } public ByteBuffer toByteBuffer(int index, int length) { + if (slices.length == 1) { + return slices[0].toByteBuffer(index, length); + } + ByteBuffer[] buffers = toByteBuffers(index, length); ByteBuffer merged = ByteBuffer.allocate(length); for (ByteBuffer b: buffers) { @@ -450,6 +456,35 @@ public class CompositeChannelBuffer extends AbstractChannelBuffer { return buffers.toArray(new ByteBuffer[buffers.size()]); } + public String toString(int index, int length, String charsetName) { + int sliceId = sliceId(index); + if (index + length <= indices[sliceId + 1]) { + return slices[sliceId].toString( + index - indices[sliceId], length, charsetName); + } + + byte[] data = new byte[length]; + int dataIndex = 0; + int i = sliceId; + + while (length > 0) { + ChannelBuffer s = slices[i]; + int adjustment = indices[i]; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + s.getBytes(index - adjustment, data, dataIndex, localLength); + index += localLength; + dataIndex += localLength; + length -= localLength; + i ++; + } + + try { + return new String(data, charsetName); + } catch (UnsupportedEncodingException e) { + throw new UnsupportedCharsetException(charsetName); + } + } + private int sliceId(int index) { int lastSliceId = this.lastSliceId; if (index >= indices[lastSliceId]) { diff --git a/src/main/java/org/jboss/netty/buffer/DuplicatedChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/DuplicatedChannelBuffer.java index f26305511b..520a620c24 100644 --- a/src/main/java/org/jboss/netty/buffer/DuplicatedChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/DuplicatedChannelBuffer.java @@ -166,4 +166,8 @@ public class DuplicatedChannelBuffer extends AbstractChannelBuffer implements Wr public ByteBuffer toByteBuffer(int index, int length) { return buffer.toByteBuffer(index, length); } + + public String toString(int index, int length, String charsetName) { + return buffer.toString(index, length, charsetName); + } } diff --git a/src/main/java/org/jboss/netty/buffer/DynamicChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/DynamicChannelBuffer.java index 78191753a5..8ea8f7e61c 100644 --- a/src/main/java/org/jboss/netty/buffer/DynamicChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/DynamicChannelBuffer.java @@ -231,6 +231,10 @@ public class DynamicChannelBuffer extends AbstractChannelBuffer { return buffer.toByteBuffer(index, length); } + + public String toString(int index, int length, String charsetName) { + return buffer.toString(index, length, charsetName); + } private void ensureWritableBytes(int requestedBytes) { if (requestedBytes <= writableBytes()) { return; diff --git a/src/main/java/org/jboss/netty/buffer/HeapChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/HeapChannelBuffer.java index 5542814e15..84d652f0d6 100644 --- a/src/main/java/org/jboss/netty/buffer/HeapChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/HeapChannelBuffer.java @@ -26,9 +26,11 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; +import java.nio.charset.UnsupportedCharsetException; /** * @@ -151,4 +153,12 @@ public abstract class HeapChannelBuffer extends AbstractChannelBuffer { public ByteBuffer toByteBuffer(int index, int length) { return ByteBuffer.wrap(array, index, length); } + + public String toString(int index, int length, String charsetName) { + try { + return new String(array, index, length, charsetName); + } catch (UnsupportedEncodingException e) { + throw new UnsupportedCharsetException(charsetName); + } + } } diff --git a/src/main/java/org/jboss/netty/buffer/ReadOnlyChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/ReadOnlyChannelBuffer.java index 8a95a27d8a..629dbfdafd 100644 --- a/src/main/java/org/jboss/netty/buffer/ReadOnlyChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/ReadOnlyChannelBuffer.java @@ -165,6 +165,10 @@ public class ReadOnlyChannelBuffer extends AbstractChannelBuffer implements Wrap return buffer.toByteBuffer(index, length).asReadOnlyBuffer(); } + public String toString(int index, int length, String charsetName) { + return buffer.toString(index, length, charsetName); + } + public int capacity() { return buffer.capacity(); } diff --git a/src/main/java/org/jboss/netty/buffer/SlicedChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/SlicedChannelBuffer.java index 69ec6194e0..cab48c3968 100644 --- a/src/main/java/org/jboss/netty/buffer/SlicedChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/SlicedChannelBuffer.java @@ -193,6 +193,11 @@ public class SlicedChannelBuffer extends AbstractChannelBuffer implements Wrappe return buffer.toByteBuffer(index + adjustment, length); } + public String toString(int index, int length, String charsetName) { + checkIndex(index, length); + return buffer.toString(index + adjustment, length, charsetName); + } + private void checkIndex(int index) { if (index < 0 || index >= capacity()) { throw new IndexOutOfBoundsException(); diff --git a/src/main/java/org/jboss/netty/buffer/TruncatedChannelBuffer.java b/src/main/java/org/jboss/netty/buffer/TruncatedChannelBuffer.java index a4b000c94d..9f0c4687f7 100644 --- a/src/main/java/org/jboss/netty/buffer/TruncatedChannelBuffer.java +++ b/src/main/java/org/jboss/netty/buffer/TruncatedChannelBuffer.java @@ -187,6 +187,11 @@ public class TruncatedChannelBuffer extends AbstractChannelBuffer implements Wra return buffer.toByteBuffer(index, length); } + public String toString(int index, int length, String charsetName) { + checkIndex(index, length); + return buffer.toString(index, length, charsetName); + } + private void checkIndex(int index) { if (index < 0 || index >= capacity()) { throw new IndexOutOfBoundsException(); diff --git a/src/main/java/org/jboss/netty/handler/codec/replay/ReplayingDecoderBuffer.java b/src/main/java/org/jboss/netty/handler/codec/replay/ReplayingDecoderBuffer.java index 3e99085266..8b4e5f58c1 100644 --- a/src/main/java/org/jboss/netty/handler/codec/replay/ReplayingDecoderBuffer.java +++ b/src/main/java/org/jboss/netty/handler/codec/replay/ReplayingDecoderBuffer.java @@ -394,6 +394,16 @@ class ReplayingDecoderBuffer implements ChannelBuffer { return buffer.toByteBuffers(index, length); } + public String toString(int index, int length, String charsetName) { + checkIndex(index, length); + return buffer.toString(index, length, charsetName); + } + + public String toString(String charsetName) { + reject(); + return null; + } + @Override public String toString() { return buffer.toString(); diff --git a/src/main/java/org/jboss/netty/handler/codec/string/StringDecoder.java b/src/main/java/org/jboss/netty/handler/codec/string/StringDecoder.java index 39387e810c..294f3fef7e 100644 --- a/src/main/java/org/jboss/netty/handler/codec/string/StringDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/string/StringDecoder.java @@ -73,9 +73,8 @@ public class StringDecoder implements ChannelUpstreamHandler { return; } - ChannelBuffer src = (ChannelBuffer) e.getMessage(); - byte[] dst = new byte[src.readableBytes()]; - src.getBytes(src.readerIndex(), dst); - fireMessageReceived(context, e.getChannel(), new String(dst, charsetName)); + fireMessageReceived( + context, e.getChannel(), + ((ChannelBuffer) e.getMessage()).toString(charsetName)); } } diff --git a/src/main/java/org/jboss/netty/handler/codec/string/StringEncoder.java b/src/main/java/org/jboss/netty/handler/codec/string/StringEncoder.java index 1333fba586..f54bd351a1 100644 --- a/src/main/java/org/jboss/netty/handler/codec/string/StringEncoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/string/StringEncoder.java @@ -22,11 +22,11 @@ */ package org.jboss.netty.handler.codec.string; +import static org.jboss.netty.buffer.ChannelBuffers.*; import static org.jboss.netty.channel.Channels.*; import java.nio.charset.Charset; -import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.ChannelDownstreamHandler; import org.jboss.netty.channel.ChannelEvent; import org.jboss.netty.channel.ChannelHandlerContext; @@ -73,7 +73,7 @@ public class StringEncoder implements ChannelDownstreamHandler { return; } - String src = (String) e.getMessage(); - write(context, e.getChannel(), e.getFuture(), ChannelBuffers.wrappedBuffer(src.getBytes(charsetName))); + write(context, e.getChannel(), e.getFuture(), + wrappedBuffer(String.valueOf(e.getMessage()), charsetName)); } }