1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package sun.nio.ch; 28 29 import java.io.*; 30 import java.nio.*; 31 import java.nio.channels.*; 32 import java.nio.channels.spi.*; 33 import java.util.Objects; 34 35 /** 36 * This class is defined here rather than in java.nio.channels.Channels 37 * so that code can be shared with SocketAdaptor. 38 * 39 * @author Mike McCloskey 40 * @author Mark Reinhold 41 * @since 1.4 42 */ 43 44 public class ChannelInputStream 45 extends InputStream 46 { 47 read(ReadableByteChannel ch, ByteBuffer bb, boolean block)48 public static int read(ReadableByteChannel ch, ByteBuffer bb, 49 boolean block) 50 throws IOException 51 { 52 if (ch instanceof SelectableChannel) { 53 SelectableChannel sc = (SelectableChannel)ch; 54 synchronized (sc.blockingLock()) { 55 boolean bm = sc.isBlocking(); 56 if (!bm) 57 throw new IllegalBlockingModeException(); 58 if (bm != block) 59 sc.configureBlocking(block); 60 int n = ch.read(bb); 61 if (bm != block) 62 sc.configureBlocking(bm); 63 return n; 64 } 65 } else { 66 return ch.read(bb); 67 } 68 } 69 70 protected final ReadableByteChannel ch; 71 private ByteBuffer bb = null; 72 private byte[] bs = null; // Invoker's previous array 73 private byte[] b1 = null; 74 ChannelInputStream(ReadableByteChannel ch)75 public ChannelInputStream(ReadableByteChannel ch) { 76 this.ch = ch; 77 } 78 read()79 public synchronized int read() throws IOException { 80 if (b1 == null) 81 b1 = new byte[1]; 82 int n = this.read(b1); 83 if (n == 1) 84 return b1[0] & 0xff; 85 return -1; 86 } 87 read(byte[] bs, int off, int len)88 public synchronized int read(byte[] bs, int off, int len) 89 throws IOException 90 { 91 Objects.checkFromIndexSize(off, len, bs.length); 92 if (len == 0) 93 return 0; 94 95 ByteBuffer bb = ((this.bs == bs) 96 ? this.bb 97 : ByteBuffer.wrap(bs)); 98 bb.limit(Math.min(off + len, bb.capacity())); 99 bb.position(off); 100 this.bb = bb; 101 this.bs = bs; 102 return read(bb); 103 } 104 read(ByteBuffer bb)105 protected int read(ByteBuffer bb) 106 throws IOException 107 { 108 return ChannelInputStream.read(ch, bb, true); 109 } 110 available()111 public int available() throws IOException { 112 // special case where the channel is to a file 113 if (ch instanceof SeekableByteChannel) { 114 SeekableByteChannel sbc = (SeekableByteChannel)ch; 115 long rem = Math.max(0, sbc.size() - sbc.position()); 116 return (rem > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)rem; 117 } 118 return 0; 119 } 120 skip(long n)121 public synchronized long skip(long n) throws IOException { 122 // special case where the channel is to a file 123 if (ch instanceof SeekableByteChannel) { 124 SeekableByteChannel sbc = (SeekableByteChannel)ch; 125 long pos = sbc.position(); 126 long newPos; 127 if (n > 0) { 128 newPos = pos + n; 129 long size = sbc.size(); 130 if (newPos < 0 || newPos > size) { 131 newPos = size; 132 } 133 } else { 134 newPos = Long.max(pos + n, 0); 135 } 136 sbc.position(newPos); 137 return newPos - pos; 138 } 139 return super.skip(n); 140 } 141 close()142 public void close() throws IOException { 143 ch.close(); 144 } 145 146 } 147