2 * @(#)FCGIInterface.java
5 * FastCGi compatibility package Interface
8 * Copyright (c) 1996 Open Market, Inc.
10 * See the file "LICENSE.TERMS" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
17 import java.util.Properties;
18 import FCGIGlobalDefs;
20 import FCGIInputStream;
21 import FCGIOutputStream;
26 * This is the FastCGI interface that the application calls to communicate with the
27 * FastCGI web server. This version is single threaded, and handles one request at
28 * a time, which is why we can have a static variable for it.
30 public class FCGIInterface {
37 public static FCGIRequest request = null;
38 public static boolean acceptCalled = false;
39 public static boolean isFCGI = true;
40 public static Properties startupProps;
41 public static ServerSocket srvSocket;
48 * Accepts a new request from the HTTP server and creates
49 * a conventional execution environment for the request.
50 * If the application was invoked as a FastCGI server,
51 * the first call to FCGIaccept indicates that the application
52 * has completed its initialization and is ready to accept
53 * a request. Subsequent calls to FCGI_accept indicate that
54 * the application has completed its processing of the
55 * current request and is ready to accept a new request.
56 * If the application was invoked as a CGI program, the first
57 * call to FCGIaccept is essentially a no-op and the second
58 * call returns EOF (-1) as does an error. Application should exit.
60 * If the application was invoked as a FastCGI server,
61 * and this is not the first call to this procedure,
62 * FCGIaccept first flushes any buffered output to the HTTP server.
64 * On every call, FCGIaccept accepts the new request and
65 * reads the FCGI_PARAMS stream into System.props. It also creates
66 * streams that understand FastCGI protocol and take input from
67 * the HTTP server send output and error output to the HTTP server,
68 * and assigns these new streams to System.in, System.out and
69 * System.err respectively.
71 * For now, we will just return an int to the caller, which is why
72 * this method catches, but doen't throw Exceptions.
76 public int FCGIaccept() {
80 * If first call, mark it and if fcgi save original system properties,
81 * If not first call, and we are cgi, we should be gone.
84 isFCGI = System.getProperties().containsKey("FCGI_PORT");
88 * save original system properties (nonrequest)
89 * and get a server socket
93 startupProps = new Properties(System.getProperties());
95 new String(System.getProperty("FCGI_PORT"));
96 if (str.length() <= 0) {
99 int portNum = Integer.parseInt(str);
102 srvSocket = new ServerSocket(portNum);
103 } catch (IOException e) {
104 request.socket = null;
116 * If we are cgi, just leave everything as is, otherwise set up env
120 acceptResult = FCGIAccept();
121 } catch (IOException e) {
124 if (acceptResult < 0){
129 * redirect stdin, stdout and stderr to fcgi socket
131 System.setIn(new BufferedInputStream(request.inStream, 8192));
132 System.setOut(new PrintStream(new BufferedOutputStream(
133 request.outStream, 8192)));
134 System.setErr(new PrintStream(new BufferedOutputStream(
135 request.errStream, 512)));
136 System.setProperties(request.params);
142 * Accepts a new request from the HTTP server.
143 * Finishes the request accepted by the previous call
144 * to FCGI_Accept. Sets up the FCGI environment and reads
145 * saved and per request environmental varaibles into
146 * the request object. (This is redundant on System.props
147 * as long as we can handle only one request object.)
149 int FCGIAccept() throws IOException{
151 boolean isNewConnection;
152 boolean errCloseEx = false;
153 boolean outCloseEx = false;
155 if (request != null) {
157 * Complete the previous request
162 boolean prevRequestfailed = (errCloseEx || outCloseEx ||
163 request.inStream.getFCGIError() != 0 ||
164 request.inStream.getException() != null);
165 if (prevRequestfailed || !request.keepConnection ) {
166 request.socket.close();
167 request.socket = null;
169 if (prevRequestfailed) {
175 * Get a Request and initialize some variables
177 request = new FCGIRequest();
178 request.socket = null;
179 request.inStream = null;
181 isNewConnection = false;
184 * if connection isnt open accept a new connection (blocking)
187 if (request.socket == null){
189 request.socket = srvSocket.accept();
190 } catch (IOException e) {
191 request.socket = null;
195 isNewConnection = true;
198 /* Try reading from new connection. If the read fails and
199 * it was an old connection the web server probably closed it;
200 *try making a new connection before giving up
202 request.isBeginProcessed = false;
204 new FCGIInputStream((FileInputStream)request.
205 socket.getInputStream(),
207 request.inStream.fill();
208 if (request.isBeginProcessed) {
211 request.socket.close();
213 request.socket = null;
214 if (isNewConnection) {
219 * Set up the objects for the new request
222 request.params = new Properties(startupProps);
223 switch(request.role) {
224 case FCGIGlobalDefs.def_FCGIResponder:
225 request.params.put("ROLE","RESPONDER");
227 case FCGIGlobalDefs.def_FCGIAuthorizer:
228 request.params.put("ROLE", "AUTHORIZER");
230 case FCGIGlobalDefs.def_FCGIFilter:
231 request.params.put("ROLE", "FILTER");
236 request.inStream.setReaderType(FCGIGlobalDefs.def_FCGIParams);
238 * read the rest of request parameters
240 if (new FCGIMessage(request.inStream).readParams(request.params) < 0) {
243 request.inStream.setReaderType(FCGIGlobalDefs.def_FCGIStdin);
245 = new FCGIOutputStream((FileOutputStream)request.socket.
246 getOutputStream(), 8192,
247 FCGIGlobalDefs.def_FCGIStdout,request);
249 = new FCGIOutputStream((FileOutputStream)request.socket.
250 getOutputStream(), 512,
251 FCGIGlobalDefs.def_FCGIStderr,request);
252 request.numWriters = 2;