View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.buffer;
17  
18  import io.netty.util.internal.StringUtil;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.nio.ByteBuffer;
24  import java.nio.ByteOrder;
25  import java.nio.ReadOnlyBufferException;
26  import java.nio.channels.FileChannel;
27  import java.nio.channels.GatheringByteChannel;
28  import java.nio.channels.ScatteringByteChannel;
29  
30  
31  /**
32   * Read-only ByteBuf which wraps a read-only ByteBuffer.
33   */
34  class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf {
35  
36      protected final ByteBuffer buffer;
37      private final ByteBufAllocator allocator;
38      private ByteBuffer tmpNioBuf;
39  
40      ReadOnlyByteBufferBuf(ByteBufAllocator allocator, ByteBuffer buffer) {
41          super(buffer.remaining());
42          if (!buffer.isReadOnly()) {
43              throw new IllegalArgumentException("must be a readonly buffer: " + StringUtil.simpleClassName(buffer));
44          }
45  
46          this.allocator = allocator;
47          this.buffer = buffer.slice().order(ByteOrder.BIG_ENDIAN);
48          writerIndex(this.buffer.limit());
49      }
50  
51      @Override
52      protected void deallocate() { }
53  
54      @Override
55      public boolean isWritable() {
56          return false;
57      }
58  
59      @Override
60      public boolean isWritable(int numBytes) {
61          return false;
62      }
63  
64      @Override
65      public ByteBuf ensureWritable(int minWritableBytes) {
66          throw new ReadOnlyBufferException();
67      }
68  
69      @Override
70      public int ensureWritable(int minWritableBytes, boolean force) {
71          return 1;
72      }
73  
74      @Override
75      public byte getByte(int index) {
76          ensureAccessible();
77          return _getByte(index);
78      }
79  
80      @Override
81      protected byte _getByte(int index) {
82          return buffer.get(index);
83      }
84  
85      @Override
86      public short getShort(int index) {
87          ensureAccessible();
88          return _getShort(index);
89      }
90  
91      @Override
92      protected short _getShort(int index) {
93          return buffer.getShort(index);
94      }
95  
96      @Override
97      public short getShortLE(int index) {
98          ensureAccessible();
99          return _getShortLE(index);
100     }
101 
102     @Override
103     protected short _getShortLE(int index) {
104         return ByteBufUtil.swapShort(buffer.getShort(index));
105     }
106 
107     @Override
108     public int getUnsignedMedium(int index) {
109         ensureAccessible();
110         return _getUnsignedMedium(index);
111     }
112 
113     @Override
114     protected int _getUnsignedMedium(int index) {
115         return (getByte(index) & 0xff)     << 16 |
116                (getByte(index + 1) & 0xff) << 8  |
117                getByte(index + 2) & 0xff;
118     }
119 
120     @Override
121     public int getUnsignedMediumLE(int index) {
122         ensureAccessible();
123         return _getUnsignedMediumLE(index);
124     }
125 
126     @Override
127     protected int _getUnsignedMediumLE(int index) {
128         return getByte(index)      & 0xff       |
129                (getByte(index + 1) & 0xff) << 8 |
130                (getByte(index + 2) & 0xff) << 16;
131     }
132 
133     @Override
134     public int getInt(int index) {
135         ensureAccessible();
136         return _getInt(index);
137     }
138 
139     @Override
140     protected int _getInt(int index) {
141         return buffer.getInt(index);
142     }
143 
144     @Override
145     public int getIntLE(int index) {
146         ensureAccessible();
147         return _getIntLE(index);
148     }
149 
150     @Override
151     protected int _getIntLE(int index) {
152         return ByteBufUtil.swapInt(buffer.getInt(index));
153     }
154 
155     @Override
156     public long getLong(int index) {
157         ensureAccessible();
158         return _getLong(index);
159     }
160 
161     @Override
162     protected long _getLong(int index) {
163         return buffer.getLong(index);
164     }
165 
166     @Override
167     public long getLongLE(int index) {
168         ensureAccessible();
169         return _getLongLE(index);
170     }
171 
172     @Override
173     protected long _getLongLE(int index) {
174         return ByteBufUtil.swapLong(buffer.getLong(index));
175     }
176 
177     @Override
178     public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
179         return getBytes(index, dst, dstIndex, length, false);
180     }
181 
182     @Override
183     public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
184         checkReadableBytes(length);
185         getBytes(readerIndex, dst, dstIndex, length, true);
186         readerIndex += length;
187         return this;
188     }
189 
190     protected ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length, boolean internal) {
191         checkDstIndex(index, length, dstIndex, dst.capacity());
192         if (dst.hasArray()) {
193             getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
194         } else if (dst.nioBufferCount() > 0) {
195             for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
196                 int bbLen = bb.remaining();
197                 getBytes(index, bb, internal);
198                 index += bbLen;
199             }
200         } else {
201             dst.setBytes(dstIndex, this, index, length);
202         }
203         return this;
204     }
205 
206     @Override
207     public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
208         return getBytes(index, dst, dstIndex, length, false);
209     }
210 
211     @Override
212     public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
213         checkReadableBytes(length);
214         getBytes(readerIndex, dst, dstIndex, length, true);
215         readerIndex += length;
216         return this;
217     }
218 
219     protected ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) {
220         checkDstIndex(index, length, dstIndex, dst.length);
221 
222         final ByteBuffer tmpBuf = nioBuffer(internal);
223         tmpBuf.clear().position(index).limit(index + length);
224         tmpBuf.get(dst, dstIndex, length);
225         return this;
226     }
227 
228     @Override
229     public ByteBuf getBytes(int index, ByteBuffer dst) {
230         return getBytes(index, dst, false);
231     }
232 
233     @Override
234     public ByteBuf readBytes(ByteBuffer dst) {
235         int length = dst.remaining();
236         checkReadableBytes(length);
237         getBytes(readerIndex, dst, true);
238         readerIndex += length;
239         return this;
240     }
241 
242     private ByteBuf getBytes(int index, ByteBuffer dst, boolean internal) {
243         checkIndex(index, dst.remaining());
244 
245         final ByteBuffer tmpBuf = nioBuffer(internal);
246         tmpBuf.clear().position(index).limit(index + dst.remaining());
247         dst.put(tmpBuf);
248         return this;
249     }
250 
251     @Override
252     public ByteBuf setByte(int index, int value) {
253         throw new ReadOnlyBufferException();
254     }
255 
256     @Override
257     protected void _setByte(int index, int value) {
258         throw new ReadOnlyBufferException();
259     }
260 
261     @Override
262     public ByteBuf setShort(int index, int value) {
263         throw new ReadOnlyBufferException();
264     }
265 
266     @Override
267     protected void _setShort(int index, int value) {
268         throw new ReadOnlyBufferException();
269     }
270 
271     @Override
272     public ByteBuf setShortLE(int index, int value) {
273         throw new ReadOnlyBufferException();
274     }
275 
276     @Override
277     protected void _setShortLE(int index, int value) {
278         throw new ReadOnlyBufferException();
279     }
280 
281     @Override
282     public ByteBuf setMedium(int index, int value) {
283         throw new ReadOnlyBufferException();
284     }
285 
286     @Override
287     protected void _setMedium(int index, int value) {
288         throw new ReadOnlyBufferException();
289     }
290 
291     @Override
292     public ByteBuf setMediumLE(int index, int value) {
293         throw new ReadOnlyBufferException();
294     }
295 
296     @Override
297     protected void _setMediumLE(int index, int value) {
298         throw new ReadOnlyBufferException();
299     }
300 
301     @Override
302     public ByteBuf setInt(int index, int value) {
303         throw new ReadOnlyBufferException();
304     }
305 
306     @Override
307     protected void _setInt(int index, int value) {
308         throw new ReadOnlyBufferException();
309     }
310 
311     @Override
312     public ByteBuf setIntLE(int index, int value) {
313         throw new ReadOnlyBufferException();
314     }
315 
316     @Override
317     protected void _setIntLE(int index, int value) {
318         throw new ReadOnlyBufferException();
319     }
320 
321     @Override
322     public ByteBuf setLong(int index, long value) {
323         throw new ReadOnlyBufferException();
324     }
325 
326     @Override
327     protected void _setLong(int index, long value) {
328         throw new ReadOnlyBufferException();
329     }
330 
331     @Override
332     public ByteBuf setLongLE(int index, long value) {
333         throw new ReadOnlyBufferException();
334     }
335 
336     @Override
337     protected void _setLongLE(int index, long value) {
338         throw new ReadOnlyBufferException();
339     }
340 
341     @Override
342     public int capacity() {
343         return maxCapacity();
344     }
345 
346     @Override
347     public ByteBuf capacity(int newCapacity) {
348         throw new ReadOnlyBufferException();
349     }
350 
351     @Override
352     public ByteBufAllocator alloc() {
353         return allocator;
354     }
355 
356     @Override
357     public ByteOrder order() {
358         return ByteOrder.BIG_ENDIAN;
359     }
360 
361     @Override
362     public ByteBuf unwrap() {
363         return null;
364     }
365 
366     @Override
367     public boolean isReadOnly() {
368         return buffer.isReadOnly();
369     }
370 
371     @Override
372     public boolean isDirect() {
373         return buffer.isDirect();
374     }
375 
376     @Override
377     public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
378         return getBytes(index, out, length, false);
379     }
380 
381     @Override
382     public ByteBuf readBytes(OutputStream out, int length) throws IOException {
383         checkReadableBytes(length);
384         getBytes(readerIndex, out, length, true);
385         readerIndex += length;
386         return this;
387     }
388 
389     private ByteBuf getBytes(int index, OutputStream out, int length, boolean internal) throws IOException {
390         ensureAccessible();
391         if (length == 0) {
392             return this;
393         }
394 
395         if (buffer.hasArray()) {
396             out.write(buffer.array(), index + buffer.arrayOffset(), length);
397         } else {
398             byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
399             ByteBuffer tmpBuf = nioBuffer(internal);
400             tmpBuf.clear().position(index);
401             tmpBuf.get(tmp, 0, length);
402             out.write(tmp, 0, length);
403         }
404         return this;
405     }
406 
407     @Override
408     public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
409         return getBytes(index, out, length, false);
410     }
411 
412     @Override
413     public int readBytes(GatheringByteChannel out, int length) throws IOException {
414         checkReadableBytes(length);
415         int readBytes = getBytes(readerIndex, out, length, true);
416         readerIndex += readBytes;
417         return readBytes;
418     }
419 
420     private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
421         ensureAccessible();
422         if (length == 0) {
423             return 0;
424         }
425 
426         ByteBuffer tmpBuf = nioBuffer(internal);
427         tmpBuf.clear().position(index).limit(index + length);
428         return out.write(tmpBuf);
429     }
430 
431     @Override
432     public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
433         return getBytes(index, out, position, length, false);
434     }
435 
436     @Override
437     public int readBytes(FileChannel out, long position, int length) throws IOException {
438         checkReadableBytes(length);
439         int readBytes = getBytes(readerIndex, out, position, length, true);
440         readerIndex += readBytes;
441         return readBytes;
442     }
443 
444     private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
445         ensureAccessible();
446         if (length == 0) {
447             return 0;
448         }
449 
450         ByteBuffer tmpBuf = nioBuffer(internal);
451         tmpBuf.clear().position(index).limit(index + length);
452         return out.write(tmpBuf, position);
453     }
454 
455     @Override
456     public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
457         throw new ReadOnlyBufferException();
458     }
459 
460     @Override
461     public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
462         throw new ReadOnlyBufferException();
463     }
464 
465     @Override
466     public ByteBuf setBytes(int index, ByteBuffer src) {
467         throw new ReadOnlyBufferException();
468     }
469 
470     @Override
471     public int setBytes(int index, InputStream in, int length) throws IOException {
472         throw new ReadOnlyBufferException();
473     }
474 
475     @Override
476     public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
477         throw new ReadOnlyBufferException();
478     }
479 
480     @Override
481     public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
482         throw new ReadOnlyBufferException();
483     }
484 
485     protected final ByteBuffer internalNioBuffer() {
486         ByteBuffer tmpNioBuf = this.tmpNioBuf;
487         if (tmpNioBuf == null) {
488             this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
489         }
490         return tmpNioBuf;
491     }
492 
493     @Override
494     public ByteBuf copy(int index, int length) {
495         ensureAccessible();
496         ByteBuffer src;
497         try {
498             // Always duplicate the buffer so it's safe to call copy from multiple threads.
499             src = (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length);
500         } catch (IllegalArgumentException ignored) {
501             throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
502         }
503 
504         ByteBuf dst = src.isDirect() ? alloc().directBuffer(length) : alloc().heapBuffer(length);
505         dst.writeBytes(src);
506         return dst;
507     }
508 
509     @Override
510     public int nioBufferCount() {
511         return 1;
512     }
513 
514     @Override
515     public ByteBuffer[] nioBuffers(int index, int length) {
516         return new ByteBuffer[] { nioBuffer(index, length) };
517     }
518 
519     @Override
520     public ByteBuffer nioBuffer(int index, int length) {
521         checkIndex(index, length);
522         return (ByteBuffer) buffer.duplicate().position(index).limit(index + length);
523     }
524 
525     @Override
526     public ByteBuffer internalNioBuffer(int index, int length) {
527         ensureAccessible();
528         return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
529     }
530 
531     @Override
532     public final boolean isContiguous() {
533         return true;
534     }
535 
536     @Override
537     public boolean hasArray() {
538         return buffer.hasArray();
539     }
540 
541     @Override
542     public byte[] array() {
543         return buffer.array();
544     }
545 
546     @Override
547     public int arrayOffset() {
548         return buffer.arrayOffset();
549     }
550 
551     @Override
552     public boolean hasMemoryAddress() {
553         return false;
554     }
555 
556     @Override
557     public long memoryAddress() {
558         throw new UnsupportedOperationException();
559     }
560 
561     private ByteBuffer nioBuffer(boolean internal) {
562         return internal ? internalNioBuffer() : buffer.duplicate();
563     }
564 
565     @Override
566     public ByteBuf duplicate() {
567         return new ReadOnlyDuplicatedByteBuf(this);
568     }
569 
570     @Override
571     public ByteBuf slice(int index, int length) {
572         return new ReadOnlySlicedByteBuf(this, index, length);
573     }
574 
575     @Override
576     public ByteBuf asReadOnly() {
577         return this;
578     }
579 
580     @SuppressWarnings("deprecation")
581     private static final class ReadOnlySlicedByteBuf extends SlicedByteBuf {
582         ReadOnlySlicedByteBuf(ByteBuf buffer, int index, int length) {
583             super(buffer, index, length);
584         }
585 
586         @Override
587         public ByteBuf asReadOnly() {
588             return this;
589         }
590 
591         @Override
592         public ByteBuf slice(int index, int length) {
593             return new ReadOnlySlicedByteBuf(this, index, length);
594         }
595 
596         @Override
597         public ByteBuf duplicate() {
598             return slice(0, capacity()).setIndex(readerIndex(), writerIndex());
599         }
600 
601         @Override
602         public boolean isWritable() {
603             return false;
604         }
605 
606         @Override
607         public boolean isWritable(int numBytes) {
608             return false;
609         }
610 
611         @Override
612         public int ensureWritable(int minWritableBytes, boolean force) {
613             return 1;
614         }
615     }
616 
617     @SuppressWarnings("deprecation")
618     private static final class ReadOnlyDuplicatedByteBuf extends DuplicatedByteBuf {
619         ReadOnlyDuplicatedByteBuf(ByteBuf buffer) {
620             super(buffer);
621         }
622 
623         @Override
624         public ByteBuf asReadOnly() {
625             return this;
626         }
627 
628         @Override
629         public ByteBuf slice(int index, int length) {
630             return new ReadOnlySlicedByteBuf(this, index, length);
631         }
632 
633         @Override
634         public ByteBuf duplicate() {
635             return new ReadOnlyDuplicatedByteBuf(this);
636         }
637 
638         @Override
639         public boolean isWritable() {
640             return false;
641         }
642 
643         @Override
644         public boolean isWritable(int numBytes) {
645             return false;
646         }
647 
648         @Override
649         public int ensureWritable(int minWritableBytes, boolean force) {
650             return 1;
651         }
652     }
653 }