2 * @(#)FCGIInputStream.java
4 * FastCGi compatibility package Interface
7 * Copyright (c) 1996 Open Market, Inc.
9 * See the file "LICENSE" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 * $Id: FCGIInputStream.java,v 1.4 2000/03/21 12:12:25 robs Exp $
19 * This stream manages buffered reads of FCGI messages.
21 public class FCGIInputStream extends InputStream
23 private static final String RCSID = "$Id: FCGIInputStream.java,v 1.4 2000/03/21 12:12:25 robs Exp $";
29 public boolean isClosed;
31 /* require methods to set, get and clear */
33 private Exception errex;
41 public int contentLen;
42 public int paddingLen;
44 public boolean eorStop;
45 public FCGIRequest request;
47 public InputStream in;
51 * Creates a new input stream to manage fcgi prototcol stuff
52 * @param in the input stream bufLen length of buffer streamType
54 public FCGIInputStream(FileInputStream inStream, int bufLen,
59 buffLen = Math.min(bufLen,FCGIGlobalDefs.def_FCGIMaxLen);
60 buff = new byte[buffLen];
62 stop = rdNext = buffStop = 0;
72 * Reads a byte of data. This method will block if no input is
74 * @return the byte read, or -1 if the end of the
76 * @exception IOException If an I/O error has occurred.
78 public int read() throws IOException {
80 return buff[rdNext++] & 0xff;
87 return buff[rdNext++] & 0xff;
92 * Reads into an array of bytes. This method will
93 * block until some input is available.
94 * @param b the buffer into which the data is read
95 * @return the actual number of bytes read, -1 is
96 * returned when the end of the stream is reached.
97 * @exception IOException If an I/O error has occurred.
99 public int read(byte b[]) throws IOException {
100 return read(b, 0, b.length);
104 * Reads into an array of bytes.
105 * Blocks until some input is available.
106 * @param b the buffer into which the data is read
107 * @param off the start offset of the data
108 * @param len the maximum number of bytes read
109 * @return the actual number of bytes read, -1 is
110 * returned when the end of the stream is reached.
111 * @exception IOException If an I/O error has occurred.
113 public int read(byte b[], int off, int len) throws IOException {
120 *Fast path: len bytes already available.
123 if (len <= stop - rdNext){
124 System.arraycopy(buff, rdNext, b, off, len);
129 *General case: stream is closed or fill needs to be called
134 m = Math.min(len - bytesMoved, stop - rdNext);
135 System.arraycopy(buff, rdNext, b, off, m);
138 if (bytesMoved == len)
150 * Reads into an array of bytes. This method will
151 * block until some input is available.
152 * @param b the buffer into which the data is read
153 * @param off the start offset of the data
154 * @param len the maximum number of bytes read
155 * @return the actual number of bytes read, -1 is
156 * returned when the end of the stream is reached.
157 * @exception IOException If an I/O error has occurred.
159 public void fill() throws IOException {
160 byte[] headerBuf = new byte[FCGIGlobalDefs.def_FCGIHeaderLen];
166 * If buffer is empty, do a read
168 if (rdNext == buffStop) {
170 count = in.read(buff, 0, buffLen);
171 } catch (IOException e) {
176 setFCGIError(FCGIGlobalDefs.def_FCGIProtocolError);
180 buffStop = count; // 1 more than we read
182 /* Now buf is not empty: If the current record contains more content
183 * bytes, deliver all that are present in buff to callers buffer
184 * unless he asked for less than we have, in which case give him less
186 if (contentLen > 0) {
187 count = Math.min(contentLen, buffStop - rdNext);
190 stop = rdNext + count;
195 if (contentLen > 0) {
203 /* Content has been consumed by client.
204 * If record was padded, skip over padding
206 if (paddingLen > 0) {
207 count = Math.min(paddingLen, buffStop - rdNext);
210 if (paddingLen > 0) {
211 continue; // more padding to read
214 /* All done with current record, including the padding.
215 * If we are in a recursive call from Process Header, deliver EOF
223 * Fill header with bytes from input buffer - get the whole header.
225 count = Math.min(headerBuf.length - headerLen, buffStop - rdNext);
226 System.arraycopy(buff,rdNext, headerBuf, headerLen, count);
229 if (headerLen < headerBuf.length) {
234 * Interperet the header. eorStop prevents ProcessHeader from
235 * reading past the end of record when using stream to read content
240 status = new FCGIMessage(this).processHeader(headerBuf);
244 case FCGIGlobalDefs.def_FCGIStreamRecord:
245 if (contentLen == 0) {
251 case FCGIGlobalDefs.def_FCGISkip:
254 case FCGIGlobalDefs.def_FCGIBeginRecord:
256 * If this header marked the beginning of a new
257 * request, return role info to caller
260 case FCGIGlobalDefs.def_FCGIMgmtRecord:
266 setFCGIError(status);
274 * Skips n bytes of input.
275 * @param n the number of bytes to be skipped
276 * @return the actual number of bytes skipped.
277 * @exception IOException If an I/O error has occurred.
279 public long skip(long n) throws IOException {
280 byte data[] = new byte[(int)n];
281 return in.read(data);
285 * An FCGI error has occurred. Save the error code in the stream
286 * for diagnostic purposes and set the stream state so that
289 public void setFCGIError(int errnum) {
291 * Preserve only the first error.
299 * An Exception has occurred. Save the Exception in the stream
300 * for diagnostic purposes and set the stream state so that
303 public void setException(Exception errexpt) {
305 * Preserve only the first error.
314 * Clear the stream error code and end-of-file indication.
316 public void clearFCGIError() {
320 * XXX: should clear isClosed but work is needed to make it safe
325 * Clear the stream error code and end-of-file indication.
327 public void clearException() {
331 * XXX: should clear isClosed but work is needed to make it safe
337 * accessor method since var is private
339 public int getFCGIError() {
343 * accessor method since var is private
345 public Exception getException() {
349 * Re-initializes the stream to read data of the specified type.
351 public void setReaderType(int streamType) {
363 * Close the stream. This method does not really exist for BufferedInputStream in java,
364 * but is implemented here for compatibility with the FCGI structures being used. It
365 * doent really throw any IOExceptions either, but that's there for compatiblity with
366 * the InputStreamInterface.
368 public void close() throws IOException{
374 * Returns the number of bytes that can be read without blocking.
377 public int available() throws IOException {
378 return stop - rdNext + in.available();