KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > http > server22 > WebApplication


1 package com.quadcap.http.server22;
2
3 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.File JavaDoc;
42 import java.io.InputStream JavaDoc;
43 import java.io.InputStreamReader JavaDoc;
44 import java.io.IOException JavaDoc;
45 import java.io.Reader JavaDoc;
46
47 import java.util.ArrayList JavaDoc;
48 import java.util.Collections JavaDoc;
49 import java.util.Comparator JavaDoc;
50 import java.util.Enumeration JavaDoc;
51 import java.util.HashMap JavaDoc;
52 import java.util.Hashtable JavaDoc;
53 import java.util.List JavaDoc;
54 import java.util.Properties JavaDoc;
55 import java.util.Vector JavaDoc;
56
57 import java.net.URL JavaDoc;
58 import java.net.MalformedURLException JavaDoc;
59
60 import javax.servlet.RequestDispatcher JavaDoc;
61 import javax.servlet.Servlet JavaDoc;
62 import javax.servlet.ServletContext JavaDoc;
63 import javax.servlet.ServletException JavaDoc;
64 import javax.servlet.ServletRequest JavaDoc;
65 import javax.servlet.ServletResponse JavaDoc;
66
67 import javax.servlet.http.HttpServlet JavaDoc;
68 import javax.servlet.http.HttpServletRequest JavaDoc;
69 import javax.servlet.http.HttpSession JavaDoc;
70 import javax.servlet.http.HttpSessionContext JavaDoc;
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 /**
79  * This class provides a wrapper for a Web Application, implementing
80  * the application's ServletContext interface.
81  *
82  * @author Stan Bailes
83  */

