Update Servlet 3.0 classes to spec snapshot as of early March 2009. Still not final.
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Fri, 17 Apr 2009 16:30:56 +0000 (16:30 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Fri, 17 Apr 2009 16:30:56 +0000 (16:30 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@766075 13f79535-47bb-0310-9956-ffa450edef68

17 files changed:
java/javax/servlet/AsyncContext.java [deleted file]
java/javax/servlet/AsyncDispatcher.java [new file with mode: 0644]
java/javax/servlet/AsyncEvent.java
java/javax/servlet/AsyncListener.java
java/javax/servlet/ServletContext.java
java/javax/servlet/ServletRequest.java
java/javax/servlet/ServletRequestWrapper.java
java/javax/servlet/SessionTrackingMode.java
java/javax/servlet/http/HttpServlet.java
java/javax/servlet/http/HttpUtils.java [deleted file]
java/org/apache/catalina/connector/Request.java
java/org/apache/catalina/connector/RequestFacade.java
java/org/apache/catalina/core/ApplicationContext.java
java/org/apache/catalina/core/ApplicationContextFacade.java
java/org/apache/catalina/core/DummyRequest.java
java/org/apache/catalina/core/LocalStrings.properties
java/org/apache/jasper/servlet/JspCServletContext.java

diff --git a/java/javax/servlet/AsyncContext.java b/java/javax/servlet/AsyncContext.java
deleted file mode 100644 (file)
index cf36c69..0000000
+++ /dev/null
@@ -1,33 +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;
-
-/**
- * @since 3.0
- * $Id$
- * TODO SERVLET3
- */
-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);
-}
diff --git a/java/javax/servlet/AsyncDispatcher.java b/java/javax/servlet/AsyncDispatcher.java
new file mode 100644 (file)
index 0000000..e05cf6e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+* 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;
+
+/**
+ * @since 3.0
+ * TODO SERVLET3 - Add comments
+ */
+public interface AsyncDispatcher {
+    void forward(ServletRequest request, ServletResponse response)
+            throws IllegalStateException;
+}
index 1d5d77e..e165291 100644 (file)
@@ -19,7 +19,7 @@ package javax.servlet;
 /**
  * @since 3.0
  * $Id$
- * TODO SERVLET3
+ * TODO SERVLET3 - Add comments
  */
 public class AsyncEvent {
     private ServletRequest request;
index 20ac2ac..f618f4b 100644 (file)
 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;
 }
index d449052..f7f5661 100644 (file)
@@ -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<String,String> 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<String,String> initParameters,
-            boolean isAsyncSupported);
+            String className, Map<String,String> 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<DispatcherType> 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<DispatcherType> 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<SessionTrackingMode> sessionTrackingModes);
+            EnumSet<SessionTrackingMode> sessionTrackingModes)
+            throws IllegalStateException, IllegalArgumentException;
     
     /**
      * 
@@ -724,6 +768,12 @@ public interface ServletContext {
      * @since 3.0
      */
     public EnumSet<SessionTrackingMode> getEffectiveSessionTrackingModes();
+    
+    /**
+     * 
+     * @param path
+     * @return
+     * @since 3.0
+     */
+    public AsyncDispatcher getAsyncDispatcher(String path);
 }
-
-
index 21c486d..a330989 100644 (file)
@@ -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);
 }
 
index ece9ea3..3f0d083 100644 (file)
@@ -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);
-    }
-
 }
 
index fcb49af..878d462 100644 (file)
@@ -22,6 +22,6 @@ package javax.servlet;
  */
 public enum SessionTrackingMode {
     COOKIE,
-    URL,
-    SSL
+    SSL,
+    URL
 }
