package Serfler; // Serfler - an Http server written in Java based on servlets // Copyright (c) 1998 by Douglas Harris // Distributed under the GNU General Public License // // A copy is included with this software distribution. // The package is available from // http://spectral.mscs.mu.edu/javadev/src/serfler.zip // import javax.servlet.*; import java.util.*; import java.io.*; public class SerflerContext extends ClassLoader implements ServletContext{ static Hashtable localServlets = new Hashtable(); static Properties serflerProperties; static public String sDocumentRoot="/"; // Should start and end with slash static public String sImageDirectory="/images"; // Should start and end with slash static public String sServletDirectory="/javadev/servletCode"; static String sServerInfo="WebServlet 0.5";; static PrintWriter sServerLogWriter = new PrintWriter(System.err); String sLogFileName="/tmp/serfler.log"; ServletConfig serflerConfig = new Serfler.SerflerConfig(); public static Servlet qFileServlet; public static Servlet qLoadServlet; public static Servlet qDefaultServlet; public static Servlet qUnknownServlet; public static Servlet qErrorServlet; public SerflerContext(){ } public void init(Properties serflerProperties){ this.serflerProperties=serflerProperties; sDocumentRoot=serflerProperties.getProperty("document.dir",sDocumentRoot); System.out.println("sDocumentRoot: "+sDocumentRoot); sServletDirectory=serflerProperties.getProperty("servlet.code",sServletDirectory); System.out.println("sServletDirectory: "+sServletDirectory); sImageDirectory=serflerProperties.getProperty("image.dir",sImageDirectory); System.out.println("sImageDirectory: "+sImageDirectory); sLogFileName= serflerProperties.getProperty("server.log", sLogFileName); System.out.println("sLogFileName: "+sLogFileName); try{ sServerLogWriter = new PrintWriter(new FileOutputStream(sLogFileName),true); System.out.println("Logging at:" + sLogFileName); } catch(IOException x){ log(x,"Changing log file to "+sLogFileName); } } /* * START implementation of ServletContext */ /** * Enumerates the servlets in this context (server). Only servlets * that are accessible will be returned. The enumeration always * includes the servlet itself. */ public Enumeration getServletNames(){ return localServlets.keys(); } // DEPRECATED public Enumeration getServlets(){ return getServletNames(); } /** * Returns the servlet for the specified name. * @param name the name of the servlet * @return the Servlet, or null if not found * @exception ServletException if the servlet could not be initialized */ public Servlet getServlet(String name) throws ServletException{ return (Servlet)localServlets.get(name); } /** * Writes a message to the servlet log file. * @param msg the message to be written */ public void log(String msg){ Date date=new Date(System.currentTimeMillis()); String head="["+date.toString()+"] "; sServerLogWriter.println(head+msg); //System.out.println("LOG: "+head+msg); } /** * Writes a message to the servlet log file. * @param msg the message to be written */ public void log(Exception x, String msg){ log(x.toString()+": "+msg); } /** * Applies alias rules to the specified virtual path and returns the * corresponding real path. Returns null if the translation could not * be performed. * @param path the real path to be translated */ public String getRealPath(String path){ int index; String prefix="/images"; if (path.equals(prefix)){ path=sImageDirectory; return path.replace('/',File.separatorChar); } if (path.startsWith(prefix+"/")){ path=sImageDirectory+path.substring(prefix.length()); return path.replace('/',File.separatorChar); } // JDH Do any more aliasing needed here if (path.startsWith("/~")){ path=path.substring(2); index=path.indexOf("/"); if (index<0){ path="/home/"+path+"/public_html"; }else{ path="/home/"+path.substring(0,index+1)+"public_html"+path.substring(index); } }else{ if (path.startsWith("/")){ path=path.substring(1); } if (!sDocumentRoot.startsWith("/")){ sDocumentRoot="/"+sDocumentRoot; } if (!sDocumentRoot.endsWith("/")){ sDocumentRoot=sDocumentRoot+"/"; } path=sDocumentRoot+path; if (path.equals("/")){ path="/../"; } } return path.replace('/',File.separatorChar); } /** * Returns the mime type of the specified file, or null if not known. * @param file file name whose mime type is required */ public String getMimeType(String file){ return Utilities.MimeProperties.getMimeType(file); } /** * Returns the name and version of the Web server under which the * servlet is running. Same as the CGI variable SERVER_SOFTWARE. */ public String getServerInfo(){ return sServerInfo; } /** * Returns an attribute of the server given the specified key name. * This allows access to additional information about the server not * already provided by the other methods in this interface. Attribute * names should follow the same convention as package names, and those * beginning with 'com.sun.*' are reserved for use by Sun Microsystems. * @param name the attribute key name * @return the value of the attribute, or null if not defined */ public Object getAttribute(String name){ return null; } /* * END implementation of ServletContext */ /* * START loader code */ /* * Added loadClass for JDK1.1 compatibility * Just remove it for JDK1.2 */ public synchronized Class loadClass(String className, boolean resolve) throws ClassNotFoundException{ Class c=null; c=findSystemClass(className); if (c==null){ c=findLoadedClass(className); } if (c==null){ c=findLocalClass(className); } if (resolve && c!=null){ resolveClass(c); } return c; } public synchronized Class findLocalClass(String className){ Class c=null; byte[] byteCode = getClassByteCode(className); if (byteCode != null) { c=(defineClass(className, byteCode, 0, byteCode.length)); } return c; } private byte[] getClassByteCode(String className){ byte result[]; String fileName= sServletDirectory+File.separatorChar+className+".class"; try { FileInputStream i = new FileInputStream(fileName); result = new byte[i.available()]; i.read(result); return result; } catch (Exception x){ return null; } } public Servlet getServletInstance(String servletClassName){ Class servletClass=null; Servlet servletInstance=null; try{ servletClass=loadClass(servletClassName); if (servletClass!=null){ servletInstance=(Servlet)servletClass.newInstance(); } } catch(IllegalAccessException x){ log("getServletInstance: threw "+x.toString()); } catch(InstantiationException x){ log("getServletInstance: threw "+x.toString()); } catch(ClassNotFoundException x){ log("getServletInstance: threw "+x.toString()); } catch(ClassCastException x){ log("getServletInstance: threw "+x.toString()); } return servletInstance; } public boolean addServlet(String name, Servlet instance){ ServletConfig cfg=(ServletConfig)new SerflerConfig(this); return addServlet(name, instance, cfg); } public boolean addServlet(String name, Servlet inst, ServletConfig cfg){ boolean isOK=false; String logString="addServlet("+name+", inst, cfg)"; try{ inst.init(cfg); localServlets.put(name, inst); isOK=true; }catch (Exception x){ log(x,logString); }finally{ return isOK; } } public void loadSerflerServlets(){ try{ qFileServlet = getServletInstance("Serfler.Servlet.FileServlet"); if (qFileServlet==null){ System.err.println("No File Servlet"); System.exit(10); } qFileServlet.init(serflerConfig); qLoadServlet =getServletInstance("Serfler.Servlet.LoadServlet"); if (qFileServlet==null){ System.err.println("No Load Servlet"); System.exit(10); } qLoadServlet.init(serflerConfig); qDefaultServlet =getServletInstance("Serfler.Servlet.DefaultServlet"); if (qFileServlet==null){ System.err.println("No Default Servlet"); System.exit(10); } qDefaultServlet.init(serflerConfig); qUnknownServlet =getServletInstance("Serfler.Servlet.UnknownServlet"); if (qFileServlet==null){ System.err.println("No Unknown Servlet"); System.exit(10); } qUnknownServlet.init(serflerConfig); qErrorServlet = getServletInstance("Serfler.Servlet.ErrorServlet"); if (qFileServlet==null){ System.err.println("No Error Servlet"); System.exit(10); } qErrorServlet.init(serflerConfig); } catch(ServletException x){ x.printStackTrace(System.out); System.exit(1); } } public void setServlets(){ if (!addServlet("hello",getServletInstance("HelloWorldServlet"))){ log("addServlet(hello) failed"); } if (!addServlet("simple",getServletInstance("SimpleServlet"))){ log("addServlet(simple) failed"); } if (!addServlet("date",getServletInstance("DateServlet"))){ log("addServlet(date) failed"); } if (!addServlet("snoop",getServletInstance("SnoopServlet"))){ log("addServlet(snoop) failed"); } /*JDH Use properties file for more*/ } public static void main(String[] args){ SerflerContext loader = new SerflerContext(); if (loader==null){ System.err.println("No loader!"); System.exit(1); } Servlet servlet; loader.loadSerflerServlets(); loader.setServlets(); for (int i=0;i