8000 - Added CgiServlet from original javaxt-server project. · javaxt-project/javaxt-jetty@4976501 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4976501

Browse files
author
pborissow
committed
- Added CgiServlet from original javaxt-server project.
git-svn-id: svn://192.168.0.80/JavaXT/javaxt-jetty@850 2c7b0aa6-e0b2-3c4e-bb4a-8b65b6c465ff
1 parent 3738f6a commit 4976501

File tree

1 file changed

+351
-0
lines changed

1 file changed

+351
-0
lines changed
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
package javaxt.http.servlet;
2+
import java.io.IOException;
3+
import java.io.InputStream;
4+
import java.io.OutputStream;
5+
import java.util.StringTokenizer;
6+
7+
//******************************************************************************
8+
//** CGI Servlet
9+
//******************************************************************************
10+
/**
11+
* Http Servlet used to run CGI programs. Based on CgiServlet.java, v1.8
12+
* developed by Jef Poskanzer (acme.com).
13+
*
14+
******************************************************************************/
15+
16+
public class CgiServlet extends HttpServlet {
17+
18+
private java.io.File executable;
19+
20+
//**************************************************************************
21+
//** Constructor
22+
//**************************************************************************
23+
24+
public CgiServlet(java.io.File executable){
25+
this.executable = executable;
26+
}
27+
28+
29+
//**************************************************************************
30+
//** getServletInfo
31+
//**************************************************************************
32+
/** Returns a string containing information about the author, version, and
33+
* copyright of the servlet.
34+
*/
35+
public String getServletInfo() {
36+
return "JavaXT CGI Servlet";
37+
}
38+
39+
40+
//**************************************************************************
41+
//** getParameters
42+
//**************************************************************************
43+
/** Returns a list of parameters that are used to instantiate the CGI
44+
* application.
45+
*/
46+
protected java.util.ArrayList<String> getParameters(HttpServletRequest request){
47+
java.util.ArrayList<String> env = new java.util.ArrayList<String>();
48+
//env.add("PATH=" + "/usr/local/bin:/usr/ucb:/bin:/usr/bin");
49+
env.add("GATEWAY_INTERFACE=" + "CGI/1.1");
50+
env.add("SERVER_SOFTWARE=" + getServletContext().getServerInfo());
51+
env.add("SERVER_PROTOCOL=" + request.getProtocol());
52+
env.add("SERVER_NAME=" + request.getServerName());
53+
env.add("SERVER_PORT=" + request.getServerPort());
54+
env.add("REMOTE_ADDR=" + request.getRemoteAddr());
55+
env.add("REMOTE_HOST=" + request.getRemoteHost());
56+
env.add("REQUEST_METHOD=" + request.getMethod());
57+
env.add("SCRIPT_NAME=" + request.getServletPath());
58+
59+
int contentLength = request.getContentLength();
60+
if (contentLength!=-1) env.add("CONTENT_LENGTH=" + contentLength);
61+
62+
String contentType = request.getContentType();
63+
if (contentType!=null) env.add("CONTENT_TYPE=" + contentType);
64+
65+
String pathInfo = request.getPathInfo();
66+
if (pathInfo!=null) env.add("PATH_INFO=" + pathInfo);
67+
68+
String pathTranslated = request.getPathTranslated();
69+
if (pathTranslated!=null) env.add("PATH_TRANSLATED=" + pathTranslated);
70+
71+
String queryString = request.getQueryString();
72+
if (queryString!=null) env.add("QUERY_STRING=" + queryString);
73+
74+
String remoteUser = request.getRemoteUser();
75+
if (remoteUser!=null) env.add("REMOTE_USER=" + remoteUser);
76+
77+
String authType = request.getAuthType();
78+
if (authType!=null) env.add("AUTH_TYPE=" + authType);
79+
80+
java.util.Enumeration<String> hnEnum = request.getHeaderNames();
81+
while (hnEnum.hasMoreElements()) {
82+
String name = hnEnum.nextElement();
83+
String value = request.getHeader(name);
84+
if (value == null) value = "";
85+
env.add("HTTP_" + name.toUpperCase().replace('-', '_') + "=" + value);
86+
}
87+
return env;
88+
}
89+
90+
91+
//**************************************************************************
92+
//** processRequest
93+
//**************************************************************************
94+
/** Services a single request from the client.
95+
* @param request the servlet request
96+
* @param response the servlet response
97+
* @exception ServletException when an exception has occurred
98+
*/
99+
public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
100+
String method = request.getMethod().toUpperCase();
101+
if (!(method.equals("GET") || method.equals("POST"))) {
102+
response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
103+
return;
104+
}
105+
106+
107+
//Generate a list of parameters used to instantiate the CGI application
108+
java.util.ArrayList<String> env = getParameters(request);
109+
String[] parameters = new String[env.size()+1];
110+
parameters[0] = executable.toString();
111+
for (int i=0; i<parameters.length; i++){
112+
if (i>0) parameters[i] = env.get(i-1);
113+
}
114+
115+
116+
try{
117+
118+
//Run executable via Command Line
119+
Runtime runtime = Runtime.getRuntime();
120+
Process process = runtime.exec(parameters, null, executable.getParentFile());
121+
122+
123+
//If this is a POST, pass the body of the request to the process
124+
if (method.equals("POST")) {
125+
OutputStream outputStream = process.getOutputStream();
126+
InputStream inputStream = request.getInputStream();
127+
byte[] b = new byte[1024];
128+
int x=0;
129+
while ( (x = inputStream.read(b)) != -1) {
130+
outputStream.write(b,0,x);
131+
}
132+
inputStream.close();
133+
outputStream.close();
134+
}
135+
136+
137+
//Parse output streams
138+
StreamReader s1 = new StreamReader(process.getInputStream(), response);
139+
ErrorStreamReader s2 = new ErrorStreamReader(process.getErrorStream());
140+
s1.start();
141+
s2.start();
142+
process.waitFor();
143+
s1.join();
144+
s2.join();
145+
146+
147+
//Explicitly clean up every the process by calling close on each stream
148+
try{process.getInputStream().close();} catch(Exception ex){}
149+
try{process.getErrorStream().close();} catch(Exception ex){}
150+
try{process.getOutputStream().close();} catch(Exception ex){}
151+
152+
//Explicitly destroy the process even if the process is already terminated
153+
try{process.destroy();} catch(Exception ex){}
154+
155+
process = null;
156+
157+
}
158+
catch(IOException e){
159+
throw e;
160+
}
161+
catch(InterruptedException e){
162+
//throw e;
163+
return;
164+
}
165+
}
166+
167+
168+
//**************************************************************************
169+
//** StreamReader Class
170+
//**************************************************************************
171+
/** Thread used to process the standard output stream. */
172+
173+
private class StreamReader implements Runnable {
174+
175+
private InputStream is;
176+
private HttpServletResponse response;
177+
private Thread thread;
178+
private byte[] b = new byte[1];
179+
180+
public StreamReader(InputStream is, HttpServletResponse response){
181+
this.is = is;
182+
this.response = response;
183+
}
184+
185+
public void start() {
186+
thread = new Thread(this);
187+
thread.start();
188+
}
189+
190+
public void run() {
191+
192+
try {
193+
//Parse the list few lines returned from the executable. These
194+
//may contain HTTP response headers
195+
boolean firstLine = true;
196+
while (true) {
197+
String line = readLine();
198+
if (line==null) break;
199+
line = line.trim();
200+
if (line.equals("")) break;
201+
202+
int colon = line.indexOf(":");
203+
if (colon == -1) {
204+
// No colon. If it's the first line, parse it for status.
205+
if (firstLine) {
206+
StringTokenizer tok = new StringTokenizer(line, " ");
207+
try {
208+
switch (tok.countTokens()) {
209+
case 2:
210+
tok.nextToken();
211+
response.setStatus(Integer.parseInt(tok.nextToken()));
212+
break;
213+
case 3:
214+
tok.nextToken();
215+
response.setStatus(Integer.parseInt(tok.nextToken()), tok.nextToken());
216+
break;
217+
}
218+
} catch (NumberFormatException ignore) {
219+
}
220+
} else {
221+
// No colon and it's not the first line? Ignore.
222+
}
223+
} else {
224+
// There's a colon. Check for certain special headers.
225+
String name = line.substring(0, colon);
226+
String value = line.substring(colon + 1).trim();
227+
if (name.equalsIgnoreCase("Status")) {
228+
StringTokenizer tok = new StringTokenizer(value, " ");
229+
try {
230+
switch (tok.countTokens()) {
231+
case 1:
232+
response.setStatus(Integer.parseInt(tok.nextToken()));
233+
break;
234+
case 2:
235+
response.setStatus(Integer.parseInt(tok.nextToken()), tok.nextToken());
236+
break;
237+
}
238+
} catch (NumberFormatException ignore) {
239+
}
240+
} else if (name.equalsIgnoreCase("Content-type")) {
241+
response.setContentType(value);
242+
} else if (name.equalsIgnoreCase("Content-length")) {
243+
try {
244+
response.setContentLength(Integer.parseInt(value));
245+
} catch (NumberFormatException ignore) {
246+
}
247+
} else if (name.equalsIgnoreCase("Location")) {
248+
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
249+
response.setHeader(name, value);
250+
} else if (name.equalsIgnoreCase("Set-Cookie")) {
251+
int x = value.indexOf("=");
252+
if (x > 0) {
253+
String n = value.substring(0, x);
254+
String v = value.substring(x + 1).trim();
255+
response.addCookie(new Cookie(n, v));
256+
}
257+
} else {
258+
// Not a special header. Just set it.
259+
response.setHeader(name, value);
260+
}
261+
}
262+
}
263+
264+
265+
//Set transfer encoding
266+
response.setHeader("Transfer-Encoding", "Chunked");
267+
268+
269+
//Tranfer remaining bytes from the standard output stream to
270+
//the servlet output stream
271+
OutputStream outputStream = response.getOutputStream();
272+
byte[] b = new byte[1024];
273+
int x=0;
274+
while ( (x = is.read(b)) != -1) {
275+
outputStream.write(b,0,x);
276+
}
277+
278+
//Close the input and output streams
279+
outputStream.close();
280+
is.close();
281+
282+
}
283+
catch (IOException e) {
284+
// response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
285+
// There's some weird bug in Java, when reading from a Process
286+
// you get a spurious IOException. We have to ignore it.
287+
}
288+
catch (Exception e) {
289+
e.printStackTrace();
290+
return;
291+
}
292+
}
293+
294+
private String readLine() throws IOException {
295+
StringBuffer str = new StringBuffer();
296+
while (true){
297+
if (is.read(b)==-1) break;
298+
byte c = b[0];
299+
if (c=='\n') break;
300+
str.append((char) c);
301+
}
302+
return str.toString();
303+
}
304+
305+
public void join() throws InterruptedException {
306+
thread.join();
307+
}
308+
309+
} //End StreamReader Class
310+
311+
312+
//**************************************************************************
313+
//** ErrorStreamReader Class
314+
//**************************************************************************
315+
/** Thread used to read the standard output streams. */
316+
317+
private class ErrorStreamReader implements Runnable {
318+
319+
private InputStream is;
320+
private Thread thread;
321+
private byte[] b = new byte[1];
322+
323+
public ErrorStreamReader(InputStream is){
324+
this.is = is;
325+
}
326+
327+
public void start() {
328+
thread = new Thread(this);
329+
thread.start();
330+
}
331+
332+
public void run() {
333+
try {
334+
while (true) {
335+
if (is.read(b)==-1) break;
336+
}
337+
is.close();
338+
}
339+
catch (Exception e) {
340+
//System.out.println ("Problem reading stream... :" + ex);
341+
e.printStackTrace();
342+
return;
343+
}
344+
}
345+
346+
public void join() throws InterruptedException {
347+
thread.join();
348+
}
349+
350+
} //End ErrorStreamReader Class
351+
}

0 commit comments

Comments
 (0)
0