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