Source code: com/prolifics/servlet/ProlificsHttpServlet.java
1 /*************************************************/
2 /* Copyright (c) 2000 */
3 /* by */
4 /* JYACC, Inc., New York NY USA */
5 /* and contributors. */
6 /* Use of this program is governed by the */
7 /* JYACC Public License Version 1.0, a copy of */
8 /* which can be obtained at */
9 /* http://www.possl.org/jyacc-license.html */
10 /*************************************************/
11
12 /* @(#)ProlificsHttpServlet.java 77.12 00/05/18 17:04:14 */
13
14 package com.prolifics.servlet;
15 import java.io.*;
16 import java.util.*;
17
18 import javax.servlet.*;
19 import javax.servlet.http.*;
20 /* import javax.security.cert.*; */
21
22 import sun.security.x509.*;
23
24 /**
25 * Prolifics servlet. This servlet passes the HTTP requests to
26 * a Prolifics application, and outputs the result from the Prolifics
27 * application to the browser.
28 *
29 *
30 * <a name=methods_used></a>
31 * <br>
32 * <br>
33 * The following methods in HttpServletRequest are used by ProlificsHttpServlet
34 * (see the Sun Servlet documentation for details):
35 * <pre>
36 * String getAuthType()
37 * int getContentLength()
38 * String getContentType()
39 * Cookie[] getCookies()
40 * String getHeader(String name)
41 * Enumeration getHeaderNames()
42 * ServletInputStream getInputStream()
43 * String getMethod()
44 * String getPathInfo()
45 * String getPathTranslated()
46 * String getProtocol()
47 * String getQueryString()
48 * String getRemoteAddr()
49 * String getRemoteHost()
50 * String getRemoteUser()
51 * String getRequestURI()
52 * String getServerName()
53 * int getServerPort()
54 * String getServletPath()
55 * </pre>
56 * <br>
57 * The following methods in HttpServletResponse are used by ProlificsHttpServlet
58 * (see the Sun Servlet documentation for details):
59 * <pre>
60 # void addCookie(Cookie cookie)
61 * ServletOutputStream getOutputStream()
62 * void setContentLength(int length)
63 * void setContentType(String type)
64 * void setHeader(String name, String value)
65 * void setStatus(int)
66 * void setStatus(int code, String message)
67 * </pre>
68 * @version @(#)ProlificsHttpServlet.java 77.12 00/05/18 17:04:14
69 * @author Prolifics
70 */
71 public
72 class ProlificsHttpServlet extends HttpServlet
73 {
74 private static String sccsid = "@(#)ProlificsHttpServlet.java 77.10 00/01/21 13:08:10";
75 private static Boolean allowChunking = null;
76 private static final byte nul = 0;
77
78 private static final int EOF = -1;
79 private static final int WEB_CLIENT_UNDEFINED = 0;
80 private static final int WEB_CLIENT_END_LIST = 1;
81 private static final int WEB_CLIENT_ARGUMENTS = 2;
82 private static final int WEB_CLIENT_ENVIRONMENT = 3;
83 private static final int WEB_CLIENT_CLEAN = 4;
84
85 private void
86 sendRequest(String WebAppName, int content_len,
87 InputStream in, OutputStream so, HttpEnv env)
88 throws IOException
89 {
90 if (content_len < 0)
91 {
92 content_len = 0;
93 }
94 int envlen = env.getEnvLen();
95 int dstlen = envlen + 16 + WebAppName.length() + 1 +
96 content_len;
97 byte dst[] = new byte[dstlen];
98 int offset = 0;
99 int argcount = 1;
100 int argsize = WebAppName.length() + 1;
101 int envcount = env.getEnvCount();
102
103 dst[offset] = WEB_CLIENT_ARGUMENTS; offset++;
104 dst[offset] = (byte) ( argcount & 0xff ); offset++;
105 dst[offset] = (byte) ( (argcount >> 8) & 0xff ); offset++;
106 dst[offset] = (byte) ( argsize & 0xff ); offset++;
107 dst[offset] = (byte) ( (argsize >> 8) & 0xff ); offset++;
108 dst[offset] = (byte) ( (argsize >> 16) & 0xff ); offset++;
109 dst[offset] = (byte) ( (argsize >> 24) & 0xff ); offset++;
110 offset += copystrtoba(dst, offset, WebAppName) + 1;
111 dst[offset] = WEB_CLIENT_END_LIST; offset++;
112 dst[offset] = WEB_CLIENT_ENVIRONMENT; offset++;
113 dst[offset] = (byte) ( envcount & 0xff ); offset++;
114 dst[offset] = (byte) ( (envcount >> 8) & 0xff ); offset++;
115 dst[offset] = (byte) ( envlen & 0xff ); offset++;
116 dst[offset] = (byte) ( (envlen >> 8) & 0xff ); offset++;
117 dst[offset] = (byte) ( (envlen >> 16) & 0xff ); offset++;
118 dst[offset] = (byte) ( (envlen >> 24) & 0xff ); offset++;
119 for (Enumeration enum = env.keys(); enum.hasMoreElements() ;)
120 {
121 String name = (String) enum.nextElement();
122 String value = (String) env.get(name);
123 offset +=copystrtoba(dst, offset, name + "=" + value);
124 offset++;
125 }
126 dst[offset] = WEB_CLIENT_END_LIST; offset++;
127
128
129 int remlen = content_len;
130 while (remlen > 0)
131 {
132 int len = in.read(dst, offset, remlen);
133 if (len == -1)
134 {
135 throw new IOException();
136 }
137 remlen -= len;
138 offset += len;
139 }
140 /*
141 FileOutputStream sendfile = new FileOutputStream("senddbg.txt");
142
143 sendfile.write(dst);
144 sendfile.close();
145 */
146 so.write(dst);
147 so.flush();
148 }
149
150 public void init (ServletConfig config) throws ServletException
151 {
152 super.init(config);
153 String allowChunkingStr =
154 config.getInitParameter("AllowChunking");
155 if (allowChunkingStr != null && ! allowChunkingStr.equals(""))
156 {
157 this.allowChunking = new Boolean(allowChunkingStr);
158 }
159 }
160
161 private ServletOutputStream getOut(HttpServletRequest req,
162 HttpServletResponse res, Boolean chunked)
163 throws IOException
164 {
165 ServletOutputStream out = res.getOutputStream();
166 boolean allowChunking = true;
167
168 if (chunked != null)
169 {
170 allowChunking = chunked.booleanValue();
171 }
172 else if (this.allowChunking != null)
173 {
174 allowChunking = this.allowChunking.booleanValue();
175 }
176 else
177 {
178 allowChunking = req.getProtocol().equals("HTTP/1.1");
179 }
180
181 if (req.getProtocol().equals("HTTP/1.1") && allowChunking)
182 {
183 res.setHeader("Transfer-encoding", "chunked");
184 out = new FilterServletOutputStream(
185 new BufferedOutputStream(
186 new ChunkedOutputStream(out)));
187 }
188
189 return out;
190 }
191
192 /*
193 public void getinp (InputStream in, ServletOutputStream out, int cl)
194 throws ServletException, IOException
195 {
196 byte buf[] = new byte[512];
197
198 if (cl > 0)
199 {
200 out.println("<h1>Input:</h1>");
201 }
202 out.println("<pre>");
203
204 for (int total=0, rd=0; total < cl; total += rd)
205 {
206 int rdlen = 0;
207 rdlen = buf.length;
208 if (rdlen > cl - total)
209 {
210 rdlen = cl - total;
211 }
212 rd = in.read(buf, 0, rdlen);
213
214 if (rd <= 0)
215 {
216 break;
217 }
218
219 out.write(buf, 0, rd);
220 }
221 out.println("</pre>");
222 }
223 */
224
225 /**
226 * Passes the GET request to a Prolifics application.
227 * @param req The request object
228 * @param res The response object
229 * @exception IOException IOException.
230 * @exception ServletException ServletException.
231 * @see #methods_used
232 */
233 public void doGet (HttpServletRequest req,
234 HttpServletResponse res)
235 throws ServletException, IOException
236 {
237 doGet(req, res, null, null);
238 }
239
240 /**
241 * Passes the GET request to a Prolifics application.
242 * @param req The request object.
243 * @param res The response object.
244 * @param appname The name of the Prolifics application that should handle the request.
245 * @param chunked Controls the use of <b>Transfer-encoding: chunked</b>.
246 * <ul type=circle>
247 * <li><code>TRUE</code> = chunked<br>
248 * <li><code>FALSE</code> = not chunked<br>
249 * <li><code>null</code> = decide automatically<br>
250 * </ul>
251 * @exception IOException IOException.
252 * @exception ServletException ServletException.
253 * @see #methods_used
254 */
255 public void doGet (HttpServletRequest req,
256 HttpServletResponse res,
257 String appname, Boolean chunked)
258 throws ServletException, IOException
259 {
260 Comm comm = null;
261 ServletInputStream in = null;
262 ServletOutputStream out = null;
263
264 try
265 {
266 in = req.getInputStream();
267 out = getOut(req, res, chunked);
268 HttpEnv env = new HttpEnv();
269
270 comm = new Comm();
271
272 if (appname == null)
273 {
274 int slashPos = 0;
275 appname = req.getPathInfo();
276 if (appname == null)
277 {
278 appname = "";
279 throw new Exception("No application name");
280 }
281 slashPos = appname.indexOf('/', 1);
282 if (slashPos == -1)
283 {
284 slashPos = appname.length();
285 }
286 appname = appname.substring(1, slashPos);
287 }
288
289 String pathinfo;
290 pathinfo = req.getPathInfo();
291 if (pathinfo != null)
292 {
293 int slashPos = pathinfo.indexOf('/', 1);
294 if (slashPos == -1)
295 {
296 pathinfo = null;
297 }
298 else
299 {
300 pathinfo = pathinfo.substring(slashPos);
301 }
302 }
303 String querystring = req.getQueryString();
304 String URL = pathinfo;
305 if (URL == null)
306 {
307 URL = "<none>";
308 }
309 if (querystring != null)
310 {
311 URL = URL + "?" + querystring;
312 }
313 comm.open(appname, URL);
314
315 InputStream si = comm.getInputStream();
316 OutputStream so = comm.getOutputStream();
317 /*
318 InputStream si = new FileInputStream("d:\\users\\eric\\servlets\\COM\\prolifics\\servlet\\recv.txt");
319 OutputStream so = new FileOutputStream("d:\\users\\eric\\servlets\\COM\\prolifics\\servlet\\send.txt");
320 */
321
322 env.add("CONTENT_LENGTH", req.getContentLength());
323 env.add("CONTENT_TYPE", req.getContentType());
324 env.add("HTTP_ACCEPT", req.getHeader("Accept"));
325 env.add("HTTP_ACCEPT_CHARSET", req.getHeader("Accept-Charset"));
326 env.add("HTTP_ACCEPT_ENCODING",
327 req.getHeader("Accept-Encoding"));
328 env.add("HTTP_ACCEPT_LANGUAGE",
329 req.getHeader("Accept-Language"));
330 env.add("HTTP_AUTHORIZATION", req.getHeader("Authorization"));
331 env.add("HTTP_CONNECTION", req.getHeader("Connection"));
332 env.add("HTTP_COOKIE", req.getHeader("Cookie"));
333 env.add("HTTP_HOST", req.getHeader("Host"));
334 env.add("HTTP_IF_MODIFIED_SINCE",
335 req.getHeader("If-Modified-Since"));
336 env.add("HTTP_PROXY_CONNECTION",
337 req.getHeader("Proxy-Connection"));
338 env.add("HTTP_REFERER", req.getHeader("Referer"));
339 env.add("HTTP_USER_AGENT", req.getHeader("User-Agent"));
340 env.add("HTTP_USER_DEFINED", req.getHeader("User-Defined"));
341 env.add("REQUEST_METHOD", req.getMethod());
342 env.add("REQUEST_URI", req.getRequestURI());
343
344 env.add("SERVLET_PATH", req.getServletPath());
345 env.add("SCRIPT_NAME", req.getServletPath() + "/" + appname);
346 env.add("PATH_INFO", pathinfo);
347 String pathtrans;
348 pathtrans = req.getPathTranslated();
349 if (pathtrans != null && pathinfo != null)
350 {
351 pathtrans = pathtrans.substring(0,
352 pathtrans.length()-req.getPathInfo().length())+
353 pathinfo;
354 }
355 env.add("PATH_TRANSLATED", pathtrans);
356
357 env.add("GATEWAY_INTERFACE", "CGI/1.1");
358 env.add("QUERY_STRING", querystring);
359 env.add("SERVER_NAME", req.getServerName());
360 env.add("SERVER_PORT", req.getServerPort());
361 env.add("SERVER_PROTOCOL", req.getProtocol());
362 env.add("SERVER_SOFTWARE", getServletContext().getServerInfo());
363 env.add("SERVER_URL", getServerURL(req));
364 env.add("REMOTE_USER", req.getRemoteUser());
365 env.add("REMOTE_ADDR", req.getRemoteAddr());
366 env.add("REMOTE_HOST", req.getRemoteHost());
367 env.add("AUTH_TYPE", req.getAuthType());
368
369 Cookie cookie[] = req.getCookies();
370 if (cookie != null && cookie.length > 0)
371 {
372 String cookie_str = "";
373 String sep = "";
374 for (int idx = 0; idx < cookie.length; idx++)
375 {
376 cookie_str = cookie_str + sep +
377 cookie[idx].getName() + "=" +
378 cookie[idx].getValue();
379 sep = "; ";
380 }
381 env.add("HTTP_COOKIE", cookie_str);
382 }
383
384 Enumeration hdrs = req.getHeaderNames();
385 if (hdrs.hasMoreElements())
386 {
387 while (hdrs.hasMoreElements())
388 {
389 String name = (String)hdrs.nextElement();
390 String httpName = name.replace('-', '_');
391 httpName = "HTTP_" + httpName.toUpperCase();
392 env.add(httpName, req.getHeader(name));
393 }
394 }
395
396 sendRequest(appname, req.getContentLength(),
397 in, so, env);
398 env = null;
399
400 HttpOutputStream pout =
401 new HttpOutputStream(res, out);
402 byte buf[] = new byte[512];
403 for (;;)
404 {
405 int len;
406 len = si.read(buf, 0, buf.length);
407 if (len <= 0)
408 {
409 break;
410 }
411 pout.write(buf, 0, len);
412 }
413
414 pout.flush();
415 pout.close();
416 }
417 catch (Exception excp)
418 {
419 getServletContext().log(excp,
420 getClass().getName() + ": "+ "Prolifics servlet");
421 res.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
422 res.setContentType("text/html");
423 out.println("<html><head><title>Error</title></head>");
424 out.println("<body><h1>Cannot connect to application \"");
425 out.println(appname);
426 out.println("\"</h1></body></html>");
427 /* excp.printStackTrace(new PrintStream(out)); */
428 out.close();
429 }
430 finally
431 {
432 if (comm != null)
433 {
434 try
435 {
436 comm.close();
437 }
438 finally
439 {
440 comm.destroy();
441 }
442 }
443 }
444 }
445
446 /**
447 * Passes the POST request to a Prolifics application.
448 * @param req The request object
449 * @param res The response object
450 * @exception IOException IOException.
451 * @exception ServletException ServletException.
452 * @see #methods_used
453 */
454 public void doPost (HttpServletRequest req, HttpServletResponse res)
455 throws ServletException, IOException
456 {
457 doPost (req, res, null, null);
458 }
459
460 /**
461 * Passes the POST request to a Prolifics application.
462 * @param req The request object.
463 * @param res The response object.
464 * @param appname The name of the Prolifics application that should handle the request.
465 * @param chunked Controls the use of <b>Transfer-encoding: chunked</b>.
466 * <ul type=circle>
467 * <li><code>TRUE</code> = chunked<br>
468 * <li><code>FALSE</code> = not chunked<br>
469 * <li><code>null</code> = decide automatically<br>
470 * </ul>
471 * @exception IOException IOException.
472 * @exception ServletException ServletException.
473 * @see #methods_used
474 */
475 public void doPost (HttpServletRequest req,
476 HttpServletResponse res,
477 String appname, Boolean chunked)
478 throws ServletException, IOException
479 {
480 doGet(req, res, appname, chunked);
481 }
482
483 /*
484 private void print(ServletOutputStream out, String name, String value)
485 throws IOException
486 {
487 out.print(" " + name + ": ");
488 out.println(value == null ? "<none>" : value);
489 }
490
491 private void print(ServletOutputStream out, String name, int value)
492 throws IOException
493 {
494 out.print(" " + name + ": ");
495 if (value == -1)
496 {
497 out.println("<none>");
498 }
499 else
500 {
501 out.println(Integer.toString(value));
502 }
503 }
504 */
505
506 /**
507 * Describes the servlet.
508 */
509 public String getServletInfo()
510 {
511 return "Prolifics servlet";
512 }
513
514 private static int copystrtoba(byte dst[], int offset, String src)
515 {
516 /* try */
517 {
518 byte bsrc[] = Comm.stringToBytes(src);
519 System.arraycopy(bsrc, 0, dst, offset, bsrc.length);
520 dst[offset+bsrc.length] = nul;
521 return bsrc.length;
522 }
523 /*
524 catch (UnsupportedEncodingException ignored)
525 {
526 return 0;
527 }
528 */
529 }
530
531 private static String getServerURL (HttpServletRequest req)
532 {
533 int port = req.getServerPort ();
534 String scheme = req.getScheme ();
535 String portStr = "";
536 String serverURL = null;
537
538 if ((scheme.equals ("http") && port != 80) ||
539 (scheme.equals ("https") && port != 443))
540 {
541 portStr = ":" + port;
542 }
543
544 serverURL = scheme + "://" + req.getServerName () + portStr;
545
546 return serverURL;
547 }
548 }