1 package com.quadcap.http.server22; 2 3 40 41 import java.io.File ; 42 import java.io.InputStream ; 43 import java.io.InputStreamReader ; 44 import java.io.IOException ; 45 import java.io.Reader ; 46 47 import java.util.ArrayList ; 48 import java.util.Collections ; 49 import java.util.Comparator ; 50 import java.util.Enumeration ; 51 import java.util.HashMap ; 52 import java.util.Hashtable ; 53 import java.util.List ; 54 import java.util.Properties ; 55 import java.util.Vector ; 56 57 import java.net.URL ; 58 import java.net.MalformedURLException ; 59 60 import javax.servlet.RequestDispatcher ; 61 import javax.servlet.Servlet ; 62 import javax.servlet.ServletContext ; 63 import javax.servlet.ServletException ; 64 import javax.servlet.ServletRequest ; 65 import javax.servlet.ServletResponse ; 66 67 import javax.servlet.http.HttpServlet ; 68 import javax.servlet.http.HttpServletRequest ; 69 import javax.servlet.http.HttpSession ; 70 import javax.servlet.http.HttpSessionContext ; 71 72 import com.quadcap.io.dir.Directory; 73 import com.quadcap.io.dir.Entry; 74 75 import com.quadcap.util.Debug; 76 import com.quadcap.util.Util; 77 78 84 public class WebApplication implements ServletContext { 85 WebServer server; 86 WebClassLoader classLoader; 87 String contextPath; 88 89 92 HashMap servlets = new HashMap (); 93 94 97 Hashtable sessions = new Hashtable (); 98 99 102 Hashtable attributes = new Hashtable (); 103 104 107 Hashtable mimeTypes = new Hashtable (); 108 109 112 Hashtable pathMappings = new Hashtable (); 113 Hashtable extMappings = new Hashtable (); 114 Hashtable exactMappings = new Hashtable (); 115 116 WebServlet defaultServlet = null; 117 118 121 List welcomeFiles = new ArrayList (); 122 123 126 String errorPage = null; 127 128 131 Directory docRoot; 132 133 String displayName = ""; 134 135 long sessionCount = 0; 136 int sessionTimeout = 3600; 137 138 Properties initParams = new Properties (); 139 140 public WebApplication() {} 141 142 public void init(WebServer server, String root, Directory dir) 143 throws ServletException , IOException 144 { 145 if (Trace.level() > 0) { 147 Debug.println(toString() + ".init(" + root + ", " + 148 dir.getRootPath() + ")"); 149 } 150 this.server = server; 152 this.docRoot = dir; 153 this.contextPath = root; 154 155 File tmp = server.getTempDir(); 156 File myTmp = new File (tmp, root); 157 if (!myTmp.isDirectory() && !myTmp.mkdirs()) { 158 throw new ServletException ("Can't create repository: " + myTmp); 159 } 160 setAttribute("repository", myTmp); 161 classLoader = new WebClassLoader(dir, myTmp); 162 classLoader.init(); 163 attributes.put("com.quadcap.classLoader", classLoader); 164 InputStream dis = ClassLoader.getSystemResourceAsStream( 165 "com/quadcap/http/server22/defaultContext.xml"); 166 if (dis == null) { 167 throw new ServletException ("Can't load default context"); 168 } 169 Reader dfr = new InputStreamReader (dis); 170 try { 171 parseDeploymentDescriptor(dfr); 172 } finally { 173 dfr.close(); 174 } 175 setDisplayName(""); 176 177 Entry entry = dir.getEntry("WEB-INF/web.xml"); 178 if (entry != null) { 179 Reader ddr = new InputStreamReader (entry.getInputStream()); 180 try { 181 parseDeploymentDescriptor(ddr); 182 } finally { 183 ddr.close(); 184 } 185 } 186 resolveServlets(pathMappings); 187 resolveServlets(extMappings); 188 resolveServlets(exactMappings); 189 loadInitialServlets(); 190 } 191 192 public void shutdown() { 193 synchronized (sessions) { 194 Enumeration e = sessions.keys(); 195 while (e.hasMoreElements()) { 196 String sessionId = (String )e.nextElement(); 197 HSession session = (HSession)getSession(sessionId); 198 session.invalidate(); 199 } 200 } 201 if (docRoot != null) { 202 try { 203 docRoot.close(); 204 } catch (Throwable t) {} 205 } 206 } 207 208 final void resolveServlets(Hashtable t) { 209 Enumeration e = t.keys(); 210 while (e.hasMoreElements()) { 211 Object key = e.nextElement(); 212 Object obj = t.get(key); 213 if (obj instanceof String ) { 214 Object s = servlets.get(obj); 215 if (s == null) { 216 Debug.println("No servlet for mapping: " + obj); 217 t.remove(key); 218 } else { 219 t.put(key, s); 220 } 221 } 222 } 223 } 224 225 void parseDeploymentDescriptor(Reader r) 226 throws ServletException , IOException { 227 try { 228 new DDParser().parse(r, this); 229 } catch (Exception e) { 230 throw new ServletException (e); 231 } finally { 232 r.close(); 233 } 234 } 235 236 public void setDisplayName(String name) { 237 this.displayName = name; 238 } 239 240 public String getDisplayName() { 241 return displayName; 242 } 243 244 public void addInitParam(String prop, String val) { 245 initParams.setProperty(prop, val); 246 } 247 248 public Enumeration getInitParameterNames() { 249 return initParams.keys(); 250 } 251 252 public String getInitParameter(String name) { 253 return initParams.getProperty(name); 254 } 255 256 public void addWelcomeFile(String s) { 257 welcomeFiles.add(s.trim()); 258 } 259 260 public List getWelcomeFiles() { 261 if (welcomeFiles.size() == 0) { 262 welcomeFiles.add("index.html"); 263 welcomeFiles.add("index.jsp"); 264 } 265 return welcomeFiles; 266 } 267 268 public void addServlet(WebServlet servlet) { 269 if (Trace.level() > 1) { 271 Debug.println(toString() + ".addServlet(" + 272 servlet.getServletName() + ")"); 273 } 274 servlets.put(servlet.getServletName(), servlet); 276 } 277 278 WebServlet getServletForRequest(HttpDispatcher rd) { 279 String path = rd.getServletPath(); 280 281 WebServlet s = (WebServlet)exactMappings.get(path); 282 if (s != null) { 283 rd.setServlet(s, path); 284 } else { 285 int lastDot = -1; 286 for (int i = path.length() - 1; i >= 0; i--) { 287 char c = path.charAt(i); 288 if (c == '/') { 289 String subPath = path.substring(0, i); 290 s = (WebServlet)pathMappings.get(subPath); 291 if (s != null) { 292 rd.setServlet(s, subPath); 293 rd.setPathInfo(path.substring(i)); 294 break; 295 } 296 } else if (c == '.' && lastDot < 0) { 297 lastDot = i; 298 } 299 } 300 if (s == null && lastDot >= 0) { 301 String ext = path.substring(lastDot + 1); 302 s = (WebServlet)extMappings.get(ext); 303 if (s != null) { 304 rd.setServlet(s, path); 305 } 306 } 307 if (s == null) { 308 s = defaultServlet; 309 rd.setServlet(s, path); 310 } 311 } 312 if (Trace.level() > 1) { 314 Debug.println(toString() + ".getServlet(" + path + ") = " + s); 315 } 316 return s; 318 } 319 320 public void setSessionTimeout(int timeout) { 321 this.sessionTimeout = timeout; 322 } 323 324 public int getSessionTimeout() { 325 return sessionTimeout; 326 } 327 328 public void addServletMapping(String servletName, String urlPattern) { 329 if (Trace.level() > 0) { 331 Debug.println(this + ".addServletMapping(" + servletName + 332 ", " + urlPattern + ")"); 333 } 334 336 if (urlPattern.equals("*.*")) { 337 defaultServlet = (WebServlet)servlets.get(servletName); 338 } else if (urlPattern.endsWith("*")) { 339 String path = urlPattern.substring(0, urlPattern.length() - 2); 340 pathMappings.put(path, servletName); 341 } else if (urlPattern.startsWith("*.")) { 342 String ext = urlPattern.substring(2); 343 extMappings.put(ext, servletName); 344 } else { 345 exactMappings.put(urlPattern, servletName); 346 } 347 } 348 349 public void setErrorPage(String errorPage) { 350 this.errorPage = errorPage; 351 } 352 353 public String getErrorPage() { 354 return errorPage; 355 } 356 357 public Object getAttribute(String name) { 358 return attributes.get(name); 359 } 360 361 public Enumeration getAttributeNames() { 362 return attributes.keys(); 363 } 364 365 public void setAttribute(String name, Object val) { 366 attributes.put(name, val); 367 } 368 369 public void removeAttribute(String name) { 370 attributes.remove(name); 371 } 372 373 379 public String getServerInfo() { 380 return "Quadcap Web Server 3.4"; 383 } 385 386 389 public int getMajorVersion() { 390 return 2; 391 } 392 393 396 public int getMinorVersion() { 397 return 2; 398 } 399 400 public ServletContext getContext(String path) { 401 return server.getContext(path); 402 } 403 404 408 public RequestDispatcher getRequestDispatcher(String path) { 409 HttpDispatcher rd = new HttpDispatcher(this, path); 410 WebServlet ws = getServletForRequest(rd); 411 return (ws != null) ? rd : null; 412 } 413 414 public RequestDispatcher getNamedDispatcher(String name) { 415 WebServlet ws = (WebServlet)servlets.get(name); 416 if (ws != null) { 417 return new HttpDispatcher(ws, name); 418 } else { 419 return null; 420 } 421 } 422 423 public RequestDispatcher getRelativeRequestDispatcher(String path, 424 HttpRequest base) { 425 if (path.charAt(0) == '/') { 426 return getRequestDispatcher(path); 427 } else { 428 String spath = base.getServletPath(); 429 int spos = spath.length() - 1; 430 while (spos >= 0 && spath.charAt(spos) != '/') spos--; 431 432 while (path.startsWith("./") || path.startsWith("../")) { 433 if (path.startsWith("./")) { 434 path = path.substring(2); 435 } else { 436 if (spos > 0) { 437 spos--; 438 while (spos >= 0 && spath.charAt(spos) != '/') spos--; 439 } else { 440 return null; 441 } 442 } 443 } 444 String absPath = spath.substring(0, spos+1) + path; 445 return getRequestDispatcher(absPath); 446 } 447 } 448 449 void addMimeMapping(String ext, String type) { 450 if (Trace.level() > 0) { 452 Debug.println(toString() + ".addMimeMapping(" + ext + 453 ", " + type + ")"); 454 } 455 mimeTypes.put(ext, type); 457 } 458 459 public String getMimeType(String file) { 460 String type = null; 461 int lastDot = file.lastIndexOf('.'); 462 int lastSep = file.lastIndexOf('/'); 463 if (lastDot != -1 && (lastSep == -1 || lastDot > lastSep)) { 464 String ext = file.substring(lastDot + 1); 465 type = (String )mimeTypes.get(ext); 466 if (type == null) { 467 type = server.getMimeTypeForExt(ext); 468 } 469 } 470 return type; 471 } 472 473 478 String resolveDirectory(String path) { 479 String ret = path; 480 String sav = path + "/"; 481 if (sav.endsWith("//")) { 482 sav = sav.substring(0, sav.length()-1); 483 } 484 Entry e = docRoot.getEntry(path); 485 if (e != null) { 486 if (e.isDirectory()) { 487 e = null; 488 List w = getWelcomeFiles(); 489 for (int i = 0; e == null && i < w.size(); i++) { 490 e = docRoot.getEntry(path = sav + w.get(i)); 491 } 492 } 493 } 494 if (e != null) ret = path; 495 return ret; 496 } 497 498 public String getRealPath(String path) { 499 String rpath = resolveDirectory(path); 500 String ret = docRoot.getRealPath(rpath); 501 return ret; 502 } 503 504 public URL getResource(String path) throws MalformedURLException { 505 return docRoot.getURL(path); 506 } 507 508 public InputStream getResourceAsStream(String path) { 509 try { 510 URL url = getResource(path); 511 if (url != null) { 512 return url.openStream(); 513 } 514 } catch (Throwable t) {} 515 return null; 516 } 517 518 525 public HSession getSession(String sessionId) { 526 synchronized (sessions) { 527 return (HSession)sessions.get(sessionId); 528 } 529 } 530 531 void removeSession(HSession session) { 532 if (Trace.level() > 1) { 534 Debug.println("removeSession(" + session.getId() + ")"); 535 } 536 synchronized (sessions) { 538 sessions.remove(session.getId()); 539 } 540 } 541 542 545 public HSession createSession() { 546 String sessionId = server.makeSessionId(); 547 if (Trace.level() > 1) { 549 Debug.println("++++++ createSession(): " + sessionId); 550 } 551 HSession session = new HSession(this, sessionId, sessionTimeout); 553 synchronized (sessions) { 554 sessions.put(sessionId, session); 555 } 556 return session; 557 } 558 559 563 public void expireSessions() { 564 synchronized (sessions) { 565 Enumeration e = sessions.keys(); 566 long now = System.currentTimeMillis(); 567 while (e.hasMoreElements()) { 568 String sessionId = (String )e.nextElement(); 569 HSession session = (HSession)getSession(sessionId); 570 if (now - session.getLastAccessedTime() > 571 (session.getMaxInactiveInterval() * 1000)) { 572 try { 573 session.invalidate(); 574 } catch (Throwable t) { 575 Debug.print(t); 576 } 577 } 578 } 579 } 580 } 581 582 587 public void log(String msg) { 588 Debug.println(msg); 589 } 590 591 599 public void log(Exception e, String msg) { 600 Debug.println(msg); 601 Debug.print(e); 602 } 603 604 611 public void log(String msg, Throwable e) { 612 Debug.println(msg); 613 Debug.print(e); 614 } 615 616 619 public Servlet getServlet(String name) { 620 return null; 621 } 622 623 626 public Enumeration getServletNames() { 627 return new Vector ().elements(); 628 } 629 630 633 public Enumeration getServlets() { 634 return new Vector ().elements(); 635 } 636 637 public String getContextPath() { 638 return contextPath; 639 } 640 641 645 public String getContextClassPath() { 646 return classLoader.getClassPath(); 647 } 648 649 final ClassLoader getClassLoader() { 650 return classLoader; 651 } 652 653 final void loadInitialServlets() throws ServletException { 654 ServletException ex = null; 655 656 ArrayList l = new ArrayList (); 657 l.addAll(servlets.values()); 658 Collections.sort(l, new Comparator () { 659 public int compare(Object a, Object b) { 660 WebServlet wa = (WebServlet)a; 661 WebServlet wb = (WebServlet)b; 662 if (wa.getLoadOnStartup() < wb.getLoadOnStartup()) return -1; 663 if (wa.getLoadOnStartup() > wb.getLoadOnStartup()) return 1; 664 return 0; 665 } 666 }); 667 for (int i = 0; i < l.size(); i++) { 668 WebServlet w = (WebServlet)l.get(i); 669 if (w.getLoadOnStartup() >= 0) { 670 try { 671 w.init(); 672 } catch (ServletException e) { 673 ex = e; 674 Debug.print(e); 675 } 676 } 677 } 678 679 if (ex != null) throw ex; 680 } 681 682 public WebServer getWebServer() { return server; } 683 684 public String getRootPath() { return docRoot.getRootPath(); } 685 686 public boolean isDirectory(String d) { 687 try { 688 return docRoot.getEntry(d).isDirectory(); 689 } catch (Throwable t) { 690 return false; 691 } 692 } 693 694 public String toString() { 696 return "[" + contextPath + "]"; 697 } 698 } 700 | Popular Tags |