Author: costin Date: Wed Apr 23 07:23:28 2008 New Revision: 650881 URL: http://svn.apache.org/viewvc?rev=650881&view=rev Log: Add back JSP support - in a more flexible form, and without dep on jasper ( or jsp for that matter :-). While I don't think non-JSP files will use this, at least I don't feel bad about tomcat-lite including jsp support
More cleanup, and a simpler way to locate extensions and move more code to 'user space'. Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/AddonSupport.java (with props) tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserTemplateClassMapper.java (with props) tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspFileTemplateServlet.java (with props) tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/PreCompileFilter.java (with props) tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java (with props) tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java (with props) tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java (with props) Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletConfigImpl.java tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestImpl.java tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserSessionManager.java tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletConfigImpl.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletConfigImpl.java?rev=650881&r1=650880&r2=650881&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletConfigImpl.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletConfigImpl.java Wed Apr 23 07:23:28 2008 @@ -53,16 +53,6 @@ private static final String[] DEFAULT_SERVLET_METHODS = new String[] { "GET", "HEAD", "POST" }; - public static final String JSP_SERVLET_CLASS = - "org.apache.tomcat.servlets.jsp.JspProxyServlet"; - - public static final String JSP_SERVLET_NAME = "jsp"; - - public static final String JSP_SERVLET_COMPILER_CLASS = - "org.apache.tomcat.servlets.jsp.JspCompileServlet"; - - public static final String JSP_SERVLET_COMPILER_NAME = "jspCompiler"; - public static final String SINGLE_THREADED_PROXY = "org.apache.tomcat.servlets.jsp.SingleThreadedProxyServlet"; Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java?rev=650881&r1=650880&r2=650881&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java Wed Apr 23 07:23:28 2008 @@ -54,6 +54,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.servlets.addon.AddonSupport; import org.apache.tomcat.servlets.addon.ConfigurableContextListeners; import org.apache.tomcat.servlets.addon.ConfigurableServletContext; import org.apache.tomcat.servlets.addon.UserSessionManager; @@ -62,7 +63,6 @@ import org.apache.tomcat.servlets.config.ServletData; import org.apache.tomcat.servlets.config.WebAppData; import org.apache.tomcat.servlets.config.WebXml; -import org.apache.tomcat.servlets.file.WebdavServlet; import org.apache.tomcat.servlets.util.Enumerator; import org.apache.tomcat.servlets.util.RequestUtil; import org.apache.tomcat.servlets.util.UrlUtils; @@ -98,10 +98,6 @@ transient Log log; - /** Prefix for all internal webapps. - */ - public static String CONTAINER_PREFIX = "__x_"; - /** * Prefix to use in servlet names that are used internally. */ @@ -301,52 +297,10 @@ * @param name Name of the context attribute to return */ public Object getAttribute(String name) { - if (name.startsWith(CONTAINER_PREFIX)) { - Object o = getContainerAttribute(name); - if (o != null) return o; - } return (attributes.get(name)); } /** - * Tomcat-lite core has the goal to provide maximum power to webapps, by - * exposing internals and allowing apps to take container-specific - * optimizations. However it tries to avoid the need for a servlet to - * depend on tomcat-lite, so servlets can be generic, but still check - * and use special features if tomcat-lite is detected. - * - * Example use of attributes ( and the tomcat-lite independent way ): - * - CONTAINER_PREFIX + servlet_ + servletname -> returns a servlet, - * similar with the old deprecated getServlet() method. Equivalent - * mechanism: have the serlvet load-on-startup and set the attribute with - * 'this'. Benefit: more power to the app on controlling the lifecycle, - * more flexiblity, use servlets as java beans, with real methods insted - * of just service() - a mini-component model based on servlets. - * - * - * @param name - */ - private Object getContainerAttribute(String name) { - // special code to avoid load-on-startup for container servlets - // like jsp - if (name.startsWith(CONTAINER_PREFIX + "servlet_")) { - String sname = name.substring(CONTAINER_PREFIX.length() + - "servlet_".length()); - - ServletConfigImpl sc = getServletConfig(sname); - if (sc == null) return null; - try { - Servlet s = sc.loadServlet(); - return s; - } catch (ServletException e) { - e.printStackTrace(); - } - } - return null; - } - - - /** * Return an enumeration of the names of the context attributes * associated with this context. */ @@ -991,10 +945,6 @@ } setWelcomeFiles(wFiles); - if (d.sessionTimeout > 0 ) { - setSessionTimeout(d.sessionTimeout); - } - Iterator i2 = d.filters.values().iterator(); while (i2.hasNext()) { FilterData fd = (FilterData)i2.next(); @@ -1004,14 +954,16 @@ Iterator i3 = d.servlets.values().iterator(); while (i3.hasNext()) { ServletData sd = (ServletData) i3.next(); - // jsp-file equivalent to JspProxyServlet + arg + // jsp-file if (sd.servletClass == null) { if (sd.jspFile == null) { log.error("Missing servlet class for " + sd.servletName); continue; } - sd.servletClass = ServletConfigImpl.JSP_SERVLET_CLASS; - sd.initParams.put(CONTAINER_PREFIX + "jspFile", sd.jspFile); + sd.servletClass = SERVLETS_PACKAGE + + ".jsp.JspFileTemplateServlet"; + sd.initParams.put(AddonSupport.ADDON_PREFIX + "jsp-file", + sd.jspFile); } ServletConfigImpl sw = @@ -1101,8 +1053,10 @@ public void init() throws ServletException { String base = getBasePath(); if (base == null) { - webAppData = new WebAppData(); - return; + initDefaults(); + webAppData = new WebAppData(); + initDefaultsPostConfig(); + return; } if (webAppData != null && webAppData.fileName != null) { @@ -1120,9 +1074,9 @@ } if (webAppData == null) { // Add default mappings. - initDefaults(); - readWebXml(base); + readWebXml(base); // will call initDefaults() } + initDefaultsPostConfig(); } public ArrayList getClasspath(File directory, File classesDir) { @@ -1209,52 +1163,70 @@ public UserSessionManager getManager() { if (manager == null) { - manager = (UserSessionManager) servlets.get(USERSPACE_PREFIX + - ".SessionManager"); - } - if (manager == null) { - ServletConfigImpl managerS = new ServletConfigImpl(this, - "sessionManager", - SERVLETS_PACKAGE + ".session.SessionManagerServlet"); - try { - manager = (UserSessionManager) managerS.allocate(); - } catch (ServletException e) { - e.printStackTrace(); - } + manager = (UserSessionManager) AddonSupport.getUserExtension(this, + UserSessionManager.class); + manager.setContext(this); + if (webAppData.sessionTimeout > 0 ) { + manager.setSessionTimeout(webAppData.sessionTimeout); + } } return manager; } - private static String SERVLETS_PACKAGE = "org.apache.tomcat.servlets"; + + // TODO: configurable ? init-params + public String getSessionCookieName() { + return "JSESSIONID"; + } + + static String SERVLETS_PACKAGE = "org.apache.tomcat.servlets"; + + private void initDefaultsPostConfig() { + for (String sname: facade.ctxDefaultInitParam.keySet()) { + String path = facade.ctxDefaultInitParam.get(sname); + webAppData.contextParam.put(sname, path); + } + String usm = AddonSupport.ADDON_PREFIX + + UserSessionManager.class.getSimpleName(); + if (webAppData.contextParam.get(usm) == null) { + webAppData.contextParam.put(usm, + SERVLETS_PACKAGE + ".session.SessionManagerServlet"); + } + + } private void initDefaults() throws ServletException { - //ServletData sd = new ServletData(); - //sd.servletName = "default"; - + File f = new File(basePath + "/WEB-INF/tmp"); + f.mkdirs(); + setAttribute("javax.servlet.context.tempdir", + f); + ServletConfigImpl fileS = new ServletConfigImpl(this, "default", SERVLETS_PACKAGE + ".file.WebdavServlet"); addServletConfig(fileS); addMapping("/", fileS); - File f = new File(basePath + "/WEB-INF/tmp"); - f.mkdirs(); - setAttribute("javax.servlet.context.tempdir", - f.getAbsolutePath()); - - fileS = new ServletConfigImpl(this, - ServletConfigImpl.JSP_SERVLET_NAME, - ServletConfigImpl.JSP_SERVLET_CLASS); + // *.jsp support + fileS = new ServletConfigImpl(this, + "jspwildcard", + SERVLETS_PACKAGE + ".jsp.WildcardTemplateServlet"); addMapping("*.jsp", fileS); addServletConfig(fileS); - fileS = new ServletConfigImpl(this, - ServletConfigImpl.JSP_SERVLET_COMPILER_NAME, - ServletConfigImpl.JSP_SERVLET_COMPILER_CLASS); - f = new File(basePath + "/WEB-INF/classes"); - f.mkdirs(); - fileS.initParams.put("scratchdir", f.getAbsolutePath()); - addServletConfig(fileS); + // TODO: make this customizable, avoid loading it on startup + // Set the class name as default in the addon support + + for (String sname: facade.preloadServlets.keySet()) { + String sclass = facade.preloadServlets.get(sname); + fileS = new ServletConfigImpl(this, sname, sclass); + addServletConfig(fileS); + } + for (String sname: facade.preloadMappings.keySet()) { + String path = facade.preloadMappings.get(sname); + ServletConfigImpl servletConfig = getServletConfig(sname); + addMapping(path, servletConfig); + } } public void readWebXml(InputStream is) throws ServletException { Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestImpl.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestImpl.java?rev=650881&r1=650880&r2=650881&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestImpl.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestImpl.java Wed Apr 23 07:23:28 2008 @@ -2355,7 +2355,7 @@ * TODO: should be done in manager */ protected void parseSessionCookiesId() { - String sessionCookieName = context.getManager().getSessionCookieName(); + String sessionCookieName = context.getSessionCookieName(); // Parse session id from cookies Cookies serverCookies = coyoteRequest.getCookies(); Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java?rev=650881&r1=650880&r2=650881&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java Wed Apr 23 07:23:28 2008 @@ -7,8 +7,10 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.servlet.Filter; import javax.servlet.Servlet; @@ -20,12 +22,13 @@ import org.apache.coyote.ActionCode; import org.apache.coyote.ActionHook; import org.apache.coyote.Adapter; -import org.apache.coyote.OutputBuffer; -import org.apache.coyote.ProtocolHandler; import org.apache.coyote.Request; import org.apache.coyote.Response; import org.apache.coyote.adapters.CoyoteServer; import org.apache.coyote.adapters.MapperAdapter; +import org.apache.coyote.client.BlockingCoyoteBuffers; +import org.apache.tomcat.servlets.addon.AddonSupport; +import org.apache.tomcat.servlets.addon.UserTemplateClassMapper; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.http.mapper.MappingData; @@ -54,7 +57,14 @@ // Discovered or default Host/Context mapper Filter hostMapper; - ProtocolHandler connector; + // Servlets to preload in each context, configurable from CLI or API + Map<String,String> preloadServlets = new HashMap(); + Map<String,String> preloadMappings = new HashMap(); + Map<String,String> ctxDefaultInitParam = new HashMap(); + + CoyoteServer coyote = new CoyoteServer(); + + protected boolean daemon = false; private TomcatLite() { } @@ -105,12 +115,16 @@ System.err.println("Engine.start() " + (t1-t0)); } + public void setDaemon(boolean d) { + coyote.setDaemon(d); + } + public void startConnector() { - connector = CoyoteServer.getDefaultConnector(port); - connector.setAdapter(this); + coyote.setPort(port); + coyote.addAdapter("/", this); try { - connector.init(); - connector.start(); + coyote.init(); + coyote.start(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -127,6 +141,42 @@ addServletContext("", pathDir[1], pathDir[0]); } + public void setJspCompiler(boolean b) { + addDefaultInitParam(AddonSupport.ADDON_PREFIX + + UserTemplateClassMapper.class.getSimpleName(), + ServletContextImpl.SERVLETS_PACKAGE + + ".jsp.JasperCompilerTemplateClassMapper"); + setPreload("jsp:" + ServletContextImpl.SERVLETS_PACKAGE + + ".jsp.JspCompileServlet"); + } + + public void setPreload(String servletNameClass) { + String[] nv = servletNameClass.split(":"); + preloadServlets.put(nv[0], nv[1]); + } + + public void addPreload(String servletName, String servletClassName) { + preloadServlets.put(servletName, servletClassName); + } + + public void setDefaultInitParam(String nameValue) { + String[] nv = nameValue.split(":"); + ctxDefaultInitParam.put(nv[0], nv[1]); + } + + public void addDefaultInitParam(String name, String value) { + ctxDefaultInitParam.put(name, value); + } + + public void setPreloadMappings(String servletPath) { + String[] nv = servletPath.split(":"); + preloadMappings.put(nv[0], nv[1]); + } + + public void addPreloadMapping(String servletName, String path) { + preloadMappings.put(servletName, path); + } + public void stop() { Iterator i1 = contexts.iterator(); while (i1.hasNext()) { @@ -137,12 +187,10 @@ e.printStackTrace(); } } - if (connector != null) { - try { - connector.destroy(); - } catch (Exception e) { - e.printStackTrace(); - } + try { + coyote.stop(); + } catch (Exception e) { + e.printStackTrace(); } } @@ -443,15 +491,8 @@ ServletRequestImpl req = createMessage(); req.setRequestURI(uri); ServletResponseImpl res = req.getResponse(); - res.getCoyoteResponse().setOutputBuffer(new OutputBuffer() { - public int doWrite(ByteChunk chunk, - Response response) - throws IOException { - int len = chunk.getLength(); - out.append(chunk.getBuffer(), chunk.getStart(), len); - return len; - } - }); + res.getCoyoteResponse().setOutputBuffer( + new BlockingCoyoteBuffers.ByteChunkOutputBuffer(out)); return req; } @@ -526,12 +567,11 @@ return false; } - public static final int ADAPTER_NOTES = 1; public void service(Request req, Response res) throws Exception { // find the facades - ServletRequestImpl sreq = (ServletRequestImpl) req.getNote(ADAPTER_NOTES); - ServletResponseImpl sres = (ServletResponseImpl) res.getNote(ADAPTER_NOTES); + ServletRequestImpl sreq = (ServletRequestImpl) req.getNote(CoyoteServer.ADAPTER_REQ_NOTE); + ServletResponseImpl sres = (ServletResponseImpl) res.getNote(CoyoteServer.ADAPTER_RES_NOTE); if (sreq == null) { sreq = new ServletRequestImpl(); sres = new ServletResponseImpl(); @@ -540,17 +580,20 @@ sreq.setResponse(sres); sres.setRequest(sreq); - req.setNote(ADAPTER_NOTES, sreq); - res.setNote(ADAPTER_NOTES, sres); + req.setNote(CoyoteServer.ADAPTER_REQ_NOTE, sreq); + res.setNote(CoyoteServer.ADAPTER_RES_NOTE, sres); } service(sreq, sres); - sres.outputBuffer.flush(); - res.finish(); - sreq.recycle(); - sres.recycle(); + if (res.getNote(CoyoteServer.COMET_RES_NOTE) == null) { + sres.outputBuffer.flush(); + res.finish(); + + sreq.recycle(); + sres.recycle(); + } } public void endRequest(ServletRequestImpl req, Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/AddonSupport.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/AddonSupport.java?rev=650881&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/AddonSupport.java (added) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/AddonSupport.java Wed Apr 23 07:23:28 2008 @@ -0,0 +1,65 @@ +/* + */ +package org.apache.tomcat.servlets.addon; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; + +/** + * Simple mechanism to separate the addon interface from the impl. + * + * The initial approach was to register the implementation class using + * web.xml in webapps that provided extensions, having servlet/filter init + * code register the extensions ( or implement the APIs ). The problem is + * startup time and complexity, and required container code. + * + * This class still uses webapps as the 'module' unit, but uses context + * init params and attributes. It can work in an arbitrary container, without + * changes. + */ +public class AddonSupport { + public static String ADDON_PREFIX = + System.getProperty("org.apache.tomcat.servlets.addon", + "org.apache.tomcat.servlets.addon."); + + public static String getInitParameter(ServletConfig config, String name) { + return config.getInitParameter(ADDON_PREFIX + name); + } + + /** + * This is called from the servlet engine or servlets to get access to an + * extension in user space ( i.e. inside the webapp ). + * + * A context init param can be used to declare the implementation class. + * + * A webapp could also use a load-on-startup or context listener to + * register the object as a context attribute. + */ + public static Object getUserExtension(ServletContext ctx, String name) { + Object ext = ctx.getAttribute(ADDON_PREFIX + name); + if (ext == null) { + String className = ctx.getInitParameter(ADDON_PREFIX + name); + if (className != null) { + // TODO: make sure the right loader is used + try { + Class c = Class.forName(className); + ext = c.newInstance(); + return ext; + } catch (Throwable e) { + e.printStackTrace(); + return null; + } + } + } + return ext; + } + + public static void setUserExtension(ServletContext ctx, String name, + Object ext) { + ctx.setAttribute(ADDON_PREFIX + name, ext); + } + + public static Object getUserExtension(ServletContext ctx, Class c) { + return getUserExtension(ctx, c.getSimpleName()); + } +} Propchange: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/AddonSupport.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserSessionManager.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserSessionManager.java?rev=650881&r1=650880&r2=650881&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserSessionManager.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserSessionManager.java Wed Apr 23 07:23:28 2008 @@ -4,6 +4,7 @@ import java.io.IOException; +import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; /** @@ -18,19 +19,22 @@ */ public interface UserSessionManager { - HttpSession findSession(String requestedSessionId) throws IOException; + + + HttpSession findSession(String requestedSessionId) throws IOException; - HttpSession createSession(String requestedSessionId); + HttpSession createSession(String requestedSessionId); - boolean isValid(HttpSession session); + boolean isValid(HttpSession session); - void access(HttpSession session); + void access(HttpSession session); - void endAccess(HttpSession session); + void endAccess(HttpSession session); - String getSessionCookieName(); - - void setSessionTimeout(int to); + + void setSessionTimeout(int to); + + void setContext(ServletContext ctx); } Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserTemplateClassMapper.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserTemplateClassMapper.java?rev=650881&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserTemplateClassMapper.java (added) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserTemplateClassMapper.java Wed Apr 23 07:23:28 2008 @@ -0,0 +1,34 @@ +/* + */ +package org.apache.tomcat.servlets.addon; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +/** + * Mapps a templating name ( like a jsp file ) to a class name + * generated by the template compiler. + * + * This class is needed at runtime to support *.jsp mappings + * or <jsp-file>. + * The UserTemplateCompiler is only needed to support run-time + * compilation - if ahead-of-time is used ( i.e. production system ), + * all generated files should be mapped via explicit + * <servlet><class-name> or using <jsp-file> - so they can have init + * parameters. + * It is possible to use the *.jsp, but you lose init params and get a bit + * of overhead. + * + * @author Costin Manolache + */ +public interface UserTemplateClassMapper { + + public Servlet loadProxy(String jspFile, + ServletContext ctx, + ServletConfig config) throws ServletException; + + public String getClassName(String templateName); + +} Propchange: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/addon/UserTemplateClassMapper.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspFileTemplateServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspFileTemplateServlet.java?rev=650881&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspFileTemplateServlet.java (added) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspFileTemplateServlet.java Wed Apr 23 07:23:28 2008 @@ -0,0 +1,72 @@ +package org.apache.tomcat.servlets.jsp; + +import java.io.IOException; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tomcat.servlets.addon.AddonSupport; +import org.apache.tomcat.servlets.addon.UserTemplateClassMapper; + +/** + * Support for <servlet><jsp-file> config. + * + * A servlet can be configured with a jsp-file instead of a class. This can + * be translated into a regular servlet, with JspFileTemplateServlet class and + * the jsp-file as init parameter. + * + * This servlet is not jsp specific - you can put any templating file in the + * jsp-file config ( if you can ignore the jsp in the name of the attribute ). + * The file will be converted to a servlet by a custom addon ( jasper in most + * cases ) + * + * @author Costin Manolache + */ +public class JspFileTemplateServlet extends HttpServlet { + + String jspFile; + Servlet realJspServlet; + + UserTemplateClassMapper mapper; + + /** + * If called from a <jsp-file> servlet, compile the servlet and init it. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + // Support <servlet><jsp-file> + String jspFileParam = AddonSupport.getInitParameter(config, "jsp-file"); + // TODO: use extension to find the right UserTemplateClassMapper. + mapper = + (UserTemplateClassMapper) AddonSupport.getUserExtension( + config.getServletContext(), + UserTemplateClassMapper.class); + if (mapper == null) { + mapper = new SimpleTemplateClassMapper(); + } + + if (jspFile == null && jspFileParam != null) { + jspFile = jspFileParam; + } + // exception will be thrown if not set properly + realJspServlet = mapper.loadProxy(jspFile, getServletContext(), + config); + } + + public void setJspFile(String jspFile) { + this.jspFile = jspFile; + } + + protected void service(HttpServletRequest req, HttpServletResponse res) + throws ServletException, IOException + { + // TODO: support reload + + // realJspServlet will be set - init will fail otherwise. + realJspServlet.service(req, res); + } +} Propchange: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspFileTemplateServlet.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/PreCompileFilter.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/PreCompileFilter.java?rev=650881&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/PreCompileFilter.java (added) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/PreCompileFilter.java Wed Apr 23 07:23:28 2008 @@ -0,0 +1,71 @@ +package org.apache.tomcat.servlets.jsp; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; + +/** + * Filter for JSPs to support 'preCompile' support. + * This is a silly feature, can and should be left out in prod. + * It needs to be used in the default config to pass the tests. + * + * @author Costin Manolache + */ +public class PreCompileFilter extends HttpServlet { + // Copied from jasper.Constants to avoid compile dep + /** + * The query parameter that causes the JSP engine to just + * pregenerated the servlet but not invoke it. + */ + public static final String PRECOMPILE = + System.getProperty("org.apache.jasper.Constants.PRECOMPILE", "jsp_precompile"); + + /** + * If called from a <jsp-file> servlet, compile the servlet and init it. + */ + public void init(ServletConfig arg0) throws ServletException { + super.init(arg0); + } + + boolean preCompile(HttpServletRequest request) throws ServletException { + String queryString = request.getQueryString(); + if (queryString == null) { + return (false); + } + int start = queryString.indexOf(PRECOMPILE); + if (start < 0) { + return (false); + } + queryString = + queryString.substring(start + PRECOMPILE.length()); + if (queryString.length() == 0) { + return (true); // ?jsp_precompile + } + if (queryString.startsWith("&")) { + return (true); // ?jsp_precompile&foo=bar... + } + if (!queryString.startsWith("=")) { + return (false); // part of some other name or value + } + int limit = queryString.length(); + int ampersand = queryString.indexOf("&"); + if (ampersand > 0) { + limit = ampersand; + } + String value = queryString.substring(1, limit); + if (value.equals("true")) { + return (true); // ?jsp_precompile=true + } else if (value.equals("false")) { + // Spec says if jsp_precompile=false, the request should not + // be delivered to the JSP page; the easiest way to implement + // this is to set the flag to true, and precompile the page anyway. + // This still conforms to the spec, since it says the + // precompilation request can be ignored. + return (true); // ?jsp_precompile=false + } else { + throw new ServletException("Cannot have request parameter " + + PRECOMPILE + " set to " + value); + } + } +} Propchange: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/PreCompileFilter.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java?rev=650881&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java (added) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java Wed Apr 23 07:23:28 2008 @@ -0,0 +1,211 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.servlets.jsp; + +import java.util.Vector; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +import org.apache.tomcat.servlets.addon.UserTemplateClassMapper; + +/** + * Extracted from Jasper - maps a template file ( foo/my.jsp ) to a classname + * that is generated by the UserTemplateCompiler. + * + * TODO: transform this to an interface, paired with UserTemplateCompiler. + * + * @author Costin Manolache + */ +public class SimpleTemplateClassMapper implements UserTemplateClassMapper { + + /** + * Load the proxied jsp, if any. + * @param config + * @throws ServletException + */ + public Servlet loadProxy(String jspFile, + ServletContext ctx, + ServletConfig config) throws ServletException { + String mangledClass = getClassName( jspFile ); + + HttpServlet jsp = null; + Class jspC = null; + + // Already created + if( jspC == null ) { + try { + jspC=Class.forName( mangledClass ); + } catch( Throwable t ) { + // Not found - first try + } + } + + if (jspC == null) { + // Class not found - needs to be compiled + return compileAndInitPage(ctx, jspFile, config); + } + + try { + jsp=(HttpServlet)jspC.newInstance(); + } catch( Throwable t ) { + t.printStackTrace(); + } + jsp.init(config); + return jsp; + } + + + protected Servlet compileAndInitPage(ServletContext ctx, + String jspUri, + ServletConfig cfg) + throws ServletException { + throw new ServletException("Pre-compiled page not found, please " + + "add a compiler addon to compile at runtime"); + } + + /** Convert an identifier to a class name, using jasper conventions + * + * @param jspUri a relative JSP file + * @return class name that would be generated by jasper + */ + public String getClassName( String jspUri ) { + int iSep = jspUri.lastIndexOf('/') + 1; + String className = makeJavaIdentifier(jspUri.substring(iSep)); + String basePackageName = JSP_PACKAGE_NAME; + + iSep--; + String derivedPackageName = (iSep > 0) ? + makeJavaPackage(jspUri.substring(1,iSep)) : ""; + + if (derivedPackageName.length() == 0) { + return basePackageName + "." + className; + } + return basePackageName + '.' + derivedPackageName + "." + className; + } + + // ------------- Copied from jasper --------------------------- + + private static final String JSP_PACKAGE_NAME = "org.apache.jsp"; + + private static final String makeJavaIdentifier(String identifier) { + StringBuffer modifiedIdentifier = + new StringBuffer(identifier.length()); + if (!Character.isJavaIdentifierStart(identifier.charAt(0))) { + modifiedIdentifier.append('_'); + } + for (int i = 0; i < identifier.length(); i++) { + char ch = identifier.charAt(i); + if (Character.isJavaIdentifierPart(ch) && ch != '_') { + modifiedIdentifier.append(ch); + } else if (ch == '.') { + modifiedIdentifier.append('_'); + } else { + modifiedIdentifier.append(mangleChar(ch)); + } + } + if (isJavaKeyword(modifiedIdentifier.toString())) { + modifiedIdentifier.append('_'); + } + return modifiedIdentifier.toString(); + } + + private static final String javaKeywords[] = { + "abstract", "assert", "boolean", "break", "byte", "case", + "catch", "char", "class", "const", "continue", + "default", "do", "double", "else", "enum", "extends", + "final", "finally", "float", "for", "goto", + "if", "implements", "import", "instanceof", "int", + "interface", "long", "native", "new", "package", + "private", "protected", "public", "return", "short", + "static", "strictfp", "super", "switch", "synchronized", + "this", "throws", "transient", "try", "void", + "volatile", "while" }; + + private static final String makeJavaPackage(String path) { + String classNameComponents[] = split(path,"/"); + StringBuffer legalClassNames = new StringBuffer(); + for (int i = 0; i < classNameComponents.length; i++) { + legalClassNames.append(makeJavaIdentifier(classNameComponents[i])); + if (i < classNameComponents.length - 1) { + legalClassNames.append('.'); + } + } + return legalClassNames.toString(); + } + + private static final String [] split(String path, String pat) { + Vector comps = new Vector(); + int pos = path.indexOf(pat); + int start = 0; + while( pos >= 0 ) { + if(pos > start ) { + String comp = path.substring(start,pos); + comps.add(comp); + } + start = pos + pat.length(); + pos = path.indexOf(pat,start); + } + if( start < path.length()) { + comps.add(path.substring(start)); + } + String [] result = new String[comps.size()]; + for(int i=0; i < comps.size(); i++) { + result[i] = (String)comps.elementAt(i); + } + return result; + } + + + /** + * Test whether the argument is a Java keyword + */ + private static boolean isJavaKeyword(String key) { + int i = 0; + int j = javaKeywords.length; + while (i < j) { + int k = (i+j)/2; + int result = javaKeywords[k].compareTo(key); + if (result == 0) { + return true; + } + if (result < 0) { + i = k+1; + } else { + j = k; + } + } + return false; + } + + /** + * Mangle the specified character to create a legal Java class name. + */ + private static final String mangleChar(char ch) { + char[] result = new char[5]; + result[0] = '_'; + result[1] = Character.forDigit((ch >> 12) & 0xf, 16); + result[2] = Character.forDigit((ch >> 8) & 0xf, 16); + result[3] = Character.forDigit((ch >> 4) & 0xf, 16); + result[4] = Character.forDigit(ch & 0xf, 16); + return new String(result); + } + +} Propchange: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java?rev=650881&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java (added) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java Wed Apr 23 07:23:28 2008 @@ -0,0 +1,62 @@ +/* + */ +package org.apache.tomcat.servlets.jsp; + +import java.util.Stack; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** For SingleThreadedServlet support. + * + * This is container independent. + * + * Will maintain a pool of servlets, etc + * + * + * @author Costin Manolache + */ +public class SingleThreadedProxyServlet extends HttpServlet { + + private Class classClass = null; + private transient boolean singleThreadModel = false; + /** + * Stack containing the STM instances. + */ + private transient Stack instancePool = null; + + /** + * Extra params: + * - servlet-class - the class of the single-threaded servlet + * - + * + */ + public void init() { + + } + + public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException { + synchronized (instancePool) { + if (instancePool.isEmpty()) { + try { + Servlet newServlet = null; // loadServlet(); + + // todo: should we init each of them ? + + newServlet.service(req, res); + + + } catch (Throwable e) { + throw new ServletException("allocate ", + e); + } + } + Servlet s = (Servlet) instancePool.pop(); + } + + + } +} Propchange: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java?rev=650881&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java (added) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java Wed Apr 23 07:23:28 2008 @@ -0,0 +1,87 @@ +package org.apache.tomcat.servlets.jsp; + +import java.io.IOException; +import java.util.HashMap; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tomcat.servlets.addon.AddonSupport; +import org.apache.tomcat.servlets.addon.UserTemplateClassMapper; + + +/** + * + * @author Costin Manolache + */ +public class WildcardTemplateServlet extends HttpServlet { + + // for the '*.jsp' case - need to keep track of the jsps + HashMap<String, Servlet> jsps=new HashMap<String, Servlet>(); + + UserTemplateClassMapper mapper; + + /** + * If called from a <jsp-file> servlet, compile the servlet and init it. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mapper = + (UserTemplateClassMapper) AddonSupport.getUserExtension(config.getServletContext(), + UserTemplateClassMapper.class); + if (mapper == null) { + mapper = new SimpleTemplateClassMapper(); + } + } + + // TODO: use context extensions to register the servlet as if it would be + // loaded from web.xml + + protected void service(HttpServletRequest req, HttpServletResponse res) + throws ServletException, IOException + { + // This is a *.jsp mapping. + String jspPath = null; + + /** + * Magic to get the jsp file from the mappings or container + */ + if (jspPath == null) { + jspPath = (String)req.getAttribute("org.apache.catalina.jsp_file"); + } + if (jspPath == null) { + // RequestDispatcher.include() + jspPath = (String)req.getAttribute("javax.servlet.include.servlet_path"); + if (jspPath != null) { + String pathInfo = (String)req.getAttribute("javax.servlet.include.path_info"); + if (pathInfo != null) { + jspPath += pathInfo; + } + } else { + jspPath = req.getServletPath(); + String pathInfo = req.getPathInfo(); + if (pathInfo != null) { + jspPath += pathInfo; + } + } + } + + // now we should have jspUri == the path to the jsp. + Servlet realJspServlet = jsps.get(jspPath); + if (realJspServlet == null) { + realJspServlet = mapper.loadProxy(jspPath, + getServletContext(), getServletConfig()); + if (realJspServlet != null) { + jsps.put(jspPath, realJspServlet); + } else { + throw new ServletException(jspPath + " not found"); + } + } + + realJspServlet.service(req, res); + } +} Propchange: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java?rev=650881&r1=650880&r2=650881&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java Wed Apr 23 07:23:28 2008 @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Date; -import java.util.EventListener; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -58,11 +57,6 @@ protected ServletContext context; - static class ExpiringMap { - - - } - /** * The distributable flag for Sessions created by this Manager. If this @@ -147,7 +141,6 @@ */ protected int processExpiresFrequency = 6; - public static final String INTERNAL_PREFIX = "__x_"; static List EMPTY_LIST = new ArrayList(); public List getEventListeners() { @@ -157,17 +150,6 @@ return l; } - public static SessionManagerServlet getSessionManager(ServletContext ctx) { - SessionManagerServlet result = - (SessionManagerServlet)ctx.getAttribute(INTERNAL_PREFIX + ".SessionManager"); - if (result == null) { - result = new SessionManagerServlet(); - result.setContext(ctx); - ctx.setAttribute(INTERNAL_PREFIX + ".SessionManager", result); - } - return result; - } - public void setSessionCounter(int sessionCounter) { this.sessionCounter = sessionCounter; } @@ -374,16 +356,12 @@ } - public void destroy() { - initialized=false; + public SessionManagerServlet() { + randomG.init(); } - public void init() { - getServletContext().setAttribute(INTERNAL_PREFIX + ".SessionManager", - this); - randomG.init(); - - // TODO: process init params to configure randomG and the manager + public void destroy() { + initialized=false; } /** @@ -541,6 +519,11 @@ ThreadLocal httpSession; + public String getSessionCookieName() { + return "JSESSIONID"; + } + + /** Parse the cookies. Since multiple session cookies could be set ( * different paths for example ), we need to lookup and find a valid one * for our context. @@ -568,10 +551,6 @@ } - public String getSessionCookieName() { - return "JSESSIONID"; - } - public boolean isValid(HttpSession session) { return ((HttpSessionImpl) session).isValid(); } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]