1 /* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java $ 3 * $Revision: 576077 $ 4 * $Date: 2007-09-16 04:50:22 -0700 (Sun, 16 Sep 2007) $ 5 * 6 * ==================================================================== 7 * Licensed to the Apache Software Foundation (ASF) under one 8 * or more contributor license agreements. See the NOTICE file 9 * distributed with this work for additional information 10 * regarding copyright ownership. The ASF licenses this file 11 * to you under the Apache License, Version 2.0 (the 12 * "License"); you may not use this file except in compliance 13 * with the License. You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, 18 * software distributed under the License is distributed on an 19 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 20 * KIND, either express or implied. See the License for the 21 * specific language governing permissions and limitations 22 * under the License. 23 * ==================================================================== 24 * 25 * This software consists of voluntary contributions made by many 26 * individuals on behalf of the Apache Software Foundation. For more 27 * information on the Apache Software Foundation, please see 28 * <http://www.apache.org/>. 29 * 30 */ 31 32 package org.apache.http.impl.io; 33 34 import java.io.IOException; 35 import java.io.InputStream; 36 37 import org.apache.http.io.SessionInputBuffer; 38 import org.apache.http.io.HttpTransportMetrics; 39 import org.apache.http.params.CoreConnectionPNames; 40 import org.apache.http.params.HttpParams; 41 import org.apache.http.params.HttpProtocolParams; 42 import org.apache.http.protocol.HTTP; 43 import org.apache.http.util.ByteArrayBuffer; 44 import org.apache.http.util.CharArrayBuffer; 45 46 /** 47 * Abstract base class for session input buffers that stream data 48 * from a {@link InputStream}. 49 * 50 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> 51 * 52 * 53 * @deprecated Please use {@link java.net.URL#openConnection} instead. 54 * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> 55 * for further details. 56 */ 57 @Deprecated 58 public abstract class AbstractSessionInputBuffer implements SessionInputBuffer { 59 60 private InputStream instream; 61 private byte[] buffer; 62 private int bufferpos; 63 private int bufferlen; 64 65 private ByteArrayBuffer linebuffer = null; 66 67 private String charset = HTTP.US_ASCII; 68 private boolean ascii = true; 69 private int maxLineLen = -1; 70 71 private HttpTransportMetricsImpl metrics; 72 73 protected void init(final InputStream instream, int buffersize, final HttpParams params) { 74 if (instream == null) { 75 throw new IllegalArgumentException("Input stream may not be null"); 76 } 77 if (buffersize <= 0) { 78 throw new IllegalArgumentException("Buffer size may not be negative or zero"); 79 } 80 if (params == null) { 81 throw new IllegalArgumentException("HTTP parameters may not be null"); 82 } 83 this.instream = instream; 84 this.buffer = new byte[buffersize]; 85 this.bufferpos = 0; 86 this.bufferlen = 0; 87 this.linebuffer = new ByteArrayBuffer(buffersize); 88 this.charset = HttpProtocolParams.getHttpElementCharset(params); 89 this.ascii = this.charset.equalsIgnoreCase(HTTP.US_ASCII) 90 || this.charset.equalsIgnoreCase(HTTP.ASCII); 91 this.maxLineLen = params.getIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, -1); 92 this.metrics = new HttpTransportMetricsImpl(); 93 } 94 95 protected int fillBuffer() throws IOException { 96 // compact the buffer if necessary 97 if (this.bufferpos > 0) { 98 int len = this.bufferlen - this.bufferpos; 99 if (len > 0) { 100 System.arraycopy(this.buffer, this.bufferpos, this.buffer, 0, len); 101 } 102 this.bufferpos = 0; 103 this.bufferlen = len; 104 } 105 int l; 106 int off = this.bufferlen; 107 int len = this.buffer.length - off; 108 l = this.instream.read(this.buffer, off, len); 109 if (l == -1) { 110 return -1; 111 } else { 112 this.bufferlen = off + l; 113 this.metrics.incrementBytesTransferred(l); 114 return l; 115 } 116 } 117 118 protected boolean hasBufferedData() { 119 return this.bufferpos < this.bufferlen; 120 } 121 122 public int read() throws IOException { 123 int noRead = 0; 124 while (!hasBufferedData()) { 125 noRead = fillBuffer(); 126 if (noRead == -1) { 127 return -1; 128 } 129 } 130 return this.buffer[this.bufferpos++] & 0xff; 131 } 132 133 public int read(final byte[] b, int off, int len) throws IOException { 134 if (b == null) { 135 return 0; 136 } 137 int noRead = 0; 138 while (!hasBufferedData()) { 139 noRead = fillBuffer(); 140 if (noRead == -1) { 141 return -1; 142 } 143 } 144 int chunk = this.bufferlen - this.bufferpos; 145 if (chunk > len) { 146 chunk = len; 147 } 148 System.arraycopy(this.buffer, this.bufferpos, b, off, chunk); 149 this.bufferpos += chunk; 150 return chunk; 151 } 152 153 public int read(final byte[] b) throws IOException { 154 if (b == null) { 155 return 0; 156 } 157 return read(b, 0, b.length); 158 } 159 160 private int locateLF() { 161 for (int i = this.bufferpos; i < this.bufferlen; i++) { 162 if (this.buffer[i] == HTTP.LF) { 163 return i; 164 } 165 } 166 return -1; 167 } 168 169 public int readLine(final CharArrayBuffer charbuffer) throws IOException { 170 if (charbuffer == null) { 171 throw new IllegalArgumentException("Char array buffer may not be null"); 172 } 173 this.linebuffer.clear(); 174 int noRead = 0; 175 boolean retry = true; 176 while (retry) { 177 // attempt to find end of line (LF) 178 int i = locateLF(); 179 if (i != -1) { 180 // end of line found. 181 if (this.linebuffer.isEmpty()) { 182 // the entire line is preset in the read buffer 183 return lineFromReadBuffer(charbuffer, i); 184 } 185 retry = false; 186 int len = i + 1 - this.bufferpos; 187 this.linebuffer.append(this.buffer, this.bufferpos, len); 188 this.bufferpos = i + 1; 189 } else { 190 // end of line not found 191 if (hasBufferedData()) { 192 int len = this.bufferlen - this.bufferpos; 193 this.linebuffer.append(this.buffer, this.bufferpos, len); 194 this.bufferpos = this.bufferlen; 195 } 196 noRead = fillBuffer(); 197 if (noRead == -1) { 198 retry = false; 199 } 200 } 201 if (this.maxLineLen > 0 && this.linebuffer.length() >= this.maxLineLen) { 202 throw new IOException("Maximum line length limit exceeded"); 203 } 204 } 205 if (noRead == -1 && this.linebuffer.isEmpty()) { 206 // indicate the end of stream 207 return -1; 208 } 209 return lineFromLineBuffer(charbuffer); 210 } 211 212 private int lineFromLineBuffer(final CharArrayBuffer charbuffer) 213 throws IOException { 214 // discard LF if found 215 int l = this.linebuffer.length(); 216 if (l > 0) { 217 if (this.linebuffer.byteAt(l - 1) == HTTP.LF) { 218 l--; 219 this.linebuffer.setLength(l); 220 } 221 // discard CR if found 222 if (l > 0) { 223 if (this.linebuffer.byteAt(l - 1) == HTTP.CR) { 224 l--; 225 this.linebuffer.setLength(l); 226 } 227 } 228 } 229 l = this.linebuffer.length(); 230 if (this.ascii) { 231 charbuffer.append(this.linebuffer, 0, l); 232 } else { 233 // This is VERY memory inefficient, BUT since non-ASCII charsets are 234 // NOT meant to be used anyway, there's no point optimizing it 235 String s = new String(this.linebuffer.buffer(), 0, l, this.charset); 236 charbuffer.append(s); 237 } 238 return l; 239 } 240 241 private int lineFromReadBuffer(final CharArrayBuffer charbuffer, int pos) 242 throws IOException { 243 int off = this.bufferpos; 244 int len; 245 this.bufferpos = pos + 1; 246 // BEGIN android-changed 247 // The first test below was fixed to not try to skip beyond the 248 // start of the live part of the buffer. 249 if (pos > off && this.buffer[pos - 1] == HTTP.CR) { 250 // skip CR if found 251 pos--; 252 } 253 // END android-changed 254 len = pos - off; 255 if (this.ascii) { 256 charbuffer.append(this.buffer, off, len); 257 } else { 258 // This is VERY memory inefficient, BUT since non-ASCII charsets are 259 // NOT meant to be used anyway, there's no point optimizing it 260 String s = new String(this.buffer, off, len, this.charset); 261 charbuffer.append(s); 262 } 263 return len; 264 } 265 266 public String readLine() throws IOException { 267 CharArrayBuffer charbuffer = new CharArrayBuffer(64); 268 int l = readLine(charbuffer); 269 if (l != -1) { 270 return charbuffer.toString(); 271 } else { 272 return null; 273 } 274 } 275 276 public HttpTransportMetrics getMetrics() { 277 return this.metrics; 278 } 279 280 } 281