From 2e261b75d6dd749b5ea354e16750c64b81faa42c Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 29 Apr 2014 20:35:49 +0200 Subject: [PATCH] 433692 improved buffer resizing --- .../jetty/client/GZIPContentDecoder.java | 6 +- .../util/BufferingResponseListener.java | 90 +++++++++++-------- .../eclipse/jetty/client/HttpClientTest.java | 25 ++++-- .../org/eclipse/jetty/http/HttpGenerator.java | 10 +-- .../org/eclipse/jetty/io/WriteFlusher.java | 6 +- .../jetty/server/handler/ContextHandler.java | 11 +-- .../spdy/generator/HeadersBlockGenerator.java | 4 +- .../jetty/spdy/parser/HeadersBlockParser.java | 13 ++- .../eclipse/jetty/util/ArrayTernaryTrie.java | 10 ++- .../org/eclipse/jetty/util/BufferUtil.java | 24 ++++- .../jetty/util/ByteArrayISO8859Writer.java | 10 +-- .../eclipse/jetty/util/BufferUtilTest.java | 35 ++++++++ .../websocket/client/masks/FixedMasker.java | 5 +- .../websocket/common/WebSocketFrame.java | 5 +- .../websocket/server/ab/AbstractABCase.java | 5 +- 15 files changed, 161 insertions(+), 98 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java b/jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java index 8a457a6e89f..ab8f2a40b5f 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java @@ -246,14 +246,12 @@ public class GZIPContentDecoder implements ContentDecoder if (output == null) { // Save the inflated bytes and loop to see if we have finished - output = new byte[decoded]; - System.arraycopy(bytes, 0, output, 0, decoded); + output = Arrays.copyOf(bytes, decoded); } else { // Accumulate inflated bytes and loop to see if we have finished - byte[] newOutput = new byte[output.length + decoded]; - System.arraycopy(output, 0, newOutput, 0, output.length); + byte[] newOutput = Arrays.copyOf(output, output.length+decoded); System.arraycopy(bytes, 0, newOutput, output.length, decoded); output = newOutput; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java index bc5f8146f8e..b15083973e4 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java @@ -18,11 +18,14 @@ package org.eclipse.jetty.client.util; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; +import java.util.Arrays; import java.util.Locale; import org.eclipse.jetty.client.api.Response; @@ -30,6 +33,7 @@ import org.eclipse.jetty.client.api.Response.Listener; import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.util.BufferUtil; /** *

Implementation of {@link Listener} that buffers the content up to a maximum length @@ -40,7 +44,7 @@ import org.eclipse.jetty.http.HttpHeader; public abstract class BufferingResponseListener extends Listener.Adapter { private final int maxLength; - private volatile byte[] buffer = new byte[0]; + private volatile ByteBuffer buffer; private volatile String encoding; /** @@ -58,53 +62,57 @@ public abstract class BufferingResponseListener extends Listener.Adapter */ public BufferingResponseListener(int maxLength) { - this.maxLength = maxLength; + this.maxLength=maxLength; } @Override public void onHeaders(Response response) { + super.onHeaders(response); + HttpFields headers = response.getHeaders(); long length = headers.getLongField(HttpHeader.CONTENT_LENGTH.asString()); if (length > maxLength) { response.abort(new IllegalArgumentException("Buffering capacity exceeded")); + return; } - else + + buffer=BufferUtil.allocate((length > 0)?(int)length:1024); + + String contentType = headers.get(HttpHeader.CONTENT_TYPE); + if (contentType != null) { - String contentType = headers.get(HttpHeader.CONTENT_TYPE); - if (contentType != null) + String charset = "charset="; + int index = contentType.toLowerCase(Locale.ENGLISH).indexOf(charset); + if (index > 0) { - String charset = "charset="; - int index = contentType.toLowerCase(Locale.ENGLISH).indexOf(charset); + String encoding = contentType.substring(index + charset.length()); + // Sometimes charsets arrive with an ending semicolon + index = encoding.indexOf(';'); if (index > 0) - { - String encoding = contentType.substring(index + charset.length()); - // Sometimes charsets arrive with an ending semicolon - index = encoding.indexOf(';'); - if (index > 0) - encoding = encoding.substring(0, index); - this.encoding = encoding; - } + encoding = encoding.substring(0, index); + this.encoding = encoding; } } } @Override public void onContent(Response response, ByteBuffer content) - { - long newLength = buffer.length + content.remaining(); - if (newLength > maxLength) + { + int length = content.remaining(); + if (length>BufferUtil.space(buffer)) { - response.abort(new IllegalArgumentException("Buffering capacity exceeded")); - } - else - { - byte[] newBuffer = new byte[(int)newLength]; - System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); - content.get(newBuffer, buffer.length, content.remaining()); - buffer = newBuffer; + int requiredCapacity = buffer.capacity()+length; + if (requiredCapacity>maxLength) + response.abort(new IllegalArgumentException("Buffering capacity exceeded")); + + int newCapacity = Math.min(Integer.highestOneBit(requiredCapacity) << 1, maxLength); + buffer = BufferUtil.ensureCapacity(buffer,newCapacity); } + + BufferUtil.append(buffer, content); + } @Override @@ -121,7 +129,9 @@ public abstract class BufferingResponseListener extends Listener.Adapter */ public byte[] getContent() { - return buffer; + if (buffer==null) + return new byte[0]; + return BufferUtil.toArray(buffer); } /** @@ -144,14 +154,9 @@ public abstract class BufferingResponseListener extends Listener.Adapter */ public String getContentAsString(String encoding) { - try - { - return new String(getContent(), encoding); - } - catch (UnsupportedEncodingException x) - { - throw new UnsupportedCharsetException(encoding); - } + if (buffer==null) + return null; + return BufferUtil.toString(buffer, Charset.forName(encoding)); } /** @@ -161,6 +166,19 @@ public abstract class BufferingResponseListener extends Listener.Adapter */ public String getContentAsString(Charset encoding) { - return new String(getContent(), encoding); + if (buffer==null) + return null; + return BufferUtil.toString(buffer, encoding); + } + + /* ------------------------------------------------------------ */ + /** + * @return Content as InputStream + */ + public InputStream getContentAsInputStream() + { + if (buffer==null) + return new ByteArrayInputStream(new byte[]{}); + return new ByteArrayInputStream(buffer.array(), buffer.arrayOffset(), buffer.remaining()); } } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java index bedd3482776..fb596783310 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java @@ -37,12 +37,14 @@ import java.util.List; import java.util.NoSuchElementException; import java.util.Random; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.zip.GZIPOutputStream; + import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; @@ -1038,26 +1040,33 @@ public class HttpClientTest extends AbstractHttpClientServerTest } }); - final AtomicInteger complete = new AtomicInteger(); + final Exchanger ex = new Exchanger(); BufferingResponseListener listener = new BufferingResponseListener() { @Override public void onComplete(Result result) { - complete.incrementAndGet(); + try + { + ex.exchange(result.getResponse()); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } } }; - ContentResponse response = client.newRequest("localhost", connector.getLocalPort()) + + client.newRequest("localhost", connector.getLocalPort()) .scheme(scheme) - .onResponseContent(listener) - .onComplete(listener) - .send(); + .send(listener); + + Response response = ex.exchange(null); Assert.assertEquals(200, response.getStatus()); - Assert.assertEquals(1, complete.get()); Assert.assertArrayEquals(content, listener.getContent()); - Assert.assertArrayEquals(content, response.getContent()); + } @Test 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 e99d3cc8153..a51e4ba7b85 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 @@ -22,6 +22,7 @@ import java.io.IOException; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import org.eclipse.jetty.http.HttpTokens.EndOfContent; import org.eclipse.jetty.util.BufferUtil; @@ -916,10 +917,8 @@ public class HttpGenerator line[versionLength+6+reason.length()]=HttpTokens.LINE_FEED; __preprepared[i] = new PreparedResponse(); - __preprepared[i]._reason=new byte[line.length-versionLength-7] ; - System.arraycopy(line,versionLength+5,__preprepared[i]._reason,0,line.length-versionLength-7); - __preprepared[i]._schemeCode=new byte[versionLength+5]; - System.arraycopy(line,0,__preprepared[i]._schemeCode,0,versionLength+5); + __preprepared[i]._schemeCode = Arrays.copyOfRange(line, 0,versionLength+5); + __preprepared[i]._reason = Arrays.copyOfRange(line, versionLength+5, line.length-2); __preprepared[i]._responseLine=line; } } @@ -1091,8 +1090,7 @@ public class HttpGenerator { super(header,value); int cbl=header.getBytesColonSpace().length; - _bytes=new byte[cbl+value.length()+2]; - System.arraycopy(header.getBytesColonSpace(),0,_bytes,0,cbl); + _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'; diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java index dd44e531e32..fccc6229552 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.WritePendingException; +import java.util.Arrays; import java.util.EnumMap; import java.util.EnumSet; import java.util.Set; @@ -301,10 +302,7 @@ abstract public class WriteFlusher if (consumed == length) return EMPTY_BUFFERS; - int newLength = length - consumed; - ByteBuffer[] result = new ByteBuffer[newLength]; - System.arraycopy(buffers, consumed, result, 0, newLength); - return result; + return Arrays.copyOfRange(buffers,consumed,length); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 333aecdcc97..397cde1fd13 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -1214,20 +1214,17 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu _protectedTargets = null; return; } - - _protectedTargets = new String[targets.length]; - System.arraycopy(targets, 0, _protectedTargets, 0, targets.length); + + _protectedTargets = Arrays.copyOf(targets, targets.length); } /* ------------------------------------------------------------ */ - public String[] getProtectedTargets () + public String[] getProtectedTargets() { if (_protectedTargets == null) return null; - String[] tmp = new String[_protectedTargets.length]; - System.arraycopy(_protectedTargets, 0, tmp, 0, _protectedTargets.length); - return tmp; + return Arrays.copyOf(_protectedTargets, _protectedTargets.length); } diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java index e5cf6be9762..bf3dfa668a3 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java @@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -62,8 +63,7 @@ public class HeadersBlockGenerator for (int i = 1; i < values.size(); ++i) { byte[] moreValueBytes = values.get(i).getBytes(iso1); - byte[] newValueBytes = new byte[valueBytes.length + 1 + moreValueBytes.length]; - System.arraycopy(valueBytes, 0, newValueBytes, 0, valueBytes.length); + byte[] newValueBytes = Arrays.copyOf(valueBytes,valueBytes.length + 1 + moreValueBytes.length); newValueBytes[valueBytes.length] = 0; System.arraycopy(moreValueBytes, 0, newValueBytes, valueBytes.length + 1, moreValueBytes.length); valueBytes = newValueBytes; diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java index e0fdd564711..f597fbf15bc 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.spdy.parser; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.zip.ZipException; import org.eclipse.jetty.spdy.CompressionDictionary; @@ -114,16 +115,14 @@ public abstract class HeadersBlockParser int needed = length - accumulated; if (remaining < needed) { - byte[] local = new byte[accumulated + remaining]; - System.arraycopy(data, 0, local, 0, accumulated); + byte[] local = Arrays.copyOf(data,accumulated + remaining); buffer.get(local, accumulated, remaining); data = local; return false; } else { - byte[] local = new byte[length]; - System.arraycopy(data, 0, local, 0, accumulated); + byte[] local = Arrays.copyOf(data,length); buffer.get(local, accumulated, needed); data = local; return true; @@ -199,8 +198,7 @@ public abstract class HeadersBlockParser else { // Last pass needed to decompress, merge decompressed bytes - byte[] result = new byte[decompressed.length + count]; - System.arraycopy(decompressed, 0, result, 0, decompressed.length); + byte[] result = Arrays.copyOf(decompressed,decompressed.length+count); System.arraycopy(buffer, 0, result, decompressed.length, count); return ByteBuffer.wrap(result); } @@ -214,8 +212,7 @@ public abstract class HeadersBlockParser } else { - byte[] result = new byte[decompressed.length + buffer.length]; - System.arraycopy(decompressed, 0, result, 0, decompressed.length); + byte[] result = Arrays.copyOf(decompressed,decompressed.length+buffer.length); System.arraycopy(buffer, 0, result, decompressed.length, buffer.length); decompressed = result; } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java index d397716bcc0..fdca4ce1350 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.util; import java.nio.ByteBuffer; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -107,11 +108,12 @@ public class ArrayTernaryTrie extends AbstractTrie */ public ArrayTernaryTrie(ArrayTernaryTrie trie, double factor) { - this(trie.isCaseInsensitive(),(int)(trie._value.length*factor)); + super(trie.isCaseInsensitive()); + int capacity=(int)(trie._value.length*factor); _rows=trie._rows; - System.arraycopy(trie._value,0,_value,0,trie._value.length); - System.arraycopy(trie._tree,0,_tree,0,trie._tree.length); - System.arraycopy(trie._key,0,_key,0,trie._key.length); + _value=Arrays.copyOf(trie._value, capacity); + _tree=Arrays.copyOf(trie._tree, capacity*ROW_SIZE); + _key=Arrays.copyOf(trie._key, capacity); } /* ------------------------------------------------------------ */ diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java index 16d3701a2da..bd7cb06ecd1 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java @@ -30,6 +30,7 @@ import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import org.eclipse.jetty.util.resource.Resource; @@ -215,15 +216,18 @@ public class BufferUtil */ public static byte[] toArray(ByteBuffer buffer) { - byte[] to = new byte[buffer.remaining()]; if (buffer.hasArray()) { byte[] array = buffer.array(); - System.arraycopy(array, buffer.arrayOffset() + buffer.position(), to, 0, to.length); + int from=buffer.arrayOffset() + buffer.position(); + return Arrays.copyOfRange(array,from,from+buffer.remaining()); } else + { + byte[] to = new byte[buffer.remaining()]; buffer.slice().get(to); - return to; + return to; + } } /* ------------------------------------------------------------ */ @@ -1022,6 +1026,20 @@ public class BufferUtil return true; } + public static ByteBuffer ensureCapacity(ByteBuffer buffer, int capacity) + { + if (buffer==null) + return allocate(capacity); + + if (buffer.capacity()>=capacity) + return buffer; + + if (buffer.hasArray()) + return ByteBuffer.wrap(Arrays.copyOfRange(buffer.array(), buffer.arrayOffset(), buffer.arrayOffset()+capacity),buffer.position(),buffer.remaining()); + + throw new UnsupportedOperationException(); + } + } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java index cf1e23ffea1..80df88198be 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java @@ -22,6 +22,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; +import java.util.Arrays; /* ------------------------------------------------------------ */ @@ -253,19 +254,14 @@ public class ByteArrayISO8859Writer extends Writer { if (_fixed) throw new IOException("Buffer overflow: "+_buf.length); - byte[] buf = new byte[(_buf.length+n)*4/3]; - System.arraycopy(_buf,0,buf,0,_size); - _buf=buf; + _buf=Arrays.copyOf(_buf,(_buf.length+n)*4/3); } } - /* ------------------------------------------------------------ */ public byte[] getByteArray() { - byte[] data=new byte[_size]; - System.arraycopy(_buf,0,data,0,_size); - return data; + return Arrays.copyOf(_buf,_size); } } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java index 042d6b28b41..fbe60670368 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java @@ -289,6 +289,41 @@ public class BufferUtilTest int capacity = BufferUtil.TEMP_BUFFER_SIZE*2+1024; testWriteToWithBufferThatDoesNotExposeArray(capacity); } + + + @Test + public void testEnsureCapacity() throws Exception + { + ByteBuffer b = BufferUtil.toBuffer("Goodbye Cruel World"); + assertTrue(b==BufferUtil.ensureCapacity(b, 0)); + assertTrue(b==BufferUtil.ensureCapacity(b, 10)); + assertTrue(b==BufferUtil.ensureCapacity(b, b.capacity())); + + + ByteBuffer b1 = BufferUtil.ensureCapacity(b, 64); + assertTrue(b!=b1); + assertEquals(64, b1.capacity()); + assertEquals("Goodbye Cruel World", BufferUtil.toString(b1)); + + b1.position(8); + b1.limit(13); + assertEquals("Cruel", BufferUtil.toString(b1)); + ByteBuffer b2 = b1.slice(); + assertEquals("Cruel", BufferUtil.toString(b2)); + System.err.println(BufferUtil.toDetailString(b2)); + assertEquals(8, b2.arrayOffset()); + assertEquals(5, b2.capacity()); + + assertTrue(b2==BufferUtil.ensureCapacity(b2, 5)); + + ByteBuffer b3 = BufferUtil.ensureCapacity(b2, 64); + assertTrue(b2!=b3); + assertEquals(64, b3.capacity()); + assertEquals("Cruel", BufferUtil.toString(b3)); + assertEquals(0, b3.arrayOffset()); + + } + private void testWriteToWithBufferThatDoesNotExposeArray(int capacity) throws IOException { diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/masks/FixedMasker.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/masks/FixedMasker.java index 6f44aef8c59..2b3fc76f3b5 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/masks/FixedMasker.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/masks/FixedMasker.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.websocket.client.masks; +import java.util.Arrays; + import org.eclipse.jetty.websocket.common.WebSocketFrame; public class FixedMasker implements Masker @@ -32,10 +34,9 @@ public class FixedMasker implements Masker public FixedMasker(byte[] mask) { - this.mask = new byte[4]; // Copy to avoid that external code keeps a reference // to the array parameter to modify masking on-the-fly - System.arraycopy(mask,0,mask,0,4); + this.mask=Arrays.copyOf(mask, 4); } @Override diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketFrame.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketFrame.java index b4b811cd789..4ed27a08237 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketFrame.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketFrame.java @@ -154,10 +154,7 @@ public abstract class WebSocketFrame implements Frame masked = copy.masked; mask = null; if (copy.mask != null) - { - mask = new byte[copy.mask.length]; - System.arraycopy(copy.mask,0,mask,0,mask.length); - } + mask = Arrays.copyOf(copy.mask, copy.mask.length); } @Override diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/AbstractABCase.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/AbstractABCase.java index 1b282b93026..4d0930c2396 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/AbstractABCase.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/AbstractABCase.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.server.ab; import java.net.URI; import java.nio.ByteBuffer; +import java.util.Arrays; import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.util.BufferUtil; @@ -113,9 +114,7 @@ public abstract class AbstractABCase implements Fuzzed */ protected ByteBuffer copyOf(byte[] payload) { - byte copy[] = new byte[payload.length]; - System.arraycopy(payload,0,copy,0,payload.length); - return ByteBuffer.wrap(copy); + return ByteBuffer.wrap(Arrays.copyOf(payload,payload.length)); } /**