You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by cr...@apache.org on 2001/08/01 05:04:05 UTC

cvs commit: jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core ApplicationDispatcher.java

craigmcc    01/07/31 20:04:05

  Modified:    catalina/src/share/org/apache/catalina HttpRequest.java
                        InstanceEvent.java Request.java
               catalina/src/share/org/apache/catalina/authenticator
                        AuthenticatorBase.java BasicAuthenticator.java
                        Constants.java DigestAuthenticator.java
                        FormAuthenticator.java SSLAuthenticator.java
                        SingleSignOn.java
               catalina/src/share/org/apache/catalina/connector
                        HttpRequestBase.java RequestBase.java
               catalina/src/share/org/apache/catalina/core
                        ApplicationDispatcher.java
  Log:
  Omnibus changes to clean up interactions with J2EE RI's security model.
  
  Request/RequestBase - Implement a "notes" capability like that recently added
  for sessions.
  
  HttpRequest/HttpRequestBase - Remove the "ssoId" property, which was used to
  track the "single sign on" identity (if any) for this request.  This value
  is now passed as a note.
  
  InstanceEvent/ApplicationDispatcher - Send "before dispatch" and "after
  dispatch" events around the service() call of a dispatched-to servlet, so
  "run as" identity lookups look in the correct place.
  
  org.apache.catalina.authenticator.* - Several changes
  - Pass the username and password used to authenticate the user (if any)
    as request notes so that the EJB layer can access them
  - Register the username and password with SingleSignOnValve as needed
  
  Revision  Changes    Path
  1.4       +4 -18     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/HttpRequest.java
  
  Index: HttpRequest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/HttpRequest.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- HttpRequest.java	2001/07/29 03:43:54	1.3
  +++ HttpRequest.java	2001/08/01 03:04:04	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/HttpRequest.java,v 1.3 2001/07/29 03:43:54 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2001/07/29 03:43:54 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/HttpRequest.java,v 1.4 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.4 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -76,7 +76,7 @@
    * produce the corresponding <code>HttpResponse</code>.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.3 $ $Date: 2001/07/29 03:43:54 $
  + * @version $Revision: 1.4 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public interface HttpRequest extends Request {
  @@ -147,12 +147,6 @@
   
   
       /**
  -     * Return the single sign on identifier this request is associated with.
  -     */
  -    public String getSsoId();
  -
  -
  -    /**
        * Set the authentication type used for this request, if any; otherwise
        * set the type to <code>null</code>.  Typical values are "BASIC",
        * "DIGEST", or "SSL".
  @@ -245,14 +239,6 @@
        * @param path The servlet path
        */
       public void setServletPath(String path);
  -
  -
  -    /**
  -     * Set the single sign on identifier this request is associated with.
  -     *
  -     * @param ssoId The new SSO identifier (if any)
  -     */
  -    public void setSsoId(String ssoId);
   
   
       /**
  
  
  
  1.6       +42 -8     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/InstanceEvent.java
  
  Index: InstanceEvent.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/InstanceEvent.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- InstanceEvent.java	2001/07/30 20:35:49	1.5
  +++ InstanceEvent.java	2001/08/01 03:04:04	1.6
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/InstanceEvent.java,v 1.5 2001/07/30 20:35:49 craigmcc Exp $
  - * $Revision: 1.5 $
  - * $Date: 2001/07/30 20:35:49 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/InstanceEvent.java,v 1.6 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.6 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -78,7 +78,7 @@
    * as opposed to the Wrapper component that manages it.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.5 $ $Date: 2001/07/30 20:35:49 $
  + * @version $Revision: 1.6 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public final class InstanceEvent
  @@ -103,14 +103,20 @@
   
       /**
        * The event indicating that the <code>service()</code> method is about
  -     * to be called for this instance.
  +     * to be called on a servlet.  The <code>servlet</code> property contains
  +     * the servlet being called, and the <code>request</code> and
  +     * <code>response</code> properties contain the current request and
  +     * response being processed.
        */
       public static final String BEFORE_SERVICE_EVENT = "beforeService";
   
   
       /**
        * The event indicating that the <code>service()</code> method has
  -     * returned.
  +     * returned.  The <code>servlet</code> property contains the servlet
  +     * that was called, and the <code>request</code> and
  +     * <code>response</code> properties contain the current request and
  +     * response being processed.
        */
       public static final String AFTER_SERVICE_EVENT = "afterService";
   
  @@ -130,9 +136,35 @@
   
   
       /**
  +     * The event indicating that the <code>service()</code> method of a
  +     * servlet accessed via a request dispatcher is about to be called.
  +     * The <code>servlet</code> property contains a reference to the
  +     * dispatched-to servlet instance, and the <code>request</code> and
  +     * <code>response</code> properties contain the current request and
  +     * response being processed.  The <code>wrapper</code> property will
  +     * contain a reference to the dispatched-to Wrapper.
  +     */
  +    public static final String BEFORE_DISPATCH_EVENT = "beforeDispatch";
  +
  +
  +    /**
  +     * The event indicating that the <code>service()</code> method of a
  +     * servlet accessed via a request dispatcher has returned.  The
  +     * <code>servlet</code> property contains a reference to the
  +     * dispatched-to servlet instance, and the <code>request</code> and
  +     * <code>response</code> properties contain the current request and
  +     * response being processed.  The <code>wrapper</code> property will
  +     * contain a reference to the dispatched-to Wrapper.
  +     */
  +    public static final String AFTER_DISPATCH_EVENT = "afterDispatch";
  +
  +
  +    /**
        * The event indicating that the <code>doFilter()</code> method of a
        * Filter is about to be called.  The <code>filter</code> property
  -     * contains a reference to the relevant filter instance.
  +     * contains a reference to the relevant filter instance, and the
  +     * <code>request</code> and <code>response</code> properties contain
  +     * the current request and response being processed.
        */
       public static final String BEFORE_FILTER_EVENT = "beforeFilter";
   
  @@ -140,7 +172,9 @@
       /**
        * The event indicating that the <code>doFilter()</code> method of a
        * Filter has returned.  The <code>filter</code> property contains
  -     * a reference to the relevant filter instance.
  +     * a reference to the relevant filter instance, and the
  +     * <code>request</code> and <code>response</code> properties contain
  +     * the current request and response being processed.
        */
       public static final String AFTER_FILTER_EVENT = "afterFilter";
   
  
  
  
  1.5       +40 -4     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Request.java
  
  Index: Request.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Request.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Request.java	2001/07/22 20:13:30	1.4
  +++ Request.java	2001/08/01 03:04:04	1.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Request.java,v 1.4 2001/07/22 20:13:30 pier Exp $
  - * $Revision: 1.4 $
  - * $Date: 2001/07/22 20:13:30 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Request.java,v 1.5 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.5 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -68,6 +68,7 @@
   import java.io.InputStream;
   import java.io.IOException;
   import java.net.Socket;
  +import java.util.Iterator;
   import javax.servlet.ServletException;
   import javax.servlet.ServletInputStream;
   import javax.servlet.ServletRequest;
  @@ -79,7 +80,7 @@
    * produce the corresponding <code>Response</code>.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.4 $ $Date: 2001/07/22 20:13:30 $
  + * @version $Revision: 1.5 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public interface Request {
  @@ -231,6 +232,22 @@
   
   
       /**
  +     * Return the object bound with the specified name to the internal notes
  +     * for this request, or <code>null</code> if no such binding exists.
  +     *
  +     * @param name Name of the note to be returned
  +     */
  +    public Object getNote(String name);
  +
  +
  +    /**
  +     * Return an Iterator containing the String names of all notes bindings
  +     * that exist for this request.
  +     */
  +    public Iterator getNoteNames();
  +
  +
  +    /**
        * Release all object references, and initialize instance variables, in
        * preparation for reuse of this object.
        */
  @@ -238,6 +255,15 @@
   
   
       /**
  +     * Remove any object bound to the specified name in the internal notes
  +     * for this request.
  +     *
  +     * @param name Name of the note to be removed
  +     */
  +    public void removeNote(String name);
  +
  +
  +    /**
        * Set the content length associated with this Request.
        *
        * @param length The new content length
  @@ -253,6 +279,16 @@
        * @param type The new content type
        */
       public void setContentType(String type);
  +
  +
  +    /**
  +     * Bind an object to a specified name in the internal notes associated
  +     * with this request, replacing any existing binding for this name.
  +     *
  +     * @param name Name to which the object should be bound
  +     * @param value Object to be bound to the specified name
  +     */
  +    public void setNote(String name, Object value);
   
   
       /**
  
  
  
  1.22      +27 -8     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java
  
  Index: AuthenticatorBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- AuthenticatorBase.java	2001/07/31 02:00:02	1.21
  +++ AuthenticatorBase.java	2001/08/01 03:04:04	1.22
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v 1.21 2001/07/31 02:00:02 craigmcc Exp $
  - * $Revision: 1.21 $
  - * $Date: 2001/07/31 02:00:02 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v 1.22 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.22 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -121,7 +121,7 @@
    * requests.  Requests of any other type will simply be passed through.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.21 $ $Date: 2001/07/31 02:00:02 $
  + * @version $Revision: 1.22 $ $Date: 2001/08/01 03:04:04 $
    */
   
   
  @@ -951,9 +951,12 @@
        * @param response The servlet response we are generating
        * @param principal The authenticated Principal to be registered
        * @param authType The authentication type to be registered
  +     * @param username Username used to authenticate (if any)
  +     * @param password Password used to authenticate (if any)
        */
       protected void register(HttpRequest request, HttpResponse response,
  -                            Principal principal, String authType) {
  +                            Principal principal, String authType,
  +                            String username, String password) {
   
           if (debug >= 1)
               log("Authenticated '" + principal.getName() + "' with type '"
  @@ -962,13 +965,29 @@
           // Cache the authentication information in our request
           request.setAuthType(authType);
           request.setUserPrincipal(principal);
  +        if (username != null)
  +            request.setNote(Constants.REQ_USERNAME_NOTE, username);
  +        else
  +            request.removeNote(Constants.REQ_USERNAME_NOTE);
  +        if (password != null)
  +            request.setNote(Constants.REQ_PASSWORD_NOTE, password);
  +        else
  +            request.removeNote(Constants.REQ_PASSWORD_NOTE);
   
           // Cache the authentication information in our session, if any
           if (cache) {
  -            Session session = getSession((HttpRequest) request);
  +            Session session = getSession(request, false);
               if (session != null) {
                   session.setAuthType(authType);
                   session.setPrincipal(principal);
  +                if (username != null)
  +                    session.setNote(Constants.SESS_USERNAME_NOTE, username);
  +                else
  +                    session.removeNote(Constants.SESS_USERNAME_NOTE);
  +                if (password != null)
  +                    session.setNote(Constants.SESS_PASSWORD_NOTE, password);
  +                else
  +                    session.removeNote(Constants.SESS_PASSWORD_NOTE);
               }
           }
   
  @@ -986,8 +1005,8 @@
           hres.addCookie(cookie);
   
           // Register this principal with our SSO valve
  -        sso.register(value, principal, authType);
  -        request.setSsoId(value);
  +        sso.register(value, principal, authType, username, password);
  +        request.setNote(Constants.REQ_SSOID_NOTE, value);
   
       }
   
  
  
  
  1.10      +43 -20    jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java
  
  Index: BasicAuthenticator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- BasicAuthenticator.java	2001/07/22 20:09:19	1.9
  +++ BasicAuthenticator.java	2001/08/01 03:04:04	1.10
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java,v 1.9 2001/07/22 20:09:19 pier Exp $
  - * $Revision: 1.9 $
  - * $Date: 2001/07/22 20:09:19 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java,v 1.10 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.10 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -84,7 +84,7 @@
    * and Digest Access Authentication."
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.9 $ $Date: 2001/07/22 20:09:19 $
  + * @version $Revision: 1.10 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public final class BasicAuthenticator
  @@ -156,12 +156,13 @@
           HttpServletResponse hres =
               (HttpServletResponse) response.getResponse();
           String authorization = request.getAuthorization();
  -        if (authorization != null) {
  -            principal = findPrincipal(authorization, context.getRealm());
  -            if (principal != null) {
  -                register(request, response, principal, Constants.BASIC_METHOD);
  -                return (true);
  -            }
  +        String username = parseUsername(authorization);
  +        String password = parsePassword(authorization);
  +        principal = context.getRealm().authenticate(username, password);
  +        if (principal != null) {
  +            register(request, response, principal, Constants.BASIC_METHOD,
  +                     username, password);
  +            return (true);
           }
   
           // Send an "unauthorized" response and an appropriate challenge
  @@ -183,17 +184,13 @@
   
   
       /**
  -     * Parse the specified authorization credentials, and return the
  -     * associated Principal that these credentials authenticate (if any)
  -     * from the specified Realm.  If there is no such Principal, return
  -     * <code>null</code>.
  +     * Parse the username from the specified authorization credentials.
  +     * If none can be found, return <code>null</code>.
        *
        * @param authorization Authorization credentials from this request
  -     * @param realm Realm used to authenticate Principals
        */
  -    private static Principal findPrincipal(String authorization, Realm realm) {
  +    private String parseUsername(String authorization) {
   
  -        // Validate the authorization credentials format
           if (authorization == null)
               return (null);
           if (!authorization.startsWith("Basic "))
  @@ -207,12 +204,38 @@
           if (colon < 0)
               return (null);
           String username = unencoded.substring(0, colon).trim();
  -        String password = unencoded.substring(colon + 1).trim();
  +        //        String password = unencoded.substring(colon + 1).trim();
  +        return (username);
   
  -        // Validate these credentials in our associated realm
  -        return (realm.authenticate(username, password));
  +    }
   
  +
  +    /**
  +     * Parse the password from the specified authorization credentials.
  +     * If none can be found, return <code>null</code>.
  +     *
  +     * @param authorization Authorization credentials from this request
  +     */
  +    private String parsePassword(String authorization) {
  +
  +        if (authorization == null)
  +            return (null);
  +        if (!authorization.startsWith("Basic "))
  +            return (null);
  +        authorization = authorization.substring(6).trim();
  +
  +        // Decode and parse the authorization credentials
  +        String unencoded =
  +          new String(base64Helper.decode(authorization.getBytes()));
  +        int colon = unencoded.indexOf(':');
  +        if (colon < 0)
  +            return (null);
  +        //        String username = unencoded.substring(0, colon).trim();
  +        String password = unencoded.substring(colon + 1).trim();
  +        return (password);
  +
       }
  +
   
   
   }
  
  
  
  1.7       +95 -11    jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/Constants.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Constants.java	2001/07/31 02:00:02	1.6
  +++ Constants.java	2001/08/01 03:04:04	1.7
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/Constants.java,v 1.6 2001/07/31 02:00:02 craigmcc Exp $
  - * $Revision: 1.6 $
  - * $Date: 2001/07/31 02:00:02 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/Constants.java,v 1.7 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.7 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -83,18 +83,102 @@
       // Form based authentication constants
       public static final String FORM_ACTION = "/j_security_check";
       public static final String FORM_PASSWORD = "j_password";
  -    public static final String FORM_PASSWORD_NOTE =
  -        "org.apache.catalina.authenticator.PASSWORD";
  +    public static final String FORM_USERNAME = "j_username";
  +
  +    // Cookie name for single sign on support
  +    public static final String SINGLE_SIGN_ON_COOKIE = "JSESSIONIDSSO";
  +
  +
  +    // --------------------------------------------------------- Request Notes
  +
  +
  +    /**
  +     * <p>If a user has been authenticated by the web layer, by means of a
  +     * login method other than CLIENT_CERT, the username and password
  +     * used to authenticate the user will be attached to the request as
  +     * Notes for use by other server components.  A server component can
  +     * also call several existing methods on Request to determine whether
  +     * or not any user has been authenticated:</p>
  +     * <ul>
  +     * <li><strong>((HttpServletRequest) getRequest()).getAuthType()</strong>
  +     *     will return BASIC, CLIENT-CERT, DIGEST, FORM, or <code>null</code>
  +     *     if there is no authenticated user.</li>
  +     * <li><strong>((HttpServletRequest) getRequest()).getUserPrincipal()</strong>
  +     *     will return the authenticated <code>Principal</code> returned by the
  +     *     <code>Realm</code> that authenticated this user.</li>
  +     * </ul>
  +     * <p>If CLIENT_CERT authentication was performed, the certificate chain
  +     * will be available as a request attribute, as defined in the
  +     * servlet specification.</p>
  +     */
  +
  +
  +    /**
  +     * The notes key for the password used to authenticate this user.
  +     */
  +    public static final String REQ_PASSWORD_NOTE =
  +      "org.apache.catalina.request.PASSWORD";
  +
  +
  +    /**
  +     * The notes key for the username used to authenticate this user.
  +     */
  +    public static final String REQ_USERNAME_NOTE =
  +      "org.apache.catalina.request.USERNAME";
  +
  +
  +    /**
  +     * The notes key to track the single-sign-on identity with which this
  +     * request is associated.
  +     */
  +    public static final String REQ_SSOID_NOTE =
  +      "org.apache.catalina.request.SSOID";
  +
  +
  +    // ---------------------------------------------------------- Session Notes
  +
  +
  +    /**
  +     * If the <code>cache</code> property of our authenticator is set, and
  +     * the current request is part of a session, authentication information
  +     * will be cached to avoid the need for repeated calls to
  +     * <code>Realm.authenticate()</code>, under the following keys:
  +     */
  +
  +
  +    /**
  +     * The notes key for the password used to authenticate this user.
  +     */
  +    public static final String SESS_PASSWORD_NOTE =
  +      "org.apache.catalina.session.PASSWORD";
  +
  +
  +    /**
  +     * The notes key for the username used to authenticate this user.
  +     */
  +    public static final String SESS_USERNAME_NOTE =
  +      "org.apache.catalina.session.USERNAME";
  +
  +
  +    /**
  +     * The following note keys are used during form login processing to
  +     * cache required information prior to the completion of authentication.
  +     */
  +
  +
  +    /**
  +     * The previously authenticated principal (if caching is disabled).
  +     */
       public static final String FORM_PRINCIPAL_NOTE =
           "org.apache.catalina.authenticator.PRINCIPAL";
  +
  +
  +    /**
  +     * The original request information, to which the user will be
  +     * redirected if authentication succeeds.
  +     */
       public static final String FORM_REQUEST_NOTE =
           "org.apache.catalina.authenticator.REQUEST";
  -    public static final String FORM_USERNAME = "j_username";
  -    public static final String FORM_USERNAME_NOTE =
  -        "org.apache.catailna.authenticator.USERNAME";
   
  -    // Cookie name for single sign on support
  -    public static final String SINGLE_SIGN_ON_COOKIE = "JSESSIONIDSSO";
   
   }
  -
  
  
  
  1.9       +44 -5     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/DigestAuthenticator.java
  
  Index: DigestAuthenticator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/DigestAuthenticator.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- DigestAuthenticator.java	2001/07/22 20:09:19	1.8
  +++ DigestAuthenticator.java	2001/08/01 03:04:04	1.9
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/DigestAuthenticator.java,v 1.8 2001/07/22 20:09:19 pier Exp $
  - * $Revision: 1.8 $
  - * $Date: 2001/07/22 20:09:19 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/DigestAuthenticator.java,v 1.9 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.9 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -88,7 +88,7 @@
    *
    * @author Craig R. McClanahan
    * @author Remy Maucherat
  - * @version $Revision: 1.8 $ $Date: 2001/07/22 20:09:19 $
  + * @version $Revision: 1.9 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public final class DigestAuthenticator
  @@ -230,8 +230,10 @@
           if (authorization != null) {
               principal = findPrincipal(hreq, authorization, context.getRealm());
               if (principal != null) {
  +                String username = parseUsername(authorization);
                   register(request, response, principal,
  -                         Constants.DIGEST_METHOD);
  +                         Constants.DIGEST_METHOD,
  +                         username, null);
                   return (true);
               }
           }
  @@ -331,6 +333,43 @@
   
           return (realm.authenticate(userName, response, nOnce, nc, cnonce, qop,
                                      realmName, md5a2));
  +
  +    }
  +
  +
  +    /**
  +     * Parse the username from the specified authorization string.  If none
  +     * can be identified, return <code>null</code>
  +     *
  +     * @param authorization Authorization string to be parsed
  +     */
  +    private String parseUsername(String authorization) {
  +
  +        //System.out.println("Authorization token : " + authorization);
  +        // Validate the authorization credentials format
  +        if (authorization == null)
  +            return (null);
  +        if (!authorization.startsWith("Digest "))
  +            return (null);
  +        authorization = authorization.substring(7).trim();
  +
  +        StringTokenizer commaTokenizer =
  +            new StringTokenizer(authorization, ",");
  +
  +        while (commaTokenizer.hasMoreTokens()) {
  +            String currentToken = commaTokenizer.nextToken();
  +            int equalSign = currentToken.indexOf('=');
  +            if (equalSign < 0)
  +                return null;
  +            String currentTokenName =
  +                currentToken.substring(0, equalSign).trim();
  +            String currentTokenValue =
  +                currentToken.substring(equalSign + 1).trim();
  +            if ("username".equals(currentTokenName))
  +                return (removeQuotes(currentTokenValue));
  +        }
  +
  +        return (null);
   
       }
   
  
  
  
  1.16      +15 -12    jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java
  
  Index: FormAuthenticator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- FormAuthenticator.java	2001/07/31 02:00:02	1.15
  +++ FormAuthenticator.java	2001/08/01 03:04:04	1.16
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v 1.15 2001/07/31 02:00:02 craigmcc Exp $
  - * $Revision: 1.15 $
  - * $Date: 2001/07/31 02:00:02 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v 1.16 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.16 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -88,7 +88,7 @@
    * Authentication, as described in the Servlet API Specification, Version 2.2.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.15 $ $Date: 2001/07/31 02:00:02 $
  + * @version $Revision: 1.16 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public final class FormAuthenticator
  @@ -152,7 +152,7 @@
               if (debug >= 1)
                   log("Already authenticated '" +
                       principal.getName() + "'");
  -            String ssoId = request.getSsoId();
  +            String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
               if (ssoId != null)
                   associate(ssoId, getSession(request, true));
               return (true);
  @@ -164,9 +164,9 @@
               if (debug >= 1)
                   log("Checking for reauthenticate in session " + session);
               String username =
  -                (String) session.getNote(Constants.FORM_USERNAME_NOTE);
  +                (String) session.getNote(Constants.SESS_USERNAME_NOTE);
               String password =
  -                (String) session.getNote(Constants.FORM_PASSWORD_NOTE);
  +                (String) session.getNote(Constants.SESS_PASSWORD_NOTE);
               if ((username != null) && (password != null)) {
                   if (debug >= 1)
                       log("Reauthenticating username '" + username + "'");
  @@ -175,7 +175,8 @@
                   if (principal != null) {
                       session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
                       register(request, response, principal,
  -                             Constants.FORM_METHOD);
  +                             Constants.FORM_METHOD,
  +                             username, password);
                       return (true);
                   }
                   if (debug >= 1)
  @@ -191,8 +192,10 @@
                   log("Restore request from session '" + session.getId() + "'");
               principal = (Principal)
                   session.getNote(Constants.FORM_PRINCIPAL_NOTE);
  -            register(request, response, principal, Constants.FORM_METHOD);
  -            String ssoId = request.getSsoId();
  +            register(request, response, principal, Constants.FORM_METHOD,
  +                     (String) session.getNote(Constants.SESS_USERNAME_NOTE),
  +                     (String) session.getNote(Constants.SESS_PASSWORD_NOTE));
  +            String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
               if (ssoId != null)
                   associate(ssoId, session);
               if (restoreRequest(request, session)) {
  @@ -274,8 +277,8 @@
   
           // If we are not caching, save the username and password as well
           if (!cache) {
  -            session.setNote(Constants.FORM_USERNAME_NOTE, username);
  -            session.setNote(Constants.FORM_PASSWORD_NOTE, password);
  +            session.setNote(Constants.SESS_USERNAME_NOTE, username);
  +            session.setNote(Constants.SESS_PASSWORD_NOTE, password);
           }
   
           // Redirect the user to the original request URI (which will cause
  
  
  
  1.9       +6 -5      jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java
  
  Index: SSLAuthenticator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- SSLAuthenticator.java	2001/07/30 20:04:04	1.8
  +++ SSLAuthenticator.java	2001/08/01 03:04:04	1.9
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java,v 1.8 2001/07/30 20:04:04 craigmcc Exp $
  - * $Revision: 1.8 $
  - * $Date: 2001/07/30 20:04:04 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java,v 1.9 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.9 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -86,7 +86,7 @@
    * that utilizes SSL certificates to identify client users.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.8 $ $Date: 2001/07/30 20:04:04 $
  + * @version $Revision: 1.9 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public final class SSLAuthenticator
  @@ -169,7 +169,8 @@
           }
   
           // Cache the principal (if requested) and record this authentication
  -        register(request, response, principal, Constants.CERT_METHOD);
  +        register(request, response, principal, Constants.CERT_METHOD,
  +                 null, null);
           return (true);
   
       }
  
  
  
  1.8       +28 -9     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java
  
  Index: SingleSignOn.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- SingleSignOn.java	2001/07/29 03:43:54	1.7
  +++ SingleSignOn.java	2001/08/01 03:04:04	1.8
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java,v 1.7 2001/07/29 03:43:54 craigmcc Exp $
  - * $Revision: 1.7 $
  - * $Date: 2001/07/29 03:43:54 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java,v 1.8 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.8 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -109,7 +109,7 @@
    * </ul>
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.7 $ $Date: 2001/07/29 03:43:54 $
  + * @version $Revision: 1.8 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public class SingleSignOn
  @@ -336,7 +336,7 @@
               (HttpServletRequest) request.getRequest();
           HttpServletResponse hres =
               (HttpServletResponse) response.getResponse();
  -        ((HttpRequest) request).setSsoId(null);
  +        request.removeNote(Constants.REQ_SSOID_NOTE);
   
           // Has a valid user already been authenticated?
           if (debug >= 1)
  @@ -378,9 +378,17 @@
                   log(" Found cached principal '" +
                       entry.principal.getName() + "' with auth type '" +
                       entry.authType + "'");
  -            ((HttpRequest) request).setSsoId(cookie.getValue());
  +            request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue());
               ((HttpRequest) request).setAuthType(entry.authType);
               ((HttpRequest) request).setUserPrincipal(entry.principal);
  +            if (entry.username != null)
  +                request.setNote(Constants.REQ_USERNAME_NOTE, entry.username);
  +            else
  +                request.removeNote(Constants.REQ_USERNAME_NOTE);
  +            if (entry.password != null)
  +                request.setNote(Constants.REQ_PASSWORD_NOTE, entry.password);
  +            else
  +                request.removeNote(Constants.REQ_PASSWORD_NOTE);
           } else {
               if (debug >= 1)
                   log(" No cached principal found, erasing SSO cookie");
  @@ -482,15 +490,19 @@
        * @param principal Associated user principal that is identified
        * @param authType Authentication type used to authenticate this
        *  user principal
  +     * @param username Username used to authenticate this user
  +     * @param password Password used to authenticate this user
        */
  -    void register(String ssoId, Principal principal, String authType) {
  +    void register(String ssoId, Principal principal, String authType,
  +                  String username, String password) {
   
           if (debug >= 1)
               log("Registering sso id '" + ssoId + "' for user '" +
                   principal.getName() + "' with auth type '" + authType + "'");
   
           synchronized (cache) {
  -            cache.put(ssoId, new SingleSignOnEntry(principal, authType));
  +            cache.put(ssoId, new SingleSignOnEntry(principal, authType,
  +                                                   username, password));
           }
   
       }
  @@ -562,14 +574,21 @@
   
       public String authType = null;
   
  +    public String password = null;
  +
       public Principal principal = null;
   
       public Session sessions[] = new Session[0];
  +
  +    public String username = null;
   
  -    public SingleSignOnEntry(Principal principal, String authType) {
  +    public SingleSignOnEntry(Principal principal, String authType,
  +                             String username, String password) {
           super();
           this.principal = principal;
           this.authType = authType;
  +        this.username = username;
  +        this.password = password;
       }
   
       public synchronized void addSession(SingleSignOn sso, Session session) {
  
  
  
  1.29      +4 -33     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpRequestBase.java
  
  Index: HttpRequestBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpRequestBase.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- HttpRequestBase.java	2001/07/29 03:43:54	1.28
  +++ HttpRequestBase.java	2001/08/01 03:04:04	1.29
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpRequestBase.java,v 1.28 2001/07/29 03:43:54 craigmcc Exp $
  - * $Revision: 1.28 $
  - * $Date: 2001/07/29 03:43:54 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpRequestBase.java,v 1.29 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.29 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -101,7 +101,7 @@
    * be implemented.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.28 $ $Date: 2001/07/29 03:43:54 $
  + * @version $Revision: 1.29 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public class HttpRequestBase
  @@ -265,12 +265,6 @@
   
   
       /**
  -     * The single sign on identifier with which this request is associated.
  -     */
  -    protected String ssoId = null;
  -
  -
  -    /**
        * The Principal who has been authenticated for this Request.
        */
       protected Principal userPrincipal = null;
  @@ -302,28 +296,6 @@
       }
   
   
  -    /**
  -     * Return the single sign on identifier this request is associated with.
  -     */
  -    public String getSsoId() {
  -
  -        return (ssoId);
  -
  -    }
  -
  -
  -    /**
  -     * Set the single sign on identifier this request is associated with.
  -     *
  -     * @param ssoId The new SSO identifier (if any)
  -     */
  -    public void setSsoId(String ssoId) {
  -
  -        this.ssoId = ssoId;
  -
  -    }
  -
  -
       // --------------------------------------------------------- Public Methods
   
   
  @@ -452,7 +424,6 @@
           secure = false;
           servletPath = null;
           session = null;
  -        ssoId = null;
           userPrincipal = null;
   
       }
  
  
  
  1.17      +72 -4     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/RequestBase.java
  
  Index: RequestBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/RequestBase.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- RequestBase.java	2001/07/25 04:27:29	1.16
  +++ RequestBase.java	2001/08/01 03:04:04	1.17
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/RequestBase.java,v 1.16 2001/07/25 04:27:29 remm Exp $
  - * $Revision: 1.16 $
  - * $Date: 2001/07/25 04:27:29 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/RequestBase.java,v 1.17 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.17 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -75,6 +75,7 @@
   import java.util.ArrayList;
   import java.util.Enumeration;
   import java.util.HashMap;
  +import java.util.Iterator;
   import java.util.Locale;
   import java.util.Map;
   import javax.servlet.RequestDispatcher;
  @@ -98,7 +99,7 @@
    * the connector-specific methods need to be implemented.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.16 $ $Date: 2001/07/25 04:27:29 $
  + * @version $Revision: 1.17 $ $Date: 2001/08/01 03:04:04 $
    */
   
   public abstract class RequestBase
  @@ -182,6 +183,13 @@
   
   
       /**
  +     * Internal notes associated with this request by Catalina components
  +     * and event listeners.
  +     */
  +    private transient HashMap notes = new HashMap();
  +
  +
  +    /**
        * The protocol name and version associated with this Request.
        */
       protected String protocol = null;
  @@ -515,6 +523,34 @@
   
   
       /**
  +     * Return the object bound with the specified name to the internal notes
  +     * for this request, or <code>null</code> if no such binding exists.
  +     *
  +     * @param name Name of the note to be returned
  +     */
  +    public Object getNote(String name) {
  +
  +        synchronized (notes) {
  +            return (notes.get(name));
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Return an Iterator containing the String names of all notes bindings
  +     * that exist for this request.
  +     */
  +    public Iterator getNoteNames() {
  +
  +        synchronized (notes) {
  +            return (notes.keySet().iterator());
  +        }
  +
  +    }
  +
  +
  +    /**
        * Release all object references, and initialize instance variables, in
        * preparation for reuse of this object.
        */
  @@ -529,6 +565,7 @@
           context = null;
           input = null;
           locales.clear();
  +        notes.clear();
           protocol = null;
           reader = null;
           remoteAddr = null;
  @@ -546,6 +583,21 @@
   
   
       /**
  +     * Remove any object bound to the specified name in the internal notes
  +     * for this request.
  +     *
  +     * @param name Name of the note to be removed
  +     */
  +    public void removeNote(String name) {
  +
  +        synchronized (notes) {
  +            notes.remove(name);
  +        }
  +
  +    }
  +
  +
  +    /**
        * Set the content length associated with this Request.
        *
        * @param length The new content length
  @@ -569,6 +621,22 @@
           this.contentType = type;
           if (type.indexOf(';') >= 0)
               characterEncoding = RequestUtil.parseCharacterEncoding(type);
  +
  +    }
  +
  +
  +    /**
  +     * Bind an object to a specified name in the internal notes associated
  +     * with this request, replacing any existing binding for this name.
  +     *
  +     * @param name Name to which the object should be bound
  +     * @param value Object to be bound to the specified name
  +     */
  +    public void setNote(String name, Object value) {
  +
  +        synchronized (notes) {
  +            notes.put(name, value);
  +        }
   
       }
   
  
  
  
  1.24      +30 -4     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java
  
  Index: ApplicationDispatcher.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- ApplicationDispatcher.java	2001/07/22 20:25:08	1.23
  +++ ApplicationDispatcher.java	2001/08/01 03:04:04	1.24
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java,v 1.23 2001/07/22 20:25:08 pier Exp $
  - * $Revision: 1.23 $
  - * $Date: 2001/07/22 20:25:08 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java,v 1.24 2001/08/01 03:04:04 craigmcc Exp $
  + * $Revision: 1.24 $
  + * $Date: 2001/08/01 03:04:04 $
    *
    * ====================================================================
    *
  @@ -87,10 +87,13 @@
   import org.apache.catalina.Globals;
   import org.apache.catalina.HttpRequest;
   import org.apache.catalina.HttpResponse;
  +import org.apache.catalina.InstanceEvent;
   import org.apache.catalina.Logger;
   import org.apache.catalina.Request;
   import org.apache.catalina.Response;
   import org.apache.catalina.Wrapper;
  +import org.apache.catalina.core.StandardWrapper;
  +import org.apache.catalina.util.InstanceSupport;
   import org.apache.catalina.util.StringManager;
   
   
  @@ -105,7 +108,7 @@
    * <code>javax.servlet.ServletResponseWrapper</code>.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.23 $ $Date: 2001/07/22 20:25:08 $
  + * @version $Revision: 1.24 $ $Date: 2001/08/01 03:04:04 $
    */
   
   final class ApplicationDispatcher
  @@ -176,6 +179,10 @@
           this.pathInfo = pathInfo;
           this.queryString = queryString;
           this.name = name;
  +        if (wrapper instanceof StandardWrapper)
  +            this.support = ((StandardWrapper) wrapper).getInstanceSupport();
  +        else
  +            this.support = new InstanceSupport(wrapper);
   
           if (debug >= 1)
               log("servletPath=" + this.servletPath + ", pathInfo=" +
  @@ -278,6 +285,13 @@
   
   
       /**
  +     * The InstanceSupport instance associated with our Wrapper (used to
  +     * send "before dispatch" and "after dispatch" events.
  +     */
  +    private InstanceSupport support = null;
  +
  +
  +    /**
        * The Wrapper associated with the resource that will be forwarded to
        * or included.
        */
  @@ -638,6 +652,8 @@
                   request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
               else
                   request.removeAttribute(Globals.JSP_FILE_ATTR);
  +            support.fireInstanceEvent(InstanceEvent.BEFORE_DISPATCH_EVENT,
  +                                      servlet, request, response);
               if (servlet != null) {
                   //                if (debug >= 2)
                   //                    log("  Calling service(), jspFile=" + jspFile);
  @@ -649,24 +665,34 @@
                   }
               }
               request.removeAttribute(Globals.JSP_FILE_ATTR);
  +            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
  +                                      servlet, request, response);
           } catch (IOException e) {
               request.removeAttribute(Globals.JSP_FILE_ATTR);
  +            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
  +                                      servlet, request, response);
               log(sm.getString("applicationDispatcher.serviceException",
                                wrapper.getName()), e);
               ioException = e;
           } catch (UnavailableException e) {
               request.removeAttribute(Globals.JSP_FILE_ATTR);
  +            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
  +                                      servlet, request, response);
               log(sm.getString("applicationDispatcher.serviceException",
                                wrapper.getName()), e);
               servletException = e;
               wrapper.unavailable(e);
           } catch (ServletException e) {
               request.removeAttribute(Globals.JSP_FILE_ATTR);
  +            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
  +                                      servlet, request, response);
               log(sm.getString("applicationDispatcher.serviceException",
                                wrapper.getName()), e);
               servletException = e;
           } catch (RuntimeException e) {
               request.removeAttribute(Globals.JSP_FILE_ATTR);
  +            support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
  +                                      servlet, request, response);
               log(sm.getString("applicationDispatcher.serviceException",
                                wrapper.getName()), e);
               runtimeException = e;