Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/http/impl/io/AbstractHttpDataReceiver.java


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