don't need this - it doesn't work
[catagits/fcgi2.git] / java / FCGIInterface.java
CommitLineData
61962ef7 1/*
2 * @(#)FCGIInterface.java
3 *
4 *
5 * FastCGi compatibility package Interface
6 *
7 *
8 * Copyright (c) 1996 Open Market, Inc.
9 *
10 * See the file "LICENSE.TERMS" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * $Id: FCGIInterface.java,v 1.1 1999/01/31 02:45:49 roberts Exp $
14 */
15
16import java.net.*;
17import java.io.*;
18import java.util.Properties;
19import FCGIGlobalDefs;
20import FCGIRequest;
21import FCGIInputStream;
22import FCGIOutputStream;
23import FCGIMessage;
24
25/*
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.
29 */
30public class FCGIInterface {
31
32 /*
33 * Class variables
34 */
35 public static FCGIRequest request = null;
36 public static boolean acceptCalled = false;
37 public static boolean isFCGI = true;
38 public static Properties startupProps;
39 public static ServerSocket srvSocket;
40
41 /*
42 * Accepts a new request from the HTTP server and creates
43 * a conventional execution environment for the request.
44 * If the application was invoked as a FastCGI server,
45 * the first call to FCGIaccept indicates that the application
46 * has completed its initialization and is ready to accept
47 * a request. Subsequent calls to FCGI_accept indicate that
48 * the application has completed its processing of the
49 * current request and is ready to accept a new request.
50 * If the application was invoked as a CGI program, the first
51 * call to FCGIaccept is essentially a no-op and the second
52 * call returns EOF (-1) as does an error. Application should exit.
53 *
54 * If the application was invoked as a FastCGI server,
55 * and this is not the first call to this procedure,
56 * FCGIaccept first flushes any buffered output to the HTTP server.
57 *
58 * On every call, FCGIaccept accepts the new request and
59 * reads the FCGI_PARAMS stream into System.props. It also creates
60 * streams that understand FastCGI protocol and take input from
61 * the HTTP server send output and error output to the HTTP server,
62 * and assigns these new streams to System.in, System.out and
63 * System.err respectively.
64 *
65 * For now, we will just return an int to the caller, which is why
66 * this method catches, but doen't throw Exceptions.
67 *
68 */
69 public int FCGIaccept() {
70 int acceptResult = 0;
71
72 /*
73 * If first call, mark it and if fcgi save original system properties,
74 * If not first call, and we are cgi, we should be gone.
75 */
76 if (!acceptCalled){
77 isFCGI = System.getProperties().containsKey("FCGI_PORT");
78 acceptCalled = true;
79 if (isFCGI) {
80 /*
81 * save original system properties (nonrequest)
82 * and get a server socket
83 */
84 System.out.close();
85 System.err.close();
86 startupProps = new Properties(System.getProperties());
87 String str =
88 new String(System.getProperty("FCGI_PORT"));
89 if (str.length() <= 0) {
90 return -1;
91 }
92 int portNum = Integer.parseInt(str);
93
94 try {
95 srvSocket = new ServerSocket(portNum);
96 } catch (IOException e) {
97 request.socket = null;
98 srvSocket = null;
99 request = null;
100 return -1;
101 }
102 }
103 }
104 else {
105 if (!isFCGI){
106 return -1;
107 }
108 }
109 /*
110 * If we are cgi, just leave everything as is, otherwise set up env
111 */
112 if (isFCGI){
113 try {
114 acceptResult = FCGIAccept();
115 } catch (IOException e) {
116 return -1;
117 }
118 if (acceptResult < 0){
119 return -1;
120 }
121
122 /*
123 * redirect stdin, stdout and stderr to fcgi socket
124 */
125 System.setIn(new BufferedInputStream(request.inStream, 8192));
126 System.setOut(new PrintStream(new BufferedOutputStream(
127 request.outStream, 8192)));
128 System.setErr(new PrintStream(new BufferedOutputStream(
129 request.errStream, 512)));
130 System.setProperties(request.params);
131 }
132 return 0;
133 }
134
135 /*
136 * Accepts a new request from the HTTP server.
137 * Finishes the request accepted by the previous call
138 * to FCGI_Accept. Sets up the FCGI environment and reads
139 * saved and per request environmental varaibles into
140 * the request object. (This is redundant on System.props
141 * as long as we can handle only one request object.)
142 */
143 int FCGIAccept() throws IOException{
144
145 boolean isNewConnection;
146 boolean errCloseEx = false;
147 boolean outCloseEx = false;
148
149 if (request != null) {
150 /*
151 * Complete the previous request
152 */
153 System.err.close();
154 System.out.close();
155 boolean prevRequestfailed = (errCloseEx || outCloseEx ||
156 request.inStream.getFCGIError() != 0 ||
157 request.inStream.getException() != null);
158 if (prevRequestfailed || !request.keepConnection ) {
159 request.socket.close();
160 request.socket = null;
161 }
162 if (prevRequestfailed) {
163 request = null;
164 return -1;
165 }
166 }
167 else {
168 /*
169 * Get a Request and initialize some variables
170 */
171 request = new FCGIRequest();
172 request.socket = null;
173 request.inStream = null;
174 }
175 isNewConnection = false;
176
177 /*
178 * if connection isnt open accept a new connection (blocking)
179 */
180 for(;;) {
181 if (request.socket == null){
182 try {
183 request.socket = srvSocket.accept();
184 } catch (IOException e) {
185 request.socket = null;
186 request = null;
187 return -1;
188 }
189 isNewConnection = true;
190 }
191
192 /* Try reading from new connection. If the read fails and
193 * it was an old connection the web server probably closed it;
194 * try making a new connection before giving up
195 */
196 request.isBeginProcessed = false;
197 request.inStream =
198 new FCGIInputStream((FileInputStream)request.
199 socket.getInputStream(),
200 8192, 0, request);
201 request.inStream.fill();
202 if (request.isBeginProcessed) {
203 break;
204 }
205 request.socket.close();
206
207 request.socket = null;
208 if (isNewConnection) {
209 return -1;
210 }
211 }
212 /*
213 * Set up the objects for the new request
214 */
215 request.params = new Properties(startupProps);
216 switch(request.role) {
217 case FCGIGlobalDefs.def_FCGIResponder:
218 request.params.put("ROLE","RESPONDER");
219 break;
220 case FCGIGlobalDefs.def_FCGIAuthorizer:
221 request.params.put("ROLE", "AUTHORIZER");
222 break;
223 case FCGIGlobalDefs.def_FCGIFilter:
224 request.params.put("ROLE", "FILTER");
225 break;
226 default:
227 return -1;
228 }
229 request.inStream.setReaderType(FCGIGlobalDefs.def_FCGIParams);
230 /*
231 * read the rest of request parameters
232 */
233 if (new FCGIMessage(request.inStream).readParams(request.params) < 0) {
234 return -1;
235 }
236 request.inStream.setReaderType(FCGIGlobalDefs.def_FCGIStdin);
237 request.outStream
238 = new FCGIOutputStream((FileOutputStream)request.socket.
239 getOutputStream(), 8192,
240 FCGIGlobalDefs.def_FCGIStdout,request);
241 request.errStream
242 = new FCGIOutputStream((FileOutputStream)request.socket.
243 getOutputStream(), 512,
244 FCGIGlobalDefs.def_FCGIStderr,request);
245 request.numWriters = 2;
246 return 0;
247 }
248}