From 6ba144b9066d90570023fd360fa0515fcbd0ff64 Mon Sep 17 00:00:00 2001 From: markt Date: Fri, 17 Apr 2009 16:30:56 +0000 Subject: [PATCH] Update Servlet 3.0 classes to spec snapshot as of early March 2009. Still not final. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@766075 13f79535-47bb-0310-9956-ffa450edef68 --- .../{AsyncContext.java => AsyncDispatcher.java} | 15 +- java/javax/servlet/AsyncEvent.java | 2 +- java/javax/servlet/AsyncListener.java | 7 +- java/javax/servlet/ServletContext.java | 70 ++++- java/javax/servlet/ServletRequest.java | 33 +-- java/javax/servlet/ServletRequestWrapper.java | 56 ++-- java/javax/servlet/SessionTrackingMode.java | 4 +- java/javax/servlet/http/HttpServlet.java | 7 +- java/javax/servlet/http/HttpUtils.java | 283 --------------------- java/org/apache/catalina/connector/Request.java | 38 +-- .../apache/catalina/connector/RequestFacade.java | 51 ++-- .../apache/catalina/core/ApplicationContext.java | 123 +++++++-- .../catalina/core/ApplicationContextFacade.java | 33 ++- java/org/apache/catalina/core/DummyRequest.java | 14 +- .../apache/catalina/core/LocalStrings.properties | 16 +- .../apache/jasper/servlet/JspCServletContext.java | 18 +- 16 files changed, 321 insertions(+), 449 deletions(-) rename java/javax/servlet/{AsyncContext.java => AsyncDispatcher.java} (71%) delete mode 100644 java/javax/servlet/http/HttpUtils.java diff --git a/java/javax/servlet/AsyncContext.java b/java/javax/servlet/AsyncDispatcher.java similarity index 71% rename from java/javax/servlet/AsyncContext.java rename to java/javax/servlet/AsyncDispatcher.java index cf36c697c..e05cf6ee2 100644 --- a/java/javax/servlet/AsyncContext.java +++ b/java/javax/servlet/AsyncDispatcher.java @@ -18,16 +18,9 @@ package javax.servlet; /** * @since 3.0 - * $Id$ - * TODO SERVLET3 + * TODO SERVLET3 - Add comments */ -public interface AsyncContext { - ServletRequest getRequest(); - ServletResponse getResponse(); - boolean hasOriginalRequestAndResponse(); - void forward(); - void forward(String path); - void forward(ServletContext context, String path); - void complete(); - void start(Runnable run); +public interface AsyncDispatcher { + void forward(ServletRequest request, ServletResponse response) + throws IllegalStateException; } diff --git a/java/javax/servlet/AsyncEvent.java b/java/javax/servlet/AsyncEvent.java index 1d5d77e1f..e16529196 100644 --- a/java/javax/servlet/AsyncEvent.java +++ b/java/javax/servlet/AsyncEvent.java @@ -19,7 +19,7 @@ package javax.servlet; /** * @since 3.0 * $Id$ - * TODO SERVLET3 + * TODO SERVLET3 - Add comments */ public class AsyncEvent { private ServletRequest request; diff --git a/java/javax/servlet/AsyncListener.java b/java/javax/servlet/AsyncListener.java index 20ac2ac1c..f618f4b26 100644 --- a/java/javax/servlet/AsyncListener.java +++ b/java/javax/servlet/AsyncListener.java @@ -17,13 +17,14 @@ package javax.servlet; import java.io.IOException; +import java.util.EventListener; /** * @since 3.0 * $Id$ - * TODO SERVLET3 + * TODO SERVLET3 - Add comments */ -public interface AsyncListener { - void onComplete(AsyncEvent event) throws IOException; +public interface AsyncListener extends EventListener { + void onDoneAsync(AsyncEvent event) throws IOException; void onTimeout(AsyncEvent event) throws IOException; } diff --git a/java/javax/servlet/ServletContext.java b/java/javax/servlet/ServletContext.java index d4490528d..f7f566166 100644 --- a/java/javax/servlet/ServletContext.java +++ b/java/javax/servlet/ServletContext.java @@ -643,14 +643,38 @@ public interface ServletContext { */ public String getServletContextName(); + + + /** + * + * @param servletName + * @param description + * @param className + * @param initParameters + * @param loadOnStartup + * @throws IllegalArgumentException If the servlet name already exists + * @throws IllegalStateException If the context has already been + * initialised + * @since 3.0 + */ + public void addServlet(String servletName, String description, + String className, Map initParameters, + int loadOnStartup) + throws IllegalArgumentException, IllegalStateException; + /** * * @param servletName * @param urlPatterns + * @throws IllegalArgumentException If urlPatters is null or empty + * @throws IllegalStateException If the context has already been + * initialised + * * @since 3.0 */ - public void addServletMapping(String servletName, String[] urlPatterns); + public void addServletMapping(String servletName, String[] urlPatterns) + throws IllegalArgumentException, IllegalStateException; /** * @@ -658,12 +682,15 @@ public interface ServletContext { * @param description * @param className * @param initParameters - * @param isAsyncSupported + * @throws IllegalArgumentException If the filter name already exists + * @throws IllegalStateException If the context has already been + * initialised + * * @since 3.0 */ public void addFilter(String filterName, String description, - String className, Map initParameters, - boolean isAsyncSupported); + String className, Map initParameters) + throws IllegalArgumentException, IllegalStateException; /** * @@ -671,11 +698,15 @@ public interface ServletContext { * @param dispatcherTypes * @param isMatchAfter * @param servletNames + * @throws IllegalArgumentException If servletNames is null or empty + * @throws IllegalStateException If the context has already been + * initialised * @since 3.0 */ public void addFilterMappingForServletNames(String filterName, EnumSet dispatcherTypes, boolean isMatchAfter, - String... servletNames); + String... servletNames) + throws IllegalArgumentException, IllegalStateException; /** * @@ -683,18 +714,24 @@ public interface ServletContext { * @param dispatcherTypes * @param isMatchAfter * @param urlPatterns +4 * * @since 3.0 */ public void addFilterMappingForUrlPatterns(String filterName, EnumSet dispatcherTypes, boolean isMatchAfter, - String... urlPatterns); + String... urlPatterns) + throws IllegalArgumentException, IllegalStateException; + /** * * @param sessionCookieConfig + * @throws IllegalStateException If the context has already been + * initialised * @since 3.0 */ - public void setSessionCookieConfig(SessionCookieConfig sessionCookieConfig); + public void setSessionCookieConfig(SessionCookieConfig sessionCookieConfig) + throws IllegalStateException; /** * @@ -706,10 +743,17 @@ public interface ServletContext { /** * * @param sessionTrackingModes + * @throws IllegalArgumentException If sessionTrackingModes specifies + * {@link SessionTrackingMode.SSL} in + * combination with any other + * {@link SessionTrackingMode} + * @throws IllegalStateException If the context has already been + * initialised * @since 3.0 */ public void setSessionTrackingModes( - EnumSet sessionTrackingModes); + EnumSet sessionTrackingModes) + throws IllegalStateException, IllegalArgumentException; /** * @@ -724,6 +768,12 @@ public interface ServletContext { * @since 3.0 */ public EnumSet getEffectiveSessionTrackingModes(); + + /** + * + * @param path + * @return + * @since 3.0 + */ + public AsyncDispatcher getAsyncDispatcher(String path); } - - diff --git a/java/javax/servlet/ServletRequest.java b/java/javax/servlet/ServletRequest.java index 21c486d1d..a33098979 100644 --- a/java/javax/servlet/ServletRequest.java +++ b/java/javax/servlet/ServletRequest.java @@ -604,21 +604,20 @@ public interface ServletRequest { /** * * @return - * @throws java.lang.IllegalStateException + * @throws java.lang.IllegalStateException If async is not supported for + * this request * @since 3.0 */ - public AsyncContext startAsync() throws java.lang.IllegalStateException; + public void startAsync() throws java.lang.IllegalStateException; /** * - * @param servletRequest - * @param servletResponse + * @param runnable * @return * @throws java.lang.IllegalStateException * @since 3.0 */ - public AsyncContext startAsync(ServletRequest servletRequest, - ServletResponse servletResponse) + public void startAsync(Runnable runnable) throws java.lang.IllegalStateException; /** @@ -630,6 +629,13 @@ public interface ServletRequest { /** * + * @throws IllegalStateException If startAsync was never called + * @since 3.0 + */ + public void doneAsync() throws IllegalStateException; + + /** + * * @return * @since 3.0 */ @@ -640,15 +646,16 @@ public interface ServletRequest { * @return * @since 3.0 */ - public AsyncContext getAsyncContext(); + public AsyncDispatcher getAsyncDispatcher(); /** * - * @param listener + * @param path + * @return * @since 3.0 */ - public void addAsyncListener(AsyncListener listener); - + public AsyncDispatcher getAsyncDispatcher(String path); + /** * * @param listener @@ -659,11 +666,5 @@ public interface ServletRequest { public void addAsyncListener(AsyncListener listener, ServletRequest servletRequest, ServletResponse servletResponse); - /** - * - * @param timeout - * @since 3.0 - */ - public void setAsyncTimeout(long timeout); } diff --git a/java/javax/servlet/ServletRequestWrapper.java b/java/javax/servlet/ServletRequestWrapper.java index ece9ea327..3f0d08338 100644 --- a/java/javax/servlet/ServletRequestWrapper.java +++ b/java/javax/servlet/ServletRequestWrapper.java @@ -417,25 +417,22 @@ public class ServletRequestWrapper implements ServletRequest { * @throws java.lang.IllegalStateException * @since 3.0 */ - public AsyncContext startAsync() throws java.lang.IllegalStateException { - return request.startAsync(); + public void startAsync() throws java.lang.IllegalStateException { + request.startAsync(); } /** * The default behavior of this method is to return - * startAsync(ServletRequest, ServletResponse) on the wrapped request - * object. + * startAsync(Runnable) on the wrapped request object. * - * @param servletRequest - * @param servletResponse + * @param runnable * @return * @throws java.lang.IllegalStateException * @since 3.0 */ - public AsyncContext startAsync(ServletRequest servletRequest, - ServletResponse servletResponse) + public void startAsync(Runnable runnable) throws java.lang.IllegalStateException { - return request.startAsync(servletRequest, servletResponse); + request.startAsync(runnable); } /** @@ -448,7 +445,17 @@ public class ServletRequestWrapper implements ServletRequest { public boolean isAsyncStarted() { return request.isAsyncStarted(); } - + + /** + * The default behavior of this method is to return + * doneAsync() on the wrapped request object. + * @throws java.lang.IllegalStateException + * @since 3.0 + */ + public void doneAsync() throws IllegalStateException { + request.doneAsync(); + } + /** * The default behavior of this method is to return * isAsyncSupported() on the wrapped request object. @@ -462,26 +469,26 @@ public class ServletRequestWrapper implements ServletRequest { /** * The default behavior of this method is to return - * getAsyncContext() on the wrapped request object. + * getAsyncDispatcher() on the wrapped request object. * * @return * @since 3.0 */ - public AsyncContext getAsyncContext() { - return request.getAsyncContext(); + public AsyncDispatcher getAsyncDispatcher() { + return request.getAsyncDispatcher(); } /** - * The default behavior of this method is to call - * addAsyncListener(AsyncListener) on the wrapped request object. + * The default behavior of this method is to return + * getAsyncDispatcher(path) on the wrapped request object. * - * @param listener + * @return * @since 3.0 */ - public void addAsyncListener(AsyncListener listener) { - request.addAsyncListener(listener); + public AsyncDispatcher getAsyncDispatcher(String path) { + return request.getAsyncDispatcher(path); } - + /** * The default behavior of this method is to call * addAsyncListener(AsyncListener, ServletRequest, ServletResponse) on the @@ -497,16 +504,5 @@ public class ServletRequestWrapper implements ServletRequest { request.addAsyncListener(listener, servletRequest, servletResponse); } - /** - * The default behavior of this method is to call - * startAsync() on the wrapped request object. - * - * @param timeout - * @since 3.0 - */ - public void setAsyncTimeout(long timeout) { - request.setAsyncTimeout(timeout); - } - } diff --git a/java/javax/servlet/SessionTrackingMode.java b/java/javax/servlet/SessionTrackingMode.java index fcb49afc1..878d4629c 100644 --- a/java/javax/servlet/SessionTrackingMode.java +++ b/java/javax/servlet/SessionTrackingMode.java @@ -22,6 +22,6 @@ package javax.servlet; */ public enum SessionTrackingMode { COOKIE, - URL, - SSL + SSL, + URL } diff --git a/java/javax/servlet/http/HttpServlet.java b/java/javax/servlet/http/HttpServlet.java index c3db36292..96f699ee8 100644 --- a/java/javax/servlet/http/HttpServlet.java +++ b/java/javax/servlet/http/HttpServlet.java @@ -198,7 +198,8 @@ public abstract class HttpServlet extends GenericServlet { * since midnight, January 1, 1970 GMT, or * -1 if the time is not known */ - protected long getLastModified(HttpServletRequest req) { + protected long getLastModified( + @SuppressWarnings("unused") HttpServletRequest req) { return -1; } @@ -472,7 +473,9 @@ public abstract class HttpServlet extends GenericServlet { * @exception ServletException if the request for the * OPTIONS cannot be handled */ - protected void doOptions(HttpServletRequest req, HttpServletResponse resp) + protected void doOptions( + @SuppressWarnings("unused") HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException { Method[] methods = getAllDeclaredMethods(this.getClass()); diff --git a/java/javax/servlet/http/HttpUtils.java b/java/javax/servlet/http/HttpUtils.java deleted file mode 100644 index 9ce22de79..000000000 --- a/java/javax/servlet/http/HttpUtils.java +++ /dev/null @@ -1,283 +0,0 @@ -/* -* 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 javax.servlet.http; - -import javax.servlet.ServletInputStream; -import java.util.Hashtable; -import java.util.ResourceBundle; -import java.util.StringTokenizer; -import java.io.IOException; - -/** - * @deprecated As of Java(tm) Servlet API 2.3. - * These methods were only useful - * with the default encoding and have been moved - * to the request interfaces. - * -*/ - - -public class HttpUtils { - - private static final String LSTRING_FILE = - "javax.servlet.http.LocalStrings"; - private static ResourceBundle lStrings = - ResourceBundle.getBundle(LSTRING_FILE); - - - /** - * Constructs an empty HttpUtils object. - * - */ - public HttpUtils() { - // NOOP - } - - - /** - * - * Parses a query string passed from the client to the - * server and builds a HashTable object - * with key-value pairs. - * The query string should be in the form of a string - * packaged by the GET or POST method, that is, it - * should have key-value pairs in the form key=value, - * with each pair separated from the next by a & character. - * - *

A key can appear more than once in the query string - * with different values. However, the key appears only once in - * the hashtable, with its value being - * an array of strings containing the multiple values sent - * by the query string. - * - *

The keys and values in the hashtable are stored in their - * decoded form, so - * any + characters are converted to spaces, and characters - * sent in hexadecimal notation (like %xx) are - * converted to ASCII characters. - * - * @param s a string containing the query to be parsed - * - * @return a HashTable object built - * from the parsed key-value pairs - * - * @exception IllegalArgumentException if the query string - * is invalid - * - */ - static public Hashtable parseQueryString(String s) { - - String valArray[] = null; - - if (s == null) { - throw new IllegalArgumentException(); - } - Hashtable ht = new Hashtable(); - StringBuffer sb = new StringBuffer(); - StringTokenizer st = new StringTokenizer(s, "&"); - while (st.hasMoreTokens()) { - String pair = st.nextToken(); - int pos = pair.indexOf('='); - if (pos == -1) { - // XXX - // should give more detail about the illegal argument - throw new IllegalArgumentException(); - } - String key = parseName(pair.substring(0, pos), sb); - String val = parseName(pair.substring(pos+1, pair.length()), sb); - if (ht.containsKey(key)) { - String oldVals[] = ht.get(key); - valArray = new String[oldVals.length + 1]; - for (int i = 0; i < oldVals.length; i++) - valArray[i] = oldVals[i]; - valArray[oldVals.length] = val; - } else { - valArray = new String[1]; - valArray[0] = val; - } - ht.put(key, valArray); - } - return ht; - } - - - /** - * - * Parses data from an HTML form that the client sends to - * the server using the HTTP POST method and the - * application/x-www-form-urlencoded MIME type. - * - *

The data sent by the POST method contains key-value - * pairs. A key can appear more than once in the POST data - * with different values. However, the key appears only once in - * the hashtable, with its value being - * an array of strings containing the multiple values sent - * by the POST method. - * - *

The keys and values in the hashtable are stored in their - * decoded form, so - * any + characters are converted to spaces, and characters - * sent in hexadecimal notation (like %xx) are - * converted to ASCII characters. - * - * - * - * @param len an integer specifying the length, - * in characters, of the - * ServletInputStream - * object that is also passed to this - * method - * - * @param in the ServletInputStream - * object that contains the data sent - * from the client - * - * @return a HashTable object built - * from the parsed key-value pairs - * - * - * @exception IllegalArgumentException if the data - * sent by the POST method is invalid - * - */ - static public Hashtable parsePostData(int len, - ServletInputStream in) { - // XXX - // should a length of 0 be an IllegalArgumentException - - // cheap hack to return an empty hash - if (len <=0) - return new Hashtable(); - - if (in == null) { - throw new IllegalArgumentException(); - } - - // Make sure we read the entire POSTed body. - byte[] postedBytes = new byte [len]; - try { - int offset = 0; - - do { - int inputLen = in.read (postedBytes, offset, len - offset); - if (inputLen <= 0) { - String msg = lStrings.getString("err.io.short_read"); - throw new IllegalArgumentException (msg); - } - offset += inputLen; - } while ((len - offset) > 0); - - } catch (IOException e) { - throw new IllegalArgumentException(e.getMessage()); - } - - // XXX we shouldn't assume that the only kind of POST body - // is FORM data encoded using ASCII or ISO Latin/1 ... or - // that the body should always be treated as FORM data. - try { - String postedBody = new String(postedBytes, 0, len, "8859_1"); - return parseQueryString(postedBody); - } catch (java.io.UnsupportedEncodingException e) { - // XXX function should accept an encoding parameter & throw this - // exception. Otherwise throw something expected. - throw new IllegalArgumentException(e.getMessage()); - } - } - - - /* - * Parse a name in the query string. - */ - static private String parseName(String s, StringBuffer sb) { - sb.setLength(0); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { - case '+': - sb.append(' '); - break; - case '%': - try { - sb.append((char) Integer.parseInt(s.substring(i+1, i+3), - 16)); - i += 2; - } catch (NumberFormatException e) { - // XXX - // need to be more specific about illegal arg - throw new IllegalArgumentException(); - } catch (StringIndexOutOfBoundsException e) { - String rest = s.substring(i); - sb.append(rest); - if (rest.length()==2) - i++; - } - - break; - default: - sb.append(c); - break; - } - } - return sb.toString(); - } - - - /** - * - * Reconstructs the URL the client used to make the request, - * using information in the HttpServletRequest object. - * The returned URL contains a protocol, server name, port - * number, and server path, but it does not include query - * string parameters. - * - *

Because this method returns a StringBuffer, - * not a string, you can modify the URL easily, for example, - * to append query parameters. - * - *

This method is useful for creating redirect messages - * and for reporting errors. - * - * @param req a HttpServletRequest object - * containing the client's request - * - * @return a StringBuffer object containing - * the reconstructed URL - * - */ - public static StringBuffer getRequestURL (HttpServletRequest req) { - StringBuffer url = new StringBuffer (); - String scheme = req.getScheme (); - int port = req.getServerPort (); - String urlPath = req.getRequestURI(); - - url.append (scheme); // http, https - url.append ("://"); - url.append (req.getServerName ()); - if ((scheme.equals ("http") && port != 80) - || (scheme.equals ("https") && port != 443)) { - url.append (':'); - url.append (req.getServerPort ()); - } - - url.append(urlPath); - return url; - } -} - - - diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index 4981cce78..ce572f22d 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -35,7 +35,7 @@ import java.util.TimeZone; import java.util.TreeMap; import javax.security.auth.Subject; -import javax.servlet.AsyncContext; +import javax.servlet.AsyncDispatcher; import javax.servlet.AsyncListener; import javax.servlet.FilterChain; import javax.servlet.RequestDispatcher; @@ -1501,22 +1501,16 @@ public class Request } - public void addAsyncListener(AsyncListener listener, - ServletRequest servletRequest, ServletResponse servletResponse) { - // TODO SERVLET3 - } + public ServletContext getServletContext() { + return context.getServletContext(); + } - public void addAsyncListener(AsyncListener listener) { + public void startAsync() throws IllegalStateException { // TODO SERVLET3 } - public AsyncContext getAsyncContext() { + public void startAsync(Runnable runnable) throws IllegalStateException { // TODO SERVLET3 - return null; - } - - public ServletContext getServletContext() { - return context.getServletContext(); } public boolean isAsyncStarted() { @@ -1524,23 +1518,29 @@ public class Request return false; } + public void doneAsync() throws IllegalStateException { + // TODO SERVLET3 + } + public boolean isAsyncSupported() { // TODO SERVLET3 return false; } - public void setAsyncTimeout(long timeout) { + public AsyncDispatcher getAsyncDispatcher() { // TODO SERVLET3 + return null; } - public AsyncContext startAsync() throws IllegalStateException { - return startAsync(getRequest(),getResponse().getResponse()); + public AsyncDispatcher getAsyncDispatcher(String path) { + // TODO SERVLET3 + return null; } + - public AsyncContext startAsync(ServletRequest servletRequest, - ServletResponse servletResponse) throws IllegalStateException { + public void addAsyncListener(AsyncListener listener, + ServletRequest servletRequest, ServletResponse servletResponse) { // TODO SERVLET3 - return null; } // ---------------------------------------------------- HttpRequest Methods @@ -2772,5 +2772,5 @@ public class Request } return true; } - + } diff --git a/java/org/apache/catalina/connector/RequestFacade.java b/java/org/apache/catalina/connector/RequestFacade.java index f65c5319d..7485f3bf1 100644 --- a/java/org/apache/catalina/connector/RequestFacade.java +++ b/java/org/apache/catalina/connector/RequestFacade.java @@ -26,7 +26,7 @@ import java.util.Enumeration; import java.util.Locale; import java.util.Map; -import javax.servlet.AsyncContext; +import javax.servlet.AsyncDispatcher; import javax.servlet.AsyncListener; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; @@ -938,21 +938,6 @@ public class RequestFacade implements HttpServletRequest { } - public void addAsyncListener(AsyncListener listener, ServletRequest servletRequest, ServletResponse servletResponse) { - request.addAsyncListener(listener,servletRequest,servletResponse); - } - - - public void addAsyncListener(AsyncListener listener) { - request.addAsyncListener(listener); - } - - - public AsyncContext getAsyncContext() { - return request.getAsyncContext(); - } - - public ServletContext getServletContext() { if (request == null) { throw new IllegalStateException( @@ -963,30 +948,46 @@ public class RequestFacade implements HttpServletRequest { } - public boolean isAsyncStarted() { - return request.isAsyncStarted(); + public void startAsync() throws IllegalStateException { + request.startAsync(); } - public boolean isAsyncSupported() { + public void startAsync(Runnable runnable) throws IllegalStateException { + request.startAsync(runnable); + } + + + public boolean isAsyncStarted() { return request.isAsyncStarted(); } - public void setAsyncTimeout(long timeout) { - request.setAsyncTimeout(timeout); + public void doneAsync() throws IllegalStateException { + request.doneAsync(); } + + public boolean isAsyncSupported() { + return request.isAsyncStarted(); + } - public AsyncContext startAsync() throws IllegalStateException { - return request.startAsync(); + + public AsyncDispatcher getAsyncDispatcher() { + return request.getAsyncDispatcher(); } + + public AsyncDispatcher getAsyncDispatcher(String path) { + return request.getAsyncDispatcher(path); + } - public AsyncContext startAsync(ServletRequest servletRequest,ServletResponse servletResponse) throws IllegalStateException { - return request.startAsync(servletRequest, servletResponse); + + public void addAsyncListener(AsyncListener listener, ServletRequest servletRequest, ServletResponse servletResponse) { + request.addAsyncListener(listener,servletRequest,servletResponse); } + public boolean getAllowTrace() { return request.getConnector().getAllowTrace(); } diff --git a/java/org/apache/catalina/core/ApplicationContext.java b/java/org/apache/catalina/core/ApplicationContext.java index 0c0ba2f2c..eb0270065 100644 --- a/java/org/apache/catalina/core/ApplicationContext.java +++ b/java/org/apache/catalina/core/ApplicationContext.java @@ -34,6 +34,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.naming.Binding; import javax.naming.NamingException; import javax.naming.directory.DirContext; +import javax.servlet.AsyncDispatcher; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.Servlet; @@ -44,10 +45,8 @@ import javax.servlet.SessionCookieConfig; import javax.servlet.SessionTrackingMode; import org.apache.catalina.Context; -import org.apache.catalina.Engine; import org.apache.catalina.Host; import org.apache.catalina.Wrapper; -import org.apache.catalina.connector.Connector; import org.apache.catalina.deploy.ApplicationParameter; import org.apache.catalina.deploy.FilterDef; import org.apache.catalina.deploy.FilterMap; @@ -840,8 +839,14 @@ public class ApplicationContext public void addFilter(String filterName, String description, - String className, Map initParameters, - boolean isAsyncSupported) { + String className, Map initParameters) + throws IllegalArgumentException, IllegalStateException { + + if (context.findFilterDef(filterName) != null) { + throw new IllegalArgumentException(sm.getString( + "applicationContext.addFilter.iae", filterName, + getContextPath())); + } if (context.initialized) { //TODO Spec breaking enhancement to ignore this restriction @@ -855,17 +860,53 @@ public class ApplicationContext filterDef.setFilterClass(className); filterDef.getParameterMap().putAll(initParameters); context.addFilterDef(filterDef); - // TODO SERVLET3 - ASync support + } + + + public void addServlet(String servletName, String description, + String className, Map initParameters, + int loadOnStartup) + throws IllegalArgumentException, IllegalStateException { + + if (context.findFilterDef(servletName) != null) { + throw new IllegalArgumentException(sm.getString( + "applicationContext.addServlet.iae", servletName, + getContextPath())); + } + + if (context.initialized) { + //TODO Spec breaking enhancement to ignore this restriction + throw new IllegalStateException( + sm.getString("applicationContext.addServlet.ise", + getContextPath())); + } + Wrapper wrapper = context.createWrapper(); + wrapper.setName(servletName); + // Description is ignored + wrapper.setServletClass(className); + for (Map.Entry initParam : initParameters.entrySet()) { + wrapper.addInitParameter(initParam.getKey(), initParam.getValue()); + } + wrapper.setLoadOnStartup(loadOnStartup); + context.addChild(wrapper); } public void addFilterMappingForServletNames(String filterName, EnumSet dispatcherTypes, boolean isMatchAfter, - String... servletNames) { + String... servletNames) + throws IllegalArgumentException, IllegalStateException { + + if (servletNames == null || servletNames.length == 0) { + throw new IllegalArgumentException(sm.getString( + "applicationContext.addFilterMapping.iae.servlet")); + } + if (context.initialized) { //TODO Spec breaking enhancement to ignore this restriction throw new IllegalStateException(sm.getString( - "applicationContext.addFilterMapping", getContextPath())); + "applicationContext.addFilterMapping.ise", + getContextPath())); } FilterMap filterMap = new FilterMap(); for (String servletName : servletNames) { @@ -885,12 +926,20 @@ public class ApplicationContext public void addFilterMappingForUrlPatterns(String filterName, EnumSet dispatcherTypes, boolean isMatchAfter, - String... urlPatterns) { + String... urlPatterns) + throws IllegalArgumentException, IllegalStateException { + + if (urlPatterns == null || urlPatterns.length == 0) { + throw new IllegalArgumentException(sm.getString( + "applicationContext.addFilterMapping.iae.url", + getContextPath())); + } if (context.initialized) { //TODO Spec breaking enhancement to ignore this restriction throw new IllegalStateException(sm.getString( - "applicationContext.addFilterMapping", getContextPath())); + "applicationContext.addFilterMapping.ise", + getContextPath())); } FilterMap filterMap = new FilterMap(); for (String urlPattern : urlPatterns) { @@ -908,11 +957,17 @@ public class ApplicationContext } - public void addServletMapping(String servletName, String[] urlPatterns) { + public void addServletMapping(String servletName, String[] urlPatterns) + throws IllegalArgumentException, IllegalStateException { + if (urlPatterns == null || urlPatterns.length == 0) { + throw new IllegalArgumentException(sm.getString( + "applicationContext.addServletMapping.iae")); + } + if (context.initialized) { //TODO Spec breaking enhancement to ignore this restriction throw new IllegalStateException(sm.getString( - "applicationContext.addServletMapping", getContextPath())); + "applicationContext.addServletMapping.ise", getContextPath())); } for (String urlPattern : urlPatterns) { boolean jspWildCard = ("*.jsp".equals(urlPattern)); @@ -941,16 +996,7 @@ public class ApplicationContext defaultSessionTrackingModes.add(SessionTrackingMode.COOKIE); } - // Context > Host > Engine > Service - Connector[] connectors = ((Engine) context.getParent().getParent()) - .getService().findConnectors(); - // Need at least one secure connector to use the SSL session ID. - for (Connector connector : connectors) { - if (Boolean.TRUE.equals(connector.getAttribute("secure"))) { - defaultSessionTrackingModes.add(SessionTrackingMode.SSL); - break; - } - } + // SSL not enabled by default as it can only used on its own } /** @@ -970,17 +1016,25 @@ public class ApplicationContext } - public void setSessionCookieConfig(SessionCookieConfig sessionCookieConfig) { + public void setSessionCookieConfig(SessionCookieConfig sessionCookieConfig) + throws IllegalArgumentException { + + if (context.initialized) { + //TODO Spec breaking enhancement to ignore this restriction + throw new IllegalStateException(sm.getString( + "applicationContext.setSessionCookieConfig.ise", + getContextPath())); + } + this.sessionCookieConfig = sessionCookieConfig; } /** * @throws IllegalStateException if the context has already been initialised - * @throws IllegalArgumentException TODO SERVLET3 Something to do with SSL - * but the spec language is not clear - * If an unsupported tracking mode is - * requested + * @throws IllegalArgumentException If SSL is requested in combination with + * anything else or if an unsupported + * tracking mode is requested */ public void setSessionTrackingModes( EnumSet sessionTrackingModes) { @@ -995,16 +1049,29 @@ public class ApplicationContext for (SessionTrackingMode sessionTrackingMode : sessionTrackingModes) { if (!defaultSessionTrackingModes.contains(sessionTrackingMode)) { throw new IllegalArgumentException(sm.getString( - "applicationContext.setSessionTracking.iae", + "applicationContext.setSessionTracking.iae.invalid", sessionTrackingMode.toString(), getContextPath())); } } - // TODO SERVLET3 - The SSL test + + // Check SSL has not be configured with anything else + if (sessionTrackingModes.contains(SessionTrackingMode.SSL)) { + if (sessionTrackingModes.size() > 1) { + throw new IllegalArgumentException(sm.getString( + "applicationContext.setSessionTracking.iae.ssl", + getContextPath())); + } + } this.sessionTrackingModes = sessionTrackingModes; } + public AsyncDispatcher getAsyncDispatcher(String path) { + // TODO SERVLET 3 + return null; + } + // -------------------------------------------------------- Package Methods protected StandardContext getContext() { return this.context; diff --git a/java/org/apache/catalina/core/ApplicationContextFacade.java b/java/org/apache/catalina/core/ApplicationContextFacade.java index aedc9d3f6..0e19938e8 100644 --- a/java/org/apache/catalina/core/ApplicationContextFacade.java +++ b/java/org/apache/catalina/core/ApplicationContextFacade.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import javax.servlet.AsyncDispatcher; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.Servlet; @@ -388,15 +389,13 @@ public final class ApplicationContextFacade public void addFilter(String filterName, String description, - String className, Map initParameters, - boolean isAsyncSupported) { + String className, Map initParameters) { if (SecurityUtil.isPackageProtectionEnabled()) { doPrivileged("addFilter", new Object[]{filterName, description, - className, initParameters, - Boolean.valueOf(isAsyncSupported)}); + className, initParameters}); } else { context.addFilter(filterName, description, className, - initParameters, isAsyncSupported); + initParameters); } } @@ -429,6 +428,19 @@ public final class ApplicationContextFacade } + public void addServlet(String servletName, String description, + String className, Map initParameters, + int loadOnStartup) { + if (SecurityUtil.isPackageProtectionEnabled()) { + doPrivileged("addServlet", new Object[]{servletName, description, + className, initParameters, Integer.valueOf(loadOnStartup)}); + } else { + context.addServlet(servletName, description, className, initParameters, + loadOnStartup); + } + } + + public void addServletMapping(String servletName, String[] urlPatterns) { if (SecurityUtil.isPackageProtectionEnabled()) { doPrivileged("addServletMapping", @@ -490,6 +502,17 @@ public final class ApplicationContextFacade } + public AsyncDispatcher getAsyncDispatcher(String path) { + if (SecurityUtil.isPackageProtectionEnabled()) { + return (AsyncDispatcher) + doPrivileged("getAsyncDispatcher", + new Object[]{path}); + } else { + return context.getAsyncDispatcher(path); + } + } + + /** * Use reflection to invoke the requested method. Cache the method object * to speed up the process diff --git a/java/org/apache/catalina/core/DummyRequest.java b/java/org/apache/catalina/core/DummyRequest.java index 64ba14bc1..a710396d5 100644 --- a/java/org/apache/catalina/core/DummyRequest.java +++ b/java/org/apache/catalina/core/DummyRequest.java @@ -30,7 +30,7 @@ import java.util.Iterator; import java.util.Locale; import java.util.Map; -import javax.servlet.AsyncContext; +import javax.servlet.AsyncDispatcher; import javax.servlet.AsyncListener; import javax.servlet.FilterChain; import javax.servlet.RequestDispatcher; @@ -280,15 +280,13 @@ public class DummyRequest public int getRemotePort() { return -1; } public void addAsyncListener(AsyncListener listener, ServletRequest req, ServletResponse res) {} - public void addAsyncListener(AsyncListener listener) {} - public AsyncContext getAsyncContext() { return null; } public ServletContext getServletContext() { return null; } public boolean isAsyncStarted() { return false; } + public void doneAsync() {} public boolean isAsyncSupported() { return false; } - public void setAsyncTimeout(long timeout) {} - public AsyncContext startAsync() throws IllegalStateException { - return null; } - public AsyncContext startAsync(ServletRequest req, ServletResponse res) - throws IllegalStateException { return null; } + public void startAsync() throws IllegalStateException {} + public void startAsync(Runnable runnable) throws IllegalStateException {} + public AsyncDispatcher getAsyncDispatcher() { return null; } + public AsyncDispatcher getAsyncDispatcher(String path) { return null; } } diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties index 8fd443b8f..d2e57947b 100644 --- a/java/org/apache/catalina/core/LocalStrings.properties +++ b/java/org/apache/catalina/core/LocalStrings.properties @@ -13,16 +13,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -applicationContext.addFilter.ise=Filters can not be added to context {0} at this time. See SRV.4.4. -applicationContext.addFilterMapping.ise=Filter mappings can not be added to context {0} at this time. See SRV.4.4. -applicationContext.addServletMapping.ise=Servlet mappings can not be added to context {0} at this time. See SRV.4.4. +applicationContext.addFilter.iae=The filter name {0} already exists in context {1} +applicationContext.addFilter.ise=Filters can not be added to context {0} as the context has been initialised +applicationContext.addFilterMapping.iae.servlet=The list of servletNames provided was null or empty +applicationContext.addFilterMapping.iae.url=The list of urlPatterns provided was null or empty +applicationContext.addFilterMapping.ise=Filter mappings can not be added to context {0} as the context has been initialised +applicationContext.addServlet.iae=The servlet name {0} already exists in context {1} +applicationContext.addServlet.ise=Servlets can not be added to context {0} as the context has been initialised +applicationContext.addServletMapping.iae=The list of urlPatterns provided was null or empty +applicationContext.addServletMapping.ise=Servlet mappings can not be added to context {0} as the context has been initialised applicationContext.attributeEvent=Exception thrown by attributes event listener applicationContext.mapping.error=Error during mapping applicationContext.requestDispatcher.iae=Path {0} does not start with a "/" character applicationContext.resourcePaths.iae=Path {0} does not start with a "/" character applicationContext.setAttribute.namenull=Name cannot be null +applicationContext.addSessionCookieConfig.ise=Session Cookie configuration cannot be set for context {0} as the context has been initialised applicationContext.setSessionTracking.ise=The session tracking modes for context {0} cannot be set whilst the context is running -applicationContext.setSessionTracking.iae=The session tracking mode {0} requested for context {1} is not supported by that context +applicationContext.setSessionTracking.iae.invalid=The session tracking mode {0} requested for context {1} is not supported by that context +applicationContext.setSessionTracking.iae.ssl=The session tracking modes requested for context {1} included SSL and at least one other mode. SSL may not be configured with other modes. applicationDispatcher.allocateException=Allocate exception for servlet {0} applicationDispatcher.deallocateException=Deallocate exception for servlet {0} applicationDispatcher.forward.ise=Cannot forward after response has been committed diff --git a/java/org/apache/jasper/servlet/JspCServletContext.java b/java/org/apache/jasper/servlet/JspCServletContext.java index 48846fc85..632d7233e 100644 --- a/java/org/apache/jasper/servlet/JspCServletContext.java +++ b/java/org/apache/jasper/servlet/JspCServletContext.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.Set; import java.util.Vector; +import javax.servlet.AsyncDispatcher; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.Servlet; @@ -443,8 +444,7 @@ public class JspCServletContext implements ServletContext { public void addFilter(String filterName, String description, - String className, Map initParameters, - boolean isAsyncSupported) { + String className, Map initParameters) { // Do nothing } @@ -463,6 +463,14 @@ public class JspCServletContext implements ServletContext { } + public void addServlet(String servletName, String description, + String className, Map initParameters, + int loadOnStartup) throws IllegalArgumentException, + IllegalStateException { + // Do nothing + } + + public void addServletMapping(String servletName, String[] urlPatterns) { // Do nothing } @@ -493,4 +501,10 @@ public class JspCServletContext implements ServletContext { // Do nothing } + + public AsyncDispatcher getAsyncDispatcher(String path) { + // Do nothing + return null; + } + } -- 2.11.0