?? serve.java
字號:
// Serve - minimal Java HTTP server class//// Copyright (C)1996,1998 by Jef Poskanzer <jef@acme.com>. All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions// are met:// 1. Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// 2. Redistributions in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in the// documentation and/or other materials provided with the distribution.//// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF// SUCH DAMAGE.//// Visit the ACME Labs Java page for up-to-date versions of this and other// fine Java utilities: http://www.acme.com/java///// All enhancments Copyright (C)1998-2002 by Dmitriy Rogatkin// this version is compatible with JSDK 2.3// http://tjws.sourceforge.net// $Id: Serve.java,v 1.1 2004/09/08 22:00:24 drogatkin Exp $package Acme.Serve;import java.io.*;import java.util.*;import java.net.*;import java.text.*;import javax.servlet.*;import javax.servlet.http.*;/// Minimal Java HTTP server class.// <P>// This class implements a very small embeddable HTTP server.// It runs Servlets compatible with the API used by JavaSoft's// <A HREF="http://java.sun.com/products/java-server/">JavaServer</A> server.// It comes with default Servlets which provide the usual// httpd services, returning files and directory listings.// <P>// This is not in any sense a competitor for JavaServer.// JavaServer is a full-fledged HTTP server and more.// Acme.Serve is tiny, about 1500 lines, and provides only the// functionality necessary to deliver an Applet's .class files// and then start up a Servlet talking to the Applet.// They are both written in Java, they are both web servers, and// they both implement the Servlet API; other than that they couldn't// be more different.// <P>// This is actually the second HTTP server I've written.// The other one is called// <A HREF="http://www.acme.com/software/thttpd/">thttpd</A>,// it's written in C, and is also pretty small although much more// featureful than this.// <P>// Other Java HTTP servers:// <UL>// <LI> The above-mentioned <A HREF="http://java.sun.com/products/java-server/">JavaServer</A>.// <LI> W3C's <A HREF="http://www.w3.org/pub/WWW/Jigsaw/">Jigsaw</A>.// <LI> David Wilkinson's <A HREF="http://www.netlink.co.uk/users/cascade/http/">Cascade</A>.// <LI> Yahoo's <A HREF="http://www.yahoo.com/Computers_and_Internet/Software/Internet/World_Wide_Web/Servers/Java/">list of Java web servers</A>.// </UL>// <P>// A <A HREF="http://www.byte.com/art/9706/sec8/art1.htm">June 1997 BYTE magazine article</A> mentioning this server.<BR>// A <A HREF="http://www.byte.com/art/9712/sec6/art7.htm">December 1997 BYTE magazine article</A> giving it an Editor's Choice Award of Distinction.<BR>// <A HREF="/resources/classes/Acme/Serve/Serve.java">Fetch the software.</A><BR>// <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A>// <P>// @see Acme.Serve.servlet.http.HttpServlet// @see FileServlet// @see CgiServlet// make it final?public class Serve implements ServletContext, RequestDispatcher{ private static final String progName = "Serve"; public static final String ARG_PORT = "port"; public static final String ARG_THROTTLES = "throttles"; public static final String ARG_SERVLETS = "servlets"; public static final String ARG_REALMS = "realms"; public static final String ARG_ALIASES = "aliases"; public static final String ARG_CGI_PATH = "cgi-path"; public static final String ARG_SESSION_TIMEOUT = "session-timeout"; public static final String ARG_LOG_OPTIONS = "log-options"; public static final String ARG_SOCKET_FACTORY = "socketFactory"; protected static final int DEF_SESSION_TIMEOUT = 30; // in minutes protected static final int DEF_PORT = 9090; /// Main routine, if you want to run this directly as an application. public static void main( String[] args ) { Hashtable arguments = new Hashtable(20); int argc = args.length; int argn; // Parse args. if (argc == 0) // a try to read from file for java -jar server.jar try { BufferedReader br = new BufferedReader(new FileReader("cmdparams")); StringTokenizer st = new StringTokenizer(br.readLine(), " "); args = new String[st.countTokens()]; argc = args.length; // tail can be nulled for (int i=0; i<argc && st.hasMoreTokens(); i++) args[i] = st.nextToken(); } catch(Exception e) { // many can happen } for ( argn = 0; argn < argc && args[argn].charAt( 0 ) == '-'; ) { if ( args[argn].equals( "-p" ) && argn + 1 < argc ) { ++argn; arguments.put(ARG_PORT, new Integer(args[argn])); } else if ( args[argn].equals( "-t" ) && argn + 1 < argc ) { ++argn; arguments.put(ARG_THROTTLES, args[argn]); } else if ( args[argn].equals( "-s" ) && argn + 1 < argc ) { ++argn; arguments.put(ARG_SERVLETS, args[argn]); } else if ( args[argn].equals( "-r" ) && argn + 1 < argc ) { ++argn; arguments.put(ARG_REALMS, args[argn]); } else if ( args[argn].equals( "-a" ) && argn + 1 < argc ) { ++argn; arguments.put(ARG_ALIASES, args[argn]); } else if ( args[argn].equals( "-c" ) && argn + 1 < argc ) { ++argn; arguments.put(ARG_CGI_PATH, args[argn]); } else if ( args[argn].equals( "-e" ) && argn + 1 < argc ) { ++argn; try { arguments.put(ARG_SESSION_TIMEOUT, new Integer(args[argn])); } catch(NumberFormatException nfe) { } } else if ( args[argn].startsWith( "-l" ) ) { if (args[argn].length() > 2) arguments.put(ARG_LOG_OPTIONS, args[argn].substring(2).toUpperCase()); else arguments.put(ARG_LOG_OPTIONS, ""); } else if ( args[argn].startsWith( "-" ) ) { if (args[argn].length() > 1) arguments.put(args[argn].substring(1),//.toUpperCase(), argn<argc-1?args[++argn]:""); } else usage(); ++argn; } if ( argn != argc ) usage(); /** format path mapping from=givenpath;dir=realpath */ PrintStream printstream = System.err; try { printstream = new PrintStream(new FileOutputStream("AWS-"+System.currentTimeMillis()+".log"), true); System.setErr(printstream); } catch(IOException e) { System.err.println("IO problem at setting a log stream "+e); } PathTreeDictionary mappingtable = new PathTreeDictionary(); if (arguments.get(ARG_ALIASES) != null) { File file = new File( (String)arguments.get(ARG_ALIASES) ); if ( file.exists() && file.canRead() ) { try { DataInputStream in = new DataInputStream(new FileInputStream(file)); do { String mappingstr = in.readLine(); if (mappingstr == null) break; StringTokenizer maptokenzr = new StringTokenizer(mappingstr, "=;"); if (maptokenzr.hasMoreTokens()) { if (maptokenzr.nextToken("=").equalsIgnoreCase("from")) { if (maptokenzr.hasMoreTokens()) { String srcpath = maptokenzr.nextToken("=;"); if (maptokenzr.hasMoreTokens() && maptokenzr.nextToken(";=").equalsIgnoreCase("dir")) try { if (maptokenzr.hasMoreTokens()) mappingtable.put(srcpath, maptokenzr.nextToken()); } catch (NullPointerException e) { } } } } } while(true); } catch ( IOException e ) { System.err.println( "Problem reading aliases file: "+arguments.get(ARG_ALIASES) +"/" + e ); } } else System.err.println("FIle "+arguments.get(ARG_ALIASES)+" doesn't exist or not readable."); } /** format realmname=path,user:password,,,, */ PathTreeDictionary realms = new PathTreeDictionary(); if (arguments.get(ARG_REALMS) != null) { try { DataInputStream in = new DataInputStream(new FileInputStream((String)arguments.get(ARG_REALMS))); do { String realmstr = in.readLine(); if (realmstr == null) break; StringTokenizer rt = new StringTokenizer(realmstr, "=,:"); String realmname = null; BasicAuthRealm realm = null; if (rt.hasMoreTokens()) realmname=rt.nextToken(); else continue; if (rt.hasMoreTokens()) { realm = new BasicAuthRealm(realmname); realms.put(rt.nextToken(), realm); } else continue; if (rt.hasMoreTokens()) { String user = rt.nextToken(); if (rt.hasMoreTokens()) realm.put(user, rt.nextToken()); } } while(true); } catch(IOException ioe) { System.err.println("Problem in reading realms file "+arguments.get(ARG_REALMS)+"/ "+ioe); } } // Create the server. final Serve serve = new Serve( arguments, printstream ); final String cf = (String)arguments.get(ARG_SERVLETS); serve.setMappingTable(mappingtable); serve.setRealms(realms); new Thread(new Runnable() { public void run() { serve.readServlets(cf); } }).start(); // And add the standard Servlets. String throttles = (String)arguments.get(ARG_THROTTLES); if ( throttles == null ) serve.addDefaultServlets( (String)arguments.get(ARG_CGI_PATH) ); else try { serve.addDefaultServlets( (String)arguments.get(ARG_CGI_PATH), throttles ); } catch ( IOException e ) { System.err.println( "Problem reading throttles file: " + e ); System.exit( 1 ); } // And run. serve.serve(); System.exit( 0 ); } private static void usage() { System.err.println( "usage: " + progName + " [-p port] [-s servletpropertiesfile] [-a aliasmappingfile] [-l[a][r]] [-c cgi-bin-dir] [-e [-]duration_in_minutes] [-socketFactory class name and other parameters}" ); System.exit( 1 ); } private void readServlets(String cfgfile) { /** servlet.properties file format servlet.<servletname>.code=<servletclass> servlet.<servletname>.initArgs=<name=value>,<name=value> */ Hashtable servletstbl, parameterstbl; servletstbl = new Hashtable(); parameterstbl = new Hashtable(); if (cfgfile != null) { File file = new File( cfgfile ); if ( file.exists() && file.canRead() ) { try { DataInputStream in = new DataInputStream(new FileInputStream(file)); /** format of servlet.cfg file servlet_name;servlet_class;init_parameter1=value1;init_parameter2=value2... */ do { String servletdsc = in.readLine(); if (servletdsc == null) break; StringTokenizer dsctokenzr = new StringTokenizer(servletdsc, ".=,", false); if (dsctokenzr.hasMoreTokens()) { if (!dsctokenzr.nextToken().equalsIgnoreCase("servlet")) { System.err.println("No leading 'servlet' keyword, the sentence is skipped"); break; } if (dsctokenzr.hasMoreTokens()) { String servletname = dsctokenzr.nextToken(); if (dsctokenzr.hasMoreTokens()) { String lt = dsctokenzr.nextToken(); if (lt.equalsIgnoreCase("code")) { if (dsctokenzr.hasMoreTokens()) servletstbl.put(servletname, dsctokenzr.nextToken("=")); } else if (lt.equalsIgnoreCase("initArgs")) { Hashtable initparams = new Hashtable(); while (dsctokenzr.hasMoreTokens()) { String key = dsctokenzr.nextToken("=,"); if (dsctokenzr.hasMoreTokens()) initparams.put(key, dsctokenzr.nextToken(",=")); } parameterstbl.put(servletname, initparams); } else System.err.println("Unrecognized token "+lt+" in "+servletdsc+ ", the line's skipped"); } } } } while (true); } catch ( IOException e ) { System.err.println( "Problem reading cfg file: " + e ); } Enumeration se = servletstbl.keys(); String servletname; while (se.hasMoreElements()) { servletname = (String)se.nextElement(); addServlet(servletname, (String)servletstbl.get(servletname), (Hashtable)parameterstbl.get(servletname)); } } } } int port; String hostName; private PrintStream logStream; private boolean useAccLog; private boolean showUserAgent; private boolean showReferer; protected PathTreeDictionary registry; protected PathTreeDictionary realms; private PathTreeDictionary mappingtable; private Hashtable attributes;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -