2 * @(#)FCGIOutputStream.java
4 * FastCGi compatibility package Interface
6 * Copyright (c) 1996 Open Market, Inc.
8 * See the file "LICENSE.TERMS" for information on usage and redistribution
9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * $Id: FCGIOutputStream.java,v 1.2 2000/03/21 12:02:29 robs Exp $
18 * This stream understands FCGI prototcol.
21 public class FCGIOutputStream extends OutputStream {
27 public boolean isClosed;
29 /* require methods to set, get and clear */
31 private Exception errex;
39 public boolean isAnythingWritten;
40 public boolean rawWrite;
41 public FCGIRequest request;
43 public FileOutputStream out;
46 * Creates a new output stream to manage fcgi prototcol stuff
47 * @param out the output stream buflen length of buffer streamType
49 public FCGIOutputStream(FileOutputStream outStream,
50 int bufLen, int streamType,
53 buffLen = Math.min(bufLen, FCGIGlobalDefs.def_FCGIMaxLen);
54 buff = new byte[buffLen];
56 stop = buffStop = buffLen;
57 isAnythingWritten = false;
59 wrNext = FCGIGlobalDefs.def_FCGIHeaderLen;
65 * Writes a byte to the output stream.
67 public void write(int c) throws IOException {
69 buff[wrNext++] = (byte)c;
73 throw new EOFException();
77 buff[wrNext++] = (byte)c;
80 /* NOTE: ASSERT(stream->isClosed); */
81 /* bug in emptyBuffProc if not */
82 throw new EOFException();
86 * Writes an array of bytes. This method will block until the bytes
87 * are actually written.
88 * @param b the data to be written
90 public void write(byte b[]) throws IOException{
91 write(b, 0, b.length);
95 * Writes len consecutive bytes from off in the array b
96 * into the output stream. Performs no interpretation
97 * of the output bytes. Making the user convert the string to
98 * bytes is in line with current Java practice.
100 public void write(byte b[], int off, int len) throws IOException {
103 * Fast path: room for n bytes in the buffer
105 if(len <= (stop - wrNext)) {
106 System.arraycopy(b, off, buff, wrNext, len);
111 * General case: stream is closed or buffer empty procedure
117 m = Math.min(len - bytesMoved, stop - wrNext);
118 System.arraycopy(b, off, buff, wrNext, m);
121 if(bytesMoved == len) {
127 throw new EOFException();
134 * Encapsulates any buffered stream content in a FastCGI
135 * record. If !doClose, writes the data, making the buffer
138 public void empty(boolean doClose) throws IOException {
141 * Alignment padding omitted in Java
144 cLen = wrNext - FCGIGlobalDefs.def_FCGIHeaderLen;
146 System.arraycopy(new FCGIMessage().makeHeader(type,
147 request.requestID, cLen, 0),
149 FCGIGlobalDefs.def_FCGIHeaderLen);
159 isAnythingWritten = true;
161 out.write(buff, 0, wrNext);
162 } catch (IOException e) {
169 * The buffer is empty.
172 wrNext += FCGIGlobalDefs.def_FCGIHeaderLen;
179 public void close() throws IOException {
185 * if isClosed, will return with EOFException from write.
193 * Flushes any buffered output.
194 * Server-push is a legitimate application of flush.
195 * Otherwise, it is not very useful, since FCGIAccept
196 * does it implicitly. flush may reduce performance
197 * by increasing the total number of operating system calls
198 * the application makes.
200 public void flush() throws IOException {
206 * if isClosed, will return with EOFException from write.
212 * An FCGI error has occurred. Save the error code in the stream
213 * for diagnostic purposes and set the stream state so that
216 public void setFCGIError(int errnum) {
218 * Preserve only the first error.
227 * An Exception has occurred. Save the Exception in the stream
228 * for diagnostic purposes and set the stream state so that
231 public void setException(Exception errexpt) {
233 * Preserve only the first error.
242 * Clear the stream error code and end-of-file indication.
244 public void clearFCGIError() {
248 * XXX: should clear isClosed but work is needed to make it safe
254 * Clear the stream error code and end-of-file indication.
256 public void clearException() {
260 * XXX: should clear isClosed but work is needed to make it safe
266 * accessor method since var is private
268 public int etFCGIError() {
273 * accessor method since var is private
275 public Exception getException() {
280 * Writes an EOF record for the stream content if necessary.
281 * If this is the last writer to close, writes an FCGI_END_REQUEST
284 public void writeCloseRecords() throws IOException {
285 FCGIMessage msg = new FCGIMessage();
287 * Enter rawWrite mode so final records won't be
293 * Generate EOF for stream content if needed.
295 if(!(type == FCGIGlobalDefs.def_FCGIStderr
297 && !isAnythingWritten)) {
299 new byte[FCGIGlobalDefs.def_FCGIHeaderLen];
300 System.arraycopy(msg.makeHeader(type,
304 FCGIGlobalDefs.def_FCGIHeaderLen);
305 write(hdr, 0, hdr.length);
308 * Generate FCGI_END_REQUEST record if needed.
310 if(request.numWriters == 1) {
312 new byte[FCGIGlobalDefs.def_FCGIHeaderLen
313 + FCGIGlobalDefs.def_FCGIEndReqBodyLen];
314 System.arraycopy(msg.makeHeader(
315 FCGIGlobalDefs.def_FCGIEndRequest,
317 FCGIGlobalDefs.def_FCGIEndReqBodyLen,0),
319 FCGIGlobalDefs.def_FCGIHeaderLen);
320 System.arraycopy(msg.makeEndrequestBody(
322 FCGIGlobalDefs.def_FCGIRequestComplete),
324 FCGIGlobalDefs.def_FCGIHeaderLen,
325 FCGIGlobalDefs.def_FCGIEndReqBodyLen);
326 write(endReq,0, FCGIGlobalDefs.def_FCGIHeaderLen
327 + FCGIGlobalDefs.def_FCGIEndReqBodyLen);
329 request.numWriters--;