2 * @(#)FCGIInputStream.java
4 * FastCGi compatibility package Interface
7 * Copyright (c) 1996 Open Market, Inc.
9 * See the file "LICENSE.TERMS" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 * $Id: FCGIInputStream.java,v 1.1 1999/01/31 02:45:49 roberts Exp $
17 import FCGIGlobalDefs;
20 * This stream manages buffered reads of FCGI messages.
22 public class FCGIInputStream extends InputStream {
28 public boolean isClosed;
30 /* require methods to set, get and clear */
32 private Exception errex;
40 public int contentLen;
41 public int paddingLen;
43 public boolean eorStop;
44 public FCGIRequest request;
46 public InputStream in;
50 * Creates a new input stream to manage fcgi prototcol stuff
51 * @param in the input stream bufLen length of buffer streamType
53 public FCGIInputStream(FileInputStream inStream, int bufLen,
58 buffLen = Math.min(bufLen,FCGIGlobalDefs.def_FCGIMaxLen);
59 buff = new byte[buffLen];
61 stop = rdNext = buffStop = 0;
71 * Reads a byte of data. This method will block if no input is
73 * @return the byte read, or -1 if the end of the
75 * @exception IOException If an I/O error has occurred.
77 public int read() throws IOException {
79 return buff[rdNext++];
86 return buff[rdNext++];
91 * Reads into an array of bytes. This method will
92 * block until some input is available.
93 * @param b the buffer into which the data is read
94 * @return the actual number of bytes read, -1 is
95 * returned when the end of the stream is reached.
96 * @exception IOException If an I/O error has occurred.
98 public int read(byte b[]) throws IOException {
99 return read(b, 0, b.length);
103 * Reads into an array of bytes.
104 * Blocks until some input is available.
105 * @param b the buffer into which the data is read
106 * @param off the start offset of the data
107 * @param len the maximum number of bytes read
108 * @return the actual number of bytes read, -1 is
109 * returned when the end of the stream is reached.
110 * @exception IOException If an I/O error has occurred.
112 public int read(byte b[], int off, int len) throws IOException {
119 *Fast path: len bytes already available.
122 if (len <= stop - rdNext){
123 System.arraycopy(buff, rdNext, b, off, len);
128 *General case: stream is closed or fill needs to be called
133 m = Math.min(len - bytesMoved, stop - rdNext);
134 System.arraycopy(buff, rdNext, b, off, m);
137 if (bytesMoved == len)
149 * Reads into an array of bytes. This method will
150 * block until some input is available.
151 * @param b the buffer into which the data is read
152 * @param off the start offset of the data
153 * @param len the maximum number of bytes read
154 * @return the actual number of bytes read, -1 is
155 * returned when the end of the stream is reached.
156 * @exception IOException If an I/O error has occurred.
158 public void fill() throws IOException {
159 byte[] headerBuf = new byte[FCGIGlobalDefs.def_FCGIHeaderLen];
165 * If buffer is empty, do a read
167 if (rdNext == buffStop) {
169 count = in.read(buff, 0, buffLen);
170 } catch (IOException e) {
175 setFCGIError(FCGIGlobalDefs.def_FCGIProtocolError);
179 buffStop = count; // 1 more than we read
181 /* Now buf is not empty: If the current record contains more content
182 * bytes, deliver all that are present in buff to callers buffer
183 * unless he asked for less than we have, in which case give him less
185 if (contentLen > 0) {
186 count = Math.min(contentLen, buffStop - rdNext);
189 stop = rdNext + count;
194 if (contentLen > 0) {
202 /* Content has been consumed by client.
203 * If record was padded, skip over padding
205 if (paddingLen > 0) {
206 count = Math.min(paddingLen, buffStop - rdNext);
209 if (paddingLen > 0) {
210 continue; // more padding to read
213 /* All done with current record, including the padding.
214 * If we are in a recursive call from Process Header, deliver EOF
222 * Fill header with bytes from input buffer - get the whole header.
224 count = Math.min(headerBuf.length - headerLen, buffStop - rdNext);
225 System.arraycopy(buff,rdNext, headerBuf, headerLen, count);
228 if (headerLen < headerBuf.length) {
233 * Interperet the header. eorStop prevents ProcessHeader from
234 * reading past the end of record when using stream to read content
239 status = new FCGIMessage(this).processHeader(headerBuf);
243 case FCGIGlobalDefs.def_FCGIStreamRecord:
244 if (contentLen == 0) {
250 case FCGIGlobalDefs.def_FCGISkip:
253 case FCGIGlobalDefs.def_FCGIBeginRecord:
255 * If this header marked the beginning of a new
256 * request, return role info to caller
259 case FCGIGlobalDefs.def_FCGIMgmtRecord:
265 setFCGIError(status);
273 * Skips n bytes of input.
274 * @param n the number of bytes to be skipped
275 * @return the actual number of bytes skipped.
276 * @exception IOException If an I/O error has occurred.
278 public long skip(long n) throws IOException {
279 byte data[] = new byte[(int)n];
280 return in.read(data);
284 * An FCGI error has occurred. Save the error code in the stream
285 * for diagnostic purposes and set the stream state so that
288 public void setFCGIError(int errnum) {
290 * Preserve only the first error.
298 * An Exception has occurred. Save the Exception in the stream
299 * for diagnostic purposes and set the stream state so that
302 public void setException(Exception errexpt) {
304 * Preserve only the first error.
313 * Clear the stream error code and end-of-file indication.
315 public void clearFCGIError() {
319 * XXX: should clear isClosed but work is needed to make it safe
324 * Clear the stream error code and end-of-file indication.
326 public void clearException() {
330 * XXX: should clear isClosed but work is needed to make it safe
336 * accessor method since var is private
338 public int getFCGIError() {
342 * accessor method since var is private
344 public Exception getException() {
348 * Re-initializes the stream to read data of the specified type.
350 public void setReaderType(int streamType) {
362 * Close the stream. This method does not really exist for BufferedInputStream in java,
363 * but is implemented here for compatibility with the FCGI structures being used. It
364 * doent really throw any IOExceptions either, but that's there for compatiblity with
365 * the InputStreamInterface.
367 public void close() throws IOException{
373 * Returns the number of bytes that can be read without blocking.
376 public int available() throws IOException {
377 return stop - rdNext + in.available();