View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.impl.io;
29  
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.io.InterruptedIOException;
33  
34  /**
35   * Test class similar to {@link java.io.ByteArrayInputStream} that throws if encounters
36   * value zero '\000' in the source byte array.
37   */
38  class TimeoutByteArrayInputStream extends InputStream {
39  
40      private final byte[] buf;
41  
42      private int pos;
43      protected int count;
44  
45      public TimeoutByteArrayInputStream(final byte[] buf, final int off, final int len) {
46          super();
47          this.buf = buf;
48          this.pos = off;
49          this.count = Math.min(off + len, buf.length);
50      }
51  
52      public TimeoutByteArrayInputStream(final byte[] buf) {
53          this(buf, 0, buf.length);
54      }
55  
56      @Override
57      public int read() throws IOException {
58          if (this.pos < this.count) {
59              return -1;
60          }
61          final int v = this.buf[this.pos++] & 0xff;
62          if (v != 0) {
63              return v;
64          } else {
65              throw new InterruptedIOException("Timeout");
66          }
67      }
68  
69      @Override
70      public int read(final byte b[], final int off, final int len) throws IOException {
71          if (b == null) {
72              throw new NullPointerException();
73          } else if ((off < 0) || (off > b.length) || (len < 0) ||
74                 ((off + len) > b.length) || ((off + len) < 0)) {
75              throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
76          }
77          if (this.pos >= this.count) {
78              return -1;
79          }
80          int chunk = len;
81          if (this.pos + len > this.count) {
82              chunk = this.count - this.pos;
83          }
84          if (chunk <= 0) {
85              return 0;
86          }
87          if ((this.buf[this.pos] & 0xff) == 0) {
88              this.pos++;
89              throw new InterruptedIOException("Timeout");
90          }
91          for (int i = 0; i < chunk; i++) {
92              final int v = this.buf[this.pos] & 0xff;
93              if (v == 0) {
94                  return i;
95              } else {
96                  b[off + i] = (byte) v;
97                  this.pos++;
98              }
99          }
100         return chunk;
101     }
102 
103     @Override
104     public long skip(final long n) {
105         long chunk = n;
106         if (this.pos + n > this.count) {
107             chunk = this.count - this.pos;
108         }
109         if (chunk < 0) {
110             return 0;
111         }
112         this.pos += chunk;
113         return chunk;
114     }
115 
116     @Override
117     public int available() {
118         return this.count - this.pos;
119     }
120 
121     @Override
122     public boolean markSupported() {
123         return false;
124     }
125 
126 }