index c3db362..96f699e 100644 (file)
@@ -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 (file)
index 9ce22de..0000000
+++ /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 <code>HttpUtils</code> object.
-     *
-     */
-    public HttpUtils() {
-        // NOOP
-    }
-
-
-    /**
-     *
-     * Parses a query string passed from the client to the
-     * server and builds a <code>HashTable</code> 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 <i>key=value</i>,
-     * with each pair separated from the next by a &amp; character.
-     *
-     * <p>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.
-     * 
-     * <p>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 <i>%xx</i>) are
-     * converted to ASCII characters.
-     *
-     * @param s                a string containing the query to be parsed
-     *
-     * @return                a <code>HashTable</code> object built
-     *                         from the parsed key-value pairs
-     *
-     * @exception IllegalArgumentException        if the query string 
-     *                                                is invalid
-     *
-     */
-    static public Hashtable<String,String[]> parseQueryString(String s) {
-
-        String valArray[] = null;
-        
-        if (s == null) {
-            throw new IllegalArgumentException();
-        }
-        Hashtable<String,String[]> ht = new Hashtable<String,String[]>();
-        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 
-     * <i>application/x-www-form-urlencoded</i> MIME type.
-     *
-     * <p>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.
-     *
-     * <p>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 <i>%xx</i>) are
-     * converted to ASCII characters.
-     *
-     *
-     *
-     * @param len        an integer specifying the length,
-     *                        in characters, of the 
-     *                        <code>ServletInputStream</code>
-     *                        object that is also passed to this
-     *                        method
-     *
-     * @param in        the <code>ServletInputStream</code>
-     *                        object that contains the data sent
-     *                        from the client
-     * 
-     * @return                a <code>HashTable</code> object built
-     *                        from the parsed key-value pairs
-     *
-     *
-     * @exception IllegalArgumentException        if the data
-     *                        sent by the POST method is invalid
-     *
-     */
-    static public Hashtable<String,String[]> 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<String,String[]>();
-
-        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 <code>HttpServletRequest</code> object.
-     * The returned URL contains a protocol, server name, port
-     * number, and server path, but it does not include query
-     * string parameters.
-     * 
-     * <p>Because this method returns a <code>StringBuffer</code>,
-     * not a string, you can modify the URL easily, for example,
-     * to append query parameters.
-     *
-     * <p>This method is useful for creating redirect messages
-     * and for reporting errors.
-     *
-     * @param req        a <code>HttpServletRequest</code> object
-     *                        containing the client's request
-     * 
-     * @return                a <code>StringBuffer</code> 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;
-    }
-}
-
-
-
index 4981cce..ce572f2 100644 (file)
@@ -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;
     }
-    
+
 }
index f65c531..7485f3b 100644 (file)
@@ -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();
     }
index 0c0ba2f..eb02700 100644 (file)
@@ -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<String, String> initParameters,
-            boolean isAsyncSupported) {
+            String className, Map<String, String> 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<String, String> 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<String,String> initParam : initParameters.entrySet()) {
+            wrapper.addInitParameter(initParam.getKey(), initParam.getValue());
+        }
+        wrapper.setLoadOnStartup(loadOnStartup);
+        context.addChild(wrapper);
     }
 
 
     public void addFilterMappingForServletNames(String filterName,
             EnumSet<DispatcherType> 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<DispatcherType> 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<SessionTrackingMode> 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;
index aedc9d3..0e19938 100644 (file)
@@ -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<String, String> initParameters,
-            boolean isAsyncSupported) {
+            String className, Map<String, String> 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<String, String> 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
index 64ba14b..a710396 100644 (file)
@@ -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; }
 }
 
index 8fd443b..d2e5794 100644 (file)
 # 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
index 48846fc..632d723 100644 (file)
@@ -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<String, String> initParameters,
-            boolean isAsyncSupported) {
+            String className, Map<String, String> initParameters) {
         // Do nothing
     }
 
@@ -463,6 +463,14 @@ public class JspCServletContext implements ServletContext {
     }
 
 
+    public void addServlet(String servletName, String description,
+            String className, Map<String, String> 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;
+    }
+
 }