KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > http > servlets > cgi > CgiScript


1 package com.quadcap.http.servlets.cgi;
2
3 /* Copyright 1998 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.ByteArrayOutputStream JavaDoc;
42 import java.io.File JavaDoc;
43 import java.io.FileOutputStream JavaDoc;
44 import java.io.InputStream JavaDoc;
45 import java.io.IOException JavaDoc;
46 import java.io.OutputStream JavaDoc;
47
48 import java.util.Hashtable JavaDoc;
49 import java.util.Enumeration JavaDoc;
50 import java.util.Vector JavaDoc;
51
52 import java.net.URLEncoder JavaDoc;
53
54 import javax.servlet.ServletException JavaDoc;
55
56 import javax.servlet.http.HttpServletRequest JavaDoc;
57 import javax.servlet.http.HttpServletResponse JavaDoc;
58
59 import com.quadcap.http.util.HeaderParser;
60
61 import com.quadcap.io.LogInputStream;
62
63 import com.quadcap.util.text.Scanner;
64
65 import com.quadcap.util.Debug;
66
67 /**
68  * Handle a single CGI script execution.
69  *
70  * @author Stan Bailes
71  */

72 public class CgiScript {
73     CgiServlet servlet;
74     File JavaDoc script;
75     String JavaDoc interp;
76
77     static final String JavaDoc FORM_ENCODED = "application/x-www-form-urlencoded";
78     
79     public CgiScript(CgiServlet servlet, String JavaDoc interp, File JavaDoc script) {
80     this.servlet = servlet;
81     this.interp = interp;
82     this.script = script;
83     }
84
85     final String JavaDoc ns(String JavaDoc s) {
86         return s == null ? "" : s;
87     }
88     
89     public synchronized void service(HttpServletRequest JavaDoc req,
90                      HttpServletResponse JavaDoc res)
91     throws IOException JavaDoc, ServletException JavaDoc
92     {
93         boolean form = false;
94         byte[] formData = null;
95         if (req.getMethod().equalsIgnoreCase("POST") &&
96             req.getContentType().equalsIgnoreCase(FORM_ENCODED)) {
97             form = true;
98             ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
99             Enumeration JavaDoc ed = req.getParameterNames();
100             boolean first = true;
101             while (ed.hasMoreElements()) {
102                 String JavaDoc name = ed.nextElement().toString();
103                 String JavaDoc [] vals = req.getParameterValues(name);
104                 for (int i = 0; i < vals.length; i++) {
105                     if (!first) bos.write('&');
106                     first = false;
107                     bos.write(URLEncoder.encode(name).getBytes());
108                     bos.write('=');
109                     bos.write(URLEncoder.encode(vals[i]).getBytes());
110                 }
111             }
112             formData = bos.toByteArray();
113         } else {
114             formData = new byte[0];
115         }
116         //#ifdef DEBUG
117
if (Trace.bit(2)) {
118             Debug.println("formData = " + new String JavaDoc(formData));
119         }
120         //#endif
121

122
123     Vector JavaDoc env = new Vector JavaDoc();
124         if (form) {
125             env.addElement("CONTENT_LENGTH=" + formData.length);
126         } else {
127             env.addElement("CONTENT_LENGTH=" + req.getContentLength());
128         }
129     env.addElement("CONTENT_TYPE=" + req.getContentType());
130     env.addElement("DOCUMENT_ROOT=" +
131                servlet.getServletConfig().getServletContext().getRealPath("."));
132     env.addElement("GATEWAY_INTERFACE=1.1");
133     env.addElement("HTTP_ACCEPT=" + req.getHeader("Http-Accept"));
134     env.addElement("HTTP_USER_AGENT=" + req.getHeader("User-Agent"));
135     env.addElement("PATH_INFO=" + ns(req.getPathInfo()));
136     env.addElement("QUERY_STRING=" + req.getQueryString());
137     env.addElement("REQUEST_METHOD=" + req.getMethod());
138     env.addElement("SCRIPT_NAME=" + req.getServletPath());
139     env.addElement("SERVER_NAME=" + req.getServerName());
140     env.addElement("SERVER_PORT=" + req.getServerPort());
141     env.addElement("SERVER_PROTOCOL=" + req.getProtocol());
142
143     String JavaDoc[] envp = new String JavaDoc[env.size()];
144     for (int i = 0; i < env.size(); i++) {
145         envp[i] = env.elementAt(i).toString();
146             //#ifdef DEBUG
147
if (Trace.bit(2)) {
148                 Debug.println(" " + envp[i]);
149             }
150             //#endif
151
}
152
153     String JavaDoc[] cmdp = new String JavaDoc[2];
154
155     cmdp[0] = interp;
156     cmdp[1] = script.getAbsolutePath();
157
158     res.setContentType("text/html");
159
160         //#ifdef DEBUG
161
if (Trace.bit(0)) {
162             Debug.println("Invoking: " + cmdp[0] + " " + cmdp[1]);
163         }
164         //#endif
165
Process JavaDoc cgi = Runtime.getRuntime().exec(cmdp, envp);
166     InputStream JavaDoc pi = cgi.getInputStream();
167
168 // FileOutputStream fos = new FileOutputStream("cgi.log");
169
// LogInputStream lis = new LogInputStream(pi, fos, "");
170
// pi = lis;
171

172     OutputStream JavaDoc po = cgi.getOutputStream();
173     InputStream JavaDoc pe = cgi.getErrorStream();
174
175     OutputStream JavaDoc so = res.getOutputStream();
176     ByteArrayOutputStream JavaDoc se = new ByteArrayOutputStream JavaDoc();
177
178     Thread JavaDoc t1 = makeInputThread(formData, po);
179     Thread JavaDoc t2 = makeOutputThread(pi, so, res);
180     Thread JavaDoc t3 = makeCopyThread(pe, se);
181
182     t1.start();
183     t2.start();
184     t3.start();
185     int ret = 0;
186
187     try { ret = cgi.waitFor(); } catch (Exception JavaDoc e) {}
188     try { t1.join(); } catch (Exception JavaDoc e) {}
189     try { t2.join(); } catch (Exception JavaDoc e) {}
190     try { t3.join(); } catch (Exception JavaDoc e) {}
191
192         //#ifdef DEBUG
193
if (Trace.bit(1)) {
194             Debug.println("stderr: " + se.toString());
195         }
196         //#endif
197

198     //fos.flush();
199
if (ret != 0) {
200         throw new ServletException JavaDoc("Script failed: " + se.toString());
201     }
202     }
203
204     /**
205      * Create a thread which copies bytes from an input stream to
206      * an output stream until end of file is reached.
207      */

208     public static Thread JavaDoc makeInputThread(final byte[] formData,
209                     final OutputStream JavaDoc out) {
210     Thread JavaDoc t = new Thread JavaDoc() {
211         public void run() {
212         int c;
213         try {
214             out.write(formData);
215             out.close();
216         } catch (IOException JavaDoc e) {
217             Debug.print(e);
218         }
219         }
220     };
221     return t;
222     }
223
224     public static Thread JavaDoc makeOutputThread(final InputStream JavaDoc in,
225                       final OutputStream JavaDoc out,
226                       final HttpServletResponse JavaDoc res) {
227     Thread JavaDoc t = new Thread JavaDoc() {
228         Hashtable JavaDoc headers = new Hashtable JavaDoc();
229         Scanner scanner = new Scanner(in);
230         boolean terminate = false;
231         public void run() {
232         int c;
233         try {
234             try {
235             HeaderParser.parseHeaders(scanner, headers);
236             } catch (Throwable JavaDoc e) {
237             Debug.print(e);
238             //#ifdef DEBUG
239
Debug.println("scanner = " + scanner.getLog());
240             //#endif
241
}
242             Enumeration JavaDoc e = headers.keys();
243             while (e.hasMoreElements()) {
244             String JavaDoc hdr = (String JavaDoc)e.nextElement();
245             String JavaDoc val = (String JavaDoc)headers.get(hdr);
246             if (hdr.equals("status")) {
247                 int code = Integer.parseInt(val.substring(0,3));
248                 String JavaDoc reason = val.substring(4);
249                 if (code == 303) {
250                 res.sendRedirect(reason);
251                 return;
252                 } else {
253                 res.setStatus(code, reason);
254                 }
255             } else if (hdr.equals("content-type")) {
256                 res.setContentType(val);
257             } else if (hdr.equals("location")) {
258                 res.sendRedirect(val);
259             } else {
260                 res.setHeader(hdr, val);
261             }
262             }
263             
264             while (!terminate && (c = in.read()) >= 0) {
265             out.write(c);
266             }
267         } catch (IOException JavaDoc e) {
268             Debug.print(e);
269         }
270         }
271         public void terminate() {
272         this.terminate = true;
273         }
274     };
275     return t;
276     }
277     
278     /**
279      * Create a thread which copies bytes from an input stream to
280      * an output stream until end of file is reached.
281      */

282     public static Thread JavaDoc makeCopyThread(final InputStream JavaDoc in,
283                     final OutputStream JavaDoc out) {
284     Thread JavaDoc t = new Thread JavaDoc() {
285         boolean terminate = false;
286         public void run() {
287         int c;
288         try {
289             while (!terminate && (c = in.read()) >= 0) out.write(c);
290         } catch (IOException JavaDoc e) {
291             Debug.print(e);
292         }
293         }
294         public void terminate() {
295         this.terminate = true;
296         }
297     };
298     return t;
299     }
300
301 }
302     
303
Popular Tags