You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2009/04/04 18:24:36 UTC
svn commit: r761964 [5/10] - in /tomcat/trunk/modules/tomcat-lite/java: ./
org/ org/apache/ org/apache/tomcat/ org/apache/tomcat/addons/
org/apache/tomcat/integration/ org/apache/tomcat/integration/jmx/
org/apache/tomcat/integration/simple/ org/apache/...
Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java Sat Apr 4 16:24:34 2009
@@ -0,0 +1,642 @@
+/*
+ * 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.lite;
+
+import java.io.File;
+import java.io.IOException;
+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;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tomcat.integration.ObjectManager;
+import org.apache.tomcat.integration.simple.SimpleObjectManager;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.buf.UriNormalizer;
+import org.apache.tomcat.util.http.mapper.MappingData;
+
+/**
+ * Simpler, lower footprint serlvet engine.
+ *
+ * Uses ObjectManager to integate with an embedding app
+ * - the object names it uses:
+ *
+ * Internal objects created by Tomcat and registered for management
+ * and injection:
+ * - Servlet:CONTEXT_PATH:SERVLETNAME - a ServletWrapper
+ * - ServletContext:CONTEXT_PATH
+ * - ProtocolHandler:ep-PORT - coyote ProtocolHandler
+ * - CoyoteServer:CoyoteServer-PORT
+ * - CoyoteAdapter:PATH - for the coyote used Adapter
+ * - TomcatLite - this object.
+ * - Connector - the connector object
+ *
+ * Plugins to be constructed by framework ( defaults set in initDefaults ):
+ * - UserSessionManager
+ * - UserTemplateClassMapper
+ * - ContextPreinitListener
+ * - Connector
+ * - WebappServletMapper
+ * - WebappFilterMapper
+ * - default-servlet
+ * - jspwildcard-servlet
+ * - Foo-servlet - servlet named Foo
+ *
+ *
+ * @author Costin Manolache
+ */
+public class TomcatLite implements Runnable {
+
+ private String serverDirName;
+ private File workDir;
+
+ // all contexts - hostMapper knows about hostnames and how they are mapped.
+ // this shouldn't be needed if we want to delegate ctx management
+ private ArrayList<ServletContextImpl> contexts = new ArrayList();
+
+ URLClassLoader contextParentLoader;
+
+ // Discovered or default Host/Context mapper
+ Filter hostMapper;
+
+ // 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();
+
+ Connector coyoteAdapter;
+
+ ObjectManager om;
+
+ static String SERVLETS_PACKAGE = "org.apache.tomcat.servlets";
+
+
+ protected boolean daemon = false;
+
+ public TomcatLite() {
+ }
+
+ public TomcatLite(ObjectManager om) {
+ this.setObjectManager(om);
+ }
+
+ // --------------- start/stop ---------------
+
+ /**
+ * Return the object manager associated with this tomcat.
+ * If none set, create a minimal one with the default
+ * values.
+ */
+ public ObjectManager getObjectManager() {
+ if (om == null) {
+ // Defaults.
+ om = new ObjectManager();
+ SimpleObjectManager props = new SimpleObjectManager(om);
+ // Init defaults. If using a custom OM, you should register
+ // at the default objects as well.
+ props.loadResource("org/apache/tomcat/lite/config.properties");
+ }
+ return om;
+ }
+
+ public void setObjectManager(ObjectManager om) {
+ this.om = om;
+ }
+
+ public List/*<ServletContextImpl>*/ getWebapps() {
+ return contexts;
+ }
+
+ public URLClassLoader getContextParentLoader() {
+ if (contextParentLoader == null) {
+
+ ClassLoader parent = this.getClass().getClassLoader();
+ contextParentLoader = new URLClassLoader(new URL[] {},
+ parent);
+
+ /*if (engineRepo == null) {
+ engineRepo = new Repository();
+ engineRepo.setParentClassLoader(parent);
+ }
+
+ contextParentLoader =
+ engineRepo.getClassLoader();
+ */
+ }
+ return contextParentLoader;
+ }
+
+ public void start() throws IOException {
+ long t0 = System.currentTimeMillis();
+
+ // start all contexts
+ // init all contexts
+ Iterator i1 = contexts.iterator();
+ while (i1.hasNext()) {
+ ServletContextImpl ctx = (ServletContextImpl) i1.next();
+ try {
+ ctx.start();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ long t1 = System.currentTimeMillis();
+ System.err.println("Engine.start() " + (t1-t0));
+ }
+
+
+ /**
+ * Add a context - used for IntrospectionUtils.
+ *
+ * ContextPath:ContextBaseDir
+ */
+ public void setContext(String c) throws ServletException {
+ String[] pathDir = c.split(":", 2);
+ addServletContext("", pathDir[1], pathDir[0]);
+ }
+
+ public void setServletContexts(List<ServletContext> c) throws ServletException {
+ for (ServletContext ctx: c) {
+ addServletContext((ServletContextImpl) ctx);
+ }
+ }
+
+ 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()) {
+ ServletContextImpl ctx = (ServletContextImpl) i1.next();
+ try {
+ ctx.destroy();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ stopConnector();
+ }
+
+ // -------------- Context add/remove --------------
+
+ public static String[] DEFAULT_WELCOME = { "index.html" };
+
+ public void addServletContext(ServletContextImpl ctx) throws ServletException {
+ ctx.setTomcat(this);
+ if (hostMapper == null) {
+ hostMapper = new WebappContextMapper();
+ }
+
+ ((WebappContextMapper) hostMapper).addHost(ctx.getHostname(), null);
+ ((WebappContextMapper) hostMapper).addContext(ctx.getHostname(),
+ ctx);
+
+ contexts.add(ctx);
+
+ getObjectManager().bind("ServletContext:" + ctx.getContextPath(),
+ ctx);
+
+ }
+
+ /**
+ * Add a context.
+ *
+ * web.xml will be read as part of init, and the initialization will be
+ * part of start or lazy.
+ *
+ * @param hostname - ""
+ * if default host, or string to be matched with Host header
+ * @param basePath = directory where the webapp is installed
+ * @param path -
+ * context path, "/" for root, "/examples", etc
+ * @return a servlet context
+ * @throws ServletException
+ */
+ public ServletContext addServletContext(String hostname,
+ String basePath,
+ String path)
+ throws ServletException
+ {
+ ServletContextImpl ctx = new ServletContextImpl();
+ ctx.setContextPath(path);
+ ctx.setBasePath(basePath);
+ addServletContext(ctx);
+ return ctx;
+ }
+
+ public void removeServletContext(ServletContext sctx)
+ throws ServletException
+ {
+ ServletContextImpl ctx = (ServletContextImpl) sctx;
+ // TODO: destroy all servlets and filters
+ // TODO: clean up any other reference to the context or its loader
+ notifyRemove(ctx);
+ }
+
+
+ /**
+ * Required for ServletContext.getContext(uri);
+ * @throws ServletException
+ * @throws IOException
+ */
+ public ServletContextImpl getContext(ServletContextImpl impl, String uri)
+ throws IOException, ServletException {
+ // Create a request - needs to be simplified
+ ServletRequestImpl req = createMessage(impl, impl.contextPath, uri);
+ hostMapper.doFilter(req, null, null);
+ return req.getContext();
+ }
+
+ public ServletResponseImpl service(ServletRequestImpl req) throws IOException, Exception {
+ ServletResponseImpl res = req.getResponse();
+ service(req, res);
+ endRequest(req, res);
+ return res;
+ }
+
+ public void service(ServletRequestImpl req, ServletResponseImpl res)
+ throws Exception, IOException {
+ // parse the session id from URI
+ req.parseSessionId();
+
+ try {
+ UriNormalizer.decodeRequest(req.getCoyoteRequest().decodedURI(),
+ req.getCoyoteRequest().requestURI(),
+ req.getCoyoteRequest().getURLDecoder());
+ } catch(IOException ioe) {
+ res.setStatus(400);
+ return;
+ }
+
+ MappingData mapRes = req.getMappingData();
+ try {
+ // TODO: make hostMapper configurable, implement interface,
+ // simple to set on ROOT context
+ hostMapper.doFilter(req, null, null);
+
+
+ ServletContextImpl ctx = (ServletContextImpl)mapRes.context;
+ if( ctx == null ) {
+ // TODO: 404
+ res.setStatus(404);
+ return;
+ }
+ req.setContext(ctx);
+
+ // bind class loader
+ Thread.currentThread().setContextClassLoader(ctx.getClassLoader());
+
+ WebappServletMapper mapper = ctx.getMapper();
+ mapper.map(req.getCoyoteRequest().decodedURI(), mapRes);
+
+ // Possible redirect
+ MessageBytes redirectPathMB = mapRes.redirectPath;
+ if (!redirectPathMB.isNull()) {
+ String redirectPath = res.urlEncoder.encodeURL(redirectPathMB.toString());
+ String query = req.getQueryString();
+ if (req.isRequestedSessionIdFromURL()) {
+ // This is not optimal, but as this is not very common, it
+ // shouldn't matter
+ redirectPath = redirectPath + ";" + ServletRequestImpl.SESSION_PARAMETER_NAME + "="
+ + req.getRequestedSessionId();
+ }
+ if (query != null) {
+ // This is not optimal, but as this is not very common, it
+ // shouldn't matter
+ redirectPath = redirectPath + "?" + query;
+ }
+ res.sendRedirect(redirectPath);
+ return;
+ }
+
+ req.parseSessionCookiesId();
+
+ ServletConfigImpl h=(ServletConfigImpl)mapRes.wrapper;
+ if (h != null) {
+ 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 )
+ mapRes.recycle();
+ }
+ }
+
+ /** Coyote / mapper adapter. Result of the mapper.
+ *
+ * This replaces the valve chain, the path is:
+ * 1. coyote calls mapper -> result Adapter
+ * 2. service is called. Additional filters are set on the wrapper.
+ * @param mapRes
+ */
+ private void serviceServlet(ServletContextImpl ctx,
+ ServletRequestImpl req,
+ ServletResponseImpl res,
+ ServletConfigImpl servletConfig,
+ MappingData mapRes)
+ throws IOException {
+ Servlet servlet = null;
+ try {
+ 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(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;
+ }
+
+ // servlet completed without exception. Check status
+ int status = res.getStatus();
+ if (status != 200 && !res.isCommitted()) {
+ String statusPage = ctx.findStatusPage(status);
+
+ if (statusPage != null) {
+ ctx.handleStatusPage(req, res, status, statusPage);
+ } else {
+ // Send a default message body.
+ // TODO: maybe other mechanism to customize default.
+ res.defaultStatusPage(status, res.getMessage());
+ }
+ }
+ } catch (Throwable t) {
+ ctx.handleError(req, res, t);
+ } finally {
+ 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) {
+ }
+
+ void notifyRemove(Object o) {
+ }
+
+ public void setServerDir(String dir) {
+ this.serverDirName = dir;
+ }
+
+ public File getWork() {
+ if (workDir == null) {
+ if (serverDirName == null) {
+ serverDirName = "./";
+ }
+ File rootDirFile = new File(serverDirName);
+ workDir = new File(rootDirFile, "tomcat-work");
+ if (workDir.exists()) {
+ workDir.mkdirs();
+ }
+ }
+ return workDir;
+ }
+
+ /**
+ * Init
+ *
+ * @throws ServletException
+ * @throws IOException
+ */
+ public void init() throws ServletException, IOException {
+ getObjectManager().bind("TomcatLite", this);
+ if (contexts.size() == 0) {
+ setContext("/:./webapps/ROOT");
+ }
+ getConnector().setObjectManager(getObjectManager());
+ Iterator i1 = contexts.iterator();
+ while (i1.hasNext()) {
+ ServletContextImpl ctx = (ServletContextImpl) i1.next();
+ try {
+ ctx.init();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Initialize an webapp and add it to the server.
+ * - load web.xml
+ * - call
+ *
+ * @param rootDir
+ * @param path
+ * @param deployServlet
+ */
+ public void init(String rootDir, String path)
+ throws ServletException, IOException {
+
+ long t0 = System.currentTimeMillis();
+
+ ServletContextImpl ctx =
+ (ServletContextImpl)addServletContext(null,
+ rootDir,
+ path);
+ ctx.init();
+
+ long t1 = System.currentTimeMillis();
+
+ // At this point all config is loaded. Contexts are not yet init()
+ // - this will happen on start.
+ System.err.println("Context.init() " + path + " " + (t1-t0));
+ }
+
+ /**
+ * Get an empty request/response pair ( response available
+ * as getResponse() ). Optional set input and output buffers.
+ *
+ * This can be used for a connector-less interface to tomcat lite.
+ *
+ * TODO: make it independent of coyote !
+ */
+
+ public ServletRequestImpl createMessage() {
+ ServletRequestImpl req = new ServletRequestImpl();
+ ServletResponseImpl res = req.getResponse();
+
+ getConnector().initRequest(req, res);
+
+ req.getCoyoteRequest().method().setString("GET");
+ req.getCoyoteRequest().protocol().setString("HTTP/1.1");
+
+ return req;
+ }
+
+ /**
+ * Used internally for mapping.
+ */
+ private ServletRequestImpl createMessage(ServletContextImpl deployCtx,
+ String ctxPath,
+ String reqPath) {
+ ServletRequestImpl req = createMessage();
+ req.setContextPath(ctxPath);
+ req.setContext(deployCtx);
+ req.setRequestURI(ctxPath + reqPath);
+ return req;
+ }
+
+
+ /**
+ * Set a global filter that will be used for context mapping.
+ *
+ * The filter will get a request, with requestUri and hostname set.
+ *
+ * It needs to compute the context path and set it as an attribute.
+ *
+ * Advanced features may include on-demand loading of webapps, large scale
+ * virtual hosting, etc.
+ */
+ public void setContextMapper(Filter hostMapper2) {
+ this.hostMapper = hostMapper2;
+ }
+
+ public void endRequest(ServletRequestImpl req,
+ ServletResponseImpl res) throws IOException {
+ res.outputBuffer.flush();
+ res.getCoyoteResponse().finish();
+ }
+
+ public Connector getConnector() {
+ if (coyoteAdapter == null) {
+ coyoteAdapter = (Connector) getObjectManager().get(Connector.class);
+ setConnector(coyoteAdapter);
+ }
+ return coyoteAdapter;
+ }
+
+ public void setConnector(Connector c) {
+ coyoteAdapter = c;
+ coyoteAdapter.setTomcatLite(this);
+ getObjectManager().bind("Connector", coyoteAdapter);
+ }
+
+
+ public void setDaemon(boolean d) {
+ getConnector();
+ if (coyoteAdapter != null) {
+ coyoteAdapter.setDaemon(d);
+ }
+ }
+
+ public void startConnector() {
+ getConnector();
+ if (coyoteAdapter != null) {
+ coyoteAdapter.start();
+ }
+ }
+
+ public void stopConnector() {
+ getConnector();
+ if (coyoteAdapter != null) {
+ coyoteAdapter.stop();
+ }
+ }
+
+ public void run() {
+ try {
+ execute();
+ } catch (ServletException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void execute() throws ServletException, IOException {
+ init();
+ start();
+ startConnector();
+ }
+}
Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java Sat Apr 4 16:24:34 2009
@@ -0,0 +1,132 @@
+package org.apache.tomcat.lite;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.http.mapper.MappingData;
+
+/**
+ * This handles host and context mapping.
+ *
+ * The default implementation for tomcat lite is very limitted -
+ * no support for virtual hosts, no support for contexts deeper than
+ * 1 level. The intention is to override this with more advanced mappers.
+ *
+ * With 'ConfigurableHosts' interface it is possible for a smart
+ * mapper to load/unload virtual hosts at runtime, maybe from a
+ * database. It should be possible to use databases to store huge number
+ * of hosts or webapps.
+ *
+ */
+public class WebappContextMapper implements Filter {
+
+ ServletContext rootContext;
+ Map<MessageBytes, ServletContext> contexts = new HashMap();
+
+ public WebappContextMapper() {
+ }
+
+ public void addHost(String name, String[] aliases) {
+ }
+
+ /**
+ * Add a new Context to an existing Host.
+ *
+ * @param hostName Virtual host name this context belongs to
+ * @param contextPath Context path
+ * @param context Context object
+ * @param welcomeResources Welcome files defined for this context
+ * @param resources Static resources of the context
+ */
+ public void addContext(String hostName,
+ ServletContext context)
+ throws ServletException
+ {
+ String path = context.getContextPath();
+ if (path.lastIndexOf("/") > 0) {
+ throw new ServletException("Base context mapper supports only one level");
+ }
+ if ("/".equals(path)) {
+ rootContext = context;
+ }
+ MessageBytes mb = MessageBytes.newInstance();
+ mb.setChars(path.toCharArray(), 0, path.length());
+ contexts.put(mb, context);
+ }
+
+
+ /**
+ * Remove a context from an existing host.
+ *
+ * @param hostName Virtual host name this context belongs to
+ * @param path Context path
+ */
+ public void removeContext(String hostName, String path)
+ throws ServletException {
+ if ("/".equals(path)) {
+ rootContext = null;
+ }
+ contexts.remove(path);
+ }
+
+ /**
+ * Map the specified URI.
+ */
+ private void mapContext(ServletRequestImpl req)
+ throws IOException, ServletException {
+ MessageBytes uriMB = req.getDecodedRequestURIMB();
+ MappingData mappingData = req.getMappingData();
+ uriMB.toChars();
+ CharChunk uri = uriMB.getCharChunk();
+
+
+ if (uri.length() < 2 || contexts.size() == 0) {
+ mappingData.context = rootContext;
+ if (rootContext != null) {
+ mappingData.contextPath.setString(rootContext.getContextPath());
+ }
+ return;
+ }
+
+ int nextSlash = uri.indexOf('/', 1);
+ if (nextSlash == -1) {
+ nextSlash = uri.length();
+ }
+ mappingData.contextPath.setChars(uri.getChars(), 0, nextSlash);
+ ServletContext servletContext = contexts.get(mappingData.contextPath);
+
+ if (servletContext != null) {
+ mappingData.context = servletContext;
+ } else {
+ mappingData.context = rootContext;
+ if (rootContext != null) {
+ mappingData.contextPath.setString(rootContext.getContextPath());
+ }
+ }
+ }
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ public void doFilter(ServletRequest request,
+ ServletResponse response,
+ FilterChain chain)
+ throws IOException, ServletException {
+ ServletRequestImpl req = (ServletRequestImpl)request;
+ mapContext(req);
+ }
+
+ public void destroy() {
+ }
+}
\ No newline at end of file
Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java Sat Apr 4 16:24:34 2009
@@ -0,0 +1,529 @@
+/*
+ * 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.lite;
+
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tomcat.servlets.util.RequestUtil;
+
+/**
+ * First filter after the context and servlet are mapped. It will add
+ * web.xml-defined filters.
+ *
+ * costin: This is another mapping - done in RequestDispatcher or initial
+ * mapping.
+ * Also: StandardHostValve - sets attribute for error pages,
+ * StandardWrapperValve - mapping per invocation
+ *
+ * @author Greg Murray
+ * @author Remy Maucherat
+ */
+public class WebappFilterMapper implements Filter {
+
+
+ // -------------------------------------------------------------- Constants
+
+
+ public static final int ERROR = 1;
+ public static final Integer ERROR_INTEGER = new Integer(ERROR);
+ public static final int FORWARD = 2;
+ public static final Integer FORWARD_INTEGER = new Integer(FORWARD);
+ public static final int INCLUDE = 4;
+ public static final Integer INCLUDE_INTEGER = new Integer(INCLUDE);
+ public static final int REQUEST = 8;
+ public static final Integer REQUEST_INTEGER = new Integer(REQUEST);
+
+ /**
+ * Request dispatcher state.
+ */
+ public static final String DISPATCHER_TYPE_ATTR =
+ "org.apache.catalina.core.DISPATCHER_TYPE";
+
+ /**
+ * Request dispatcher path.
+ */
+ public static final String DISPATCHER_REQUEST_PATH_ATTR =
+ "org.apache.catalina.core.DISPATCHER_REQUEST_PATH";
+
+
+ // ----------------------------------------------------------- Constructors
+ ServletContextImpl servletContext;
+
+ public WebappFilterMapper() {
+ }
+
+ public WebappFilterMapper(ServletContextImpl impl) {
+ servletContext = impl;
+ }
+
+ public void setServletContext(ServletContextImpl sc) {
+ servletContext = sc;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ ArrayList filterMaps = new ArrayList();
+
+ public void addMapping(String filterName,
+ String url,
+ String servletName,
+ String type[]) {
+ FilterMap map = new FilterMap();
+ map.setURLPattern(url);
+ map.setFilterName(filterName);
+ map.setServletName(servletName);
+ filterMaps.add(map);
+ }
+
+ /**
+ * Construct and return a FilterChain implementation that will wrap the
+ * execution of the specified servlet instance. If we should not execute
+ * a filter chain at all, return <code>null</code>.
+ *
+ * @param request The servlet request we are processing
+ * @param servlet The servlet instance to be wrapped
+ */
+ public FilterChainImpl createFilterChain(ServletRequest request,
+ ServletConfigImpl wrapper,
+ Servlet servlet) {
+
+ // If there is no servlet to execute, return null
+ if (servlet == null)
+ return (null);
+
+ // get the dispatcher type
+ int dispatcher = -1;
+ if (request.getAttribute(DISPATCHER_TYPE_ATTR) != null) {
+ Integer dispatcherInt =
+ (Integer) request.getAttribute(DISPATCHER_TYPE_ATTR);
+ dispatcher = dispatcherInt.intValue();
+ }
+ String requestPath = null;
+ Object attribute = request.getAttribute(DISPATCHER_REQUEST_PATH_ATTR);
+
+ if (attribute != null){
+ requestPath = attribute.toString();
+ }
+
+ HttpServletRequest hreq = null;
+ if (request instanceof HttpServletRequest)
+ hreq = (HttpServletRequest)request;
+
+ // Create and initialize a filter chain object
+ FilterChainImpl filterChain = null;
+ if ((request instanceof ServletRequestImpl)) {
+ ServletRequestImpl req = (ServletRequestImpl) request;
+ filterChain = (FilterChainImpl) req.getFilterChain();
+ filterChain.release();
+ } else {
+ // Security: Do not recycle
+ filterChain = new FilterChainImpl();
+ }
+
+ filterChain.setServlet(wrapper, servlet);
+
+ // If there are no filter mappings, we are done
+ if ((filterMaps.size() == 0))
+ return (filterChain);
+
+ // Acquire the information we will need to match filter mappings
+ String servletName = wrapper.getServletName();
+
+ int n = 0;
+
+ // TODO(costin): optimize: separate in 2 lists, one for url-mapped, one for
+ // servlet-name. Maybe even separate list for dispatcher and
+ // non-dispatcher
+
+ // TODO(costin): optimize: set the FilterConfig in the FilterMap, to
+ // avoid second hash lookup
+
+ // Add the relevant path-mapped filters to this filter chain
+ for (int i = 0; i < filterMaps.size(); i++) {
+ FilterMap filterMap = (FilterMap)filterMaps.get(i);
+ if (!matchDispatcher(filterMap ,dispatcher)) {
+ continue;
+ }
+ if (!matchFiltersURL(filterMap, requestPath))
+ continue;
+ FilterConfigImpl filterConfig =
+ servletContext.getFilter(filterMap.getFilterName());
+ if (filterConfig == null) {
+ // FIXME - log configuration problem
+ continue;
+ }
+ filterChain.addFilter(filterConfig);
+ n++;
+ }
+
+ // Add filters that match on servlet name second
+ for (int i = 0; i < filterMaps.size(); i++) {
+ FilterMap filterMap = (FilterMap)filterMaps.get(i);
+ if (!matchDispatcher(filterMap ,dispatcher)) {
+ continue;
+ }
+ if (!matchFiltersServlet(filterMap, servletName))
+ continue;
+ FilterConfigImpl filterConfig =
+ servletContext.getFilter(filterMap.getFilterName());
+ if (filterConfig == null) {
+ ; // FIXME - log configuration problem
+ continue;
+ }
+ filterChain.addFilter(filterConfig);
+ n++;
+ }
+
+ // Return the completed filter chain
+ return (filterChain);
+
+ }
+
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * Return <code>true</code> if the context-relative request path
+ * matches the requirements of the specified filter mapping;
+ * otherwise, return <code>null</code>.
+ *
+ * @param filterMap Filter mapping being checked
+ * @param requestPath Context-relative request path of this request
+ */
+ private boolean matchFiltersURL(FilterMap filterMap, String requestPath) {
+
+ if (requestPath == null)
+ return (false);
+
+ // Match on context relative request path
+ String testPath = filterMap.getURLPattern();
+ if (testPath == null)
+ return (false);
+
+ // Case 1 - Exact Match
+ if (testPath.equals(requestPath))
+ return (true);
+
+ // Case 2 - Path Match ("/.../*")
+ if (testPath.equals("/*"))
+ return (true);
+ if (testPath.endsWith("/*")) {
+ if (testPath.regionMatches(0, requestPath, 0,
+ testPath.length() - 2)) {
+ if (requestPath.length() == (testPath.length() - 2)) {
+ return (true);
+ } else if ('/' == requestPath.charAt(testPath.length() - 2)) {
+ return (true);
+ }
+ }
+ return (false);
+ }
+
+ // Case 3 - Extension Match
+ if (testPath.startsWith("*.")) {
+ int slash = requestPath.lastIndexOf('/');
+ int period = requestPath.lastIndexOf('.');
+ if ((slash >= 0) && (period > slash)
+ && (period != requestPath.length() - 1)
+ && ((requestPath.length() - period)
+ == (testPath.length() - 1))) {
+ return (testPath.regionMatches(2, requestPath, period + 1,
+ testPath.length() - 2));
+ }
+ }
+
+ // Case 4 - "Default" Match
+ return (false); // NOTE - Not relevant for selecting filters
+
+ }
+
+
+ /**
+ * Return <code>true</code> if the specified servlet name matches
+ * the requirements of the specified filter mapping; otherwise
+ * return <code>false</code>.
+ *
+ * @param filterMap Filter mapping being checked
+ * @param servletName Servlet name being checked
+ */
+ private boolean matchFiltersServlet(FilterMap filterMap,
+ String servletName) {
+
+ if (servletName == null) {
+ return (false);
+ } else {
+ if (servletName.equals(filterMap.getServletName())) {
+ return (true);
+ } else {
+ return false;
+ }
+ }
+
+ }
+
+
+ /**
+ * Convienience method which returns true if the dispatcher type
+ * matches the dispatcher types specified in the FilterMap
+ */
+ private boolean matchDispatcher(FilterMap filterMap, int dispatcher) {
+ switch (dispatcher) {
+ case FORWARD : {
+ if (filterMap.getDispatcherMapping() == FilterMap.FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.FORWARD_ERROR ||
+ filterMap.getDispatcherMapping() == FilterMap.INCLUDE_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE) {
+ return true;
+ }
+ break;
+ }
+ case INCLUDE : {
+ if (filterMap.getDispatcherMapping() == FilterMap.INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR ||
+ filterMap.getDispatcherMapping() == FilterMap.INCLUDE_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE) {
+ return true;
+ }
+ break;
+ }
+ case REQUEST : {
+ if (filterMap.getDispatcherMapping() == FilterMap.REQUEST ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE) {
+ return true;
+ }
+ break;
+ }
+ case ERROR : {
+ if (filterMap.getDispatcherMapping() == FilterMap.ERROR ||
+ filterMap.getDispatcherMapping() == FilterMap.FORWARD_ERROR ||
+ filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR ||
+ filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE ||
+ filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE) {
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+ }
+
+
+ // -------------------- Map elements -----------------------
+
+ public static class FilterMap implements Serializable {
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * The name of this filter to be executed when this mapping matches
+ * a particular request.
+ */
+
+ public static final int ERROR = 1;
+ public static final int FORWARD = 2;
+ public static final int FORWARD_ERROR =3;
+ public static final int INCLUDE = 4;
+ public static final int INCLUDE_ERROR = 5;
+ public static final int INCLUDE_ERROR_FORWARD =6;
+ public static final int INCLUDE_FORWARD = 7;
+ public static final int REQUEST = 8;
+ public static final int REQUEST_ERROR = 9;
+ public static final int REQUEST_ERROR_FORWARD = 10;
+ public static final int REQUEST_ERROR_FORWARD_INCLUDE = 11;
+ public static final int REQUEST_ERROR_INCLUDE = 12;
+ public static final int REQUEST_FORWARD = 13;
+ public static final int REQUEST_INCLUDE = 14;
+ public static final int REQUEST_FORWARD_INCLUDE= 15;
+
+ // represents nothing having been set. This will be seen
+ // as equal to a REQUEST
+ private static final int NOT_SET = -1;
+
+ private int dispatcherMapping=NOT_SET;
+
+ private String filterName = null;
+
+ /**
+ * The URL pattern this mapping matches.
+ */
+ private String urlPattern = null;
+
+ /**
+ * The servlet name this mapping matches.
+ */
+ private String servletName = null;
+
+
+
+ public String getFilterName() {
+ return (this.filterName);
+ }
+
+ public void setFilterName(String filterName) {
+ this.filterName = filterName;
+ }
+
+
+ public String getServletName() {
+ return (this.servletName);
+ }
+
+ public void setServletName(String servletName) {
+ this.servletName = servletName;
+ }
+
+
+ public String getURLPattern() {
+ return (this.urlPattern);
+ }
+
+ public void setURLPattern(String urlPattern) {
+ this.urlPattern = RequestUtil.URLDecode(urlPattern);
+ }
+
+ /**
+ *
+ * This method will be used to set the current state of the FilterMap
+ * representing the state of when filters should be applied:
+ *
+ * ERROR
+ * FORWARD
+ * FORWARD_ERROR
+ * INCLUDE
+ * INCLUDE_ERROR
+ * INCLUDE_ERROR_FORWARD
+ * REQUEST
+ * REQUEST_ERROR
+ * REQUEST_ERROR_INCLUDE
+ * REQUEST_ERROR_FORWARD_INCLUDE
+ * REQUEST_INCLUDE
+ * REQUEST_FORWARD,
+ * REQUEST_FORWARD_INCLUDE
+ *
+ */
+ public void setDispatcher(String dispatcherString) {
+ String dispatcher = dispatcherString.toUpperCase();
+
+ if (dispatcher.equals("FORWARD")) {
+
+ // apply FORWARD to the global dispatcherMapping.
+ switch (dispatcherMapping) {
+ case NOT_SET : dispatcherMapping = FORWARD; break;
+ case ERROR : dispatcherMapping = FORWARD_ERROR; break;
+ case INCLUDE : dispatcherMapping = INCLUDE_FORWARD; break;
+ case INCLUDE_ERROR : dispatcherMapping = INCLUDE_ERROR_FORWARD; break;
+ case REQUEST : dispatcherMapping = REQUEST_FORWARD; break;
+ case REQUEST_ERROR : dispatcherMapping = REQUEST_ERROR_FORWARD; break;
+ case REQUEST_ERROR_INCLUDE : dispatcherMapping = REQUEST_ERROR_FORWARD_INCLUDE; break;
+ case REQUEST_INCLUDE : dispatcherMapping = REQUEST_FORWARD_INCLUDE; break;
+ }
+ } else if (dispatcher.equals("INCLUDE")) {
+ // apply INCLUDE to the global dispatcherMapping.
+ switch (dispatcherMapping) {
+ case NOT_SET : dispatcherMapping = INCLUDE; break;
+ case ERROR : dispatcherMapping = INCLUDE_ERROR; break;
+ case FORWARD : dispatcherMapping = INCLUDE_FORWARD; break;
+ case FORWARD_ERROR : dispatcherMapping = INCLUDE_ERROR_FORWARD; break;
+ case REQUEST : dispatcherMapping = REQUEST_INCLUDE; break;
+ case REQUEST_ERROR : dispatcherMapping = REQUEST_ERROR_INCLUDE; break;
+ case REQUEST_ERROR_FORWARD : dispatcherMapping = REQUEST_ERROR_FORWARD_INCLUDE; break;
+ case REQUEST_FORWARD : dispatcherMapping = REQUEST_FORWARD_INCLUDE; break;
+ }
+ } else if (dispatcher.equals("REQUEST")) {
+ // apply REQUEST to the global dispatcherMapping.
+ switch (dispatcherMapping) {
+ case NOT_SET : dispatcherMapping = REQUEST; break;
+ case ERROR : dispatcherMapping = REQUEST_ERROR; break;
+ case FORWARD : dispatcherMapping = REQUEST_FORWARD; break;
+ case FORWARD_ERROR : dispatcherMapping = REQUEST_ERROR_FORWARD; break;
+ case INCLUDE : dispatcherMapping = REQUEST_INCLUDE; break;
+ case INCLUDE_ERROR : dispatcherMapping = REQUEST_ERROR_INCLUDE; break;
+ case INCLUDE_FORWARD : dispatcherMapping = REQUEST_FORWARD_INCLUDE; break;
+ case INCLUDE_ERROR_FORWARD : dispatcherMapping = REQUEST_ERROR_FORWARD_INCLUDE; break;
+ }
+ } else if (dispatcher.equals("ERROR")) {
+ // apply ERROR to the global dispatcherMapping.
+ switch (dispatcherMapping) {
+ case NOT_SET : dispatcherMapping = ERROR; break;
+ case FORWARD : dispatcherMapping = FORWARD_ERROR; break;
+ case INCLUDE : dispatcherMapping = INCLUDE_ERROR; break;
+ case INCLUDE_FORWARD : dispatcherMapping = INCLUDE_ERROR_FORWARD; break;
+ case REQUEST : dispatcherMapping = REQUEST_ERROR; break;
+ case REQUEST_INCLUDE : dispatcherMapping = REQUEST_ERROR_INCLUDE; break;
+ case REQUEST_FORWARD : dispatcherMapping = REQUEST_ERROR_FORWARD; break;
+ case REQUEST_FORWARD_INCLUDE : dispatcherMapping = REQUEST_ERROR_FORWARD_INCLUDE; break;
+ }
+ }
+ }
+
+ public int getDispatcherMapping() {
+ // per the SRV.6.2.5 absence of any dispatcher elements is
+ // equivelant to a REQUEST value
+ if (dispatcherMapping == NOT_SET) return REQUEST;
+ else return dispatcherMapping;
+ }
+
+ }
+
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain)
+ throws IOException, ServletException {
+ }
+
+
+ public void destroy() {
+ }
+
+}
Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java Sat Apr 4 16:24:34 2009
@@ -0,0 +1,883 @@
+/*
+ * 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.lite;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.tomcat.util.buf.Ascii;
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.http.mapper.MappingData;
+
+/**
+ * Mapper, which implements the servlet API mapping rules (which are derived
+ * from the HTTP rules).
+ *
+ * Based on catalina mapper - but simplified. All host and context mappings
+ * is done in HostMapper - this is just dealing with web.xml.
+ *
+ * For corner cases ( very large number of rules, dynamic rules, etc ) you
+ * can override the mapper for a context with a class extending this.
+ *
+ * TODO: remove, use coyote-level mapper or user-space
+ */
+public class WebappServletMapper implements Filter {
+
+ /**
+ * Context associated with this wrapper, used for wrapper mapping.
+ */
+ public ContextMapElement contextMapElement = new ContextMapElement();
+
+
+ // --------------------------------------------------------- Public Methods
+ public WebappServletMapper() {
+ }
+
+ public void setServletContext(ServletContextImpl impl) {
+ contextMapElement.object = impl;
+ contextMapElement.name = impl.getContextPath();
+ }
+
+
+ /** Set context, used for wrapper mapping (request dispatcher).
+ *
+ * @param welcomeResources Welcome files defined for this context
+ * @param resources Static resources of the context
+ */
+ public void setContext(String path, String[] welcomeResources,
+ File resources) {
+ contextMapElement.name = path;
+ contextMapElement.welcomeResources = welcomeResources;
+ contextMapElement.resources = resources;
+ }
+
+
+ /**
+ * Add a wrapper to the context associated with this wrapper.
+ *
+ * @param path Wrapper mapping
+ * @param wrapper The Wrapper object
+ */
+ public void addWrapper(String path, Object wrapper) {
+ addWrapper(contextMapElement, path, wrapper);
+ }
+
+
+ public void addWrapper(String path, Object wrapper, boolean jspWildCard) {
+ addWrapper(contextMapElement, path, wrapper, jspWildCard);
+ }
+
+
+ public void addWrapper(ContextMapElement context, String path, Object wrapper) {
+ addWrapper(context, path, wrapper, false);
+ }
+
+
+ /**
+ * Adds a wrapper to the given context.
+ *
+ * @param context The context to which to add the wrapper
+ * @param path Wrapper mapping
+ * @param wrapper The Wrapper object
+ * @param jspWildCard true if the wrapper corresponds to the JspServlet
+ * and the mapping path contains a wildcard; false otherwise
+ */
+ protected void addWrapper(ContextMapElement context, String path, Object wrapper,
+ boolean jspWildCard) {
+
+ synchronized (context) {
+ WrapperMapElement newWrapper = new WrapperMapElement();
+ newWrapper.object = wrapper;
+ newWrapper.jspWildCard = jspWildCard;
+ if (path.endsWith("/*")) {
+ // Wildcard wrapper
+ newWrapper.name = path.substring(0, path.length() - 2);
+ WrapperMapElement[] oldWrappers = context.wildcardWrappers;
+ WrapperMapElement[] newWrappers =
+ new WrapperMapElement[oldWrappers.length + 1];
+ if (insertMap(oldWrappers, newWrappers, newWrapper)) {
+ context.wildcardWrappers = newWrappers;
+ int slashCount = slashCount(newWrapper.name);
+ if (slashCount > context.nesting) {
+ context.nesting = slashCount;
+ }
+ }
+ } else if (path.startsWith("*.")) {
+ // Extension wrapper
+ newWrapper.name = path.substring(2);
+ WrapperMapElement[] oldWrappers = context.extensionWrappers;
+ WrapperMapElement[] newWrappers =
+ new WrapperMapElement[oldWrappers.length + 1];
+ if (insertMap(oldWrappers, newWrappers, newWrapper)) {
+ context.extensionWrappers = newWrappers;
+ }
+ } else if (path.equals("/")) {
+ // Default wrapper
+ newWrapper.name = "";
+ context.defaultWrapper = newWrapper;
+ } else {
+ // Exact wrapper
+ newWrapper.name = path;
+ WrapperMapElement[] oldWrappers = context.exactWrappers;
+ WrapperMapElement[] newWrappers =
+ new WrapperMapElement[oldWrappers.length + 1];
+ if (insertMap(oldWrappers, newWrappers, newWrapper)) {
+ context.exactWrappers = newWrappers;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Remove a wrapper from the context associated with this wrapper.
+ *
+ * @param path Wrapper mapping
+ */
+ public void removeWrapper(String path) {
+ removeWrapper(contextMapElement, path);
+ }
+
+
+ protected void removeWrapper(ContextMapElement context, String path) {
+ synchronized (context) {
+ if (path.endsWith("/*")) {
+ // Wildcard wrapper
+ String name = path.substring(0, path.length() - 2);
+ WrapperMapElement[] oldWrappers = context.wildcardWrappers;
+ WrapperMapElement[] newWrappers =
+ new WrapperMapElement[oldWrappers.length - 1];
+ if (removeMap(oldWrappers, newWrappers, name)) {
+ // Recalculate nesting
+ context.nesting = 0;
+ for (int i = 0; i < newWrappers.length; i++) {
+ int slashCount = slashCount(newWrappers[i].name);
+ if (slashCount > context.nesting) {
+ context.nesting = slashCount;
+ }
+ }
+ context.wildcardWrappers = newWrappers;
+ }
+ } else if (path.startsWith("*.")) {
+ // Extension wrapper
+ String name = path.substring(2);
+ WrapperMapElement[] oldWrappers = context.extensionWrappers;
+ WrapperMapElement[] newWrappers =
+ new WrapperMapElement[oldWrappers.length - 1];
+ if (removeMap(oldWrappers, newWrappers, name)) {
+ context.extensionWrappers = newWrappers;
+ }
+ } else if (path.equals("/")) {
+ // Default wrapper
+ context.defaultWrapper = null;
+ } else {
+ // Exact wrapper
+ String name = path;
+ WrapperMapElement[] oldWrappers = context.exactWrappers;
+ WrapperMapElement[] newWrappers =
+ new WrapperMapElement[oldWrappers.length - 1];
+ if (removeMap(oldWrappers, newWrappers, name)) {
+ context.exactWrappers = newWrappers;
+ }
+ }
+ }
+ }
+
+ /**
+ * Map the specified URI relative to the context,
+ * mutating the given mapping data.
+ *
+ * @param uri URI
+ * @param mappingData This structure will contain the result of the mapping
+ * operation
+ */
+ public void map(MessageBytes uri, MappingData mappingData)
+ throws Exception {
+
+ uri.toChars();
+ CharChunk uricc = uri.getCharChunk();
+ //uricc.setLimit(-1);
+ internalMapWrapper(contextMapElement, uricc, mappingData);
+
+ }
+
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * Wrapper mapping.
+ */
+ private final void internalMapWrapper(ContextMapElement context,
+ CharChunk path,
+ MappingData mappingData)
+ throws Exception {
+
+ int pathOffset = path.getOffset();
+ int pathEnd = path.getEnd();
+ int servletPath = pathOffset;
+ boolean noServletPath = false;
+
+ int length = context.name.length();
+ if (length == 1) length--;
+ if (length != (pathEnd - pathOffset)) {
+ servletPath = pathOffset + length;
+ } else {
+ noServletPath = true;
+ // What is this doing ???
+ path.append('/');
+ pathOffset = path.getOffset();
+ pathEnd = path.getEnd();
+ servletPath = pathOffset+length;
+ }
+
+ path.setOffset(servletPath);
+
+ // Rule 1 -- Exact Match
+ WrapperMapElement[] exactWrappers = context.exactWrappers;
+ internalMapExactWrapper(exactWrappers, path, mappingData);
+
+ // Rule 2 -- Prefix Match
+ boolean checkJspWelcomeFiles = false;
+ WrapperMapElement[] wildcardWrappers = context.wildcardWrappers;
+ if (mappingData.wrapper == null) {
+ internalMapWildcardWrapper(wildcardWrappers, context.nesting,
+ path, mappingData);
+ if (mappingData.wrapper != null && mappingData.jspWildCard) {
+ char[] buf = path.getBuffer();
+ if (buf[pathEnd - 1] == '/') {
+ /*
+ * Path ending in '/' was mapped to JSP servlet based on
+ * wildcard match (e.g., as specified in url-pattern of a
+ * jsp-property-group.
+ * Force the context's welcome files, which are interpreted
+ * as JSP files (since they match the url-pattern), to be
+ * considered. See Bugzilla 27664.
+ */
+ mappingData.wrapper = null;
+ checkJspWelcomeFiles = true;
+ } else {
+ // See Bugzilla 27704
+ mappingData.wrapperPath.setChars(buf, path.getStart(),
+ path.getLength());
+ mappingData.pathInfo.recycle();
+ }
+ }
+ }
+
+ if(mappingData.wrapper == null && noServletPath) {
+ // The path is empty, redirect to "/"
+ mappingData.redirectPath.setChars
+ (path.getBuffer(), pathOffset, pathEnd);
+ path.setEnd(pathEnd - 1);
+ return;
+ }
+
+ // Rule 3 -- Extension Match
+ WrapperMapElement[] extensionWrappers = context.extensionWrappers;
+ if (mappingData.wrapper == null && !checkJspWelcomeFiles) {
+ internalMapExtensionWrapper(extensionWrappers, path, mappingData);
+ }
+
+ File file = null;
+ // Rule 4 -- Welcome resources processing for servlets
+ if (mappingData.wrapper == null) {
+ boolean checkWelcomeFiles = checkJspWelcomeFiles;
+ if (!checkWelcomeFiles) {
+ char[] buf = path.getBuffer();
+ checkWelcomeFiles = (buf[pathEnd - 1] == '/');
+ }
+ if (checkWelcomeFiles) {
+ for (int i = 0; (i < context.welcomeResources.length)
+ && (mappingData.wrapper == null); i++) {
+ path.setOffset(pathOffset);
+ path.setEnd(pathEnd);
+ path.append(context.welcomeResources[i], 0,
+ context.welcomeResources[i].length());
+ path.setOffset(servletPath);
+
+ // Rule 4a -- Welcome resources processing for exact macth
+ internalMapExactWrapper(exactWrappers, path, mappingData);
+
+ // Rule 4b -- Welcome resources processing for prefix match
+ if (mappingData.wrapper == null) {
+ internalMapWildcardWrapper
+ (wildcardWrappers, context.nesting,
+ path, mappingData);
+ }
+
+ // Rule 4c -- Welcome resources processing
+ // for physical folder
+ if (mappingData.wrapper == null
+ && context.resources != null) {
+ // Default servlet: check if it's file or dir to apply
+ // welcome files rules.
+ // TODO: Save the File in attributes,
+ // to avoid duplication in DefaultServlet.
+
+ String pathStr = path.toString();
+ file = new File(context.resources, pathStr);
+ if (file.exists() && !(file.isDirectory()) ) {
+
+ internalMapExtensionWrapper(extensionWrappers,
+ path, mappingData);
+ if (mappingData.wrapper == null
+ && context.defaultWrapper != null) {
+ mappingData.wrapper =
+ context.defaultWrapper.object;
+ mappingData.requestPath.setChars
+ (path.getBuffer(), path.getStart(),
+ path.getLength());
+ mappingData.wrapperPath.setChars
+ (path.getBuffer(), path.getStart(),
+ path.getLength());
+ mappingData.requestPath.setString(pathStr);
+ mappingData.wrapperPath.setString(pathStr);
+ }
+ }
+ }
+ }
+
+ path.setOffset(servletPath);
+ path.setEnd(pathEnd);
+ }
+
+ }
+
+
+ // Rule 7 -- Default servlet
+ if (mappingData.wrapper == null && !checkJspWelcomeFiles) {
+ if (context.defaultWrapper != null) {
+ mappingData.wrapper = context.defaultWrapper.object;
+ mappingData.requestPath.setChars
+ (path.getBuffer(), path.getStart(), path.getLength());
+ mappingData.wrapperPath.setChars
+ (path.getBuffer(), path.getStart(), path.getLength());
+ }
+ // Redirection to a folder
+ char[] buf = path.getBuffer();
+ if (context.resources != null && buf[pathEnd -1 ] != '/') {
+ String pathStr = path.toString();
+ file = new File( context.resources, pathStr);
+ if (file.exists() && file.isDirectory()) {
+ // Note: this mutates the path: do not do any processing
+ // after this (since we set the redirectPath, there
+ // shouldn't be any)
+ path.setOffset(pathOffset);
+ path.append('/');
+ mappingData.redirectPath.setChars
+ (path.getBuffer(), path.getStart(), path.getLength());
+ } else {
+ mappingData.requestPath.setString(pathStr);
+ mappingData.wrapperPath.setString(pathStr);
+ }
+ }
+ }
+
+ path.setOffset(pathOffset);
+ path.setEnd(pathEnd);
+ }
+
+
+ /**
+ * Exact mapping.
+ */
+ private final void internalMapExactWrapper
+ (WrapperMapElement[] wrappers, CharChunk path, MappingData mappingData) {
+ int pos = find(wrappers, path);
+ if ((pos != -1) && (path.equals(wrappers[pos].name))) {
+ mappingData.requestPath.setString(wrappers[pos].name);
+ mappingData.wrapperPath.setString(wrappers[pos].name);
+ mappingData.wrapper = wrappers[pos].object;
+ }
+ }
+
+
+ /**
+ * Wildcard mapping.
+ */
+ private final void internalMapWildcardWrapper
+ (WrapperMapElement[] wrappers, int nesting, CharChunk path,
+ MappingData mappingData) {
+
+ int pathEnd = path.getEnd();
+ int pathOffset = path.getOffset();
+
+ int lastSlash = -1;
+ int length = -1;
+ int pos = find(wrappers, path);
+ if (pos != -1) {
+ boolean found = false;
+ while (pos >= 0) {
+ if (path.startsWith(wrappers[pos].name)) {
+ length = wrappers[pos].name.length();
+ if (path.getLength() == length) {
+ found = true;
+ break;
+ } else if (path.startsWithIgnoreCase("/", length)) {
+ found = true;
+ break;
+ }
+ }
+ if (lastSlash == -1) {
+ lastSlash = nthSlash(path, nesting + 1);
+ } else {
+ lastSlash = lastSlash(path);
+ }
+ path.setEnd(lastSlash);
+ pos = find(wrappers, path);
+ }
+ path.setEnd(pathEnd);
+ if (found) {
+ mappingData.wrapperPath.setString(wrappers[pos].name);
+ if (path.getLength() > length) {
+ mappingData.pathInfo.setChars
+ (path.getBuffer(),
+ path.getOffset() + length,
+ path.getLength() - length);
+ }
+ mappingData.requestPath.setChars
+ (path.getBuffer(), path.getOffset(), path.getLength());
+ mappingData.wrapper = wrappers[pos].object;
+ mappingData.jspWildCard = wrappers[pos].jspWildCard;
+ }
+ }
+ }
+
+
+ /**
+ * Extension mappings.
+ */
+ private final void internalMapExtensionWrapper
+ (WrapperMapElement[] wrappers, CharChunk path, MappingData mappingData) {
+ char[] buf = path.getBuffer();
+ int pathEnd = path.getEnd();
+ int servletPath = path.getOffset();
+ int slash = -1;
+ for (int i = pathEnd - 1; i >= servletPath; i--) {
+ if (buf[i] == '/') {
+ slash = i;
+ break;
+ }
+ }
+ if (slash == -1 ) slash = 0;
+ if (slash >= 0) {
+ int period = -1;
+ for (int i = pathEnd - 1; i > slash; i--) {
+ if (buf[i] == '.') {
+ period = i;
+ break;
+ }
+ }
+ if (period >= 0) {
+ path.setOffset(period + 1);
+ path.setEnd(pathEnd);
+ int pos = find(wrappers, path);
+ if ((pos != -1)
+ && (path.equals(wrappers[pos].name))) {
+ mappingData.wrapperPath.setChars
+ (buf, servletPath, pathEnd - servletPath);
+ mappingData.requestPath.setChars
+ (buf, servletPath, pathEnd - servletPath);
+ mappingData.wrapper = wrappers[pos].object;
+ }
+ path.setOffset(servletPath);
+ path.setEnd(pathEnd);
+ }
+ }
+ }
+
+
+ /**
+ * Find a map elemnt given its name in a sorted array of map elements.
+ * This will return the index for the closest inferior or equal item in the
+ * given array.
+ */
+ public static final int find(MapElement[] map, CharChunk name) {
+ return find(map, name, name.getStart(), name.getEnd());
+ }
+
+
+ /**
+ * Find a map elemnt given its name in a sorted array of map elements.
+ * This will return the index for the closest inferior or equal item in the
+ * given array.
+ */
+ private static final int find(MapElement[] map, CharChunk name,
+ int start, int end) {
+
+ int a = 0;
+ int b = map.length - 1;
+
+ // Special cases: -1 and 0
+ if (b == -1) {
+ return -1;
+ }
+
+ if (compare(name, start, end, map[0].name) < 0 ) {
+ return -1;
+ }
+ if (b == 0) {
+ return 0;
+ }
+
+ int i = 0;
+ while (true) {
+ i = (b + a) / 2;
+ int result = compare(name, start, end, map[i].name);
+ if (result == 1) {
+ a = i;
+ } else if (result == 0) {
+ return i;
+ } else {
+ b = i;
+ }
+ if ((b - a) == 1) {
+ int result2 = compare(name, start, end, map[b].name);
+ if (result2 < 0) {
+ return a;
+ } else {
+ return b;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Find a map elemnt given its name in a sorted array of map elements.
+ * This will return the index for the closest inferior or equal item in the
+ * given array.
+ */
+ private static final int findIgnoreCase(MapElement[] map, CharChunk name) {
+ return findIgnoreCase(map, name, name.getStart(), name.getEnd());
+ }
+
+
+ /**
+ * Find a map elemnt given its name in a sorted array of map elements.
+ * This will return the index for the closest inferior or equal item in the
+ * given array.
+ */
+ private static final int findIgnoreCase(MapElement[] map, CharChunk name,
+ int start, int end) {
+
+ int a = 0;
+ int b = map.length - 1;
+
+ // Special cases: -1 and 0
+ if (b == -1) {
+ return -1;
+ }
+ if (compareIgnoreCase(name, start, end, map[0].name) < 0 ) {
+ return -1;
+ }
+ if (b == 0) {
+ return 0;
+ }
+
+ int i = 0;
+ while (true) {
+ i = (b + a) / 2;
+ int result = compareIgnoreCase(name, start, end, map[i].name);
+ if (result == 1) {
+ a = i;
+ } else if (result == 0) {
+ return i;
+ } else {
+ b = i;
+ }
+ if ((b - a) == 1) {
+ int result2 = compareIgnoreCase(name, start, end, map[b].name);
+ if (result2 < 0) {
+ return a;
+ } else {
+ return b;
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Find a map elemnt given its name in a sorted array of map elements.
+ * This will return the index for the closest inferior or equal item in the
+ * given array.
+ */
+ public static final int find(MapElement[] map, String name) {
+
+ int a = 0;
+ int b = map.length - 1;
+
+ // Special cases: -1 and 0
+ if (b == -1) {
+ return -1;
+ }
+
+ if (name.compareTo(map[0].name) < 0) {
+ return -1;
+ }
+ if (b == 0) {
+ return 0;
+ }
+
+ int i = 0;
+ while (true) {
+ i = (b + a) / 2;
+ int result = name.compareTo(map[i].name);
+ if (result > 0) {
+ a = i;
+ } else if (result == 0) {
+ return i;
+ } else {
+ b = i;
+ }
+ if ((b - a) == 1) {
+ int result2 = name.compareTo(map[b].name);
+ if (result2 < 0) {
+ return a;
+ } else {
+ return b;
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Compare given char chunk with String.
+ * Return -1, 0 or +1 if inferior, equal, or superior to the String.
+ */
+ private static final int compare(CharChunk name, int start, int end,
+ String compareTo) {
+ int result = 0;
+ char[] c = name.getBuffer();
+ int len = compareTo.length();
+ if ((end - start) < len) {
+ len = end - start;
+ }
+ for (int i = 0; (i < len) && (result == 0); i++) {
+ if (c[i + start] > compareTo.charAt(i)) {
+ result = 1;
+ } else if (c[i + start] < compareTo.charAt(i)) {
+ result = -1;
+ }
+ }
+ if (result == 0) {
+ if (compareTo.length() > (end - start)) {
+ result = -1;
+ } else if (compareTo.length() < (end - start)) {
+ result = 1;
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Compare given char chunk with String ignoring case.
+ * Return -1, 0 or +1 if inferior, equal, or superior to the String.
+ */
+ private static final int compareIgnoreCase(CharChunk name, int start, int end,
+ String compareTo) {
+ int result = 0;
+ char[] c = name.getBuffer();
+ int len = compareTo.length();
+ if ((end - start) < len) {
+ len = end - start;
+ }
+ for (int i = 0; (i < len) && (result == 0); i++) {
+ if (Ascii.toLower(c[i + start]) > Ascii.toLower(compareTo.charAt(i))) {
+ result = 1;
+ } else if (Ascii.toLower(c[i + start]) < Ascii.toLower(compareTo.charAt(i))) {
+ result = -1;
+ }
+ }
+ if (result == 0) {
+ if (compareTo.length() > (end - start)) {
+ result = -1;
+ } else if (compareTo.length() < (end - start)) {
+ result = 1;
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Find the position of the last slash in the given char chunk.
+ */
+ public static final int lastSlash(CharChunk name) {
+
+ char[] c = name.getBuffer();
+ int end = name.getEnd();
+ int start = name.getStart();
+ int pos = end;
+
+ while (pos > start) {
+ if (c[--pos] == '/') {
+ break;
+ }
+ }
+
+ return (pos);
+
+ }
+
+
+ /**
+ * Find the position of the nth slash, in the given char chunk.
+ */
+ public static final int nthSlash(CharChunk name, int n) {
+
+ char[] c = name.getBuffer();
+ int end = name.getEnd();
+ int start = name.getStart();
+ int pos = start;
+ int count = 0;
+
+ while (pos < end) {
+ if ((c[pos++] == '/') && ((++count) == n)) {
+ pos--;
+ break;
+ }
+ }
+
+ return (pos);
+
+ }
+
+
+ /**
+ * Return the slash count in a given string.
+ */
+ public static final int slashCount(String name) {
+ int pos = -1;
+ int count = 0;
+ while ((pos = name.indexOf('/', pos + 1)) != -1) {
+ count++;
+ }
+ return count;
+ }
+
+
+ /**
+ * Insert into the right place in a sorted MapElement array, and prevent
+ * duplicates.
+ */
+ public static final boolean insertMap
+ (MapElement[] oldMap, MapElement[] newMap, MapElement newElement) {
+ int pos = find(oldMap, newElement.name);
+ if ((pos != -1) && (newElement.name.equals(oldMap[pos].name))) {
+ return false;
+ }
+ System.arraycopy(oldMap, 0, newMap, 0, pos + 1);
+ newMap[pos + 1] = newElement;
+ System.arraycopy
+ (oldMap, pos + 1, newMap, pos + 2, oldMap.length - pos - 1);
+ return true;
+ }
+
+
+ /**
+ * Insert into the right place in a sorted MapElement array.
+ */
+ public static final boolean removeMap
+ (MapElement[] oldMap, MapElement[] newMap, String name) {
+ int pos = find(oldMap, name);
+ if ((pos != -1) && (name.equals(oldMap[pos].name))) {
+ System.arraycopy(oldMap, 0, newMap, 0, pos);
+ System.arraycopy(oldMap, pos + 1, newMap, pos,
+ oldMap.length - pos - 1);
+ return true;
+ }
+ return false;
+ }
+
+
+ // ------------------------------------------------- MapElement Inner Class
+
+
+ protected static abstract class MapElement {
+ /** hostname or path
+ */
+ public String name = null;
+ public Object object = null;
+
+ public String toString() {
+ return "MapElement: \"" + name +"\"";
+ }
+ }
+
+
+ // ---------------------------------------------------- Context Inner Class
+
+
+ public static final class ContextMapElement
+ extends MapElement {
+
+ public String[] welcomeResources = new String[0];
+ public File resources = null;
+ public WrapperMapElement defaultWrapper = null;
+ public WrapperMapElement[] exactWrappers = new WrapperMapElement[0];
+ public WrapperMapElement[] wildcardWrappers = new WrapperMapElement[0];
+ public WrapperMapElement[] extensionWrappers = new WrapperMapElement[0];
+ public int nesting = 0;
+
+ public String toString() {
+ return "ContextMapElement {" +
+ "name: \"" + name +
+ "\"\nnesting: \"" + nesting +
+ "\"\n}";
+ }
+ }
+
+
+ // ---------------------------------------------------- Wrapper Inner Class
+
+
+ public static class WrapperMapElement
+ extends MapElement {
+ public boolean jspWildCard = false;
+ }
+
+
+ public void destroy() {
+ }
+
+
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException,
+ ServletException {
+ }
+
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+
+}
Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java Sat Apr 4 16:24:34 2009
@@ -0,0 +1,59 @@
+/*
+ * 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.lite.cli;
+
+import org.apache.tomcat.integration.ObjectManager;
+import org.apache.tomcat.integration.jmx.JmxObjectManagerSpi;
+import org.apache.tomcat.integration.simple.SimpleObjectManager;
+import org.apache.tomcat.lite.TomcatLite;
+import org.apache.tomcat.lite.coyote.CoyoteHttp;
+
+/**
+ * Run tomcat lite, mostly for demo. In normal use you would
+ * embed it in an app, or use a small customized launcher.
+ *
+ * With no arguments, it'll load only the root context / from
+ * ./webapps/ROOT
+ *
+ * Most configuration can be done using web.xml files, few settings
+ * can be set by flags.
+ *
+ * @author Costin Manolache
+ */
+public class Main {
+
+ public static void main(String args[])
+ throws Exception {
+
+ if (args.length == 0) {
+ System.err.println("Please specify at least one webapp.");
+ System.err.println("Example:");
+ System.err.println("-context /:webapps/ROOT -port 9999");
+ }
+
+ // Enable CLI processing
+ SimpleObjectManager.setArgs(args);
+
+ TomcatLite lite = new TomcatLite();
+ ObjectManager om = lite.getObjectManager();
+
+ // add JMX support
+ new JmxObjectManagerSpi().register(om);
+
+ lite.run();
+ }
+}
Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties Sat Apr 4 16:24:34 2009
@@ -0,0 +1,28 @@
+# Support for PropertiesSpi - the 'dummy' framework used for tomcat-lite
+# If tomcat is used with a proper framework, you need to bind and configure
+# those objects in the framework.
+
+# --- Class names for required plugin interfaces ---
+
+org.apache.tomcat.lite.WebappServletMapper.(class)=org.apache.tomcat.lite.WebappServletMapper
+org.apache.tomcat.lite.WebappFilterMapper.(class)=org.apache.tomcat.lite.WebappFilterMapper
+
+# Sessions
+org.apache.tomcat.addons.UserSessionManager.(class)=org.apache.tomcat.servlets.session.SimpleSessionManager
+
+# *.jsp support
+org.apache.tomcat.addons.UserTemplateClassMapper.(class)=org.apache.tomcat.servlets.jsp.JasperCompilerTemplateClassMapper
+
+# Loader for web.xml - you can have your own custom class using a more efficient
+# or hardcoded.
+org.apache.tomcat.lite.ContextPreinitListener.(class)=org.apache.tomcat.lite.webxml.TomcatLiteWebXmlConfig
+
+# Connector class
+org.apache.tomcat.lite.Connector.(class)=org.apache.tomcat.lite.coyote.CoyoteHttp
+
+# --- Other required settings ---
+
+# Customize default and *.jsp mappings
+default-servlet.(class)=org.apache.tomcat.servlets.file.WebdavServlet
+jspwildcard-servlet.(class)=org.apache.tomcat.servlets.jsp.WildcardTemplateServlet
+
Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java Sat Apr 4 16:24:34 2009
@@ -0,0 +1,143 @@
+/*
+ * 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.lite.coyote;
+
+import java.io.IOException;
+
+/**
+ * Wrap an IOException identifying it as being caused by an abort
+ * of a request by a remote client.
+ *
+ * @author Glenn L. Nielsen
+ * @version $Revision: 304063 $ $Date: 2005-08-18 06:25:18 -0700 (Thu, 18 Aug 2005) $
+ */
+
+public final class ClientAbortException extends IOException {
+
+
+ //------------------------------------------------------------ Constructors
+
+
+ /**
+ * Construct a new ClientAbortException with no other information.
+ */
+ public ClientAbortException() {
+
+ this(null, null);
+
+ }
+
+
+ /**
+ * Construct a new ClientAbortException for the specified message.
+ *
+ * @param message Message describing this exception
+ */
+ public ClientAbortException(String message) {
+
+ this(message, null);
+
+ }
+
+
+ /**
+ * Construct a new ClientAbortException for the specified throwable.
+ *
+ * @param throwable Throwable that caused this exception
+ */
+ public ClientAbortException(Throwable throwable) {
+
+ this(null, throwable);
+
+ }
+
+
+ /**
+ * Construct a new ClientAbortException for the specified message
+ * and throwable.
+ *
+ * @param message Message describing this exception
+ * @param throwable Throwable that caused this exception
+ */
+ public ClientAbortException(String message, Throwable throwable) {
+
+ super();
+ this.message = message;
+ this.throwable = throwable;
+
+ }
+
+
+ //------------------------------------------------------ Instance Variables
+
+
+ /**
+ * The error message passed to our constructor (if any)
+ */
+ protected String message = null;
+
+
+ /**
+ * The underlying exception or error passed to our constructor (if any)
+ */
+ protected Throwable throwable = null;
+
+
+ //---------------------------------------------------------- Public Methods
+
+
+ /**
+ * Returns the message associated with this exception, if any.
+ */
+ public String getMessage() {
+
+ return (message);
+
+ }
+
+
+ /**
+ * Returns the cause that caused this exception, if any.
+ */
+ public Throwable getCause() {
+
+ return (throwable);
+
+ }
+
+
+ /**
+ * Return a formatted string that describes this exception.
+ */
+ public String toString() {
+
+ StringBuffer sb = new StringBuffer("ClientAbortException: ");
+ if (message != null) {
+ sb.append(message);
+ if (throwable != null) {
+ sb.append(": ");
+ }
+ }
+ if (throwable != null) {
+ sb.append(throwable.toString());
+ }
+ return (sb.toString());
+
+ }
+
+
+}
Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org