001: /*
002: * WebContext.java
003: *
004: *
005: * Copyright (c) 2003 Rimfaxe ApS (www.rimfaxe.com).
006: * All rights reserved.
007: *
008: * This package is written by Lars Andersen <lars@rimfaxe.com>
009: * and licensed by Rimfaxe ApS.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions
013: * are met:
014: *
015: * 1. Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * 2. Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in
020: * the documentation and/or other materials provided with the
021: * distribution.
022: *
023: * 3. The end-user documentation included with the redistribution, if
024: * any, must include the following acknowlegement:
025: * "This product includes software developed by Rimfaxe ApS
026: (www.rimfaxe.com)"
027: * Alternately, this acknowlegement may appear in the software itself,
028: * if and wherever such third-party acknowlegements normally appear.
029: *
030: * 4. The names "Rimfaxe", "Rimfaxe Software", "Lars Andersen" and
031: * "Rimfaxe WebServer" must not be used to endorse or promote products
032: * derived from this software without prior written permission. For written
033: * permission, please contact info@rimfaxe.com
034: *
035: * 5. Products derived from this software may not be called "Rimfaxe"
036: * nor may "Rimfaxe" appear in their names without prior written
037: * permission of the Rimfaxe ApS.
038: *
039: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
040: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
041: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
042: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
043: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
044: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
045: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
046: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
047: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
048: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
049: * SUCH DAMAGE.
050: *
051: */
052:
053: package com.rimfaxe.webserver;
054:
055: import java.util.*;
056: import com.rimfaxe.util.*;
057:
058: import org.w3c.dom.Attr;
059: import org.w3c.dom.Document;
060: import org.w3c.dom.NamedNodeMap;
061: import org.w3c.dom.Node;
062: import org.w3c.dom.NodeList;
063:
064: import javax.naming.directory.DirContext;
065:
066: import javax.naming.NamingException;
067:
068: import com.rimfaxe.webserver.webapp.*;
069: import com.rimfaxe.webserver.servletapi.jsp.JSPstore;
070:
071: import javax.naming.directory.Attribute;
072: import javax.naming.directory.Attributes;
073:
074: import org.apache.naming.resources.Resource;
075: import org.apache.naming.resources.ResourceAttributes;
076:
077: import javax.servlet.jsp.tagext.TagLibraryInfo;
078:
079: import com.rimfaxe.webserver.servletapi.RimfaxeFilterChain;
080:
081: import seda.sandStorm.lib.http.httpRequest;
082:
083: /**
084: *
085: * @author Lars Andersen
086: */
087: public class WebContext {
088: JSPstore jspstore = null;
089:
090: com.rimfaxe.webserver.webapp.Web webapp;
091: com.rimfaxe.webserver.servletapi.RimfaxeServletContext servletcontext;
092:
093: VirtualHost virtualhost = null;
094:
095: Configuration conf = null;
096:
097: String name = "ROOT";
098:
099: String root = "/";
100: String urlpath = "";
101:
102: /** Creates a new instance of WebContext */
103: public WebContext(VirtualHost vh, Node node) {
104: this .virtualhost = vh;
105: name = node.getAttributes().getNamedItem("name").getNodeValue()
106: .trim();
107: traverse(node);
108:
109: }
110:
111: public void initialize()
112: {
113: conf = ObjectStore.getConfiguration();
114:
115:
116: checkDirs();
117:
118: LoadLibraries();
119: webapp = new com.rimfaxe.webserver.webapp.Web(root+"/WEB-INF/web.xml");
120: servletcontext = new com.rimfaxe.webserver.servletapi.RimfaxeServletContext(this , virtualhost);
121:
122:
123: String[] welcomefiles = webapp.getWelcomeFileList();
124: if (welcomefiles==null)
125: welcomefiles = conf.getWebApp().getWelcomeFileList();
126:
127: if (welcomefiles!=null)
128: {
129:
130: servletcontext.setAttribute("com.rimfaxe.webserver.WELCOME_FILES", welcomefiles);
131: }
132:
133:
134:
135: org.apache.naming.resources.FileDirContext fdirctx = new org.apache.naming.resources.FileDirContext();
136: fdirctx.setDebug(0);
137: fdirctx.setDocBase(root);
138: servletcontext.setAttribute("com.rimfaxe.webserver.resources", fdirctx);
139:
140:
141: if (!this .root.startsWith("/")) root = conf.getHome()+"/"+root;
142:
143: // Perform load-on-startup on servlets
144: System.out.println("Perform load-on-startup on servlets");
145:
146: Vector servlet_list = new Vector();
147: Enumeration enum = webapp.getServletNames();
148: while (enum.hasMoreElements())
149: {
150: String s_name = (String) enum.nextElement();
151: //System.out.println("Perform load-on-startup on servlet : "+s_name);
152: Servlet servlet = webapp.getServlet(s_name);
153: if (servlet.getLoadOnStartup()>=0)
154: {
155: //
156: servlet_list.addElement(servlet);
157: }
158: }
159: // Now sort the servlet list.
160: java.util.Collections.sort(servlet_list,
161:
162: new java.util.Comparator()
163: {
164: public int compare(Object obj1, Object obj2)
165: {
166: try
167: {
168: Servlet s1 = (Servlet) obj1;
169: Servlet s2 = (Servlet) obj2;
170:
171: if (s1.getLoadOnStartup()<s2.getLoadOnStartup()) return -1;
172: if (s1.getLoadOnStartup()==s2.getLoadOnStartup()) return 0;
173: if (s1.getLoadOnStartup()>s2.getLoadOnStartup()) return 1;
174: }
175: catch (Exception e) {}
176: return -1;
177: }
178: }
179:
180: );
181:
182: com.rimfaxe.webserver.servletapi.ServletFactory factory = com.rimfaxe.webserver.servletapi.ServletFactory.getInstance();
183: enum = servlet_list.elements();
184: while (enum.hasMoreElements())
185: {
186: Servlet servlet = (Servlet) enum.nextElement();
187:
188: // load the servlet.
189: //System.out.println("Load servlet="+servlet.getName()+" with load-on-startup="+servlet.getLoadOnStartup());
190: factory.loadServlet(servlet.getName(), this , servlet);
191: }
192: }
193:
194: public void checkDirs() {
195: //System.out.println("CHECKDIRS");
196:
197: String workdir = root + "/WEB-INF/rws";
198:
199: java.io.File dir = new java.io.File(workdir);
200: if (!dir.exists())
201: dir.mkdir();
202:
203: dir = new java.io.File(workdir + "/jars");
204: if (!dir.exists())
205: dir.mkdir();
206:
207: dir = new java.io.File(workdir + "/jsp");
208: if (!dir.exists())
209: dir.mkdir();
210:
211: dir = new java.io.File(workdir + "/lib");
212: if (!dir.exists())
213: dir.mkdir();
214:
215: dir = new java.io.File(workdir + "/jsplib");
216: if (!dir.exists())
217: dir.mkdir();
218:
219: String[] filelist = dir.list();
220:
221: if ((filelist != null) && (filelist.length > 0)) {
222: for (int i = 0; i < filelist.length; i++) {
223: //System.out.println("f = "+filelist[i]);
224: try {
225: Runtime.getRuntime().exec(
226: "rm " + workdir + "/jsplib/" + filelist[i]
227: + " -Rf");
228: } catch (Exception e) {
229: // TODO
230: }
231: }
232: }
233:
234: }
235:
236: public void LoadLibraries() {
237:
238: // Load servlets lib
239: String library = "lib" + "servlets" + ".so";
240: String servlet_lib = root + "/WEB-INF/rws/lib/" + library;
241: java.io.File f = new java.io.File(servlet_lib);
242: if (f.exists()) {
243:
244: if (System.getProperty("java.vm.name").equalsIgnoreCase(
245: "GNU libgcj")) {
246: try {
247: //System.out.println("*** Loading : "+servlet_lib);
248: System.load(servlet_lib);
249: //System.out.println("*** Loading : "+servlet_lib+" -- done");
250: } catch (Exception e) {
251: System.out.println("*** Exception loading ["
252: + servlet_lib + "]\n " + e);
253: // TODO
254: }
255: }
256: }
257:
258: // Load JSP libs
259: jspstore = new JSPstore(this );
260: }
261:
262: public VirtualHost getVirtualHost() {
263: return virtualhost;
264: }
265:
266: public String processUrlPath(String req_url) {
267: if (this .urlpath.equalsIgnoreCase("/"))
268: return req_url;
269: if (this .urlpath.equalsIgnoreCase(""))
270: return req_url;
271:
272: String n_url = req_url.substring(urlpath.length() - 1);
273: //System.out.println("WEBCONTEXT converted "+req_url+" to "+n_url);
274:
275: int q_mark = n_url.indexOf('?');
276: int a_mark = n_url.indexOf('&');
277:
278: int mark = q_mark;
279: if (a_mark < q_mark)
280: mark = a_mark;
281:
282: return n_url;
283: }
284:
285: public String processQueryString(String req_url) {
286: String n_url = req_url;
287:
288: //System.out.println("Get query string from ["+n_url+"]");
289: int q_mark = n_url.indexOf('?');
290:
291: int mark = q_mark;
292:
293: if ((mark >= 0) && (mark < n_url.length()))
294: return n_url.substring(mark + 1);
295: else
296: return "";
297: }
298:
299: public Resource getResource(String path) {
300: //System.out.println("get resource -> "+path);
301: DirContext resources = (DirContext) servletcontext
302: .getAttribute("com.rimfaxe.webserver.resources");
303:
304: if (resources == null) {
305: System.out.println("Resorces == null");
306: return null;
307: }
308:
309: Object object = null;
310: Resource file = null;
311: boolean exists = true;
312: try {
313: object = resources.lookup(path);
314: if (object instanceof Resource) {
315: file = (Resource) object;
316: } else if (object instanceof DirContext) {
317: // Use Welcome file list
318: exists = false;
319: } else {
320: // Don't know how to serve another object type
321: exists = false;
322: }
323: } catch (NamingException e) {
324: exists = false;
325: }
326:
327: if (exists)
328: return file;
329: return null;
330: }
331:
332: public ResourceAttributes getResourceAttributes(String path) {
333:
334: //System.out.println("WEBCONTEXT "+name+", look for "+path);
335: DirContext resources = (DirContext) servletcontext
336: .getAttribute("com.rimfaxe.webserver.resources");
337:
338: if (resources == null)
339: return null;
340:
341: Object object = null;
342: Resource file = null;
343: boolean exists = true;
344: try {
345: object = resources.lookup(path);
346: if (object instanceof Resource) {
347: file = (Resource) object;
348: } else if (object instanceof DirContext) {
349: // Use Welcome file list
350: exists = false;
351: } else {
352: // Don't know how to serve another object type
353: exists = false;
354: }
355: } catch (NamingException e) {
356: exists = false;
357: }
358:
359: if (!exists)
360: return null;
361:
362: try {
363: return (ResourceAttributes) resources.getAttributes(path);
364: } catch (NamingException e) {
365: System.out.println("" + e);
366: }
367:
368: System.out.println("--NULL");
369: return null;
370: }
371:
372: public byte[] getResourceByteArray(String path) {
373: Resource res = getResource(path);
374: if (res == null)
375: return null;
376: else
377: return res.getContent();
378: }
379:
380: public java.io.InputStream getResourceAsStream(String path) {
381: Resource res = getResource(path);
382: if (res == null) {
383: System.out.println("getResourceAsStream returns null");
384: return null;
385: } else {
386:
387: //java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream( res.getContent() );
388: //return (java.io.InputStream) bais;
389: try {
390: return res.streamContent();
391: } catch (java.io.IOException ioe) {
392: ioe.printStackTrace(System.out);
393: }
394: }
395: return null;
396: }
397:
398: public String getJspFile(String jspuri) {
399: //System.out.println("JSP FILE = "+ this.getRoot()+jspuri);
400: return this .getRoot() + jspuri;
401: }
402:
403: public com.rimfaxe.webserver.servletapi.jsp.JSPstore getJSPstore() {
404: return jspstore;
405: }
406:
407: public com.rimfaxe.webserver.servletapi.RimfaxeServletContext getServletContext() {
408: return servletcontext;
409: }
410:
411: public com.rimfaxe.webserver.webapp.Web getWebApp() {
412: return webapp;
413: }
414:
415: public String getMimeType(String extension) {
416: String mime = getWebApp().getMimeType(extension);
417: if (mime == null) {
418: mime = conf.getWebApp().getMimeType(extension);
419: }
420:
421: return mime;
422: }
423:
424: public int getSessionExpirationInterval() {
425: SessionConfig sc = getWebApp().getSessionConfig();
426: if (sc != null) {
427: return sc.getSessionTimeout();
428: }
429:
430: sc = conf.getWebApp().getSessionConfig();
431: if (sc != null) {
432: return sc.getSessionTimeout();
433: }
434:
435: return 30 * 60; // 30 minutes
436: }
437:
438: public int matchURI(String uri) {
439: if (uri.startsWith(urlpath))
440: return urlpath.length();
441: else
442: return -1;
443: }
444:
445: public String getRoot() {
446: return root;
447: }
448:
449: public String getUrlpath() {
450: return urlpath;
451: }
452:
453: public String getUrlpathPrefix() {
454: return urlpath.substring(0, urlpath.length() - 1);
455: }
456:
457: public String getName() {
458: return name;
459: }
460:
461: public Vector getFilters(String urlpath) {
462: Vector vec = new Vector();
463:
464: String uri = urlpath;
465: StringTokenizer tkz = new StringTokenizer(urlpath, "?&;", false);
466: if (tkz.hasMoreElements())
467: uri = tkz.nextToken();
468:
469: com.rimfaxe.webserver.webapp.Web webapp_default = conf
470: .getWebApp();
471:
472: Object[] objarray = webapp.getFilterMappings().toArray();
473: for (int i = 0; i < objarray.length; i++) {
474: FilterMapping fm = (FilterMapping) objarray[i];
475: String mapping = fm.getUrlPattern();
476:
477: if (matches(mapping, uri)) {
478: Filter filter = webapp.getFilter(fm.getFilterName());
479:
480: javax.servlet.Filter javax_filter = filter
481: .getInstance(this );
482: if (javax_filter != null)
483: vec.addElement(javax_filter);
484: }
485: }
486:
487: objarray = webapp_default.getFilterMappings().toArray();
488: for (int i = 0; i < objarray.length; i++) {
489: FilterMapping fm = (FilterMapping) objarray[i];
490: String mapping = fm.getUrlPattern();
491:
492: if (matches(mapping, uri)) {
493: Filter filter = webapp_default.getFilter(fm
494: .getFilterName());
495:
496: javax.servlet.Filter javax_filter = filter
497: .getInstance(this );
498: if (javax_filter != null)
499: vec.addElement(javax_filter);
500: }
501:
502: }
503:
504: return vec;
505: }
506:
507: public Servlet getServlet(String servletname) {
508: Servlet s = getWebApp().getServlet(servletname);
509: if (s == null)
510: s = conf.getWebApp().getServlet(servletname);
511: return s;
512: }
513:
514: public String getServletName(String urlpath) {
515: String uri = urlpath;
516: StringTokenizer tkz = new StringTokenizer(urlpath, "?&;", false);
517: if (tkz.hasMoreElements())
518: uri = tkz.nextToken();
519:
520: com.rimfaxe.webserver.webapp.Web webapp_default = conf
521: .getWebApp();
522:
523: Object[] objarray = webapp.getServletMappings().toArray();
524: for (int i = 0; i < objarray.length; i++) {
525: ServletMapping sm = (ServletMapping) objarray[i];
526: String mapping = sm.getUrlPattern();
527:
528: if (matches(mapping, uri)) {
529: return sm.getServletName();
530: }
531:
532: }
533:
534: objarray = webapp_default.getServletMappings().toArray();
535: for (int i = 0; i < objarray.length; i++) {
536: ServletMapping sm = (ServletMapping) objarray[i];
537: String mapping = sm.getUrlPattern();
538:
539: if (matches(mapping, uri)) {
540: return sm.getServletName();
541: }
542:
543: }
544: return "default";
545: }
546:
547: public boolean isStatic(httpRequest req) {
548: String urlpath = req.getURL();
549: String uri = urlpath;
550: StringTokenizer tkz = new StringTokenizer(urlpath, "?&;", false);
551: if (tkz.hasMoreElements())
552: uri = tkz.nextToken();
553:
554: com.rimfaxe.webserver.webapp.Web webapp_default = conf
555: .getWebApp();
556:
557: Object[] objarray = webapp.getStaticMappings().toArray();
558: for (int i = 0; i < objarray.length; i++) {
559: StaticMapping sm = (StaticMapping) objarray[i];
560:
561: String mapping = sm.getUrlPattern();
562:
563: if (matches(mapping, uri)) {
564: //System.out.println("local static match on "+sm.getFileType()+" with max-age="+sm.getMaxAge());
565: req.setSpecial("MAX-AGE", "" + sm.getMaxAge());
566: return true;
567: }
568:
569: }
570:
571: objarray = webapp_default.getStaticMappings().toArray();
572: for (int i = 0; i < objarray.length; i++) {
573: StaticMapping sm = (StaticMapping) objarray[i];
574:
575: String mapping = sm.getUrlPattern();
576:
577: if (matches(mapping, uri)) {
578: //System.out.println("global static match on "+sm.getFileType()+" with max-age="+sm.getMaxAge());
579: req.setSpecial("MAX-AGE", "" + sm.getMaxAge());
580: return true;
581: }
582:
583: }
584: return false;
585: }
586:
587: public Hashtable getTagLibraries() {
588: return this .webapp.getTagLibraries();
589: }
590:
591: public TagLibraryInfo getTagLibrary(String uri, String prefix) {
592: //System.out.println("Get TagLib "+uri+","+prefix);
593:
594: TagLibraryInfoImpl tl = webapp.getTagLibrary(uri);
595: if (tl != null)
596: tl.setPrefix(prefix);
597: return tl;
598: }
599:
600: private String traverse(Node node) {
601:
602: StringBuffer str = new StringBuffer();
603:
604: if (node == null) {
605: return "";
606: }
607: int type = node.getNodeType();
608: switch (type) {
609:
610: case Node.DOCUMENT_NODE: {
611: traverse(((Document) node).getDocumentElement());
612: break;
613: }
614:
615: case Node.ELEMENT_NODE: {
616: if (node.getNodeName().equalsIgnoreCase("root")) {
617: NodeList children = node.getChildNodes();
618: if (children != null) {
619: int len = children.getLength();
620: for (int i = 0; i < len; i++) {
621: String val = traverse(children.item(i));
622: root = val.trim();
623: }
624: }
625: } else if (node.getNodeName().equalsIgnoreCase("urlpath")) {
626: NodeList children = node.getChildNodes();
627: if (children != null) {
628: int len = children.getLength();
629: for (int i = 0; i < len; i++) {
630: String val = traverse(children.item(i));
631: urlpath = val.trim();
632: }
633: }
634: } else {
635: NodeList children = node.getChildNodes();
636: if (children != null) {
637: int len = children.getLength();
638: for (int i = 0; i < len; i++) {
639: String val = traverse(children.item(i));
640: }
641: }
642: }
643: break;
644: }
645:
646: case Node.TEXT_NODE: {
647: //if (node instanceof TextImpl)
648: //{
649: str.append(node.getNodeValue());
650: //}
651: break;
652: }
653: }
654: return str.toString();
655: }
656:
657: public String toXML() {
658: StringBuffer buf = new StringBuffer();
659:
660: buf.append(" <webcontext name=\"" + name + "\">\n");
661:
662: buf.append(" <root> " + root + " </root>\n");
663: buf.append(" <urlpath> " + urlpath + " </urlpath>\n");
664:
665: buf.append(" </webcontext>\n");
666:
667: return "" + buf;
668: }
669:
670: public boolean matches(String sreg, String compareTo) {
671: boolean m = false;
672:
673: if (sreg.startsWith("*")) {
674: if (compareTo.endsWith(sreg.substring(1)))
675: m = true;
676: } else if (sreg.endsWith("*")) {
677: if (compareTo.startsWith(sreg.substring(0,
678: sreg.length() - 1)))
679: m = true;
680: } else if (sreg.indexOf("*") != -1) {
681: int p = sreg.indexOf("*");
682: if ((compareTo.startsWith(sreg.substring(0, p)))
683: && (compareTo.endsWith(sreg.substring(p + 1))))
684: m = true;
685: } else {
686: if (sreg.equals(compareTo))
687: m = true;
688: }
689:
690: return m;
691: }
692: }
|