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.3 2000/03/21 12:12:26 robs Exp $
18 * This stream understands FCGI prototcol.
21 public class FCGIOutputStream
24 private static final String RCSID = "$Id: FCGIOutputStream.java,v 1.3 2000/03/21 12:12:26 robs Exp $";
30 public boolean isClosed;
32 /* require methods to set, get and clear */
34 private Exception errex;
42 public boolean isAnythingWritten;
43 public boolean rawWrite;
44 public FCGIRequest request;
46 public FileOutputStream out;
49 * Creates a new output stream to manage fcgi prototcol stuff
50 * @param out the output stream buflen length of buffer streamType
52 public FCGIOutputStream(FileOutputStream outStream,
53 int bufLen, int streamType,
56 buffLen = Math.min(bufLen, FCGIGlobalDefs.def_FCGIMaxLen);
57 buff = new byte[buffLen];
59 stop = buffStop = buffLen;
60 isAnythingWritten = false;
62 wrNext = FCGIGlobalDefs.def_FCGIHeaderLen;
68 * Writes a byte to the output stream.
70 public void write(int c) throws IOException {
72 buff[wrNext++] = (byte)c;
76 throw new EOFException();
80 buff[wrNext++] = (byte)c;
83 /* NOTE: ASSERT(stream->isClosed); */
84 /* bug in emptyBuffProc if not */
85 throw new EOFException();
89 * Writes an array of bytes. This method will block until the bytes
90 * are actually written.
91 * @param b the data to be written
93 public void write(byte b[]) throws IOException{
94 write(b, 0, b.length);
98 * Writes len consecutive bytes from off in the array b
99 * into the output stream. Performs no interpretation
100 * of the output bytes. Making the user convert the string to
101 * bytes is in line with current Java practice.
103 public void write(byte b[], int off, int len) throws IOException {
106 * Fast path: room for n bytes in the buffer
108 if(len <= (stop - wrNext)) {
109 System.arraycopy(b, off, buff, wrNext, len);
114 * General case: stream is closed or buffer empty procedure
120 m = Math.min(len - bytesMoved, stop - wrNext);
121 System.arraycopy(b, off, buff, wrNext, m);
124 if(bytesMoved == len) {
130 throw new EOFException();
137 * Encapsulates any buffered stream content in a FastCGI
138 * record. If !doClose, writes the data, making the buffer
141 public void empty(boolean doClose) throws IOException {
144 * Alignment padding omitted in Java
147 cLen = wrNext - FCGIGlobalDefs.def_FCGIHeaderLen;
149 System.arraycopy(new FCGIMessage().makeHeader(type,
150 request.requestID, cLen, 0),
152 FCGIGlobalDefs.def_FCGIHeaderLen);
162 isAnythingWritten = true;
164 out.write(buff, 0, wrNext);
165 } catch (IOException e) {
172 * The buffer is empty.
175 wrNext += FCGIGlobalDefs.def_FCGIHeaderLen;
182 public void close() throws IOException {
188 * if isClosed, will return with EOFException from write.
196 * Flushes any buffered output.
197 * Server-push is a legitimate application of flush.
198 * Otherwise, it is not very useful, since FCGIAccept
199 * does it implicitly. flush may reduce performance
200 * by increasing the total number of operating system calls
201 * the application makes.
203 public void flush() throws IOException {
209 * if isClosed, will return with EOFException from write.
215 * An FCGI error has occurred. Save the error code in the stream
216 * for diagnostic purposes and set the stream state so that
219 public void setFCGIError(int errnum) {
221 * Preserve only the first error.
230 * An Exception has occurred. Save the Exception in the stream
231 * for diagnostic purposes and set the stream state so that
234 public void setException(Exception errexpt) {
236 * Preserve only the first error.
245 * Clear the stream error code and end-of-file indication.
247 public void clearFCGIError() {
251 * XXX: should clear isClosed but work is needed to make it safe
257 * Clear the stream error code and end-of-file indication.
259 public void clearException() {
263 * XXX: should clear isClosed but work is needed to make it safe
269 * accessor method since var is private
271 public int etFCGIError() {
276 * accessor method since var is private
278 public Exception getException() {
283 * Writes an EOF record for the stream content if necessary.
284 * If this is the last writer to close, writes an FCGI_END_REQUEST
287 public void writeCloseRecords() throws IOException {
288 FCGIMessage msg = new FCGIMessage();
290 * Enter rawWrite mode so final records won't be
296 * Generate EOF for stream content if needed.
298 if(!(type == FCGIGlobalDefs.def_FCGIStderr
300 && !isAnythingWritten)) {
302 new byte[FCGIGlobalDefs.def_FCGIHeaderLen];
303 System.arraycopy(msg.makeHeader(type,
307 FCGIGlobalDefs.def_FCGIHeaderLen);
308 write(hdr, 0, hdr.length);
311 * Generate FCGI_END_REQUEST record if needed.
313 if(request.numWriters == 1) {
315 new byte[FCGIGlobalDefs.def_FCGIHeaderLen
316 + FCGIGlobalDefs.def_FCGIEndReqBodyLen];
317 System.arraycopy(msg.makeHeader(
318 FCGIGlobalDefs.def_FCGIEndRequest,
320 FCGIGlobalDefs.def_FCGIEndReqBodyLen,0),
322 FCGIGlobalDefs.def_FCGIHeaderLen);
323 System.arraycopy(msg.makeEndrequestBody(
325 FCGIGlobalDefs.def_FCGIRequestComplete),
327 FCGIGlobalDefs.def_FCGIHeaderLen,
328 FCGIGlobalDefs.def_FCGIEndReqBodyLen);
329 write(endReq,0, FCGIGlobalDefs.def_FCGIHeaderLen
330 + FCGIGlobalDefs.def_FCGIEndReqBodyLen);
332 request.numWriters--;