f41b982009-05-07Martin Stjernholm // This is a roxen module. Copyright © 1999 - 2009, Roxen IS.
1430c02000-03-16Martin Nilsson 
9e39412000-02-12Martin Nilsson inherit "module";
5152931999-11-02Marcus Comstedt 
98544f2000-07-25Marcus Comstedt #include <module.h>
0917d32013-03-04Anders Johansson string cvs_version = "$Id$";
5152931999-11-02Marcus Comstedt int thread_safe=1;
3a4e182000-03-29Marcus Comstedt constant module_unique = 0;
5152931999-11-02Marcus Comstedt 
fc40392008-08-15Martin Stjernholm protected inherit "http";
5152931999-11-02Marcus Comstedt  object servlet; string status_info="";
b5dc1a2000-08-02Marcus Comstedt constant module_type = MODULE_LOCATION | MODULE_FILE_EXTENSION;
f7bd0d2001-03-03Per Hedbor constant module_name = "Java: Java Servlet bridge";
c8a8122000-11-14Marcus Comstedt constant module_doc = "An interface to Java <a href=\"http://java.sun.com/" "products/servlet/index.html""\">Servlets</a>.";
5152931999-11-02Marcus Comstedt 
0792be2000-09-10Johan Schön #if constant(Servlet.servlet)
5152931999-11-02Marcus Comstedt void stop() { if(servlet) { destruct(servlet); servlet = 0; } }
fc40392008-08-15Martin Stjernholm protected mapping(string:string) make_initparam_mapping()
5152931999-11-02Marcus Comstedt { mapping(string:string) p = ([]); string n, v;
4f641b2000-07-03Martin Nilsson  foreach(query("parameters")/"\n", string s)
5152931999-11-02Marcus Comstedt  if(2==sscanf(s, "%[^=]=%s", n, v)) p[n]=v; return p; }
b646fc2000-01-23Martin Nilsson void start(int x, Configuration conf)
5152931999-11-02Marcus Comstedt { if(x == 2) stop(); else if(x != 0) return;
98544f2000-07-25Marcus Comstedt  if(query("classname")=="NONE") { status_info = "No servlet class selected"; return; }
4f641b2000-07-03Martin Nilsson  mixed exc = catch(servlet = Servlet.servlet(query("classname"),
98544f2000-07-25Marcus Comstedt  query("codebase")-({""})));
5152931999-11-02Marcus Comstedt  status_info=""; if(exc) {
b646fc2000-01-23Martin Nilsson  report_error("Servlet: %s\n",exc[0]);
5152931999-11-02Marcus Comstedt  status_info=sprintf("<pre>%s</pre>",exc[0]); } else if(servlet) servlet->init(Servlet.conf_context(conf), make_initparam_mapping()); } string status() { return (servlet? servlet->info() || "<i>No servlet information available</i>" : "<font color=red>Servlet not loaded</font>"+"<br>"+ status_info); } string query_name() {
50f7132000-11-14Marcus Comstedt  if(query("ex"))
f620d22000-12-06Marcus Comstedt  return sprintf("Servlet %s handling extension %s",
50f7132000-11-14Marcus Comstedt  query("classname"), query("ext")*", "); else
f620d22000-12-06Marcus Comstedt  return sprintf("Servlet %s mounted on %s",
50f7132000-11-14Marcus Comstedt  query("classname"), query("location"));
5152931999-11-02Marcus Comstedt }
38b19d2000-01-25Marcus Comstedt class RXMLParseWrapper {
fc40392008-08-15Martin Stjernholm  protected object _file; protected object _id; protected string _data;
38b19d2000-01-25Marcus Comstedt  int write(string data) { _data += data; return strlen(data); } int close(void|string how) {
4f641b2000-07-03Martin Nilsson  _file->write(Roxen.parse_rxml(_data,_id));
38b19d2000-01-25Marcus Comstedt  _data=""; return _file->close(how); } mixed `->(string n) { return ::`->(n) || predef::`->(_file, n); } void create(object file, object id) { _file = file; _id = id; _data = ""; }
5152931999-11-02Marcus Comstedt }
b646fc2000-01-23Martin Nilsson mixed find_file( string f, RequestID id )
5152931999-11-02Marcus Comstedt {
b5dc1a2000-08-02Marcus Comstedt  if(!servlet || query("ex"))
5152931999-11-02Marcus Comstedt  return 0;
50f7132000-11-14Marcus Comstedt  if(id->my_fd == 0 && id->misc->trace_enter) ; /* In "Resolve path...", kluge to avoid backtrace. */ else { id->my_fd->set_read_callback(0); id->my_fd->set_close_callback(0); id->my_fd->set_blocking();
ac138f2002-01-18Tomas Nilsson  id->misc->servlet_path = query("location");
50f7132000-11-14Marcus Comstedt  id->misc->path_info = f;
ac138f2002-01-18Tomas Nilsson  id->misc->mountpoint = "";
50f7132000-11-14Marcus Comstedt  if(query("rxml"))
ae2fcb2003-03-04Anders Johansson  id->my_fd = (object)RXMLParseWrapper(id->my_fd, id);
50f7132000-11-14Marcus Comstedt  servlet->service(id); }
5152931999-11-02Marcus Comstedt 
4f641b2000-07-03Martin Nilsson  return Roxen.http_pipe_in_progress();
5152931999-11-02Marcus Comstedt }
b5dc1a2000-08-02Marcus Comstedt mixed handle_file_extension(object o, string e, RequestID id) { if(!servlet || !query("ex")) return 0;
50f7132000-11-14Marcus Comstedt  if(id->my_fd == 0 && id->misc->trace_enter) ; /* In "Resolve path...", kluge to avoid backtrace. */ else { id->my_fd->set_read_callback(0); id->my_fd->set_close_callback(0); id->my_fd->set_blocking(); id->misc->path_info = id->not_query; id->misc->mountpoint = "/"; if(query("rxml"))
ae2fcb2003-03-04Anders Johansson  id->my_fd = (object)RXMLParseWrapper(id->my_fd, id);
50f7132000-11-14Marcus Comstedt  servlet->service(id); }
b5dc1a2000-08-02Marcus Comstedt  return Roxen.http_pipe_in_progress(); }
8942842000-03-13Martin Nilsson #else
7af11b2000-09-10Johan Schön // Do not dump to a .o file if no Java is available, since it will then // not be possible to get it later on without removal of the .o file. constant dont_dump_program = 1; string status() { return #"<font color='&usr.warncolor;'>Java 2 is not available in this roxen.<p> To get Java 2: <ol> <li> Download and install Java <li> Restart roxen </ol></font>";
8942842000-03-13Martin Nilsson }
0792be2000-09-10Johan Schön mixed find_file( string f, RequestID id ) { return Roxen.http_string_answer( status(), "text/html" ); } int|mapping handle_file_extension(object o, string e, object id) { return Roxen.http_string_answer( status(), "text/html" ); }
5152931999-11-02Marcus Comstedt #endif
7af11b2000-09-10Johan Schön 
f7e56b2000-09-11Johan Schön class ClassPathList { inherit Variable.FileList; array verify_set( string|array(string) value ) { if(stringp(value)) value = ({ value }); string warn = ""; foreach( value-({""}), string value ) { Stat s = r_file_stat( value ); Stdio.File f = Stdio.File(); if( !s ) warn += value+" does not exist\n"; else if( s[ ST_SIZE ] == -2 ) ; else if( !(f->open( value, "r" )) ) warn += "Can't read "+value+"\n"; else { if( f->read(2) != "PK" ) warn += value+" is not a JAR file\n"; f->close(); } } if( strlen( warn ) ) return ({ warn, value }); return ::verify_set( value ); } }
0792be2000-09-10Johan Schön array(string) query_file_extensions() { return (query("ex")? query("ext") : ({})); }
7af11b2000-09-10Johan Schön void create() { defvar("ex", 0, "File extension servlet", TYPE_FLAG, "Use a servlet mapping based on file extension rather than " "path location."); defvar("location", "/servlet/NONE", "Servlet location", TYPE_LOCATION, "This is where the servlet will be inserted in the " "namespace of your server.", 0, lambda() { return query("ex"); }); defvar("ext", ({}), "Servlet extensions", TYPE_STRING_LIST, "All files ending with these extensions, will be handled by "+ "this servlet.", 0, lambda() { return !query("ex"); }); defvar("codebase", ClassPathList( ({"servlets"}), 0, "Class path", "Any number of directories and/or JAR " "files from which to load the servlet " "and its support classes.") ); defvar("classname", "NONE", "Class name", TYPE_STRING, "The name of the servlet class to use."); defvar("parameters", "", "Parameters", TYPE_TEXT, "Parameters for the servlet on the form " "<tt><i>name</i>=<i>value</i></tt>, one per line."); defvar("rxml", 0, "Parse RXML in servlet output", TYPE_FLAG|VAR_MORE, "If this is set, the output from the servlet handled by this " "module will be RXML parsed. NOTE: No data will be returned to the " "client until the output is fully parsed."); }