/*
* WebContext.java
*
*
* Copyright (c) 2003 Rimfaxe ApS (www.rimfaxe.com).
* All rights reserved.
*
* This package is written by Lars Andersen <lars@rimfaxe.com>
* and licensed by Rimfaxe ApS.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by Rimfaxe ApS
(www.rimfaxe.com)"
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "Rimfaxe", "Rimfaxe Software", "Lars Andersen" and
* "Rimfaxe WebServer" must not be used to endorse or promote products
* derived from this software without prior written permission. For written
* permission, please contact info@rimfaxe.com
*
* 5. Products derived from this software may not be called "Rimfaxe"
* nor may "Rimfaxe" appear in their names without prior written
* permission of the Rimfaxe ApS.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
package com.rimfaxe.webserver;
import java.util.*;
import com.rimfaxe.util.*;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.naming.directory.DirContext;
import javax.naming.NamingException;
import com.rimfaxe.webserver.webapp.*;
import com.rimfaxe.webserver.servletapi.jsp.JSPstore;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import org.apache.naming.resources.Resource;
import org.apache.naming.resources.ResourceAttributes;
import javax.servlet.jsp.tagext.TagLibraryInfo;
import com.rimfaxe.webserver.servletapi.RimfaxeFilterChain;
import seda.sandStorm.lib.http.httpRequest;
/**
*
* @author Lars Andersen
*/
public class WebContext
{
JSPstore jspstore = null;
com.rimfaxe.webserver.webapp.Web webapp;
com.rimfaxe.webserver.servletapi.RimfaxeServletContext servletcontext;
VirtualHost virtualhost = null;
Configuration conf = null;
String name = "ROOT";
String root = "/";
String urlpath = "";
/** Creates a new instance of WebContext */
public WebContext(VirtualHost vh, Node node)
{
this.virtualhost = vh;
name = node.getAttributes().getNamedItem("name").getNodeValue().trim();
traverse(node);
}
public void initialize()
{
conf = ObjectStore.getConfiguration();
checkDirs();
LoadLibraries();
webapp = new com.rimfaxe.webserver.webapp.Web(root+"/WEB-INF/web.xml");
servletcontext = new com.rimfaxe.webserver.servletapi.RimfaxeServletContext(this, virtualhost);
String[] welcomefiles = webapp.getWelcomeFileList();
if (welcomefiles==null)
welcomefiles = conf.getWebApp().getWelcomeFileList();
if (welcomefiles!=null)
{
servletcontext.setAttribute("com.rimfaxe.webserver.WELCOME_FILES", welcomefiles);
}
org.apache.naming.resources.FileDirContext fdirctx = new org.apache.naming.resources.FileDirContext();
fdirctx.setDebug(0);
fdirctx.setDocBase(root);
servletcontext.setAttribute("com.rimfaxe.webserver.resources", fdirctx);
if (!this.root.startsWith("/")) root = conf.getHome()+"/"+root;
// Perform load-on-startup on servlets
System.out.println("Perform load-on-startup on servlets");
Vector servlet_list = new Vector();
Enumeration enum = webapp.getServletNames();
while (enum.hasMoreElements())
{
String s_name = (String) enum.nextElement();
//System.out.println("Perform load-on-startup on servlet : "+s_name);
Servlet servlet = webapp.getServlet(s_name);
if (servlet.getLoadOnStartup()>=0)
{
//
servlet_list.addElement(servlet);
}
}
// Now sort the servlet list.
java.util.Collections.sort(servlet_list,
new java.util.Comparator()
{
public int compare(Object obj1, Object obj2)
{
try
{
Servlet s1 = (Servlet) obj1;
Servlet s2 = (Servlet) obj2;
if (s1.getLoadOnStartup()<s2.getLoadOnStartup()) return -1;
if (s1.getLoadOnStartup()==s2.getLoadOnStartup()) return 0;
if (s1.getLoadOnStartup()>s2.getLoadOnStartup()) return 1;
}
catch (Exception e) {}
return -1;
}
}
);
com.rimfaxe.webserver.servletapi.ServletFactory factory = com.rimfaxe.webserver.servletapi.ServletFactory.getInstance();
enum = servlet_list.elements();
while (enum.hasMoreElements())
{
Servlet servlet = (Servlet) enum.nextElement();
// load the servlet.
//System.out.println("Load servlet="+servlet.getName()+" with load-on-startup="+servlet.getLoadOnStartup());
factory.loadServlet(servlet.getName(), this, servlet);
}
}
public void checkDirs()
{
//System.out.println("CHECKDIRS");
String workdir = root+"/WEB-INF/rws";
java.io.File dir = new java.io.File(workdir);
if (!dir.exists()) dir.mkdir();
dir = new java.io.File(workdir+"/jars");
if (!dir.exists()) dir.mkdir();
dir = new java.io.File(workdir+"/jsp");
if (!dir.exists()) dir.mkdir();
dir = new java.io.File(workdir+"/lib");
if (!dir.exists()) dir.mkdir();
dir = new java.io.File(workdir+"/jsplib");
if (!dir.exists()) dir.mkdir();
String[] filelist = dir.list();
if ( (filelist!=null) && (filelist.length>0) )
{
for (int i=0; i<filelist.length; i++)
{
//System.out.println("f = "+filelist[i]);
try
{
Runtime.getRuntime().exec("rm "+workdir+"/jsplib/"+filelist[i]+" -Rf");
}
catch (Exception e)
{
// TODO
}
}
}
}
public void LoadLibraries()
{
// Load servlets lib
String library = "lib"+"servlets"+".so";
String servlet_lib = root+"/WEB-INF/rws/lib/"+library;
java.io.File f = new java.io.File(servlet_lib);
if (f.exists())
{
if (System.getProperty("java.vm.name").equalsIgnoreCase("GNU libgcj"))
{
try
{
//System.out.println("*** Loading : "+servlet_lib);
System.load(servlet_lib);
//System.out.println("*** Loading : "+servlet_lib+" -- done");
}
catch (Exception e)
{
System.out.println("*** Exception loading ["+servlet_lib+"]\n "+e);
// TODO
}
}
}
// Load JSP libs
jspstore = new JSPstore(this);
}
public VirtualHost getVirtualHost() { return virtualhost; }
public String processUrlPath(String req_url)
{
if (this.urlpath.equalsIgnoreCase("/")) return req_url;
if (this.urlpath.equalsIgnoreCase("")) return req_url;
String n_url = req_url.substring( urlpath.length()-1 );
//System.out.println("WEBCONTEXT converted "+req_url+" to "+n_url);
int q_mark = n_url.indexOf('?');
int a_mark = n_url.indexOf('&');
int mark = q_mark;
if (a_mark<q_mark) mark = a_mark;
return n_url;
}
public String processQueryString(String req_url)
{
String n_url = req_url;
//System.out.println("Get query string from ["+n_url+"]");
int q_mark = n_url.indexOf('?');
int mark = q_mark;
if ( (mark>=0) && (mark<n_url.length()) )
return n_url.substring(mark+1);
else
return "";
}
public Resource getResource(String path)
{
//System.out.println("get resource -> "+path);
DirContext resources = (DirContext) servletcontext.getAttribute("com.rimfaxe.webserver.resources");
if (resources==null)
{
System.out.println("Resorces == null");
return null;
}
Object object = null;
Resource file = null;
boolean exists = true;
try
{
object = resources.lookup(path);
if (object instanceof Resource)
{
file = (Resource) object;
}
else if (object instanceof DirContext)
{
// Use Welcome file list
exists = false;
}
else
{
// Don't know how to serve another object type
exists = false;
}
}
catch (NamingException e)
{
exists = false;
}
if (exists) return file;
return null;
}
public ResourceAttributes getResourceAttributes(String path)
{
//System.out.println("WEBCONTEXT "+name+", look for "+path);
DirContext resources = (DirContext) servletcontext.getAttribute("com.rimfaxe.webserver.resources");
if (resources==null) return null;
Object object = null;
Resource file = null;
boolean exists = true;
try
{
object = resources.lookup(path);
if (object instanceof Resource)
{
file = (Resource) object;
}
else if (object instanceof DirContext)
{
// Use Welcome file list
exists = false;
}
else
{
// Don't know how to serve another object type
exists = false;
}
}
catch (NamingException e)
{
exists = false;
}
if (!exists) return null;
try
{
return (ResourceAttributes) resources.getAttributes(path);
}
catch (NamingException e)
{
System.out.println(""+e);
}
System.out.println("--NULL");
return null;
}
public byte[] getResourceByteArray(String path)
{
Resource res = getResource(path);
if (res==null) return null;
else return res.getContent();
}
public java.io.InputStream getResourceAsStream(String path)
{
Resource res = getResource(path);
if (res==null)
{
System.out.println("getResourceAsStream returns null");
return null;
}
else
{
//java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream( res.getContent() );
//return (java.io.InputStream) bais;
try
{
return res.streamContent();
}
catch (java.io.IOException ioe)
{
ioe.printStackTrace(System.out);
}
}
return null;
}
public String getJspFile( String jspuri )
{
//System.out.println("JSP FILE = "+ this.getRoot()+jspuri);
return this.getRoot()+jspuri;
}
public com.rimfaxe.webserver.servletapi.jsp.JSPstore getJSPstore()
{
return jspstore;
}
public com.rimfaxe.webserver.servletapi.RimfaxeServletContext getServletContext()
{
return servletcontext;
}
public com.rimfaxe.webserver.webapp.Web getWebApp() { return webapp; }
public String getMimeType(String extension)
{
String mime = getWebApp().getMimeType(extension);
if (mime==null)
{
mime = conf.getWebApp().getMimeType(extension);
}
return mime;
}
public int getSessionExpirationInterval()
{
SessionConfig sc = getWebApp().getSessionConfig();
if (sc!=null)
{
return sc.getSessionTimeout();
}
sc = conf.getWebApp().getSessionConfig();
if (sc!=null)
{
return sc.getSessionTimeout();
}
return 30*60; // 30 minutes
}
public int matchURI(String uri)
{
if (uri.startsWith(urlpath))
return urlpath.length();
else
return -1;
}
public String getRoot() { return root; }
public String getUrlpath() { return urlpath; }
public String getUrlpathPrefix()
{
return urlpath.substring(0,urlpath.length()-1);
}
public String getName() { return name; }
public Vector getFilters(String urlpath)
{
Vector vec = new Vector();
String uri = urlpath;
StringTokenizer tkz = new StringTokenizer(urlpath,"?&;",false);
if (tkz.hasMoreElements()) uri = tkz.nextToken();
com.rimfaxe.webserver.webapp.Web webapp_default = conf.getWebApp();
Object[] objarray = webapp.getFilterMappings().toArray();
for (int i=0; i<objarray.length; i++)
{
FilterMapping fm = (FilterMapping) objarray[i];
String mapping = fm.getUrlPattern();
if (matches(mapping, uri))
{
Filter filter = webapp.getFilter( fm.getFilterName() );
javax.servlet.Filter javax_filter = filter.getInstance(this);
if (javax_filter!=null)
vec.addElement( javax_filter );
}
}
objarray = webapp_default.getFilterMappings().toArray();
for (int i=0; i<objarray.length; i++)
{
FilterMapping fm = (FilterMapping) objarray[i];
String mapping = fm.getUrlPattern();
if (matches(mapping, uri))
{
Filter filter = webapp_default.getFilter( fm.getFilterName() );
javax.servlet.Filter javax_filter = filter.getInstance(this);
if (javax_filter!=null)
vec.addElement( javax_filter );
}
}
return vec;
}
public Servlet getServlet(String servletname)
{
Servlet s = getWebApp().getServlet(servletname);
if (s==null) s = conf.getWebApp().getServlet(servletname);
return s;
}
public String getServletName(String urlpath)
{
String uri = urlpath;
StringTokenizer tkz = new StringTokenizer(urlpath,"?&;",false);
if (tkz.hasMoreElements()) uri = tkz.nextToken();
com.rimfaxe.webserver.webapp.Web webapp_default = conf.getWebApp();
Object[] objarray = webapp.getServletMappings().toArray();
for (int i=0; i<objarray.length; i++)
{
ServletMapping sm = (ServletMapping) objarray[i];
String mapping = sm.getUrlPattern();
if (matches(mapping, uri))
{
return sm.getServletName();
}
}
objarray = webapp_default.getServletMappings().toArray();
for (int i=0; i<objarray.length; i++)
{
ServletMapping sm = (ServletMapping) objarray[i];
String mapping = sm.getUrlPattern();
if (matches(mapping, uri))
{
return sm.getServletName();
}
}
return "default";
}
public boolean isStatic(httpRequest req)
{
String urlpath = req.getURL();
String uri = urlpath;
StringTokenizer tkz = new StringTokenizer(urlpath,"?&;",false);
if (tkz.hasMoreElements()) uri = tkz.nextToken();
com.rimfaxe.webserver.webapp.Web webapp_default = conf.getWebApp();
Object[] objarray = webapp.getStaticMappings().toArray();
for (int i=0; i<objarray.length; i++)
{
StaticMapping sm = (StaticMapping) objarray[i];
String mapping = sm.getUrlPattern();
if (matches(mapping, uri))
{
//System.out.println("local static match on "+sm.getFileType()+" with max-age="+sm.getMaxAge());
req.setSpecial("MAX-AGE", ""+sm.getMaxAge());
return true;
}
}
objarray = webapp_default.getStaticMappings().toArray();
for (int i=0; i<objarray.length; i++)
{
StaticMapping sm = (StaticMapping) objarray[i];
String mapping = sm.getUrlPattern();
if (matches(mapping, uri))
{
//System.out.println("global static match on "+sm.getFileType()+" with max-age="+sm.getMaxAge());
req.setSpecial("MAX-AGE", ""+sm.getMaxAge());
return true;
}
}
return false;
}
public Hashtable getTagLibraries()
{
return this.webapp.getTagLibraries();
}
public TagLibraryInfo getTagLibrary(String uri, String prefix)
{
//System.out.println("Get TagLib "+uri+","+prefix);
TagLibraryInfoImpl tl = webapp.getTagLibrary(uri);
if (tl!=null)
tl.setPrefix(prefix);
return tl;
}
private String traverse(Node node)
{
StringBuffer str = new StringBuffer();
if (node == null)
{
return "";
}
int type = node.getNodeType();
switch (type)
{
case Node.DOCUMENT_NODE:
{
traverse(((Document)node).getDocumentElement());
break;
}
case Node.ELEMENT_NODE:
{
if (node.getNodeName().equalsIgnoreCase("root"))
{
NodeList children = node.getChildNodes();
if (children != null)
{
int len = children.getLength();
for (int i = 0; i < len; i++)
{
String val = traverse(children.item(i));
root = val.trim();
}
}
}
else if (node.getNodeName().equalsIgnoreCase("urlpath"))
{
NodeList children = node.getChildNodes();
if (children != null)
{
int len = children.getLength();
for (int i = 0; i < len; i++)
{
String val = traverse(children.item(i));
urlpath = val.trim();
}
}
}
else
{
NodeList children = node.getChildNodes();
if (children != null)
{
int len = children.getLength();
for (int i = 0; i < len; i++)
{
String val = traverse(children.item(i));
}
}
}
break;
}
case Node.TEXT_NODE:
{
//if (node instanceof TextImpl)
//{
str.append(node.getNodeValue());
//}
break;
}
}
return str.toString();
}
public String toXML()
{
StringBuffer buf = new StringBuffer();
buf.append(" <webcontext name=\""+name+"\">\n");
buf.append(" <root> "+root+" </root>\n");
buf.append(" <urlpath> "+urlpath+" </urlpath>\n");
buf.append(" </webcontext>\n");
return ""+buf;
}
public boolean matches(String sreg, String compareTo)
{
boolean m = false;
if (sreg.startsWith("*"))
{
if ( compareTo.endsWith( sreg.substring(1)) ) m = true;
}
else if (sreg.endsWith("*"))
{
if ( compareTo.startsWith( sreg.substring(0,sreg.length()-1)) ) m = true;
}
else if (sreg.indexOf("*")!=-1)
{
int p = sreg.indexOf("*");
if (( compareTo.startsWith( sreg.substring(0,p)) ) && ( compareTo.endsWith( sreg.substring(p+1)) ))
m = true;
}
else
{
if (sreg.equals(compareTo)) m = true;
}
return m;
}
}