Home | History | Annotate | Download | only in ch
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 2001, 2002, 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 
     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 
     48     // Android-changed : This code didn't make sense. In particular, the block channel is
     49     // useless because we throw if the channel is non-blocking!. It would only make sense
     50     // if it's called on a blocking channel (but we're asked to make it non-blocking before
     51     // the read) we never do that, though.
     52     //
     53     // read(ReadableByteChannel,ByteBuffer, boolean block)
     54     public static int read(ReadableByteChannel ch, ByteBuffer bb)
     55         throws IOException
     56     {
     57         if (ch instanceof SelectableChannel) {
     58             SelectableChannel sc = (SelectableChannel)ch;
     59             synchronized (sc.blockingLock()) {
     60                 boolean bm = sc.isBlocking();
     61                 if (!bm)
     62                     throw new IllegalBlockingModeException();
     63                 // Android removed.
     64                 // if (bm != block)
     65                 //    sc.configureBlocking(block);
     66                 int n = ch.read(bb);
     67                 // Android removed.
     68                 // if (bm != block)
     69                 //     sc.configureBlocking(bm);
     70                 return n;
     71             }
     72         } else {
     73             return ch.read(bb);
     74         }
     75     }
     76 
     77     protected final ReadableByteChannel ch;
     78     private ByteBuffer bb = null;
     79     private byte[] bs = null;           // Invoker's previous array
     80     private byte[] b1 = null;
     81 
     82     public ChannelInputStream(ReadableByteChannel ch) {
     83         this.ch = ch;
     84     }
     85 
     86     public synchronized int read() throws IOException {
     87         if (b1 == null)
     88             b1 = new byte[1];
     89         int n = this.read(b1);
     90         if (n == 1)
     91             return b1[0] & 0xff;
     92         return -1;
     93     }
     94 
     95     public synchronized int read(byte[] bs, int off, int len)
     96         throws IOException
     97     {
     98         if ((off < 0) || (off > bs.length) || (len < 0) ||
     99             ((off + len) > bs.length) || ((off + len) < 0)) {
    100             throw new IndexOutOfBoundsException();
    101         } else if (len == 0)
    102             return 0;
    103 
    104         ByteBuffer bb = ((this.bs == bs)
    105                          ? this.bb
    106                          : ByteBuffer.wrap(bs));
    107         bb.limit(Math.min(off + len, bb.capacity()));
    108         bb.position(off);
    109         this.bb = bb;
    110         this.bs = bs;
    111         return read(bb);
    112     }
    113 
    114     protected int read(ByteBuffer bb)
    115         throws IOException
    116     {
    117         return ChannelInputStream.read(ch, bb);
    118     }
    119 
    120     public int available() throws IOException {
    121         // special case where the channel is to a file
    122         if (ch instanceof SeekableByteChannel) {
    123             SeekableByteChannel sbc = (SeekableByteChannel)ch;
    124             long rem = Math.max(0, sbc.size() - sbc.position());
    125             return (rem > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)rem;
    126         }
    127         return 0;
    128     }
    129 
    130     public void close() throws IOException {
    131         ch.close();
    132     }
    133 
    134 }
    135