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=439527&r1=439526&r2=439527&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 Fri Sep 1 21:30:15 2006 @@ -16,7 +16,10 @@ import javax.servlet.Servlet; import javax.servlet.ServletContext; import javax.servlet.ServletException; +import javax.servlet.UnavailableException; +import javax.servlet.http.HttpServletResponse; +import org.apache.catalina.util.RequestUtil; import org.apache.coyote.Request; import org.apache.coyote.Response; import org.apache.tomcat.lite.ctxmap.WebappContextMapper; @@ -25,6 +28,7 @@ import org.apache.tomcat.lite.webmap.WebappServletMapper; import org.apache.tomcat.servlets.config.ServletData; import org.apache.tomcat.servlets.config.WebAppData; +import org.apache.tomcat.util.loader.Repository; /** * Frontend for a minimal servlet impl for Tomcat-Lite. @@ -106,6 +110,8 @@ private EngineData engineData; + private Repository engineRepo; + private TomcatLite() { } @@ -115,9 +121,20 @@ // --------------- start/stop --------------- + public Repository getRepository() { + if (engineRepo == null) { + engineRepo = new Repository(); + engineRepo.setParentClassLoader(this.getClass().getClassLoader()); + } + return engineRepo; + } + public void start() throws IOException { long t0 = System.currentTimeMillis(); - + + Repository ctxRepo = new Repository(); + ctxRepo.setParentClassLoader(this.getClass().getClassLoader()); + // start all contexts // init all contexts for(ServletContextImpl ctx: contexts) { @@ -160,7 +177,7 @@ String path) throws ServletException { - ServletContextImpl ctx = new ServletContextImpl(); + ServletContextImpl ctx = new ServletContextImpl(this); ctx.setContextPath(path); ctx.setBasePath(basePath); @@ -193,7 +210,8 @@ } - public void service(ServletRequestImpl req, ServletResponseImpl res) throws Exception, IOException { + public void service(ServletRequestImpl req, ServletResponseImpl res) + throws Exception, IOException { // parse the session id from URI req.parseSessionId(); @@ -226,7 +244,14 @@ ServletConfigImpl h=(ServletConfigImpl)mapRes.wrapper; if (h != null) { - serviceServlet(req, res, h, mapRes ); + req.setWrapper((ServletConfigImpl)mapRes.wrapper); + serviceServlet(ctx, req, res, h, mapRes ); + // send the response... + res.flushBuffer(); + + // Recycle the wrapper request and response + req.recycle(); + res.recycle(); } } finally { if(mapRes != null ) @@ -241,35 +266,73 @@ * 2. service is called. Additional filters are set on the wrapper. * @param mapRes */ - public void serviceServlet(ServletRequestImpl request, - ServletResponseImpl response, - ServletConfigImpl servletConfig, MappingData mapRes) - throws IOException { - + private void serviceServlet(ServletContextImpl ctx, + ServletRequestImpl req, + ServletResponseImpl res, + ServletConfigImpl servletConfig, + MappingData mapRes) + throws IOException { + Servlet servlet = null; try { - Servlet servlet = servletConfig.allocate(); - WebappFilterMapper filterMap = servletConfig.getParent().getFilterMapper(); + if (servletConfig.isUnavailable()) { + handleUnavailable(res, servletConfig); + return; + } + try { + servlet = servletConfig.allocate(); + } catch(ServletException ex) { + handleUnavailable(res, servletConfig); + } + WebappFilterMapper filterMap = ctx.getFilterMapper(); FilterChainImpl chain = - filterMap.createFilterChain(request, servletConfig, servlet); + filterMap.createFilterChain(req, servletConfig, servlet); + + try { + if (chain == null) { + if (servlet != null) { + servlet.service(req, res); + } else { + System.err.println("No servlet " + req.getRequestURI()); + res.sendError(404); + } + } else { + chain.doFilter(req, res); + } + } catch(UnavailableException ex) { + servletConfig.unavailable(ex); + handleUnavailable(res, servletConfig); + return; + } - if (chain == null) { - servlet.service(request, response); - } else { - chain.doFilter(request, response); + // servlet completed without exception. Check status + int status = res.getStatus(); + String statusPage = ctx.findStatusPage(status); + + if (statusPage != null) { + ctx.handleStatusPage(req, res, status, statusPage); } - response.finishResponse(); - } catch (IOException e) { - ; } catch (Throwable t) { - t.printStackTrace(); + ctx.handleError(req, res, t); } finally { - // Recycle the wrapper request and response - request.recycle(); - response.recycle(); + if (servlet != null) { + servletConfig.deallocate(servlet); + } } } - + + private void handleUnavailable(ServletResponseImpl response, + ServletConfigImpl servletConfig) + throws IOException { + long available = servletConfig.getAvailable(); + if ((available > 0L) && (available < Long.MAX_VALUE)) + response.setDateHeader("Retry-After", available); + // TODO: handle via error pages ! + response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, + "Service unavailable"); + } + + // ------------ Notifications for JMX ---------------- void notifyAdd(Object o) { @@ -344,6 +407,30 @@ oos.close(); } + /** Create a dummy request/response object that can be used to invoke + */ + public ServletRequestImpl dummyRequest() { + // proxy is initializing - now call the proxied init() + // Invoking jspInit + ServletContextImpl ctx = new ServletContextImpl(); + + + ServletRequestImpl req = new ServletRequestImpl(); + req.setContext(ctx); + req.setQueryString("jsp_precompile=true"); + Request creq = new Request(); + Response cres = new Response(); + cres.setRequest(creq); + creq.setResponse(cres); + req.setCoyoteRequest(creq); + + ServletResponseImpl res = new ServletResponseImpl(); + res.setCoyoteResponse(cres); + res.setRequest(req); + req.setResponse(res); + + return req; + } public static void main(String args[]) throws ServletException, IOException {
Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java Fri Sep 1 21:30:15 2006 @@ -7,6 +7,7 @@ import org.apache.coyote.Adapter; import org.apache.coyote.Request; import org.apache.coyote.Response; +import org.apache.tomcat.lite.ServletContextImpl; import org.apache.tomcat.lite.TomcatLite; import org.apache.tomcat.lite.ServletRequestImpl; import org.apache.tomcat.lite.ServletResponseImpl; @@ -31,11 +32,12 @@ public CoyoteAdapter() { proto = new Http11Protocol(); proto.setAdapter(this); - facade = TomcatLite.getServletImpl(); } public void init() throws ServletException { try { + ServletContextImpl ctx = (ServletContextImpl)getServletContext(); + facade = ctx.getEngine(); proto.getEndpoint().setPort(8800); proto.getEndpoint().setDaemon(false); proto.init(); @@ -99,6 +101,7 @@ cReq.action( ActionCode.ACTION_POST_REQUEST , null); } catch( Throwable t ) { + System.out.println("ERROR IN ADAPTER SHOULD BE HANDLED IN TOMCAT"); t.printStackTrace(System.out); } Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/webmap/WebappServletMapper.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/webmap/WebappServletMapper.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/webmap/WebappServletMapper.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/webmap/WebappServletMapper.java Fri Sep 1 21:30:15 2006 @@ -229,6 +229,7 @@ boolean noServletPath = false; int length = context.name.length(); + if (length == 1) length--; if (length != (pathEnd - pathOffset)) { servletPath = pathOffset + length; } else { @@ -469,6 +470,7 @@ break; } } + if (slash == -1 ) slash = 0; if (slash >= 0) { int period = -1; for (int i = pathEnd - 1; i > slash; i--) { Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/config/ServletData.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/config/ServletData.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/config/ServletData.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/config/ServletData.java Fri Sep 1 21:30:15 2006 @@ -11,14 +11,14 @@ } public ServletData(String servletName, String servletClass) { this.servletClass = servletClass; - this.serlvetName = servletName; + this.servletName = servletName; } public HashMap initParams = new HashMap(); - public String serlvetName; + public String servletName; public String servletClass; public String jspFile; - public int loadOnStartup; + public int loadOnStartup = -1; public String runAs; public HashMap securityRoleRef = new HashMap(); // roleName -> [roleLink] Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/ReloadServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/ReloadServlet.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/ReloadServlet.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/ReloadServlet.java Fri Sep 1 21:30:15 2006 @@ -7,6 +7,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.tomcat.lite.ServletContextImpl; import org.apache.tomcat.lite.TomcatLite; public class ReloadServlet extends HttpServlet { @@ -14,7 +15,8 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - TomcatLite servletImpl = TomcatLite.getServletImpl(); + ServletContextImpl ctx = (ServletContextImpl)getServletContext(); + //facade = ctx.getEngine(); //servletImpl.reloadServletContext(getServletContext()); } Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebXml.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebXml.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebXml.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebXml.java Fri Sep 1 21:30:15 2006 @@ -138,12 +138,12 @@ confNode = DomUtil.getChild(webappNode, "session-config"); while (confNode != null ) { - confNode = DomUtil.getNext(confNode); - if (confNode != null) - throw new ServletException("Multiple session-config"); String n = DomUtil.getChildContent(confNode, "session-timeout"); int stout = Integer.parseInt(n); d.sessionTimeout = stout; + confNode = DomUtil.getNext(confNode); + if (confNode != null) + throw new ServletException("Multiple session-config"); } confNode = DomUtil.getChild(webappNode, "welcome-file-list"); @@ -248,7 +248,7 @@ } private void processErrorPage(Node confNode) { - String name = DomUtil.getChildContent(confNode,"error-location"); + String name = DomUtil.getChildContent(confNode,"location"); String c = DomUtil.getChildContent(confNode,"error-code"); String t = DomUtil.getChildContent(confNode,"exception-type"); if (c != null) { @@ -262,13 +262,13 @@ private void processServlet(Node confNode) throws ServletException { ServletData sd = new ServletData(); - sd.serlvetName = DomUtil.getChildContent(confNode,"servlet-name"); + sd.servletName = DomUtil.getChildContent(confNode,"servlet-name"); sd.servletClass = DomUtil.getChildContent(confNode,"servlet-class"); sd.jspFile = DomUtil.getChildContent(confNode,"jsp-file"); processInitParams(confNode, sd.initParams); - d.servlets.put( sd.serlvetName, sd ); + d.servlets.put( sd.servletName, sd ); String los = DomUtil.getChildContent(confNode, "load-on-startup"); if (los != null ) { @@ -300,8 +300,12 @@ private void processServletMapping(Node confNode) { String name = DomUtil.getChildContent(confNode,"servlet-name"); - String path = DomUtil.getChildContent(confNode,"url-pattern"); - + String path = DomUtil.getChildContent(confNode,"url-pattern").trim(); + + if (! (path.startsWith("/") || path.startsWith("*"))) { + // backward compat + path = "/" + path; + } d.servletMapping.put(path, name); } Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspCompileServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspCompileServlet.java?rev=439527&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspCompileServlet.java (added) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspCompileServlet.java Fri Sep 1 21:30:15 2006 @@ -0,0 +1,325 @@ +/* + * Copyright 1999,2004 The Apache Software Foundation. + * + * Licensed 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.io.IOException; +import java.lang.reflect.Constructor; +import java.util.Enumeration; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.jasper.Constants; +import org.apache.jasper.EmbeddedServletOptions; +import org.apache.jasper.Options; +import org.apache.jasper.compiler.JspRuntimeContext; +import org.apache.jasper.compiler.Localizer; +import org.apache.jasper.servlet.JspServletWrapper; +import org.apache.tomcat.servlets.jsp.*; + +/** + * Based on JspServlet, but specialized in compiling servlets. + * + */ +public class JspCompileServlet extends HttpServlet + implements JspProxyServlet.PageCompiler { + + // Logger + private Log log = LogFactory.getLog(JspCompileServlet.class); + + private ServletContext context; + private ServletConfig config; + + private Options options; + private JspRuntimeContext rctxt; + + /* + * Initializes this JspServlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + this.config = config; + this.context = config.getServletContext(); + + // Initialize the JSP Runtime Context + // Check for a custom Options implementation + String engineOptionsName = + config.getInitParameter("engineOptionsClass"); + if (engineOptionsName != null) { + // Instantiate the indicated Options implementation + try { + ClassLoader loader = Thread.currentThread() + .getContextClassLoader(); + Class engineOptionsClass = loader.loadClass(engineOptionsName); + Class[] ctorSig = { ServletConfig.class, ServletContext.class }; + Constructor ctor = engineOptionsClass.getConstructor(ctorSig); + Object[] args = { config, context }; + options = (Options) ctor.newInstance(args); + } catch (Throwable e) { + // Need to localize this. + log.warn("Failed to load engineOptionsClass", e); + // Use the default Options implementation + options = new EmbeddedServletOptions(config, context); + } + } else { + // Use the default Options implementation + options = new EmbeddedServletOptions(config, context); + } + rctxt = new JspRuntimeContext(context, options); + + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.message.scratch.dir.is", + options.getScratchDir().toString())); + log.debug(Localizer.getMessage("jsp.message.dont.modify.servlets")); + } + + context.setAttribute(JspProxyServlet.CONTAINER_PREFIX + "jspCompiler", + this); + } + + + /** + * Returns the number of JSPs for which JspServletWrappers exist, i.e., + * the number of JSPs that have been loaded into the webapp with which + * this JspServlet is associated. + * + * <p>This info may be used for monitoring purposes. + * + * @return The number of JSPs that have been loaded into the webapp with + * which this JspServlet is associated + */ + public int getJspCount() { + return this.rctxt.getJspCount(); + } + + + /** + * Resets the JSP reload counter. + * + * @param count Value to which to reset the JSP reload counter + */ + public void setJspReloadCount(int count) { + this.rctxt.setJspReloadCount(count); + } + + + /** + * Gets the number of JSPs that have been reloaded. + * + * <p>This info may be used for monitoring purposes. + * + * @return The number of JSPs (in the webapp with which this JspServlet is + * associated) that have been reloaded + */ + public int getJspReloadCount() { + return this.rctxt.getJspReloadCount(); + } + + + boolean preCompile(HttpServletRequest request) throws ServletException { + String queryString = request.getQueryString(); + if (queryString == null) { + return (false); + } + int start = queryString.indexOf(Constants.PRECOMPILE); + if (start < 0) { + return (false); + } + queryString = + queryString.substring(start + Constants.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 " + + Constants.PRECOMPILE + " set to " + + value); + } + } + + + /** This is no longer 'compiling' or invoking jsps. Just some status info + * for debugging. + */ + public void service (HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + + String jspUri = null; + + String jspFile = (String) request.getAttribute(Constants.JSP_FILE); + if (jspFile != null) { + // JSP is specified via <jsp-file> in <servlet> declaration + jspUri = jspFile; + } else { + /* + * Check to see if the requested JSP has been the target of a + * RequestDispatcher.include() + */ + jspUri = (String) request.getAttribute(Constants.INC_SERVLET_PATH); + if (jspUri != null) { + /* + * Requested JSP has been target of + * RequestDispatcher.include(). Its path is assembled from the + * relevant javax.servlet.include.* request attributes + */ + String pathInfo = (String) request.getAttribute( + "javax.servlet.include.path_info"); + if (pathInfo != null) { + jspUri += pathInfo; + } + } else { + /* + * Requested JSP has not been the target of a + * RequestDispatcher.include(). Reconstruct its path from the + * request's getServletPath() and getPathInfo() + */ + jspUri = request.getServletPath(); + String pathInfo = request.getPathInfo(); + if (pathInfo != null) { + jspUri += pathInfo; + } + } + } + + if (log.isDebugEnabled()) { + log.debug("JspEngine --> " + jspUri); + log.debug("\t ServletPath: " + request.getServletPath()); + log.debug("\t PathInfo: " + request.getPathInfo()); + log.debug("\t RealPath: " + context.getRealPath(jspUri)); + log.debug("\t RequestURI: " + request.getRequestURI()); + log.debug("\t QueryString: " + request.getQueryString()); + log.debug("\t Request Params: "); + Enumeration e = request.getParameterNames(); + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + log.debug("\t\t " + name + " = " + + request.getParameter(name)); + } + } + + try { + boolean precompile = preCompile(request); + serviceJspFile(request, response, jspUri, null, precompile); + } catch (RuntimeException e) { + throw e; + } catch (ServletException e) { + throw e; + } catch (IOException e) { + throw e; + } catch (Throwable e) { + throw new ServletException(e); + } + + } + + public void destroy() { + rctxt.destroy(); + } + + + // -------------------------------------------------------- Private Methods + + private void serviceJspFile(HttpServletRequest request, + HttpServletResponse response, String jspUri, + Throwable exception, boolean precompile) + throws ServletException, IOException { + + JspServletWrapper wrapper = + (JspServletWrapper) rctxt.getWrapper(jspUri); + if (wrapper == null) { + synchronized(this) { + wrapper = (JspServletWrapper) rctxt.getWrapper(jspUri); + if (wrapper == null) { + // Check if the requested JSP page exists, to avoid + // creating unnecessary directories and files. + if (null == context.getResource(jspUri)) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, + jspUri); + return; + } + boolean isErrorPage = exception != null; + wrapper = new JspServletWrapper(config, options, jspUri, + isErrorPage, rctxt); + rctxt.addWrapper(jspUri,wrapper); + } + } + } + + wrapper.service(request, response, precompile); + + } + + + public Servlet compileAndInitPage(ServletContext ctx, + String jspUri, + ServletConfig cfg) + throws ServletException, IOException { + + JspServletWrapper wrapper = + (JspServletWrapper) rctxt.getWrapper(jspUri); + if (wrapper == null) { + synchronized(this) { + wrapper = (JspServletWrapper) rctxt.getWrapper(jspUri); + if (wrapper == null) { + // Check if the requested JSP page exists, to avoid + // creating unnecessary directories and files. + if (null == context.getResource(jspUri)) { + return null; + } + //boolean isErrorPage = exception != null; + wrapper = new JspServletWrapper(config, options, jspUri, + false, rctxt); + rctxt.addWrapper(jspUri,wrapper); + } + } + } + + wrapper.getJspEngineContext().compile(); + return wrapper.getServlet(); + } + +} Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java Fri Sep 1 21:30:15 2006 @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Vector; +import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -11,35 +12,96 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -/** If jasper is found, it'll just forward the calls to jasper jsp servlet. +import org.apache.coyote.Request; +import org.apache.coyote.Response; +import org.apache.jasper.JasperException; +import org.apache.jasper.JspC; +import org.apache.tomcat.lite.ServletConfigImpl; +import org.apache.tomcat.lite.ServletContextImpl; +import org.apache.tomcat.lite.ServletRequestImpl; +import org.apache.tomcat.lite.ServletResponseImpl; + +/** + * If jasper is found, it'll just forward the calls to jasper jsp servlet. * * If jasper is not found - i.e. runtime without jasper compiler - it'll * compute the mangled class name ( same code as jasper ) - * and invoke the jsp servlet directly. If the class is not found, it'll execute - * "jspc" and try again. + * and invoke the jsp servlet directly. * + * TODO: If the class is not found, it'll execute "jspc" and try again. * - * * TODO: test jspc, generate files in or out web-inf dir, modify web.xml * * @author Costin Manolache */ public class JspProxyServlet extends HttpServlet { - HttpServlet realJspServlet; + public static String CONTAINER_PREFIX = "__x_"; + + // for the '*.jsp' case static HashMap jsps=new HashMap(); + String jspFile; // set if we proxy a <jsp-file> servlet + HttpServlet realJspServlet; + + PageCompiler pageCompiler; + + /** Requirements: must use the same mangling scheme as jasper. ( or update + * the scheme in this class ) + */ + public static interface PageCompiler { + + public Servlet compileAndInitPage(ServletContext ctx, String pagePath, + ServletConfig cfg) throws ServletException, IOException; + + } + + /** + * If called from a <jsp-file> servlet, compile the servlet and init it. + * + * + */ + public void init(ServletConfig arg0) throws ServletException { + super.init(arg0); + + jspFile = arg0.getInitParameter(CONTAINER_PREFIX + "jspFile"); + pageCompiler = (PageCompiler)getServletContext().getAttribute(CONTAINER_PREFIX + "jspCompiler"); + if (jspFile != null) { + realJspServlet = loadProxy(jspFile); + if (realJspServlet == null) { + try { + pageCompiler.compileAndInitPage(getServletContext(), jspFile, arg0); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + if (realJspServlet == null) { + + throw new ServletException(jspFile + " not found"); + } + realJspServlet.init(arg0); + } + + } + + protected void service(HttpServletRequest req, HttpServletResponse arg1) throws ServletException, IOException { - if( realJspServlet!=null ) { + if( jspFile!=null ) { + // realJspServlet will be set - init will fail otherwise. realJspServlet.service(req, arg1); return; } + // This is a *.jsp mapping. String jspUri=null; - - String jspFile = (String)req.getAttribute("org.apache.catalina.jsp_file"); - if (jspFile != null) { + String jspPath = null; + + if (jspPath == null) { + jspPath = (String)req.getAttribute("org.apache.catalina.jsp_file"); + } + if (jspPath != null) { // JSP is specified via <jsp-file> in <servlet> declaration jspUri = jspFile; } else { @@ -58,60 +120,85 @@ } } } - - String mangledClass = getClassName( jspFile ); - System.err.println("Class: " + mangledClass ); - - // TODO: if class not found - invoke some external jspc - HttpServlet jsp = (HttpServlet)jsps.get( mangledClass ); - if( jsp == null ) { + // now we should have jspUri == the path to the jsp. + realJspServlet = loadProxy(jspUri); + if (realJspServlet == null) { try { - Class sC=Class.forName( mangledClass ); - jsp=(HttpServlet)sC.newInstance(); - } catch( Throwable t ) { + realJspServlet = (HttpServlet)pageCompiler.compileAndInitPage(getServletContext(), jspUri, getServletConfig()); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } } - if(jsp == null) { + if (realJspServlet == null) { + throw new ServletException(jspUri + " not found"); } - // try again - if( jsp == null ) { + // that's the config for the jsp servlet, mapping *.jsp + //realJspServlet.init(getServletConfig()); + + realJspServlet.service(req, arg1); + } + + public HttpServlet loadProxy(String jspFile) { + + String mangledClass = getClassName( jspFile ); + + HttpServlet jsp = null; + Class jspC = (Class)jsps.get( mangledClass ); + if( jspC == null ) { try { - Class sC=Class.forName( mangledClass ); - jsp=(HttpServlet)sC.newInstance(); + jspC=Class.forName( mangledClass ); + jsps.put(mangledClass, jspC); } catch( Throwable t ) { - t.printStackTrace(); - arg1.setStatus(404); + return null; } - } - jsp.service( req, arg1); + } + + try { + jsp=(HttpServlet)jspC.newInstance(); + } catch( Throwable t ) { + t.printStackTrace(); + } + return jsp; } - private void compileJsp(ServletContext ctx, String jspPath) { + /** Do the compilation. + * + * Options: + * - jasper.jar in classpath, we do Class.forName for main() + * - TODO: exec jasper.sh ( or any other script set in params ) + * - TODO: redirect to a different servlet + * + * @param ctx + * @param jspPath + */ + private void compileJsp(ServletContext sctx, String jspPath) { + ServletContextImpl ctx = (ServletContextImpl)sctx; // Params to pass to jspc: // classpath - // webapp base dir String baseDir = ctx.getRealPath("/"); // jsp path ( rel. base dir ) - - - } - public void init(ServletConfig arg0) throws ServletException { - super.init(arg0); + JspC jspc = new JspC(); + jspc.setUriroot(ctx.getBasePath()); + jspc.setTrimSpaces(false); + jspc.setPoolingEnabled(true); + jspc.setErrorOnUseBeanInvalidClassAttribute(false); + jspc.setClassDebugInfo(true); + jspc.setCaching(true); + jspc.setSmapDumped(true); + try { - Class jspC = Class.forName("org.apache.jasper.servlet.JspServlet"); - realJspServlet=(HttpServlet)jspC.newInstance(); - realJspServlet.init(arg0); - } catch (ClassNotFoundException e) { - // it's ok - no jsp - log("No JSP servlet"); - } catch (Throwable e ) { + jspc.execute(); + } catch (JasperException e) { + // TODO Auto-generated catch block e.printStackTrace(); - log("No JSP servlet"); } + + } private String getClassName( String jspUri ) { Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleAuthServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleAuthServlet.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleAuthServlet.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleAuthServlet.java Fri Sep 1 21:30:15 2006 @@ -53,6 +53,14 @@ * Protocol: * * + * Attributes: + * - user + * - pass + * - chap-pass + * - userip + * - userport + * - ??? + * * * * @author Costin Manolache 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=439527&r1=439526&r2=439527&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 Fri Sep 1 21:30:15 2006 @@ -19,6 +19,7 @@ import java.io.IOException; +import java.util.ArrayList; import java.util.Date; import java.util.EventListener; import java.util.HashMap; @@ -148,10 +149,13 @@ protected int processExpiresFrequency = 6; public static final String INTERNAL_PREFIX = "_SERVLET_IMPL_"; - + static List EMPTY_LIST = new ArrayList(); public List getEventListeners() { - return (List)context.getAttribute(INTERNAL_PREFIX + ".EventListeners"); + List l = + (List)context.getAttribute(INTERNAL_PREFIX + ".EventListeners"); + if (l == null) return EMPTY_LIST; + return l; } public void addEventListener(EventListener l) { Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java Fri Sep 1 21:30:15 2006 @@ -20,10 +20,11 @@ import java.io.File; import java.io.Serializable; -import java.lang.reflect.Constructor; import java.net.MalformedURLException; import java.net.URL; +import org.apache.catalina.LifecycleException; + // Based on org.apache.catalina.Loader - removed most of the catalina-specific /** @@ -170,7 +171,8 @@ return; started = true; - log("start()"); + if (DEBUG) + log("start()"); // Construct a class loader based on our current repositories list try { @@ -205,8 +207,8 @@ if (!started) throw new RuntimeException("stop: started=false"); - //if (DEBUG) - log("stop()", null); + if (DEBUG) + log("stop()", null); //getRepository().getLoader().notifyModuleStop(this); Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Repository.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Repository.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Repository.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Repository.java Fri Sep 1 21:30:15 2006 @@ -26,7 +26,9 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; +import java.util.HashMap; import java.util.Hashtable; +import java.util.Map; import java.util.Vector; @@ -386,6 +388,9 @@ this.name=name2; } + // Collects all jars without INDEX.LIST. Can be used for debugging. + public static Map missingIndexList = new HashMap(); + /* * Work in progress: * @@ -409,7 +414,7 @@ if( ! cp.endsWith(".jar")) return; URL urlIdx=cl.findResource("META-INF/INDEX.LIST"); if( urlIdx == null ) { - log("INDEX.LIST not found, run: jar -i " + m.getClasspathString()); + missingIndexList.put(cp, "1"); return; } try { Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/http11/Http11Processor.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/http11/Http11Processor.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/http11/Http11Processor.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/http11/Http11Processor.java Fri Sep 1 21:30:15 2006 @@ -792,7 +792,7 @@ } inputBuffer.parseHeaders(); } catch (IOException e) { - e.printStackTrace(); + //e.printStackTrace(); error = true; break; } catch (Throwable t) { Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/nio/NioEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/nio/NioEndpoint.java?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/nio/NioEndpoint.java (original) +++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/nio/NioEndpoint.java Fri Sep 1 21:30:15 2006 @@ -184,34 +184,54 @@ */ class PollerThread implements Runnable { boolean daemon; + SocketChannel accepted; PollerThread(boolean daemon) { this.daemon = daemon; } + PollerThread(SocketChannel accepted) { + this.accepted = accepted; + } + public void run() { setDaemon(daemon); - + + if (accepted != null) { + System.err.println("Process multiple accept " + acceptorThreads + + " active=" + tp.getActiveCount()); + processSocket(accepted.socket()); + accepted = null; + // done processing the request - see if we go accepting work + } else { + System.err.println("New thread accept=" + acceptorThreads + + " active=" + tp.getActiveCount()); + } while( ! tp.isShutdown() ) { try { if( acceptorThreads > maxAcceptorThreads) { + System.err.println("Too many acceptors, thread end" + + " accept=" + acceptorThreads + + " active=" + tp.getActiveCount()); return; } acceptorThreads++; int selRes = selector.select(); acceptorThreads--; - - if( acceptorThreads < minAcceptorThreads ) { - // start a new polling thread - tp.execute( this ); - } - System.err.println("P: " + acceptorThreads + " A:" + - tp.getActiveCount()); - + if( selRes == 0 ) { dumpSelector(); + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException e) { + System.err.println("Interrupted"); + } continue; } + +// System.err.println("P: " + acceptorThreads + " A:" + +// tp.getActiveCount()); + Set selected = selector.selectedKeys(); @@ -222,41 +242,54 @@ // everything to other threads boolean dispatch = false; + + + // At this point we may have several accepted keys. + // we can't serialize them here - use new threads from the + // pool + if (!selI.hasNext()) { + continue; // nothing ?? + } + + SelectionKey sk = (SelectionKey)selI.next(); + selI.remove(); + + SocketChannel mySocket = null; + if( sk.isAcceptable() ) { + SelectableChannel sc = sk.channel(); + ServerSocketChannel ssc=(ServerSocketChannel)sc; + mySocket = ssc.accept(); + } else { + int readyOps = sk.readyOps(); + System.err.println("Select: " + readyOps); + } + while( selI.hasNext() ) { - SelectionKey sk = (SelectionKey)selI.next(); - selI.remove(); - if( sk.isAcceptable() ) { SelectableChannel sc = sk.channel(); ServerSocketChannel ssc=(ServerSocketChannel)sc; - SocketChannel sockC = ssc.accept(); if (sockC == null) continue; - // continue polling on a different thread - // Side effect: if pool is full, accept will be - // blocked. - // TODO: customize this if needed. If last thread, - // start returning a 'busy' message - - // now process the socket. - processSocket(sockC.socket()); + tp.execute(new PollerThread(sockC)); continue; + } else { + int readyOps = sk.readyOps(); + System.err.println("Select: " + readyOps); } - - // TODO: this is for keep alive and to fill the - // buffer - if( sk.isReadable() ) { - //SocketChannel sockC = (SocketChannel)sc; - - // Incoming data on keep-alive connection. - continue; - } - - // dispatch the socket to a pool thread - int readyOps = sk.readyOps(); - System.err.println("Select: " + readyOps); + } + + // if we don't have enough acceptors, spawn a new one. + if( acceptorThreads < minAcceptorThreads ) { + // start a new polling thread + tp.execute( this ); + } + + // done dispatching the other accepts, now process the + // first one in this thread. + if (mySocket != null) { + processSocket(mySocket.socket()); } } catch (IOException e) { @@ -267,14 +300,14 @@ } private void dumpSelector() { - System.err.println("XXXXXXXXXX Select with 0 keys " + - selector.keys().size() ); + int s = selector.keys().size(); Iterator sI = selector.keys().iterator(); while (sI.hasNext()) { SelectionKey k = (SelectionKey) sI.next(); - System.err.println("K " + k.interestOps() + - " " + k.readyOps() + " " + k.toString() + " " - + k.isValid() ); + System.err.println("K " + s + " interestOps=" + k.interestOps() + + " readyOps=" + k.readyOps() + + " isValid=" + k.isValid() + " " + + Thread.currentThread().toString()); } } @@ -304,6 +337,13 @@ step = 3; handler.process(s); + // Try to close the socket + try { + s.shutdownOutput(); + s.close(); + } catch (IOException e) { + log.error("Closing error " + e.getMessage()); + } } catch (SocketException se) { log.error("Socket error " + s.getInetAddress(), se); Modified: tomcat/sandbox/tomcat-lite/webapps/ROOT/index.html URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/webapps/ROOT/index.html?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/webapps/ROOT/index.html (original) +++ tomcat/sandbox/tomcat-lite/webapps/ROOT/index.html Fri Sep 1 21:30:15 2006 @@ -1 +1,46 @@ -Hi world +<h1>Tomcat-Lite</h1> + +<h2>TODO</h2> + + +<h2>Internal attributes</h2> + +- + +<h2>Internal Webapps</h2> + +Webapps with names starting with __x_ will be treated in special ways. +The benefit of using webapps instead of special directories and layout is +that you can use the same tools to configure and deploy as with regular +webapps. +They are loaded first, and have additional properties: + +__x_classpath* - it's WEB-INF/classes, lib will be added to the container +classpath. +In particular - you may want to place a copy of jasper.jar to +enable jsp compilation, without it tomcat-lite only supports precompiled jsps +This replaces the old tomcat server/lib, common/lib, etc. Tomcat-lite supports +only a simple classloader hierarchy ( arbitrary restriction - it would be easy + to add more with a simple module, but for now we care more about + single-jar than lots of apps with conflicting libraries ). + +__x_protocol* - the connectors. A load-on-startup servlet will start +accepting http connections. The code is dependent on tomcat-lite internals, but +can be configured and deployed using regular webapp tools. + +__x_deploy - internal tools to control deploy, reload and configuration. If it +is missing, reloading is disabled and web.xml is frozen - all configs are loaded +from tomcatLite.ser. In a production server or tiny server you don't need +web.xml parsing, reload and most of the deploy functions ( if you use lb +or are ok with a complete server restart ). + +__x_engine - engine specific servlets/filters - controls the dispatching, +servlet manager, security settings, etc. All the configuration in tomcat-lite +is done using web.xml and servlets/filters - this replaces most of +the conf/ settings in tomcat. + + + +<h2>Internal servlets</h2> + +- \ No newline at end of file Added: tomcat/sandbox/tomcat-lite/webapps/ROOT/test.jsp URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/webapps/ROOT/test.jsp?rev=439527&view=auto ============================================================================== --- tomcat/sandbox/tomcat-lite/webapps/ROOT/test.jsp (added) +++ tomcat/sandbox/tomcat-lite/webapps/ROOT/test.jsp Fri Sep 1 21:30:15 2006 @@ -0,0 +1,13 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Insert title here</title> +</head> +<body> +Test 1234 + +</body> +</html> Modified: tomcat/sandbox/tomcat-lite/webapps/__x_engine/WEB-INF/web.xml URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/webapps/__x_engine/WEB-INF/web.xml?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/webapps/__x_engine/WEB-INF/web.xml (original) +++ tomcat/sandbox/tomcat-lite/webapps/__x_engine/WEB-INF/web.xml Fri Sep 1 21:30:15 2006 @@ -4,7 +4,11 @@ <filter><filter-name>_tc_auth</filter-name><filter-class>org.apache.tomcat.servlets.sec.AccessFilter</filter-class></filter> <filter-mapping><filter-name>simpleIP</filter-name><url-pattern>/*</url-pattern></filter-mapping> - + + <servlet><servlet-name>_jsp</servlet-name><servlet-class>org.apache.tomcat.servlets.jsp.JspServlet</servlet-class> + </servlet> + <servlet-mapping><servlet-name>_jsp</servlet-name><url-pattern>*.jsp</url-pattern></servlet-mapping> +- <!-- <servlet><servlet-name>_tc_users</servlet-name><servlet-class>org.apache.tomcat.servlets.sec.DigestAuthenticator</servlet-class> <init-param><param-name>u.test</param-name><param-value>pass</param-value></init-param> </servlet> Modified: tomcat/sandbox/tomcat-lite/webapps/__x_protocol/WEB-INF/web.xml URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/webapps/__x_protocol/WEB-INF/web.xml?rev=439527&r1=439526&r2=439527&view=diff ============================================================================== --- tomcat/sandbox/tomcat-lite/webapps/__x_protocol/WEB-INF/web.xml (original) +++ tomcat/sandbox/tomcat-lite/webapps/__x_protocol/WEB-INF/web.xml Fri Sep 1 21:30:15 2006 @@ -4,7 +4,7 @@ <filter><filter-name>_tc_auth</filter-name><filter-class>org.apache.tomcat.servlets.sec.AccessFilter</filter-class></filter> <filter-mapping><filter-name>simpleIP</filter-name><url-pattern>/*</url-pattern></filter-mapping> - <filter-mapping><filter-name>_tc_auth</filter-name><url-pattern>/xxx/*</url-pattern></filter-mapping> + <filter-mapping><filter-name>_tc_auth</filter-name><url-pattern>/*</url-pattern></filter-mapping> <servlet><servlet-name>__x_connector</servlet-name><servlet-class>org.apache.tomcat.lite.http.CoyoteAdapter</servlet-class> <init-param><param-name>port</param-name><param-value>8800</param-value></init-param> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]