00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 package Acme.Serve;
00036
00037 import java.io.*;
00038 import java.util.*;
00039 import java.net.*;
00040 import java.text.*;
00041 import javax.servlet.*;
00042 import javax.servlet.http.*;
00043
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 public class Serve implements ServletContext, RequestDispatcher {
00086
00087 private static final String progName = "Serve";
00088 public static final String ARG_PORT = "port";
00089 public static final String ARG_THROTTLES = "throttles";
00090 public static final String ARG_SERVLETS = "servlets";
00091 public static final String ARG_REALMS = "realms";
00092 public static final String ARG_ALIASES = "aliases";
00093 public static final String ARG_CGI_PATH = "cgi-path";
00094 public static final String ARG_SESSION_TIMEOUT = "session-timeout";
00095 public static final String ARG_LOG_OPTIONS = "log-options";
00096 public static final String ARG_SOCKET_FACTORY = "socketFactory";
00097
00098 protected static final int DEF_SESSION_TIMEOUT = 30;
00099 protected static final int DEF_PORT = 9090;
00100
00102 public static void main(String[] args) {
00103 Hashtable arguments = new Hashtable(20);
00104
00105 int argc = args.length;
00106 int argn;
00107
00108 if (argc == 0)
00109 try {
00110 BufferedReader br = new BufferedReader(new FileReader("cmdparams"));
00111 StringTokenizer st = new StringTokenizer(br.readLine(), " ");
00112 args = new String[st.countTokens()];
00113 argc = args.length;
00114 for (int i = 0; i < argc && st.hasMoreTokens(); i++)
00115 args[i] = st.nextToken();
00116 } catch (Exception e) {
00117 }
00118 for (argn = 0; argn < argc && args[argn].charAt(0) == '-';) {
00119 if (args[argn].equals("-p") && argn + 1 < argc) {
00120 ++argn;
00121 arguments.put(ARG_PORT, new Integer(args[argn]));
00122 } else if (args[argn].equals("-t") && argn + 1 < argc) {
00123 ++argn;
00124 arguments.put(ARG_THROTTLES, args[argn]);
00125 } else if (args[argn].equals("-s") && argn + 1 < argc) {
00126 ++argn;
00127 arguments.put(ARG_SERVLETS, args[argn]);
00128 } else if (args[argn].equals("-r") && argn + 1 < argc) {
00129 ++argn;
00130 arguments.put(ARG_REALMS, args[argn]);
00131 } else if (args[argn].equals("-a") && argn + 1 < argc) {
00132 ++argn;
00133 arguments.put(ARG_ALIASES, args[argn]);
00134 } else if (args[argn].equals("-c") && argn + 1 < argc) {
00135 ++argn;
00136 arguments.put(ARG_CGI_PATH, args[argn]);
00137 } else if (args[argn].equals("-e") && argn + 1 < argc) {
00138 ++argn;
00139 try {
00140 arguments.put(ARG_SESSION_TIMEOUT, new Integer(args[argn]));
00141 } catch (NumberFormatException nfe) {
00142 }
00143 } else if (args[argn].startsWith("-l")) {
00144 if (args[argn].length() > 2)
00145 arguments.put(ARG_LOG_OPTIONS, args[argn].substring(2).toUpperCase());
00146 else
00147 arguments.put(ARG_LOG_OPTIONS, "");
00148 } else if (args[argn].startsWith("-")) {
00149 if (args[argn].length() > 1)
00150 arguments.put(args[argn].substring(1),
00151
00152 argn < argc - 1 ? args[++argn] : "");
00153 } else
00154 usage();
00155
00156 ++argn;
00157 }
00158 if (argn != argc)
00159 usage();
00163 PrintStream printstream = System.err;
00164 try {
00165 printstream = new PrintStream(new FileOutputStream("AWS-" + System.currentTimeMillis() + ".log"), true);
00166 System.setErr(printstream);
00167 } catch (IOException e) {
00168 System.err.println("IO problem at setting a log stream " + e);
00169 }
00170 PathTreeDictionary mappingtable = new PathTreeDictionary();
00171 if (arguments.get(ARG_ALIASES) != null) {
00172 File file = new File((String) arguments.get(ARG_ALIASES));
00173 if (file.exists() && file.canRead()) {
00174 try {
00175 DataInputStream in = new DataInputStream(new FileInputStream(file));
00176 do {
00177 String mappingstr = in.readLine();
00178 if (mappingstr == null)
00179 break;
00180 StringTokenizer maptokenzr = new StringTokenizer(mappingstr, "=;");
00181 if (maptokenzr.hasMoreTokens()) {
00182 if (maptokenzr.nextToken("=").equalsIgnoreCase("from")) {
00183 if (maptokenzr.hasMoreTokens()) {
00184 String srcpath = maptokenzr.nextToken("=;");
00185 if (maptokenzr.hasMoreTokens() && maptokenzr.nextToken(";=").equalsIgnoreCase("dir"))
00186 try {
00187 if (maptokenzr.hasMoreTokens())
00188 mappingtable.put(srcpath, maptokenzr.nextToken());
00189 } catch (NullPointerException e) {
00190 }
00191 }
00192 }
00193 }
00194 } while (true);
00195 } catch (IOException e) {
00196 System.err.println("Problem reading aliases file: " + arguments.get(ARG_ALIASES) + "/" + e);
00197 }
00198 } else
00199 System.err.println("FIle " + arguments.get(ARG_ALIASES) + " doesn't exist or not readable.");
00200 }
00203 PathTreeDictionary realms = new PathTreeDictionary();
00204 if (arguments.get(ARG_REALMS) != null) {
00205 try {
00206 DataInputStream in = new DataInputStream(new FileInputStream((String) arguments.get(ARG_REALMS)));
00207
00208 do {
00209 String realmstr = in.readLine();
00210 if (realmstr == null)
00211 break;
00212 StringTokenizer rt = new StringTokenizer(realmstr, "=,:");
00213 String realmname = null;
00214 BasicAuthRealm realm = null;
00215 if (rt.hasMoreTokens())
00216 realmname = rt.nextToken();
00217 else
00218 continue;
00219 if (rt.hasMoreTokens()) {
00220 realm = new BasicAuthRealm(realmname);
00221 realms.put(rt.nextToken(), realm);
00222 } else
00223 continue;
00224 if (rt.hasMoreTokens()) {
00225 String user = rt.nextToken();
00226 if (rt.hasMoreTokens())
00227 realm.put(user, rt.nextToken());
00228 }
00229 } while (true);
00230 } catch (IOException ioe) {
00231 System.err.println("Problem in reading realms file " + arguments.get(ARG_REALMS) + "/ " + ioe);
00232 }
00233 }
00234
00235
00236 final Serve serve = new Serve(arguments, printstream);
00237 final String cf = (String) arguments.get(ARG_SERVLETS);
00238 serve.setMappingTable(mappingtable);
00239 serve.setRealms(realms);
00240
00241 new Thread(new Runnable() {
00242 public void run() {
00243 serve.readServlets(cf);
00244 }
00245 }).start();
00246
00247 String throttles = (String) arguments.get(ARG_THROTTLES);
00248 if (throttles == null)
00249 serve.addDefaultServlets((String) arguments.get(ARG_CGI_PATH));
00250 else
00251 try {
00252 serve.addDefaultServlets((String) arguments.get(ARG_CGI_PATH), throttles);
00253 } catch (IOException e) {
00254 System.err.println("Problem reading throttles file: " + e);
00255 System.exit(1);
00256 }
00257
00258
00259 serve.serve();
00260
00261 System.exit(0);
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271 private static void usage() {
00272 System.err.println(
00273 "usage: "
00274 + progName
00275 + " [-p port] [-s servletpropertiesfile] [-a aliasmappingfile] [-l[a][r]] [-c cgi-bin-dir] [-e [-]duration_in_minutes] [-socketFactory class name and other parameters}");
00276 System.exit(1);
00277 }
00278
00279 private void readServlets(String cfgfile) {
00284 Hashtable servletstbl, parameterstbl;
00285 servletstbl = new Hashtable();
00286 parameterstbl = new Hashtable();
00287 if (cfgfile != null) {
00288 File file = new File(cfgfile);
00289 if (file.exists() && file.canRead()) {
00290 try {
00291 DataInputStream in = new DataInputStream(new FileInputStream(file));
00295 do {
00296 String servletdsc = in.readLine();
00297 if (servletdsc == null)
00298 break;
00299 StringTokenizer dsctokenzr = new StringTokenizer(servletdsc, ".=,", false);
00300 if (dsctokenzr.hasMoreTokens()) {
00301 if (!dsctokenzr.nextToken().equalsIgnoreCase("servlet")) {
00302 System.err.println("No leading 'servlet' keyword, the sentence is skipped");
00303 break;
00304 }
00305 if (dsctokenzr.hasMoreTokens()) {
00306 String servletname = dsctokenzr.nextToken();
00307
00308 if (dsctokenzr.hasMoreTokens()) {
00309 String lt = dsctokenzr.nextToken();
00310 if (lt.equalsIgnoreCase("code")) {
00311 if (dsctokenzr.hasMoreTokens())
00312 servletstbl.put(servletname, dsctokenzr.nextToken("="));
00313 } else if (lt.equalsIgnoreCase("initArgs")) {
00314 Hashtable initparams = new Hashtable();
00315 while (dsctokenzr.hasMoreTokens()) {
00316 String key = dsctokenzr.nextToken("=,");
00317 if (dsctokenzr.hasMoreTokens())
00318 initparams.put(key, dsctokenzr.nextToken(",="));
00319 }
00320 parameterstbl.put(servletname, initparams);
00321 } else
00322 System.err.println("Unrecognized token " + lt + " in " + servletdsc + ", the line's skipped");
00323 }
00324 }
00325 }
00326 }
00327 while (true);
00328 } catch (IOException e) {
00329 System.err.println("Problem reading cfg file: " + e);
00330 }
00331 Enumeration se = servletstbl.keys();
00332 String servletname;
00333 while (se.hasMoreElements()) {
00334 servletname = (String) se.nextElement();
00335 addServlet(servletname, (String) servletstbl.get(servletname), (Hashtable) parameterstbl.get(servletname));
00336 }
00337 }
00338 }
00339 }
00340
00341 int port;
00342 String hostName;
00343 private PrintStream logStream;
00344 private boolean useAccLog;
00345 private boolean showUserAgent;
00346 private boolean showReferer;
00347 protected PathTreeDictionary registry;
00348 protected PathTreeDictionary realms;
00349 private PathTreeDictionary mappingtable;
00350 private Hashtable attributes;
00351 sun.misc.BASE64Decoder base64Dec = new sun.misc.BASE64Decoder();
00352
00353 int uniqer;
00354 HttpSessionContextImpl sessions;
00355 static int expiredIn;
00356 protected Hashtable arguments;
00357
00359 public Serve(Hashtable arguments, PrintStream logStream) {
00360 this.arguments = arguments;
00361 this.logStream = logStream;
00362 registry = new PathTreeDictionary();
00363 realms = new PathTreeDictionary();
00364 attributes = new Hashtable();
00365 sessions = new HttpSessionContextImpl();
00366 setAccessLogged();
00367 expiredIn = arguments.get(ARG_SESSION_TIMEOUT) != null ? ((Integer) arguments.get(ARG_SESSION_TIMEOUT)).intValue() : DEF_SESSION_TIMEOUT;
00368 port = arguments.get(ARG_PORT) != null ? ((Integer) arguments.get(ARG_PORT)).intValue() : DEF_PORT;
00369 }
00370
00371 public Serve() {
00372 this(new Hashtable(), System.err);
00373 }
00374
00375 void setAccessLogged() {
00376 String logflags = (String) arguments.get(ARG_LOG_OPTIONS);
00377 if (logflags != null) {
00378 useAccLog = true;
00379 showUserAgent = logflags.indexOf('A') >= 0;
00380 showReferer = logflags.indexOf('R') >= 0;
00381 }
00382 }
00383
00384 boolean isAccessLogged() {
00385 return useAccLog;
00386 }
00387 boolean isShowReferer() {
00388 return showReferer;
00389 }
00390 boolean isShowUserAgent() {
00391 return showUserAgent;
00392 }
00393
00395
00396
00397
00398 public void addServlet(String urlPat, String className) {
00399 addServlet(urlPat, className, (Hashtable) null);
00400 }
00401
00402 public void addServlet(String urlPat, String className, Hashtable initParams) {
00403
00404 SecurityManager security = System.getSecurityManager();
00405 if (security != null) {
00406 int i = className.lastIndexOf('.');
00407 if (i != -1) {
00408 security.checkPackageAccess(className.substring(0, i));
00409 security.checkPackageDefinition(className.substring(0, i));
00410 }
00411 }
00412
00413
00414 try {
00415 addServlet(urlPat, (Servlet) Class.forName(className).newInstance(), initParams);
00416 return;
00417 } catch (ClassNotFoundException e) {
00418 log("Class not found: " + className);
00419 } catch (ClassCastException e) {
00420 log("Class cast problem: " + e.getMessage());
00421 } catch (InstantiationException e) {
00422 log("Instantiation problem: " + e.getMessage());
00423 } catch (IllegalAccessException e) {
00424 log("Illegal class access: " + e.getMessage());
00425 } catch (Exception e) {
00426 log("Unexpected problem creating servlet: " + e, e);
00427 }
00428 }
00429
00431
00432
00433
00434 public void addServlet(String urlPat, Servlet servlet) {
00435 addServlet(urlPat, servlet, (Hashtable) null);
00436 }
00437
00438 public void addServlet(String urlPat, Servlet servlet, Hashtable initParams) {
00439 try {
00440 servlet.init(new ServeConfig((ServletContext) this, initParams, urlPat));
00441 registry.put(urlPat, servlet);
00442 } catch (ServletException e) {
00443 log("Problem initializing servlet: " + e);
00444 }
00445 }
00446
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 public void addDefaultServlets(String cgi) {
00462 if (cgi != null)
00463 addServlet("/" + cgi, new Acme.Serve.CgiServlet());
00464 addServlet("/", new Acme.Serve.FileServlet());
00465 }
00466
00468
00469
00470 public void addDefaultServlets(String cgi, String throttles) throws IOException {
00471 if (cgi != null)
00472 addServlet("/" + cgi, new Acme.Serve.CgiServlet());
00473 addServlet("/", new Acme.Serve.FileServlet(throttles));
00474 }
00475
00476
00477 boolean running = true;
00478 public void serve() {
00479 final ServerSocket serverSocket;
00480 try {
00481 serverSocket = createServerSocket();
00482 } catch (IOException e) {
00483 log("Server socket: " + e);
00484 return;
00485 }
00486 hostName = serverSocket.getInetAddress().getHostName();
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 if (expiredIn > 0) {
00506 Thread t = new Thread(new Runnable() {
00507 public void run() {
00508 while (running) {
00509 try {
00510 Thread.sleep(expiredIn * 60 * 1000);
00511 } catch (InterruptedException ie) {
00512 }
00513 Enumeration e = sessions.keys();
00514 while (e.hasMoreElements()) {
00515 Object sid = e.nextElement();
00516 if (sid != null) {
00517 AcmeSession as = (AcmeSession) sessions.get(sid);
00518 if (as != null
00519 && (as.getMaxInactiveInterval() * 1000 < System.currentTimeMillis() - as.getLastAccessedTime()
00520 || !as.isValid())) {
00521
00522 as = (AcmeSession) sessions.remove(sid);
00523 if (as != null && as.isValid())
00524 try {
00525 as.invalidate();
00526 } catch (IllegalStateException ise) {
00527
00528 }
00529 }
00530 }
00531 }
00532 }
00533 }
00534 }, "Session cleaner");
00535 t.setPriority(Thread.MIN_PRIORITY);
00536 t.start();
00537 } else
00538 expiredIn = -expiredIn;
00539 System.out.println("WebServer :" + port + " is ready.");
00540 try {
00541 while (running) {
00542 Socket socket = serverSocket.accept();
00543 new ServeConnection(socket, this);
00544 }
00545 } catch (IOException e) {
00546 log("Accept: " + e);
00547 } finally {
00548 try {
00549 serverSocket.close();
00550 } catch (IOException e) {
00551 }
00552 destroyAllServlets();
00553 }
00554 }
00555
00556 public static interface SocketFactory {
00557 public ServerSocket createSocket(Hashtable arguments) throws IOException, IllegalArgumentException;
00558 }
00559
00560 protected ServerSocket createServerSocket() throws IOException {
00561 String socketFactoryClass = (String) arguments.get(ARG_SOCKET_FACTORY);
00562 if (socketFactoryClass != null)
00563 try {
00564 return ((SocketFactory) Class.forName(socketFactoryClass).newInstance()).createSocket(arguments);
00565 } catch (Exception e) {
00566 System.err.println("Couldn't create custom socket factory " + socketFactoryClass + " or call creation method. Standard socket will be created. " + e);
00567 }
00568 return new ServerSocket(port, 1000);
00569 }
00570
00571
00572
00574
00575
00576 public Servlet getServlet(String name) {
00577 try {
00578 return (Servlet) ((Object[]) registry.get(name))[0];
00579 } catch (NullPointerException npe) {
00580 return null;
00581 }
00582 }
00583
00585
00586
00587 public Enumeration getServlets() {
00588 return registry.elements();
00589 }
00590
00592
00593
00594 public Enumeration getServletNames() {
00595 return registry.keys();
00596 }
00597
00599 public void destroyAllServlets() {
00600 Enumeration en = registry.elements();
00601 while (en.hasMoreElements()) {
00602 Servlet servlet = (Servlet) en.nextElement();
00603 servlet.destroy();
00604 }
00605 registry = new PathTreeDictionary();
00606
00607 }
00608
00609 public void setMappingTable(PathTreeDictionary mappingtable) {
00610 this.mappingtable = mappingtable;
00611 }
00612
00613 public void setRealms(PathTreeDictionary realms) {
00614 this.realms = realms;
00615 }
00616
00617 Object getSession(String id) {
00618 return sessions.get(id);
00619 }
00620
00621 HttpSession createSession() {
00622 HttpSession result = new AcmeSession(generateSessionId(), expiredIn * 60, this, sessions);
00623 sessions.put(result.getId(), result);
00624 return result;
00625 }
00626
00627 void removeSession(String id) {
00628 sessions.remove(id);
00629 }
00630
00632
00633 public void log(String message) {
00634 Date date = new Date(System.currentTimeMillis());
00635 logStream.println("[" + date.toString() + "] " + message);
00636 }
00637
00638 public void log(String message, Throwable throwable) {
00639 StringWriter sw = new StringWriter();
00640 throwable.printStackTrace(new PrintWriter(sw));
00641 log(message + '\n' + sw);
00642 }
00643
00645
00646
00647 public void log(Exception exception, String message) {
00648 StringWriter sw = new StringWriter();
00649 exception.printStackTrace(new PrintWriter(sw));
00650 log("" + sw + '\n' + message);
00651 }
00652
00654
00655
00656
00657 public String getRealPath(String path) {
00658
00659 try {
00660
00661 URL url = new URL(path);
00662 path = url.getFile();
00663 new Exception("URL " + path + " specified in getRealPath").printStackTrace();
00664 path = null;
00665 } catch (MalformedURLException mfue) {
00666 }
00667 if (mappingtable != null) {
00668
00669 Object[] os = mappingtable.get(path);
00670 if (os[0] == null)
00671 return null;
00672 int slpos = ((Integer) os[1]).intValue();
00673 if (path.length() > slpos && slpos > 0) {
00674 path = path.substring(slpos + 1);
00675 } else if (path.length() > 0) {
00676 char s = path.charAt(0);
00677 if (s == '/' || s == '\\')
00678 path = path.substring(1);
00679 }
00680
00681
00682 return ((String) os[0]) + File.separatorChar + path;
00683 }
00684 return path;
00685 }
00686
00688
00689 public String getMimeType(String file) {
00690 file = file.toUpperCase();
00691
00692 if (file.endsWith(".HTML") || file.endsWith(".HTM"))
00693 return "text/html";
00694 if (file.endsWith(".TXT"))
00695 return "text/plain";
00696 if (file.endsWith(".XML"))
00697 return "text/xml";
00698 if (file.endsWith(".CSS"))
00699 return "text/css";
00700 if (file.endsWith(".SGML") || file.endsWith(".SGM"))
00701 return "text/x-sgml";
00702
00703 if (file.endsWith(".GIF"))
00704 return "image/gif";
00705 if (file.endsWith(".JPG") || file.endsWith(".JPEG") || file.endsWith(".JPE"))
00706 return "image/jpeg";
00707 if (file.endsWith(".PNG"))
00708 return "image/png";
00709 if (file.endsWith(".TIF") || file.endsWith(".TIFF"))
00710 return "image/tiff";
00711 if (file.endsWith(".RGB"))
00712 return "image/x-rgb";
00713 if (file.endsWith(".XPM"))
00714 return "image/x-xpixmap";
00715 if (file.endsWith(".XBM"))
00716 return "image/x-xbitmap";
00717 if (file.endsWith(".SVG"))
00718 return "image/svg-xml ";
00719 if (file.endsWith(".SVGZ"))
00720 return "image/svg-xml ";
00721
00722 if (file.endsWith(".AU") || file.endsWith(".SND"))
00723 return "audio/basic";
00724 if (file.endsWith(".MID") || file.endsWith(".MIDI") || file.endsWith(".RMI") || file.endsWith(".KAR"))
00725 return "audio/mid";
00726 if (file.endsWith(".MPGA") || file.endsWith(".MP2") || file.endsWith(".MP3"))
00727 return "audio/mpeg";
00728 if (file.endsWith(".WAV"))
00729 return "audio/wav";
00730 if (file.endsWith(".AIFF") || file.endsWith(".AIFC"))
00731 return "audio/aiff";
00732 if (file.endsWith(".AIF"))
00733 return "audio/x-aiff";
00734 if (file.endsWith(".RA"))
00735 return "audio/x-realaudio";
00736 if (file.endsWith(".RPM"))
00737 return "audio/x-pn-realaudio-plugin";
00738 if (file.endsWith(".RAM"))
00739 return "audio/x-pn-realaudio";
00740 if (file.endsWith(".SD2"))
00741 return "audio/x-sd2";
00742
00743 if (file.endsWith(".BIN") || file.endsWith(".DMS") || file.endsWith(".LHA") || file.endsWith(".LZH") || file.endsWith(".EXE") || file.endsWith(".CLASS"))
00744 return "application/octet-stream";
00745 if (file.endsWith(".HQX"))
00746 return "application/mac-binhex40";
00747 if (file.endsWith(".PS") || file.endsWith(".AI") || file.endsWith(".EPS"))
00748 return "application/postscript";
00749 if (file.endsWith(".PDF"))
00750 return "application/pdf";
00751 if (file.endsWith(".RTF"))
00752 return "application/rtf";
00753 if (file.endsWith(".DOC"))
00754 return "application/msword";
00755 if (file.endsWith(".PPT"))
00756 return "application/powerpoint";
00757 if (file.endsWith(".FIF"))
00758 return "application/fractals";
00759 if (file.endsWith(".P7C"))
00760 return "application/pkcs7-mime";
00761
00762 if (file.endsWith(".JS"))
00763 return "application/x-javascript";
00764 if (file.endsWith(".Z"))
00765 return "application/x-compress";
00766 if (file.endsWith(".GZ"))
00767 return "application/x-gzip";
00768 if (file.endsWith(".TAR"))
00769 return "application/x-tar";
00770 if (file.endsWith(".TGZ"))
00771 return "application/x-compressed";
00772 if (file.endsWith(".ZIP"))
00773 return "application/x-zip-compressed";
00774 if (file.endsWith(".DIR") || file.endsWith(".DCR") || file.endsWith(".DXR"))
00775 return "application/x-director";
00776 if (file.endsWith(".DVI"))
00777 return "application/x-dvi";
00778 if (file.endsWith(".TEX"))
00779 return "application/x-tex";
00780 if (file.endsWith(".LATEX"))
00781 return "application/x-latex";
00782 if (file.endsWith(".TCL"))
00783 return "application/x-tcl";
00784 if (file.endsWith(".CER") || file.endsWith(".CRT") || file.endsWith(".DER"))
00785 return "application/x-x509-ca-cert";
00786
00787 if (file.endsWith(".MPG") || file.endsWith(".MPE") || file.endsWith(".MPEG"))
00788 return "video/mpeg";
00789 if (file.endsWith(".QT") || file.endsWith(".MOV"))
00790 return "video/quicktime";
00791 if (file.endsWith(".AVI"))
00792 return "video/x-msvideo";
00793 if (file.endsWith(".MOVIE"))
00794 return "video/x-sgi-movie";
00795
00796 if (file.endsWith(".PDB") || file.endsWith(".XYZ"))
00797 return "chemical/x-pdb";
00798
00799 if (file.endsWith(".ICE"))
00800 return "x-conference/x-cooltalk";
00801 if (file.endsWith(".WRL") || file.endsWith(".VRML"))
00802 return "x-world/x-vrml";
00803 if (file.endsWith(".WML"))
00804 return "text/vnd.wap.wml";
00805 if (file.endsWith(".WMLC"))
00806 return "application/vnd.wap.wmlc";
00807 if (file.endsWith(".WMLS"))
00808 return "text/vnd.wap.wmlscript";
00809 if (file.endsWith(".WMLSC"))
00810 return "application/vnd.wap.wmlscriptc";
00811 if (file.endsWith(".WBMP"))
00812 return "image/vnd.wap.wbmp";
00813
00814 return null;
00815 }
00816
00818
00819
00820 public String getServerInfo() {
00821 return Serve.Identification.serverName + " " + Serve.Identification.serverVersion + " (" + Serve.Identification.serverUrl + ")";
00822 }
00823
00825
00826
00827
00828 public Object getAttribute(String name) {
00829
00830 return attributes.get(name);
00831 }
00832
00834 public void removeAttribute(String name) {
00835 attributes.remove(name);
00836 }
00837
00838 public void setAttribute(String name, Object object) {
00839 attributes.put(name, object);
00840 }
00841
00842 public Enumeration getAttributeNames() {
00843 return attributes.keys();
00844 }
00845
00846 public ServletContext getContext(String uripath) {
00847 return this;
00848 }
00849
00850 public int getMajorVersion() {
00851 return 2;
00852 }
00853
00854 public int getMinorVersion() {
00855 return 3;
00856 }
00857
00858
00859
00882 public java.util.Set getResourcePaths(java.lang.String path) {
00883
00884 return null;
00885 }
00886
00893 public java.lang.String getServletContextName() {
00894 return null;
00895 }
00896
00897
00898 public URL getResource(String path) throws MalformedURLException {
00899 return new URL("http", hostName, port, path);
00900 }
00901
00902 public InputStream getResourceAsStream(String path) {
00903 return null;
00904 }
00905
00906 public RequestDispatcher getRequestDispatcher(String urlpath) {
00907 return this;
00908 }
00909
00910
00911 public String getInitParameter(String param) {
00912 return null;
00913 }
00914
00915 public Enumeration getInitParameterNames() {
00916 return null;
00917 }
00918
00919 public RequestDispatcher getNamedDispatcher(String name) {
00920 return this;
00921 }
00922
00923 synchronized String generateSessionId() {
00924 return "-" + System.currentTimeMillis() + '-' + (uniqer++) + '-' + Math.round(Math.random() * 1000);
00925 }
00926
00927 public void forward(ServletRequest _request, ServletResponse _response) throws ServletException, java.io.IOException {
00928 }
00929
00930 public void include(ServletRequest _request, ServletResponse _response) throws ServletException, java.io.IOException {
00931 }
00932
00933 final static class Identification {
00934 public static final String serverName = "Rogatkin's JWS based on Acme.Serve";
00935 public static final String serverVersion = "$Revision: 1.2 $";
00936 public static final String serverUrl = "http://tjws.sourceforge.net";
00937
00939 public static void writeAddress(OutputStream o) throws IOException {
00940 PrintStream p = new PrintStream(o);
00941 p.println("<ADDRESS><A HREF=\"" + serverUrl + "\">" + serverName + " " + serverVersion + "</A></ADDRESS>");
00942 }
00943
00944 public static void writeAddress(StringBuffer sb) throws IOException {
00945 sb.append("<ADDRESS><A HREF=\"" + serverUrl + "\">" + serverName + " " + serverVersion + "</A></ADDRESS>");
00946 }
00947 }
00948 }
00949
00950 class ServeConfig implements ServletConfig {
00951
00952 private ServletContext context;
00953 private Hashtable init_params;
00954 private String servletName;
00955
00956 public ServeConfig(ServletContext context) {
00957 this(context, null, "undefined");
00958 }
00959
00960 public ServeConfig(ServletContext context, Hashtable initParams, String servletName) {
00961 this.context = context;
00962 this.init_params = initParams;
00963 this.servletName = servletName;
00964 }
00965
00966
00967
00969 public ServletContext getServletContext() {
00970 return context;
00971 }
00972
00974
00975 public String getInitParameter(String name) {
00976
00977 if (init_params != null)
00978 return (String) init_params.get(name);
00979 return null;
00980 }
00981
00983
00984 public Enumeration getInitParameterNames() {
00985
00986 if (init_params != null)
00987 return init_params.keys();
00988 return new Vector().elements();
00989 }
00990
00991 public String getServletName() {
00992 return servletName;
00993 }
00994 }
00995
00997
01000 class ServeConnection implements Runnable, HttpServletRequest, HttpServletResponse {
01001
01002 private Socket socket;
01003 private Serve serve;
01004
01005 private ServletInputStream in;
01006 private ServletOutputStream out;
01007
01008 private Hashtable formParameters;
01009 private Hashtable attributes = new Hashtable();
01010
01011 public final static String WWWFORMURLENCODE = "application/x-www-form-urlencoded";
01012 public final static String TRANSFERENCODING = "Transfer-Encoding";
01013 public final static String CHUNKED = "chunked";
01014 public final static String CONTENTLENGTH = "Content-Length";
01015 public final static String CONTENTTYPE = "Content-Type";
01016 public final static String SETCOOKIE = "Set-Cookie";
01017 public final static String COOKIE = "Cookie";
01018
01019 public final static String SESSION_COOKIE_NAME = "JSESSIONID";
01020
01021
01022
01023 private String reqMethod;
01024 private String reqUriPath;
01025 private String reqProtocol;
01026 private String reqCharEncoding;
01027 private String remoteUser;
01028 private String authType;
01029 private boolean oneOne;
01030 private boolean reqMime;
01031 String reqQuery = null;
01032 private Vector reqHeaderNames = new Vector();
01033 private Vector reqHeaderValues = new Vector();
01034 private Locale locale;
01035 private int uriLen;
01036 private static final Hashtable EMPTYHASHTABLE = new Hashtable();
01037
01038 private Vector outCookies;
01039 private Vector inCookies;
01040
01041 private String sessionCookieValue;
01042
01044 public ServeConnection(Socket socket, Serve serve) {
01045
01046 this.socket = socket;
01047 this.serve = serve;
01048
01049
01050 Thread thread = new Thread(this, "Request handler");
01051 thread.start();
01052 }
01053
01064 public String getLocalAddr() {
01065 return null;
01066 }
01067
01077 public String getLocalName() {
01078 return null;
01079 }
01080
01089 public int getLocalPort() {
01090 return serve.port;
01091 }
01092
01101 public int getRemotePort() {
01102 return serve.port;
01103 }
01104
01105
01106 public void run() {
01107 try {
01108
01109 in = new ServeInputStream(socket.getInputStream());
01110 out = new ServeOutputStream(socket.getOutputStream(), this);
01111 } catch (IOException e) {
01112 problem("Getting streams: " + e.getMessage(), SC_BAD_REQUEST);
01113 }
01114
01115 parseRequest();
01116
01117 if (serve.isAccessLogged()) {
01118 serve.log(
01119 socket.getInetAddress().toString()
01120 + ' '
01121 + reqMethod
01122 + ' '
01123 + reqUriPath
01124 + ' '
01125 + resCode
01126 + (serve.isShowReferer() ? "| " + getHeader("Referer") : "")
01127 + (serve.isShowUserAgent() ? "| " + getHeader("User-Agent") : ""));
01128 }
01129
01130 try {
01131 socket.close();
01132 } catch (IOException e) {
01133 }
01134 }
01135
01136 private void parseRequest() {
01137 byte[] lineBytes = new byte[4096];
01138 int len;
01139 String line;
01140
01141 try {
01142
01143 len = in.readLine(lineBytes, 0, lineBytes.length);
01144 if (len == -1 || len == 0) {
01145 problem("Empty request", SC_BAD_REQUEST);
01146 return;
01147 }
01148 line = new String(lineBytes, 0, len);
01149 StringTokenizer ust = new StringTokenizer(line);
01150 reqProtocol = null;
01151 if (ust.hasMoreTokens()) {
01152 reqMethod = ust.nextToken();
01153 if (ust.hasMoreTokens()) {
01154 reqUriPath = Acme.Utils.urlDecoder(ust.nextToken());
01155 if (ust.hasMoreTokens()) {
01156 reqProtocol = ust.nextToken();
01157 oneOne = !reqProtocol.toUpperCase().equals("HTTP/1.0");
01158 reqMime = true;
01159
01160 String s;
01161 while ((s = ((ServeInputStream) in).readLine()) != null) {
01162 if (s.length() == 0)
01163 break;
01164
01165 int c = s.indexOf(':', 0);
01166 if (c > 0) {
01167 String key = s.substring(0, c).trim();
01168 String value = s.substring(c + 1, s.length()).trim();
01169 reqHeaderNames.addElement(key.toLowerCase());
01170 reqHeaderValues.addElement(value);
01171 } else
01172 serve.log("header field without ':'");
01173 }
01174 } else {
01175 reqProtocol = "HTTP/0.9";
01176 oneOne = false;
01177 reqMime = false;
01178 }
01179 }
01180 }
01181 if (reqProtocol == null) {
01182 problem("Malformed request line", SC_BAD_REQUEST);
01183 return;
01184 }
01185
01186 if (oneOne) {
01187 String host = getHeader("host");
01188 if (host == null) {
01189 problem("Host header missing on HTTP/1.1 request", SC_BAD_REQUEST);
01190 return;
01191 }
01192 }
01193
01194
01195
01196
01197 int qmark = reqUriPath.indexOf('?');
01198 if (qmark > -1) {
01199 reqQuery = reqUriPath.substring(qmark + 1);
01200 reqUriPath = reqUriPath.substring(0, qmark);
01201 }
01202 if (CHUNKED.equals(getHeader(TRANSFERENCODING))) {
01203 setHeader(CONTENTLENGTH, null);
01204 ((ServeInputStream) in).chunking(true);
01205 }
01206
01207 Object[] os = serve.registry.get(reqUriPath);
01208 if (os != null) {
01209 uriLen = ((Integer) os[1]).intValue();
01210 runServlet((HttpServlet) os[0]);
01211 }
01212 } catch (IOException e) {
01213 problem("Reading request: " + e.getMessage(), SC_BAD_REQUEST);
01214 }
01215 }
01216
01217 private void runServlet(HttpServlet servlete) {
01218
01219 setStatus(SC_OK);
01220 setDateHeader("Date", System.currentTimeMillis());
01221 setHeader("Server", Serve.Identification.serverName + "/" + Serve.Identification.serverVersion);
01222 setHeader("MIME-Version", "1.0");
01223 try {
01224 parseCookies();
01225 authenificate();
01226 if (servlete instanceof SingleThreadModel)
01227 synchronized (servlete) {
01228 servlete.service((ServletRequest) this, (ServletResponse) this);
01229 } else
01230 servlete.service((ServletRequest) this, (ServletResponse) this);
01231 } catch (IOException e) {
01232 e.printStackTrace();
01233 problem("IO problem running servlet: " + e.toString(), SC_BAD_REQUEST);
01234 } catch (ServletException e) {
01235 problem("problem running servlet: " + e.toString(), SC_BAD_REQUEST);
01236 } catch (Exception e) {
01237 problem("unexpected problem running servlet: " + e.toString(), SC_INTERNAL_SERVER_ERROR);
01238 e.printStackTrace();
01239 }
01240 }
01241
01242 private boolean authenificate() throws IOException {
01243 Object[] o = serve.realms.get(getPathInfo());
01244 BasicAuthRealm realm = null;
01245 if (o == null)
01246 realm = (BasicAuthRealm) o[0];
01247 String credentials = getHeader("Authorization");
01248
01249 if (credentials != null) {
01250 credentials = credentials.substring(credentials.indexOf(' ') + 1);
01251 try {
01252 ByteArrayOutputStream baos = new ByteArrayOutputStream();
01253 serve.base64Dec.decodeBuffer(new StringBufferInputStream(credentials), baos);
01254 credentials = baos.toString();
01255 } catch (IOException e) {
01256 e.printStackTrace();
01257 }
01258 int i = credentials.indexOf(':');
01259 String user = credentials.substring(0, i);
01260 String password = credentials.substring(i + 1);
01261 remoteUser = user;
01262 authType = "Basic";
01263 if (realm == null)
01264 return true;
01265 String realPassword = (String) realm.get(user);
01266 System.err.println("User " + user + " Password " + password + " real " + realPassword);
01267 if (realPassword != null && realPassword.equals(password))
01268 return true;
01269 }
01270 if (realm == null)
01271 return true;
01272
01273 setStatus(SC_UNAUTHORIZED);
01274 setHeader("WWW-Authenticate", "basic realm=\"" + realm.name() + '"');
01275 writeHeaders();
01276 return false;
01277 }
01278
01279 private void problem(String logMessage, int resCode) {
01280 serve.log(logMessage);
01281 try {
01282 sendError(resCode);
01283 } catch (IllegalStateException e) {
01284 } catch (IOException e) {
01285 }
01286 }
01287
01288 private String decode(String str) {
01289 StringBuffer result = new StringBuffer();
01290 int l = str.length();
01291 for (int i = 0; i < l; ++i) {
01292 char c = str.charAt(i);
01293 if (c == '%' && i + 2 < l) {
01294 char c1 = str.charAt(i + 1);
01295 char c2 = str.charAt(i + 2);
01296 if (isHexit(c1) && isHexit(c2)) {
01297 result.append((char) (hexit(c1) * 16 + hexit(c2)));
01298 i += 2;
01299 } else
01300 result.append(c);
01301 } else if (c == '+')
01302 result.append(' ');
01303 else
01304 result.append(c);
01305 }
01306 return result.toString();
01307 }
01308
01309 private boolean isHexit(char c) {
01310 String legalChars = "0123456789abcdefABCDEF";
01311 return (legalChars.indexOf(c) != -1);
01312 }
01313
01314 private int hexit(char c) {
01315 if (c >= '0' && c <= '9')
01316 return c - '0';
01317 if (c >= 'a' && c <= 'f')
01318 return c - 'a' + 10;
01319 if (c >= 'A' && c <= 'F')
01320 return c - 'A' + 10;
01321 return 0;
01322 }
01323
01324 void parseCookies() {
01325 if (inCookies == null)
01326 inCookies = new Vector();
01327 try {
01328 String cookie_name;
01329 String cookie_value;
01330 String cookie_path;
01331 String cookies = getHeader(COOKIE);
01332 if (cookies == null)
01333 return;
01334
01335
01336
01337 StringTokenizer st = new StringTokenizer(cookies, ";", true);
01338
01339 while (st.hasMoreTokens()) {
01340 StringTokenizer st2 = new StringTokenizer(st.nextToken(), "=");
01341 if (st2.hasMoreTokens()) {
01342 cookie_name = st2.nextToken().trim();
01343 if (st2.hasMoreTokens()) {
01344 cookie_value = st2.nextToken(",").trim();
01345 if (cookie_value.length() > 0 && cookie_value.charAt(0) == '=')
01346 cookie_value = cookie_value.substring(1);
01347 cookie_path = "/";
01348 while (st2.hasMoreTokens()) {
01349 String cookie_atr = st2.nextToken();
01350 if ("$Version".equalsIgnoreCase(cookie_atr) || "$Path".equalsIgnoreCase(cookie_atr) || "$Domain".equalsIgnoreCase(cookie_atr))
01351 continue;
01352 cookie_path = st2.nextToken();
01353 }
01354 Cookie cookie = new Cookie(cookie_name, cookie_value);
01355
01356 cookie.setPath(cookie_path);
01357 inCookies.addElement(cookie);
01358 if (SESSION_COOKIE_NAME.equals(cookie_name) && sessionCookieValue == null) {
01359 sessionCookieValue = cookie_value;
01360 try {
01361 ((AcmeSession) serve.getSession(sessionCookieValue)).userTouch();
01362 } catch (Throwable t) {
01363 }
01364 }
01365 }
01366 }
01367 }
01368 } catch (Throwable e) {
01369 System.err.println("prepareCookies(): " + e);
01370 e.printStackTrace();
01371 }
01372 }
01373
01374
01375
01377
01378 public int getContentLength() {
01379 return getIntHeader(CONTENTLENGTH, -1);
01380 }
01381
01383
01384
01385 public String getContentType() {
01386 return getHeader(CONTENTTYPE);
01387 }
01388
01390
01391
01392 public String getProtocol() {
01393 return reqProtocol;
01394 }
01395
01397
01398
01399
01400
01401 public String getScheme() {
01402 if (socket.getClass().getName().toUpperCase().indexOf("SSL") < 0)
01403 return "http";
01404 else
01405 return "https";
01406 }
01407
01409
01410
01411 public String getServerName() {
01412 String serverName;
01413 int serverPort = 80;
01414 serverName = getHeader("Host");
01415 if (serverName != null && serverName.length() > 0) {
01416 int colon = serverName.indexOf(':');
01417 if (colon >= 0) {
01418 if (colon < serverName.length())
01419 serverPort = Integer.parseInt(serverName.substring(colon + 1));
01420 serverName = serverName.substring(0, colon);
01421 }
01422 }
01423
01424 if (serverName == null) {
01425 try {
01426 serverName = InetAddress.getLocalHost().getHostName();
01427 } catch (java.net.UnknownHostException ignore) {
01428 serverName = "127.0.0.0";
01429 }
01430 }
01431
01432 int slash = serverName.indexOf("/");
01433 if (slash >= 0)
01434 serverName = serverName.substring(slash + 1);
01435 return serverName;
01436 }
01437
01439
01440
01441 public int getServerPort() {
01442 return socket.getLocalPort();
01443 }
01444
01446
01447 public String getRemoteAddr() {
01448 return socket.getInetAddress().toString();
01449 }
01450
01452
01453
01454 public String getRemoteHost() {
01455 String result = socket.getInetAddress().getHostName();
01456 return result != null ? result : getRemoteAddr();
01457 }
01458
01460
01461
01462
01463
01464
01465 public String getRealPath(String path) {
01466 return serve.getRealPath(path);
01467 }
01468
01470
01471
01472 public ServletInputStream getInputStream() throws IOException {
01473 synchronized (in) {
01474 if (((ServeInputStream) in).isReturnedAsReader())
01475 throw new IllegalStateException("Already returned as a reader.");
01476 ((ServeInputStream) in).setReturnedAsReader(true);
01477 }
01478 return in;
01479 }
01480
01482
01483
01484
01485 public BufferedReader getReader() {
01486 synchronized (in) {
01487 if (((ServeInputStream) in).isReturnedAsStream())
01488 throw new IllegalStateException("Already returned as a stream.");
01489 ((ServeInputStream) in).setReturnedAsStream(true);
01490 }
01491 if (reqCharEncoding != null)
01492 try {
01493 return new BufferedReader(new InputStreamReader(in, reqCharEncoding));
01494 } catch (UnsupportedEncodingException uee) {
01495 }
01496 return new BufferedReader(new InputStreamReader(in));
01497 }
01498
01499 private Hashtable getParametersFromRequest() {
01500 Hashtable result = null;
01501
01502 if ("GET".equals(reqMethod)) {
01503 if (reqQuery != null)
01504 try {
01505 result = HttpUtils.parseQueryString(reqQuery);
01506 } catch (IllegalArgumentException ex) {
01507 }
01508 } else if ("POST".equals(reqMethod))
01509 if (WWWFORMURLENCODE.equals(getContentType()))
01510 try {
01511 result = HttpUtils.parsePostData(getContentLength(), getInputStream());
01512 if (reqQuery != null && reqQuery.length() > 0) {
01513 Acme.Utils.putAll(result, HttpUtils.parseQueryString(reqQuery));
01514 }
01515 } catch (Exception ex) {
01516 serve.log("Exception " + ex + " at parsing post data of length " + getContentLength());
01517 } else
01518 try {
01519 if (reqQuery != null)
01520 result = HttpUtils.parseQueryString(reqQuery);
01521 } catch (Exception ex) {
01522 }
01523 return result != null ? result : EMPTYHASHTABLE;
01524 }
01525
01527 public Enumeration getParameterNames() {
01528 if (formParameters == null)
01529 formParameters = getParametersFromRequest();
01530 return formParameters.keys();
01531 }
01532
01534
01535
01536 public String getParameter(String name) {
01537 String[] params = getParameterValues(name);
01538 if (params == null || params.length == 0)
01539 return null;
01540
01541 return params[0];
01542 }
01543
01545
01546 public String[] getParameterValues(String name) {
01547 if (formParameters == null)
01548 getParameterNames();
01549
01550 return (String[]) formParameters.get(name);
01551 }
01552
01554
01555
01556 public Object getAttribute(String name) {
01557 return attributes.get(name);
01558 }
01559
01560
01561
01563 public Cookie[] getCookies() {
01564 Cookie[] cookieArray = new Cookie[inCookies.size()];
01565 inCookies.copyInto(cookieArray);
01566 return cookieArray;
01567 }
01568
01570
01571
01572 public String getMethod() {
01573 return reqMethod;
01574 }
01575
01576
01577
01578
01579
01580
01581
01583 public String getRequestURI() {
01584 return reqUriPath;
01585 }
01586
01598 public java.lang.StringBuffer getRequestURL() {
01599 return new StringBuffer().append(getScheme()).append("://").append(serve.hostName).append(serve.port == 80 ? "" : String.valueOf(serve.port)).append(
01600 getRequestURI());
01601 }
01602
01604
01605
01606 public String getServletPath() {
01607
01608
01609
01610 return uriLen > 0 ? reqUriPath.substring(0, uriLen) : "";
01611 }
01612
01614
01615
01616 public String getPathInfo() {
01617
01618
01619
01620 return uriLen >= reqUriPath.length() ? null : reqUriPath.substring(uriLen);
01621 }
01622
01624
01625
01626 public String getPathTranslated() {
01627
01628
01629
01630 return getRealPath(getPathInfo());
01631 }
01632
01634
01635 public String getQueryString() {
01636 return reqQuery;
01637 }
01638
01640
01641 public String getRemoteUser() {
01642 return remoteUser;
01643 }
01644
01646
01647 public String getAuthType() {
01648 return authType;
01649 }
01650
01652
01653
01654 public String getHeader(String name) {
01655 int i = reqHeaderNames.indexOf(name.toLowerCase());
01656 if (i == -1)
01657 return null;
01658 return (String) reqHeaderValues.elementAt(i);
01659 }
01660
01661 public int getIntHeader(String name) {
01662 return getIntHeader(name, 0);
01663 }
01664
01666
01667
01668 public int getIntHeader(String name, int def) {
01669 String val = getHeader(name);
01670 if (val == null)
01671 return def;
01672 try {
01673 return Integer.parseInt(val);
01674 } catch (Exception e) {
01675 return def;
01676 }
01677 }
01678
01680
01681
01682 public long getLongHeader(String name, long def) {
01683 String val = getHeader(name);
01684 if (val == null)
01685 return def;
01686 try {
01687 return Long.parseLong(val);
01688 } catch (Exception e) {
01689 return def;
01690 }
01691 }
01692
01693 public long getDateHeader(String name) {
01694 String val = getHeader(name);
01695 if (val == null)
01696 return 0;
01697 try {
01698 return headerdateformat.parse(val).getTime();
01699 } catch (Exception e) {
01700 throw new IllegalArgumentException("Value " + val + " can't be converted to Date using " + headerdateformat.toPattern());
01701 }
01702
01703 }
01705
01706
01707 public long getDateHeader(String name, long def) {
01708 String val = getHeader(name);
01709 if (val == null)
01710 return def;
01711 try {
01712 return DateFormat.getDateInstance().parse(val).getTime();
01713 } catch (Exception e) {
01714 return def;
01715 }
01716 }
01717
01719 public Enumeration getHeaderNames() {
01720 return reqHeaderNames.elements();
01721 }
01722
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734 public HttpSession getSession(boolean create) {
01735
01736
01737 HttpSession result = getSession();
01738 if (result == null && create) {
01739 result = serve.createSession();
01740 }
01741 if (result != null)
01742 sessionCookieValue = result.getId();
01743 return result;
01744 }
01745
01746
01747 public HttpSession getSession() {
01748 AcmeSession result = null;
01749 if (sessionCookieValue != null) {
01750 result = (AcmeSession) serve.getSession(sessionCookieValue);
01751 if (result != null && !result.isValid()) {
01752 serve.removeSession(sessionCookieValue);
01753 result = null;
01754 }
01755 }
01756 return result;
01757 }
01758
01759 public boolean isRequestedSessionIdFromURL() {
01760 return false;
01761 }
01762
01763
01764 public Enumeration getAttributeNames() {
01765 return attributes.keys();
01766 }
01767
01768 public void setAttribute(String key, Object o) {
01769 attributes.put(key, o);
01770 }
01771
01773
01774
01775
01776 public String getRequestedSessionId() {
01777 return sessionCookieValue;
01778 }
01779
01781
01782
01783
01784 public boolean isRequestedSessionIdValid() {
01785 if (sessionCookieValue != null) {
01786 AcmeSession session = (AcmeSession) serve.getSession(sessionCookieValue);
01787 if (session != null && session.isValid()) {
01788 return true;
01789 }
01790 }
01791 return false;
01792 }
01793
01797 public boolean isRequestedSessionIdFromCookie() {
01798 return true;
01799 }
01800
01802
01803
01804 public boolean isRequestedSessionIdFromUrl() {
01805 return false;
01806 }
01807
01808
01809
01811
01812 public void setContentLength(int length) {
01813 setIntHeader(CONTENTLENGTH, length);
01814 }
01815
01817
01818 public void setContentType(String type) {
01819 setHeader(CONTENTTYPE, type != null ? type : "Unknown");
01820 }
01821
01823 public ServletOutputStream getOutputStream() {
01824 synchronized (out) {
01825 if (((ServeOutputStream) out).isReturnedAsWriter())
01826 throw new IllegalStateException("Already returned as a writer");
01827 ((ServeOutputStream) out).setReturnedAsStream(true);
01828 }
01829 return out;
01830 }
01831
01833
01834
01835
01836
01837
01838
01839 public PrintWriter getWriter() throws IOException {
01840 synchronized (out) {
01841 if (((ServeOutputStream) out).isReturnedAsStream())
01842 throw new IllegalStateException("Already was returned as servlet output stream");
01843 ((ServeOutputStream) out).setReturnedAsWriter(true);
01844 }
01845 String encoding = getCharacterEncoding();
01846 if (encoding != null)
01847 return new PrintWriter(new OutputStreamWriter(out, encoding));
01848 else
01849 return new PrintWriter(out);
01850 }
01851
01853
01854
01855
01856 public String getCharacterEncoding() {
01857 String ct = (String) resHeaderNames.get(CONTENTTYPE);
01858 if (ct != null) {
01859 int scp = ct.indexOf(';');
01860 if (scp > 0) {
01861 scp = ct.toLowerCase().indexOf("charset=", scp);
01862 if (scp >= 0) {
01863 ct = ct.substring(scp + 8);
01864 scp = ct.indexOf(' ');
01865 if (scp > 0)
01866 ct = ct.substring(0, scp);
01867 scp = ct.indexOf(';');
01868 if (scp > 0)
01869 ct = ct.substring(0, scp);
01870 return ct;
01871 }
01872 }
01873 }
01874 return null;
01875 }
01876
01877
01878
01879 public void flushBuffer() {
01880 }
01881
01888 public void resetBuffer() {
01889 throw new IllegalStateException("The method not implemented");
01890 }
01891
01892 public int getBufferSize() {
01893 return 0;
01894 }
01895
01896 public void setBufferSize(int size) {
01897 }
01898
01907
01908 public boolean isCommitted() {
01909 return headersWritten;
01910 }
01911
01918 public void reset() throws IllegalStateException {
01919 if (!isCommitted()) {
01920 outCookies.removeAllElements();
01921 resHeaderNames.clear();
01922 } else
01923 throw new IllegalStateException("Header have already been committed.");
01924 }
01925
01934 public void setLocale(java.util.Locale locale) {
01935 this.locale = locale;
01936 }
01937
01938 public java.util.Locale getLocale() {
01939 return locale;
01940 }
01941
01942
01943 public Enumeration getLocales() {
01944
01945
01946 return null;
01947 }
01948
01956 public void setCharacterEncoding(String _enc) {
01957 reqCharEncoding = _enc;
01958 }
01959
01960 public void addDateHeader(String header, long date) {
01961 addHeader(header, expdatefmt.format(new Date(date)));
01962 }
01963
01964 public void addHeader(String header, String value) {
01965 Object o = resHeaderNames.get(header);
01966 if (o == null)
01967 setHeader(header, value);
01968 else {
01969 if (o instanceof String[]) {
01970 String[] oldVal = (String[]) o;
01971 String[] newVal = new String[oldVal.length + 1];
01972 System.arraycopy(oldVal, 0, newVal, 0, oldVal.length);
01973 newVal[oldVal.length] = value;
01974 resHeaderNames.put(header, newVal);
01975 } else if (o instanceof String) {
01976 String[] newVal = new String[2];
01977 newVal[0] = (String) o;
01978 newVal[1] = value;
01979 resHeaderNames.put(header, newVal);
01980 } else
01981 throw new RuntimeException("Invalid content of header hash - " + o.getClass().getName());
01982 }
01983 }
01984
01985 public void addIntHeader(String header, int value) {
01986 addHeader(header, Integer.toString(value));
01987 }
01988
01989 public RequestDispatcher getRequestDispatcher(String urlpath) {
01990
01991 return null;
01992 }
01993
01994 public boolean isSecure() {
01995 return false;
01996 }
01997
01998 public void removeAttribute(String name) {
01999 }
02000
02001
02002 public String getContextPath() {
02003 return "";
02004 }
02005
02006 public Enumeration getHeaders(String header) {
02007 Vector result = new Vector();
02008 int i = -1;
02009 while ((i = reqHeaderNames.indexOf(header.toLowerCase(), i + 1)) >= 0)
02010 result.addElement(reqHeaderValues.elementAt(i));
02011 return result.elements();
02012 }
02013
02014 public java.security.Principal getUserPrincipal() {
02015 return null;
02016 }
02017
02018 public boolean isUserInRole(String user) {
02019 return true;
02020 }
02021
02031 public java.util.Map getParameterMap() {
02032 return (java.util.Map) formParameters;
02033 }
02034
02035
02036
02038
02039 public void addCookie(Cookie cookie) {
02040 if (outCookies == null)
02041 outCookies = new Vector();
02042
02043 outCookies.addElement(cookie);
02044 }
02045
02047
02048 public boolean containsHeader(String name) {
02049 return resHeaderNames.contains(name);
02050 }
02051
02052
02053 public String encodeURL(String url) {
02054 return url;
02055 }
02056
02057 public String encodeRedirectURL(String url) {
02058 return url;
02059 }
02060
02061 private int resCode = -1;
02062 private String resMessage = null;
02063 private Hashtable resHeaderNames = new Hashtable();
02064
02065 protected static final SimpleDateFormat expdatefmt = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss 'GMT'");
02066 protected static final SimpleDateFormat headerdateformat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
02067 static {
02068 TimeZone tz = TimeZone.getTimeZone("GMT");
02069 tz.setID("GMT");
02070 expdatefmt.setTimeZone(tz);
02071 }
02072
02074
02075
02076 public void setStatus(int resCode, String resMessage) {
02077
02078
02079 this.resCode = resCode;
02080 this.resMessage = resMessage;
02081 }
02082
02084
02085 public void setStatus(int resCode) {
02086 switch (resCode) {
02087 case SC_CONTINUE :
02088 setStatus(resCode, "Continue");
02089 break;
02090 case SC_SWITCHING_PROTOCOLS :
02091 setStatus(resCode, "Switching protocols");
02092 break;
02093 case SC_OK :
02094 setStatus(resCode, "Ok");
02095 break;
02096 case SC_CREATED :
02097 setStatus(resCode, "Created");
02098 break;
02099 case SC_ACCEPTED :
02100 setStatus(resCode, "Accepted");
02101 break;
02102 case SC_NON_AUTHORITATIVE_INFORMATION :
02103 setStatus(resCode, "Non-authoritative");
02104 break;
02105 case SC_NO_CONTENT :
02106 setStatus(resCode, "No content");
02107 break;
02108 case SC_RESET_CONTENT :
02109 setStatus(resCode, "Reset content");
02110 break;
02111 case SC_PARTIAL_CONTENT :
02112 setStatus(resCode, "Partial content");
02113 break;
02114 case SC_MULTIPLE_CHOICES :
02115 setStatus(resCode, "Multiple choices");
02116 break;
02117 case SC_MOVED_PERMANENTLY :
02118 setStatus(resCode, "Moved permanentently");
02119 break;
02120 case SC_MOVED_TEMPORARILY :
02121 setStatus(resCode, "Moved temporarily");
02122 break;
02123 case SC_SEE_OTHER :
02124 setStatus(resCode, "See other");
02125 break;
02126 case SC_NOT_MODIFIED :
02127 setStatus(resCode, "Not modified");
02128 break;
02129 case SC_USE_PROXY :
02130 setStatus(resCode, "Use proxy");
02131 break;
02132 case SC_BAD_REQUEST :
02133 setStatus(resCode, "Bad request");
02134 break;
02135 case SC_UNAUTHORIZED :
02136 setStatus(resCode, "Unauthorized");
02137 break;
02138 case SC_PAYMENT_REQUIRED :
02139 setStatus(resCode, "Payment required");
02140 break;
02141 case SC_FORBIDDEN :
02142 setStatus(resCode, "Forbidden");
02143 break;
02144 case SC_NOT_FOUND :
02145 setStatus(resCode, "Not found");
02146 break;
02147 case SC_METHOD_NOT_ALLOWED :
02148 setStatus(resCode, "Method not allowed");
02149 break;
02150 case SC_NOT_ACCEPTABLE :
02151 setStatus(resCode, "Not acceptable");
02152 break;
02153 case SC_PROXY_AUTHENTICATION_REQUIRED :
02154 setStatus(resCode, "Proxy auth required");
02155 break;
02156 case SC_REQUEST_TIMEOUT :
02157 setStatus(resCode, "Request timeout");
02158 break;
02159 case SC_CONFLICT :
02160 setStatus(resCode, "Conflict");
02161 break;
02162 case SC_GONE :
02163 setStatus(resCode, "Gone");
02164 break;
02165 case SC_LENGTH_REQUIRED :
02166 setStatus(resCode, "Length required");
02167 break;
02168 case SC_PRECONDITION_FAILED :
02169 setStatus(resCode, "Precondition failed");
02170 break;
02171 case SC_REQUEST_ENTITY_TOO_LARGE :
02172 setStatus(resCode, "Request entity too large");
02173 break;
02174 case SC_REQUEST_URI_TOO_LONG :
02175 setStatus(resCode, "Request URI too large");
02176 break;
02177 case SC_UNSUPPORTED_MEDIA_TYPE :
02178 setStatus(resCode, "Unsupported media type");
02179 break;
02180 case SC_INTERNAL_SERVER_ERROR :
02181 setStatus(resCode, "Internal server error");
02182 break;
02183 case SC_NOT_IMPLEMENTED :
02184 setStatus(resCode, "Not implemented");
02185 break;
02186 case SC_BAD_GATEWAY :
02187 setStatus(resCode, "Bad gateway");
02188 break;
02189 case SC_SERVICE_UNAVAILABLE :
02190 setStatus(resCode, "Service unavailable");
02191 break;
02192 case SC_GATEWAY_TIMEOUT :
02193 setStatus(resCode, "Gateway timeout");
02194 break;
02195 case SC_HTTP_VERSION_NOT_SUPPORTED :
02196 setStatus(resCode, "HTTP version not supported");
02197 break;
02198 default :
02199 setStatus(resCode, "");
02200 break;
02201 }
02202 }
02203
02205
02206
02207 public void setHeader(String name, String value) {
02208 resHeaderNames.put(name, value);
02209 }
02210
02212
02213
02214 public void setIntHeader(String name, int value) {
02215 setHeader(name, Integer.toString(value));
02216 }
02217
02219
02220
02221 public void setLongHeader(String name, long value) {
02222 setHeader(name, Long.toString(value));
02223 }
02224
02226
02227
02228 public void setDateHeader(String name, long value) {
02229 setHeader(name, expdatefmt.format(new Date(value)));
02230 }
02231
02232 private static final String[] weekdays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
02233
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261 private boolean headersWritten = false;
02262
02264
02265
02266 void writeHeaders() throws IOException {
02267 synchronized (this) {
02268 if (headersWritten)
02269 return;
02270
02271 headersWritten = true;
02272 }
02273 if (reqMime) {
02274
02275 out.println(reqProtocol + " " + resCode + " " + resMessage);
02276
02277 Enumeration he = resHeaderNames.keys();
02278 while (he.hasMoreElements()) {
02279 String name = (String) he.nextElement();
02280 Object o = resHeaderNames.get(name);
02281 if (o instanceof String) {
02282 String value = (String) o;
02283 if (value != null)
02284 out.println(name + ": " + value);
02285
02286
02287
02288 } else if (o instanceof String[]) {
02289 String[] values = (String[]) o;
02290 out.println(name + ": " + values[0]);
02291 for (int i = 0; i < values.length; i++)
02292 out.print("," + values[i]);
02293 out.println();
02294 }
02295 }
02296 StringBuffer sb = null;
02297 Cookie cc = null;
02298
02299
02300 if (sessionCookieValue != null) {
02301 if (outCookies == null)
02302 outCookies = new Vector();
02303 cc = new Cookie(SESSION_COOKIE_NAME, sessionCookieValue);
02304 cc.setMaxAge(Math.abs(Serve.expiredIn) * 60);
02305 outCookies.addElement(cc);
02306 }
02307
02308
02309
02310
02311
02312 for (int i = 0; outCookies != null && i < outCookies.size(); i++) {
02313 if (sb == null)
02314 sb = new StringBuffer(SETCOOKIE + ": ");
02315 else
02316
02317 sb.append("\r\n" + SETCOOKIE + ": ");
02318 cc = (Cookie) outCookies.elementAt(i);
02319 sb.append(cc.getName());
02320 sb.append('=');
02321 sb.append(cc.getValue());
02322 if (cc.getComment() != null) {
02323 sb.append("; Comment=" + cc.getComment());
02324 }
02325 if (cc.getDomain() != null) {
02326 sb.append("; Domain=" + cc.getDomain());
02327 }
02328
02329 if (cc.getMaxAge() >= 0) {
02330 sb.append("; expires=");
02331 sb.append(expdatefmt.format(new Date(System.currentTimeMillis() + 1000 * cc.getMaxAge())));
02332 }
02333 if (cc.getPath() != null) {
02334 sb.append("; Path=" + cc.getPath());
02335 }
02336 if (cc.getSecure()) {
02337 sb.append("; Secure");
02338 }
02339 if (cc.getVersion() > 0) {
02340 sb.append("; Version=" + cc.getVersion());
02341 }
02342 }
02343 if (sb != null) {
02344 out.println(sb.toString());
02345
02346 }
02347 out.println("");
02348 out.flush();
02349
02350 }
02351 }
02352
02354
02355
02356
02357 public void sendError(int resCode, String resMessage) throws IOException {
02358 setStatus(resCode, resMessage);
02359 realSendError();
02360 }
02361
02363
02364
02365
02366 public void sendError(int resCode) throws IOException {
02367 setStatus(resCode);
02368 realSendError();
02369 }
02370
02371 private void realSendError() throws IOException {
02372 if (isCommitted())
02373 throw new IllegalStateException("Can not send error, headers have been already written");
02374 synchronized (out) {
02375
02376 ((ServeOutputStream) out).setReturnedAsStream(true);
02377 ((ServeOutputStream) out).setReturnedAsWriter(true);
02378 }
02379 setContentType("text/html");
02380 StringBuffer sb = new StringBuffer(100);
02381 sb
02382 .append("<HTML><HEAD>")
02383 .append("<TITLE>" + resCode + " " + resMessage + "</TITLE>")
02384 .append("</HEAD><BODY BGCOLOR=\"#F1D0F2\">")
02385 .append("<H2>" + resCode + " " + resMessage + "</H2>")
02386 .append("<HR>");
02387 Serve.Identification.writeAddress(sb);
02388 sb.append("</BODY></HTML>");
02389 setContentLength(sb.length());
02390 out.print(sb.toString());
02391 out.flush();
02392 }
02393
02395
02396
02397
02398 public void sendRedirect(String location) throws IOException {
02399 if (isCommitted())
02400 throw new IllegalStateException("Can not redirect, headers have been already written");
02401 synchronized (out) {
02402
02403 ((ServeOutputStream) out).setReturnedAsStream(true);
02404 ((ServeOutputStream) out).setReturnedAsWriter(true);
02405 }
02406 setHeader("Location", location);
02407 setStatus(SC_MOVED_TEMPORARILY);
02408 setContentType("text/html");
02409 StringBuffer sb = new StringBuffer(200);
02410 sb.append(
02411 "<HTML><HEAD>"
02412 + "<TITLE>"
02413 + SC_MOVED_TEMPORARILY
02414 + " Moved</TITLE>"
02415 + "</HEAD><BODY BGCOLOR=\"#F1D0F2\">"
02416 + "<H2>"
02417 + SC_MOVED_TEMPORARILY
02418 + " Moved</H2>"
02419 + "This document has moved <a href="
02420 + location
02421 + ">here.<HR>");
02422 Serve.Identification.writeAddress(sb);
02423 sb.append("</BODY></HTML>");
02424 setContentLength(sb.length());
02425
02426 out.print(sb.toString());
02427 out.flush();
02428 }
02429
02430
02431
02432
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443 public String encodeUrl(String url) {
02444 return url;
02445 }
02446
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458 public String encodeRedirectUrl(String url) {
02459 return url;
02460 }
02461
02462 }
02463
02464 class BasicAuthRealm extends Hashtable {
02465 String name;
02466 BasicAuthRealm(String name) {
02467 this.name = name;
02468 }
02469
02470 String name() {
02471 return name;
02472 }
02473 }
02474
02475 class ServeInputStream extends ServletInputStream {
02476
02479 private BufferedInputStream in;
02480 private int chunksize = 0;
02481 private boolean chunking = false;
02482 private boolean returnedAsReader, returnedAsStream;
02483
02484
02487 public ServeInputStream(InputStream in) {
02488 this.in = new BufferedInputStream(in);
02489 }
02490
02491
02495 public void chunking(boolean chunking) {
02496 this.chunking = chunking;
02497 }
02498
02499
02505
02506 public String readLine() throws IOException {
02507 StringBuffer buf = new StringBuffer(1024);
02508
02509 int c;
02510 boolean cr = false;
02511 boolean lf = false;
02512
02513 LineLoop : while ((c = chunking ? read() : in.read()) != -1) {
02514 switch (c) {
02515 case 10 :
02516 lf = true;
02517 break LineLoop;
02518
02519 case 13 :
02520 cr = true;
02521 if (!chunking)
02522 in.mark(2);
02523 break;
02524
02525 default :
02526 if (cr) {
02527
02528
02529 in.reset();
02530 break LineLoop;
02531 } else
02532 buf.append((char) c);
02533 break;
02534 }
02535 }
02536
02537 if (c == -1 && buf.length() == 0)
02538 return null;
02539
02540
02541 return buf.toString();
02542 }
02543
02544
02545 public int read() throws IOException {
02546 if (chunking) {
02547 int b = -1;
02548 if (chunksize <= 0 && getChunkSize() <= 0)
02549 return -1;
02550 b = in.read();
02551 chunksize = (b < 0) ? -1 : (chunksize - 1);
02552 return b;
02553 }
02554
02555 return in.read();
02556 }
02557
02558
02559 public int read(byte b[]) throws IOException {
02560 return read(b, 0, b.length);
02561 }
02562
02563
02564 public int read(byte b[], int off, int len) throws IOException {
02565 if (chunking) {
02566 if (chunksize <= 0 && getChunkSize() <= 0)
02567 return -1;
02568 if (len > chunksize)
02569 len = chunksize;
02570 len = in.read(b, off, len);
02571 chunksize = (len < 0) ? -1 : (chunksize - len);
02572 } else
02573 len = in.read(b, off, len);
02574
02575
02576 return len;
02577 }
02578
02579
02580 public long skip(long len) throws IOException {
02581 if (chunking) {
02582 if (chunksize <= 0 && getChunkSize() <= 0)
02583 return -1;
02584 if (len > chunksize)
02585 len = chunksize;
02586 len = in.skip(len);
02587 chunksize = (len < 0) ? -1 : (chunksize - (int) len);
02588 } else
02589 len = in.skip(len);
02590 return len;
02591 }
02592
02593
02597 public int available() throws IOException {
02598 if (chunking) {
02599 int len = in.available();
02600 if (len <= chunksize)
02601 return len;
02602 return chunksize;
02603 }
02604
02605 return in.available();
02606 }
02607
02608
02609 public void close() throws IOException {
02610 in.close();
02611 chunksize = -1;
02612 }
02613
02614
02618 public boolean markSupported() {
02619 return false;
02620 }
02621
02622
02625 public void reset() {
02626 }
02627
02628
02632 public void mark(int readlimit) {
02633 }
02634
02635
02636 private int getChunkSize() throws IOException {
02637 if (chunksize < 0)
02638 return -1;
02639
02640 chunksize = -1;
02641
02642
02643 chunking = false;
02644 String line = readLine();
02645 while (line != null && line.length() == 0)
02646 line = readLine();
02647 chunking = true;
02648
02649
02650 if (line == null)
02651 return -1;
02652
02653
02654 int i = line.indexOf(';');
02655 if (i > 0)
02656 line = line.substring(0, i).trim();
02657 chunksize = Integer.parseInt(line, 16);
02658
02659
02660 if (chunksize == 0) {
02661 chunksize = -1;
02662
02663 chunking = false;
02664 }
02665 return chunksize;
02666 }
02667
02668 boolean isReturnedAsStream() {
02669 return returnedAsStream;
02670 }
02671
02672 void setReturnedAsStream(boolean _on) {
02673 returnedAsStream = _on;
02674 }
02675
02676 boolean isReturnedAsReader() {
02677 return returnedAsReader;
02678 }
02679
02680 void setReturnedAsReader(boolean _on) {
02681 returnedAsReader = _on;
02682 }
02683
02684 }
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773 class ServeOutputStream extends ServletOutputStream {
02774
02775
02776 private OutputStream out;
02777
02778 private ServeConnection conn;
02779 private boolean returnedAsStream, returnedAsWriter;
02780
02781 public ServeOutputStream(OutputStream out, ServeConnection conn) {
02782
02783 this.out = out;
02784 this.conn = conn;
02785 }
02786
02787 public void print(String s) throws IOException {
02788 write(s.getBytes());
02789 }
02790
02791 public void write(int b) throws IOException {
02792 conn.writeHeaders();
02793 out.write(b);
02794 }
02795
02796 public void write(byte[] b) throws IOException {
02797 write(b, 0, b.length);
02798 }
02799
02800 public void write(byte[] b, int off, int len) throws IOException {
02801 conn.writeHeaders();
02802 out.write(b, off, len);
02803 }
02804
02805 public void flush() throws IOException {
02806 conn.writeHeaders();
02807 out.flush();
02808 }
02809
02810 public void close() throws IOException {
02811 conn.writeHeaders();
02812 out.close();
02813 }
02814
02815 boolean isReturnedAsStream() {
02816 return returnedAsStream;
02817 }
02818
02819 void setReturnedAsStream(boolean _set) {
02820 returnedAsStream = _set;
02821 }
02822
02823 boolean isReturnedAsWriter() {
02824 return returnedAsWriter;
02825 }
02826
02827 void setReturnedAsWriter(boolean _set) {
02828 returnedAsWriter = _set;
02829 }
02830 }
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02871 class PathTreeDictionary {
02872 Node root_node;
02873
02874 PathTreeDictionary() {
02875 root_node = new Node();
02876 }
02877
02878 void put(String path, Object value) {
02879 StringTokenizer st = new StringTokenizer(path, "\\/");
02880 Node cur_node = root_node;
02881 while (st.hasMoreTokens()) {
02882 String nodename = st.nextToken();
02883 Node node = (Node) cur_node.get(nodename);
02884 if (node == null) {
02885 node = new Node();
02886 cur_node.put(nodename, node);
02887 }
02888 cur_node = node;
02889 }
02890 cur_node.object = value;
02891 }
02892
02898 Object[] get(String path) {
02899 Object[] result = new Object[2];
02900 if (path == null)
02901 return result;
02902 char[] ps = path.toCharArray();
02903 Node cur_node = root_node;
02904 int p0 = 0, lm = 0;
02905 result[0] = cur_node.object;
02906 boolean div_state = true;
02907 for (int i = 0; i < ps.length; i++) {
02908 if (ps[i] == '/' || ps[i] == '\\') {
02909 if (div_state)
02910 continue;
02911 Node node = (Node) cur_node.get(new String(ps, p0, i - p0));
02912 if (node == null) {
02913 result[1] = new Integer(lm);
02914 return result;
02915 }
02916 if (node.object != null) {
02917 result[0] = node.object;
02918 lm = i;
02919 }
02920 cur_node = node;
02921 div_state = true;
02922 } else {
02923 if (div_state) {
02924 p0 = i;
02925 div_state = false;
02926 }
02927 }
02928 }
02929 cur_node = (Node) cur_node.get(new String(ps, p0, ps.length - p0));
02930 if (cur_node != null && cur_node.object != null) {
02931 result[0] = cur_node.object;
02932 lm = ps.length;
02933 }
02934 result[1] = new Integer(lm);
02935 return result;
02936 }
02937
02938 Enumeration keys() {
02939 Vector result = new Vector();
02940 addSiblingNames(root_node, result, "");
02941 return result.elements();
02942 }
02943
02944 void addSiblingNames(Node node, Vector result, String path) {
02945 Enumeration e = node.keys();
02946 while (e.hasMoreElements()) {
02947 String pc = (String) e.nextElement();
02948 Node childNode = (Node) node.get(pc);
02949 pc = path + '/' + pc;
02950 if (childNode.object != null)
02951 result.addElement(pc);
02952 addSiblingNames(childNode, result, pc);
02953 }
02954 }
02955
02956 Enumeration elements() {
02957 Vector result = new Vector();
02958 addSiblingObjects(root_node, result);
02959 return result.elements();
02960 }
02961
02962 void addSiblingObjects(Node node, Vector result) {
02963 Enumeration e = node.keys();
02964 while (e.hasMoreElements()) {
02965 Node childNode = (Node) node.get(e.nextElement());
02966 if (childNode.object != null)
02967 result.addElement(childNode.object);
02968 addSiblingObjects(childNode, result);
02969 }
02970 }
02971
02972 class Node extends Hashtable {
02973 Object object;
02974 }
02975 }
02976
02980 class AcmeSession extends Hashtable implements HttpSession {
02981 private long createTime;
02982 private long lastAccessTime;
02983 private String id;
02984 private int inactiveInterval;
02985 private boolean expired;
02986 private ServletContext servletContext;
02987 private HttpSessionContext sessionContext;
02988
02989
02990
02991 AcmeSession(String id, ServletContext servletContext, HttpSessionContext sessionContext) {
02992 this(id, 0, servletContext, sessionContext);
02993 }
02994
02995 AcmeSession(String id, int inactiveInterval, ServletContext servletContext, HttpSessionContext sessionContext) {
02996 createTime = System.currentTimeMillis();
02997 this.id = id;
02998 this.inactiveInterval = inactiveInterval;
02999 this.servletContext = servletContext;
03000 this.sessionContext = sessionContext;
03001 }
03002 public long getCreationTime() {
03003 return createTime;
03004 }
03005
03006 public String getId() {
03007 return id;
03008 }
03009
03010 public long getLastAccessedTime() {
03011 return lastAccessTime;
03012 }
03013
03014 public void setMaxInactiveInterval(int interval) {
03015 inactiveInterval = interval;
03016 }
03017
03018 public int getMaxInactiveInterval() {
03019 return inactiveInterval;
03020 }
03021
03025 public HttpSessionContext getSessionContext() {
03026
03027 return sessionContext;
03028 }
03029
03035 public ServletContext getServletContext() {
03036 return servletContext;
03037 }
03038
03039 public java.lang.Object getAttribute(java.lang.String name) throws IllegalStateException {
03040 if (expired)
03041 throw new IllegalStateException();
03042 return get((Object) name);
03043 }
03044
03045 public java.lang.Object getValue(java.lang.String name) throws IllegalStateException {
03046 return getAttribute(name);
03047 }
03048
03049 public java.util.Enumeration getAttributeNames() throws IllegalStateException {
03050 if (expired)
03051 throw new IllegalStateException();
03052 return keys();
03053 }
03054
03055 public java.lang.String[] getValueNames() throws IllegalStateException {
03056 Enumeration e = getAttributeNames();
03057 Vector names = new Vector();
03058 while (e.hasMoreElements())
03059 names.addElement(e.nextElement());
03060 String[] result = new String[names.size()];
03061 names.copyInto(result);
03062 return result;
03063 }
03064
03065 public void setAttribute(String name, Object value) throws IllegalStateException {
03066 if (expired)
03067 throw new IllegalStateException();
03068 Object oldValue = put((Object) name, value);
03069 if (oldValue != null && oldValue instanceof HttpSessionBindingListener)
03070 ((HttpSessionBindingListener) oldValue).valueUnbound(new HttpSessionBindingEvent(this, name));
03071 if (value instanceof HttpSessionBindingListener)
03072 ((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(this, name));
03073 }
03074
03075 public void putValue(String name, Object value) throws IllegalStateException {
03076 setAttribute(name, value);
03077 }
03078
03079 public void removeAttribute(java.lang.String name) throws IllegalStateException {
03080 if (expired)
03081 throw new IllegalStateException();
03082 Object value = remove((Object) name);
03083 if (value != null && value instanceof HttpSessionBindingListener)
03084 ((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name));
03085 }
03086
03087 public void removeValue(java.lang.String name) throws IllegalStateException {
03088 removeAttribute(name);
03089 }
03090
03091 public synchronized void invalidate() throws IllegalStateException {
03092 if (expired)
03093 throw new IllegalStateException();
03094 Enumeration e = getAttributeNames();
03095 while (e.hasMoreElements()) {
03096 removeAttribute((String) e.nextElement());
03097 }
03098 setExpired(true);
03099
03100 }
03101
03102 public boolean isNew() throws IllegalStateException {
03103 if (expired)
03104 throw new IllegalStateException();
03105 return lastAccessTime == 0;
03106 }
03107
03108 private void setExpired(boolean expired) {
03109 this.expired = expired;
03110 }
03111
03112 boolean isValid() {
03113 return !expired;
03114 }
03115
03116 void userTouch() {
03117 lastAccessTime = System.currentTimeMillis();
03118 }
03119 }
03120
03121
03122
03123
03124
03125 class HttpSessionContextImpl extends Hashtable implements HttpSessionContext {
03126
03127 public java.util.Enumeration getIds() {
03128 return keys();
03129 }
03130
03131 public HttpSession getSession(java.lang.String sessionId) {
03132 return (HttpSession) get(sessionId);
03133 }
03134 }