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 
     33 
     34 /**
     35  * This class is defined here rather than in java.nio.channels.Channels
     36  * so that code can be shared with SocketAdaptor.
     37  *
     38  * @author Mike McCloskey
     39  * @author Mark Reinhold
     40  * @since 1.4
     41  */
     42 
     43 public class ChannelInputStream
     44     extends InputStream
     45 {
     46 
     47     // Android-changed: This code didn't make sense. In particular, the block channel is
     48     // useless because we throw if the channel is non-blocking!. It would only make sense
     49     // if it's called on a blocking channel (but we're asked to make it non-blocking before
     50     // the read) we never do that, though.
     51     //
     52     // read(ReadableByteChannel,ByteBuffer, boolean block)
     53     public static int read(ReadableByteChannel ch, ByteBuffer bb)
     54         throws IOException
     55     {
     56         if (ch instanceof SelectableChannel) {
     57             SelectableChannel sc = (SelectableChannel)ch;
     58             synchronized (sc.blockingLock()) {
     59                 boolean bm = sc.isBlocking();
     60                 if (!bm)
     61                     throw new IllegalBlockingModeException();
     62                 // Android-removed.
     63                 // if (bm != block)
     64                 //    sc.configureBlocking(block);
     65                 int n = ch.read(bb);
     66                 // Android-removed.
     67                 // if (bm != block)
     68                 //     sc.configureBlocking(bm);
     69                 return n;
     70             }
     71         } else {
     72             return ch.read(bb);
     73         }
     74     }
     75 
     76     protected final ReadableByteChannel ch;
     77     private ByteBuffer bb = null;
     78     private byte[] bs = null;           // Invoker's previous array
     79     private byte[] b1 = null;
     80 
     81     public ChannelInputStream(ReadableByteChannel ch) {
     82         this.ch = ch;
     83     }
     84 
     85     public synchronized int read() throws IOException {
     86         if (b1 == null)
     87             b1 = new byte[1];
     88         int n = this.read(b1);
     89         if (n == 1)
     90             return b1[0] & 0xff;
     91         return -1;
     92     }
     93 
     94     public synchronized int read(byte[] bs, int off, int len)
     95         throws IOException
     96     {
     97         if ((off < 0) || (off > bs.length) || (len < 0) ||
     98             ((off + len) > bs.length) || ((off + len) < 0)) {
     99             throw new IndexOutOfBoundsException();
    100         } else if (len == 0)
    101             return 0;
    102 
    103         ByteBuffer bb = ((this.bs == bs)
    104                          ? this.bb
    105                          : ByteBuffer.wrap(bs));
    106         bb.limit(Math.min(off + len, bb.capacity()));
    107         bb.position(off);
    108         this.bb = bb;
    109         this.bs = bs;
    110         return read(bb);
    111     }
    112 
    113     protected int read(ByteBuffer bb)
    114         throws IOException
    115     {
    116         return ChannelInputStream.read(ch, bb);
    117     }
    118 
    119     public int available() throws IOException {
    120         // special case where the channel is to a file
    121         if (ch instanceof SeekableByteChannel) {
    122             SeekableByteChannel sbc = (SeekableByteChannel)ch;
    123             long rem = Math.max(0, sbc.size() - sbc.position());
    124             return (rem > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)rem;
    125         }
    126         return 0;
    127     }
    128 
    129     public void close() throws IOException {
    130         ch.close();
    131     }
    132 
    133 }
    134