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]