84 public class WebApplication implements ServletContext JavaDoc {
85     WebServer server;
86     WebClassLoader classLoader;
87     String JavaDoc contextPath;
88     
89     /**
90      * Map name -> Servlet
91      */

92     HashMap JavaDoc servlets = new HashMap JavaDoc();
93
94     /**
95      * Session table: sessionId -> HttpSession
96      */

97     Hashtable JavaDoc sessions = new Hashtable JavaDoc();
98
99     /**
100      * Servlet context attributes
101      */

102     Hashtable JavaDoc attributes = new Hashtable JavaDoc();
103
104     /**
105      * Mime types
106      */

107     Hashtable JavaDoc mimeTypes = new Hashtable JavaDoc();
108
109     /**
110      * Path mappings
111      */

112     Hashtable JavaDoc pathMappings = new Hashtable JavaDoc();
113     Hashtable JavaDoc extMappings = new Hashtable JavaDoc();
114     Hashtable JavaDoc exactMappings = new Hashtable JavaDoc();
115
116     WebServlet defaultServlet = null;
117
118     /**
119      * Welcome file list
120      */

121     List JavaDoc welcomeFiles = new ArrayList JavaDoc();
122     
123     /**
124      * Error page
125      */

126     String JavaDoc errorPage = null;
127
128     /**
129      * My document root
130      */

131     Directory docRoot;
132
133     String JavaDoc displayName = "";
134
135     long sessionCount = 0;
136     int sessionTimeout = 3600;
137
138     Properties JavaDoc initParams = new Properties JavaDoc();
139
140     public WebApplication() {}
141
142     public void init(WebServer server, String JavaDoc root, Directory dir)
143         throws ServletException JavaDoc, IOException JavaDoc
144     {
145         //#ifdef DEBUG
146
if (Trace.level() > 0) {
147             Debug.println(toString() + ".init(" + root + ", " +
148                           dir.getRootPath() + ")");
149         }
150         //#endif
151
this.server = server;
152         this.docRoot = dir;
153         this.contextPath = root;
154
155         File JavaDoc tmp = server.getTempDir();
156         File JavaDoc myTmp = new File JavaDoc(tmp, root);
157         if (!myTmp.isDirectory() && !myTmp.mkdirs()) {
158             throw new ServletException JavaDoc("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 JavaDoc dis = ClassLoader.getSystemResourceAsStream(
165             "com/quadcap/http/server22/defaultContext.xml");
166         if (dis == null) {
167             throw new ServletException JavaDoc("Can't load default context");
168         }
169         Reader JavaDoc dfr = new InputStreamReader JavaDoc(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 JavaDoc ddr = new InputStreamReader JavaDoc(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 JavaDoc e = sessions.keys();
195             while (e.hasMoreElements()) {
196                 String JavaDoc sessionId = (String JavaDoc)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 JavaDoc t) {}
205         }
206     }
207
208     final void resolveServlets(Hashtable JavaDoc t) {
209         Enumeration JavaDoc e = t.keys();
210         while (e.hasMoreElements()) {
211             Object JavaDoc key = e.nextElement();
212             Object JavaDoc obj = t.get(key);
213             if (obj instanceof String JavaDoc) {
214                 Object JavaDoc 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 JavaDoc r)
226         throws ServletException JavaDoc, IOException JavaDoc {
227         try {
228             new DDParser().parse(r, this);
229         } catch (Exception JavaDoc e) {
230             throw new ServletException JavaDoc(e);
231         } finally {
232             r.close();
233         }
234     }
235
236     public void setDisplayName(String JavaDoc name) {
237         this.displayName = name;
238     }
239
240     public String JavaDoc getDisplayName() {
241         return displayName;
242     }
243
244     public void addInitParam(String JavaDoc prop, String JavaDoc val) {
245         initParams.setProperty(prop, val);
246     }
247
248     public Enumeration JavaDoc getInitParameterNames() {
249         return initParams.keys();
250     }
251
252     public String JavaDoc getInitParameter(String JavaDoc name) {
253         return initParams.getProperty(name);
254     }
255
256     public void addWelcomeFile(String JavaDoc s) {
257         welcomeFiles.add(s.trim());
258     }
259
260     public List JavaDoc 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         //#ifdef DEBUG
270
if (Trace.level() > 1) {
271             Debug.println(toString() + ".addServlet(" +
272                           servlet.getServletName() + ")");
273         }
274         //#endif
275
servlets.put(servlet.getServletName(), servlet);
276     }
277
278     WebServlet getServletForRequest(HttpDispatcher rd) {
279         String JavaDoc 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 JavaDoc 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 JavaDoc 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         //#ifdef DEBUG
313
if (Trace.level() > 1) {
314             Debug.println(toString() + ".getServlet(" + path + ") = " + s);
315         }
316         //#endif
317
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 JavaDoc servletName, String JavaDoc urlPattern) {
329         //#ifdef DEBUG
330
if (Trace.level() > 0) {
331             Debug.println(this + ".addServletMapping(" + servletName +
332                           ", " + urlPattern + ")");
333         }
334         //#endif
335

336         if (urlPattern.equals("*.*")) {
337             defaultServlet = (WebServlet)servlets.get(servletName);
338         } else if (urlPattern.endsWith("*")) {
339             String JavaDoc path = urlPattern.substring(0, urlPattern.length() - 2);
340             pathMappings.put(path, servletName);
341         } else if (urlPattern.startsWith("*.")) {
342             String JavaDoc ext = urlPattern.substring(2);
343             extMappings.put(ext, servletName);
344         } else {
345             exactMappings.put(urlPattern, servletName);
346         }
347     }
348
349     public void setErrorPage(String JavaDoc errorPage) {
350         this.errorPage = errorPage;
351     }
352
353     public String JavaDoc getErrorPage() {
354         return errorPage;
355     }
356
357     public Object JavaDoc getAttribute(String JavaDoc name) {
358         return attributes.get(name);
359     }
360
361     public Enumeration JavaDoc getAttributeNames() {
362         return attributes.keys();
363     }
364
365     public void setAttribute(String JavaDoc name, Object JavaDoc val) {
366         attributes.put(name, val);
367     }
368
369     public void removeAttribute(String JavaDoc name) {
370         attributes.remove(name);
371     }
372
373     /**
374      * Returns the name and version of the network service under which the
375      * servlet is running.
376      *
377      * @return the server information string
378      */

379     public String JavaDoc getServerInfo() {
380         //> return \"Quadcap Web Server [defined VERSION]\";
381
//#autogen begin
382
return "Quadcap Web Server 3.4";
383 //#autogen end
384
}
385
386     /**
387      * Return the server major version number
388      */

389     public int getMajorVersion() {
390      return 2;
391     }
392
393     /**
394      * Return the server minor version number
395      */

396     public int getMinorVersion() {
397      return 2;
398     }
399
400     public ServletContext JavaDoc getContext(String JavaDoc path) {
401         return server.getContext(path);
402     }
403
404     /**
405      * @param path is a string that must begin with '/' and is interpreted
406      * relative to this context's root
407      */

408     public RequestDispatcher JavaDoc getRequestDispatcher(String JavaDoc path) {
409         HttpDispatcher rd = new HttpDispatcher(this, path);
410         WebServlet ws = getServletForRequest(rd);
411         return (ws != null) ? rd : null;
412     }
413
414     public RequestDispatcher JavaDoc getNamedDispatcher(String JavaDoc 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 JavaDoc getRelativeRequestDispatcher(String JavaDoc path,
424                                                           HttpRequest base) {
425         if (path.charAt(0) == '/') {
426             return getRequestDispatcher(path);
427         } else {
428             String JavaDoc 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 JavaDoc absPath = spath.substring(0, spos+1) + path;
445             return getRequestDispatcher(absPath);
446         }
447     }
448
449     void addMimeMapping(String JavaDoc ext, String JavaDoc type) {
450         //#ifdef DEBUG
451
if (Trace.level() > 0) {
452             Debug.println(toString() + ".addMimeMapping(" + ext +
453                           ", " + type + ")");
454         }
455         //#endif
456
mimeTypes.put(ext, type);
457     }
458
459     public String JavaDoc getMimeType(String JavaDoc file) {
460         String JavaDoc type = null;
461     int lastDot = file.lastIndexOf('.');
462     int lastSep = file.lastIndexOf('/');
463     if (lastDot != -1 && (lastSep == -1 || lastDot > lastSep)) {
464             String JavaDoc ext = file.substring(lastDot + 1);
465             type = (String JavaDoc)mimeTypes.get(ext);
466             if (type == null) {
467                 type = server.getMimeTypeForExt(ext);
468             }
469         }
470         return type;
471     }
472
473     /**
474      * If a URI refers to a directory, use the welcome file list to find
475      * a resource in the directory to serve. Return the name of the file
476      * if found, otherwise, simply return the original directory name.
477      */

478     String JavaDoc resolveDirectory(String JavaDoc path) {
479         String JavaDoc ret = path;
480         String JavaDoc 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 JavaDoc 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 JavaDoc getRealPath(String JavaDoc path) {
499         String JavaDoc rpath = resolveDirectory(path);
500         String JavaDoc ret = docRoot.getRealPath(rpath);
501         return ret;
502     }
503
504     public URL JavaDoc getResource(String JavaDoc path) throws MalformedURLException JavaDoc {
505         return docRoot.getURL(path);
506     }
507
508     public InputStream JavaDoc getResourceAsStream(String JavaDoc path) {
509         try {
510             URL JavaDoc url = getResource(path);
511             if (url != null) {
512                 return url.openStream();
513             }
514         } catch (Throwable JavaDoc t) {}
515         return null;
516     }
517
518     /**
519      * Returns the session bound to the specified session ID.
520      *
521      * @param sessionID the ID of a particular session object
522      * @return the session name. Returns null if the session ID does not refer
523      * to a valid session.
524      */

525     public HSession getSession(String JavaDoc sessionId) {
526         synchronized (sessions) {
527             return (HSession)sessions.get(sessionId);
528         }
529     }
530   
531     void removeSession(HSession session) {
532         //#ifdef DEBUG
533
if (Trace.level() > 1) {
534         Debug.println("removeSession(" + session.getId() + ")");
535     }
536         //#endif
537
synchronized (sessions) {
538             sessions.remove(session.getId());
539         }
540     }
541
542     /**
543      * Create a new session
544      */

545     public HSession createSession() {
546         String JavaDoc sessionId = server.makeSessionId();
547         //#ifdef DEBUG
548
if (Trace.level() > 1) {
549         Debug.println("++++++ createSession(): " + sessionId);
550     }
551         //#endif
552
HSession session = new HSession(this, sessionId, sessionTimeout);
553         synchronized (sessions) {
554             sessions.put(sessionId, session);
555         }
556         return session;
557     }
558
559     /**
560      * Reap any expired sessions (sessions not active during the last
561      * interval)
562      */

563     public void expireSessions() {
564         synchronized (sessions) {
565             Enumeration JavaDoc e = sessions.keys();
566             long now = System.currentTimeMillis();
567             while (e.hasMoreElements()) {
568                 String JavaDoc sessionId = (String JavaDoc)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 JavaDoc t) {
575             Debug.print(t);
576             }
577                 }
578             }
579         }
580     }
581
582     /**
583      * Writes a message to the server's log file.
584      *
585      * @param msg the message
586      */

587     public void log(String JavaDoc msg) {
588         Debug.println(msg);
589     }
590
591     /**
592      * Write the stack backtrace for the exception and the specified message
593      * to the server's log file.
594      *
595      * @param e the exception
596      * @param msg the message
597      * @deprecated
598      */

599     public void log(Exception JavaDoc e, String JavaDoc msg) {
600         Debug.println(msg);
601         Debug.print(e);
602     }
603
604     /**
605      * Write the stack backtrace for the exception and the specified message
606      * to the server's log file.
607      *
608      * @param e the exception
609      * @param msg the message
610      */

611     public void log(String JavaDoc msg, Throwable JavaDoc e) {
612         Debug.println(msg);
613         Debug.print(e);
614     }
615     
616     /**
617      * @deprecated in 2.2
618      */

619     public Servlet JavaDoc getServlet(String JavaDoc name) {
620         return null;
621     }
622
623     /**
624      * @deprecated in 2.2
625      */

626     public Enumeration JavaDoc getServletNames() {
627         return new Vector JavaDoc().elements();
628     }
629
630     /**
631      * @deprecated in 2.2
632      */

633     public Enumeration JavaDoc getServlets() {
634         return new Vector JavaDoc().elements();
635     }
636
637     public String JavaDoc getContextPath() {
638         return contextPath;
639     }
640
641     /**
642      * Return the classpath for the context's libraries and classes
643      * under WEB-INF.
644      */

645     public String JavaDoc getContextClassPath() {
646         return classLoader.getClassPath();
647     }
648
649     final ClassLoader JavaDoc getClassLoader() {
650         return classLoader;
651     }
652
653     final void loadInitialServlets() throws ServletException JavaDoc {
654         ServletException JavaDoc ex = null;
655         
656         ArrayList JavaDoc l = new ArrayList JavaDoc();
657         l.addAll(servlets.values());
658         Collections.sort(l, new Comparator JavaDoc() {
659             public int compare(Object JavaDoc a, Object JavaDoc 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 JavaDoc 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 JavaDoc getRootPath() { return docRoot.getRootPath(); }
685
686     public boolean isDirectory(String JavaDoc d) {
687         try {
688             return docRoot.getEntry(d).isDirectory();
689         } catch (Throwable JavaDoc t) {
690             return false;
691         }
692     }
693
694     //#ifdef DEBUG
695
public String JavaDoc toString() {
696         return "[" + contextPath + "]";
697     }
698     //#endif
699
}
700
Popular Tags