Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » core » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.core;
   20   
   21   
   22   import java.io.IOException;
   23   import java.security.Principal;
   24   import java.security.PrivilegedActionException;
   25   
   26   import javax.servlet.Filter;
   27   import javax.servlet.FilterChain;
   28   import javax.servlet.Servlet;
   29   import javax.servlet.ServletException;
   30   import javax.servlet.ServletRequest;
   31   import javax.servlet.ServletResponse;
   32   import javax.servlet.http.HttpServletRequest;
   33   import javax.servlet.http.HttpServletResponse;
   34   
   35   import org.apache.catalina.CometEvent;
   36   import org.apache.catalina.CometFilter;
   37   import org.apache.catalina.CometFilterChain;
   38   import org.apache.catalina.CometProcessor;
   39   import org.apache.catalina.Globals;
   40   import org.apache.catalina.InstanceEvent;
   41   import org.apache.catalina.security.SecurityUtil;
   42   import org.apache.catalina.util.InstanceSupport;
   43   import org.apache.catalina.util.StringManager;
   44   
   45   /**
   46    * Implementation of <code>javax.servlet.FilterChain</code> used to manage
   47    * the execution of a set of filters for a particular request.  When the
   48    * set of defined filters has all been executed, the next call to
   49    * <code>doFilter()</code> will execute the servlet's <code>service()</code>
   50    * method itself.
   51    *
   52    * @author Craig R. McClanahan
   53    * @version $Revision: 734559 $ $Date: 2009-01-15 00:39:18 +0100 (Thu, 15 Jan 2009) $
   54    */
   55   
   56   final class ApplicationFilterChain implements FilterChain, CometFilterChain {
   57   
   58       // Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
   59       private final static ThreadLocal lastServicedRequest;
   60       private final static ThreadLocal lastServicedResponse;
   61   
   62       static {
   63           if (Globals.STRICT_SERVLET_COMPLIANCE) {
   64               lastServicedRequest = new ThreadLocal();
   65               lastServicedResponse = new ThreadLocal();
   66           } else {
   67               lastServicedRequest = null;
   68               lastServicedResponse = null;
   69           }
   70       }
   71   
   72       // -------------------------------------------------------------- Constants
   73   
   74   
   75       public static final int INCREMENT = 10;
   76   
   77   
   78       // ----------------------------------------------------------- Constructors
   79   
   80   
   81       /**
   82        * Construct a new chain instance with no defined filters.
   83        */
   84       public ApplicationFilterChain() {
   85   
   86           super();
   87   
   88       }
   89   
   90   
   91       // ----------------------------------------------------- Instance Variables
   92   
   93   
   94       /**
   95        * Filters.
   96        */
   97       private ApplicationFilterConfig[] filters = 
   98           new ApplicationFilterConfig[0];
   99   
  100   
  101       /**
  102        * The int which is used to maintain the current position 
  103        * in the filter chain.
  104        */
  105       private int pos = 0;
  106   
  107   
  108       /**
  109        * The int which gives the current number of filters in the chain.
  110        */
  111       private int n = 0;
  112   
  113   
  114       /**
  115        * The servlet instance to be executed by this chain.
  116        */
  117       private Servlet servlet = null;
  118   
  119   
  120       /**
  121        * The string manager for our package.
  122        */
  123       private static final StringManager sm =
  124         StringManager.getManager(Constants.Package);
  125   
  126   
  127       /**
  128        * The InstanceSupport instance associated with our Wrapper (used to
  129        * send "before filter" and "after filter" events.
  130        */
  131       private InstanceSupport support = null;
  132   
  133       
  134       /**
  135        * Static class array used when the SecurityManager is turned on and 
  136        * <code>doFilter</code> is invoked.
  137        */
  138       private static Class[] classType = new Class[]{ServletRequest.class, 
  139                                                      ServletResponse.class,
  140                                                      FilterChain.class};
  141                                                      
  142       /**
  143        * Static class array used when the SecurityManager is turned on and 
  144        * <code>service</code> is invoked.
  145        */                                                 
  146       private static Class[] classTypeUsedInService = new Class[]{
  147                                                            ServletRequest.class,
  148                                                            ServletResponse.class};
  149   
  150       /**
  151        * Static class array used when the SecurityManager is turned on and 
  152        * <code>doFilterEvent</code> is invoked.
  153        */
  154       private static Class[] cometClassType = 
  155           new Class[]{ CometEvent.class, CometFilterChain.class};
  156                                                      
  157       /**
  158        * Static class array used when the SecurityManager is turned on and 
  159        * <code>event</code> is invoked.
  160        */                                                 
  161       private static Class[] classTypeUsedInEvent = 
  162           new Class[] { CometEvent.class };
  163   
  164       // ---------------------------------------------------- FilterChain Methods
  165   
  166   
  167       /**
  168        * Invoke the next filter in this chain, passing the specified request
  169        * and response.  If there are no more filters in this chain, invoke
  170        * the <code>service()</code> method of the servlet itself.
  171        *
  172        * @param request The servlet request we are processing
  173        * @param response The servlet response we are creating
  174        *
  175        * @exception IOException if an input/output error occurs
  176        * @exception ServletException if a servlet exception occurs
  177        */
  178       public void doFilter(ServletRequest request, ServletResponse response)
  179           throws IOException, ServletException {
  180   
  181           if( Globals.IS_SECURITY_ENABLED ) {
  182               final ServletRequest req = request;
  183               final ServletResponse res = response;
  184               try {
  185                   java.security.AccessController.doPrivileged(
  186                       new java.security.PrivilegedExceptionAction() {
  187                           public Object run() 
  188                               throws ServletException, IOException {
  189                               internalDoFilter(req,res);
  190                               return null;
  191                           }
  192                       }
  193                   );
  194               } catch( PrivilegedActionException pe) {
  195                   Exception e = pe.getException();
  196                   if (e instanceof ServletException)
  197                       throw (ServletException) e;
  198                   else if (e instanceof IOException)
  199                       throw (IOException) e;
  200                   else if (e instanceof RuntimeException)
  201                       throw (RuntimeException) e;
  202                   else
  203                       throw new ServletException(e.getMessage(), e);
  204               }
  205           } else {
  206               internalDoFilter(request,response);
  207           }
  208       }
  209   
  210       private void internalDoFilter(ServletRequest request, 
  211                                     ServletResponse response)
  212           throws IOException, ServletException {
  213   
  214           // Call the next filter if there is one
  215           if (pos < n) {
  216               ApplicationFilterConfig filterConfig = filters[pos++];
  217               Filter filter = null;
  218               try {
  219                   filter = filterConfig.getFilter();
  220                   support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
  221                                             filter, request, response);
  222                   
  223                   if( Globals.IS_SECURITY_ENABLED ) {
  224                       final ServletRequest req = request;
  225                       final ServletResponse res = response;
  226                       Principal principal = 
  227                           ((HttpServletRequest) req).getUserPrincipal();
  228   
  229                       Object[] args = new Object[]{req, res, this};
  230                       SecurityUtil.doAsPrivilege
  231                           ("doFilter", filter, classType, args, principal);
  232                       
  233                       args = null;
  234                   } else {  
  235                       filter.doFilter(request, response, this);
  236                   }
  237   
  238                   support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  239                                             filter, request, response);
  240               } catch (IOException e) {
  241                   if (filter != null)
  242                       support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  243                                                 filter, request, response, e);
  244                   throw e;
  245               } catch (ServletException e) {
  246                   if (filter != null)
  247                       support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  248                                                 filter, request, response, e);
  249                   throw e;
  250               } catch (RuntimeException e) {
  251                   if (filter != null)
  252                       support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  253                                                 filter, request, response, e);
  254                   throw e;
  255               } catch (Throwable e) {
  256                   if (filter != null)
  257                       support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  258                                                 filter, request, response, e);
  259                   throw new ServletException
  260                     (sm.getString("filterChain.filter"), e);
  261               }
  262               return;
  263           }
  264   
  265           // We fell off the end of the chain -- call the servlet instance
  266           try {
  267               if (Globals.STRICT_SERVLET_COMPLIANCE) {
  268                   lastServicedRequest.set(request);
  269                   lastServicedResponse.set(response);
  270               }
  271   
  272               support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
  273                                         servlet, request, response);
  274               if ((request instanceof HttpServletRequest) &&
  275                   (response instanceof HttpServletResponse)) {
  276                       
  277                   if( Globals.IS_SECURITY_ENABLED ) {
  278                       final ServletRequest req = request;
  279                       final ServletResponse res = response;
  280                       Principal principal = 
  281                           ((HttpServletRequest) req).getUserPrincipal();
  282                       Object[] args = new Object[]{req, res};
  283                       SecurityUtil.doAsPrivilege("service",
  284                                                  servlet,
  285                                                  classTypeUsedInService, 
  286                                                  args,
  287                                                  principal);   
  288                       args = null;
  289                   } else {  
  290                       servlet.service((HttpServletRequest) request,
  291                                       (HttpServletResponse) response);
  292                   }
  293               } else {
  294                   servlet.service(request, response);
  295               }
  296               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  297                                         servlet, request, response);
  298           } catch (IOException e) {
  299               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  300                                         servlet, request, response, e);
  301               throw e;
  302           } catch (ServletException e) {
  303               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  304                                         servlet, request, response, e);
  305               throw e;
  306           } catch (RuntimeException e) {
  307               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  308                                         servlet, request, response, e);
  309               throw e;
  310           } catch (Throwable e) {
  311               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  312                                         servlet, request, response, e);
  313               throw new ServletException
  314                 (sm.getString("filterChain.servlet"), e);
  315           } finally {
  316               if (Globals.STRICT_SERVLET_COMPLIANCE) {
  317                   lastServicedRequest.set(null);
  318                   lastServicedResponse.set(null);
  319               }
  320           }
  321   
  322       }
  323   
  324   
  325       /**
  326        * Invoke the next filter in this chain, passing the specified request
  327        * and response.  If there are no more filters in this chain, invoke
  328        * the <code>service()</code> method of the servlet itself.
  329        *
  330        * @param request The servlet request we are processing
  331        * @param response The servlet response we are creating
  332        *
  333        * @exception IOException if an input/output error occurs
  334        * @exception ServletException if a servlet exception occurs
  335        */
  336       public void doFilterEvent(CometEvent event)
  337           throws IOException, ServletException {
  338   
  339           if( Globals.IS_SECURITY_ENABLED ) {
  340               final CometEvent ev = event;
  341               try {
  342                   java.security.AccessController.doPrivileged(
  343                       new java.security.PrivilegedExceptionAction() {
  344                           public Object run() 
  345                               throws ServletException, IOException {
  346                               internalDoFilterEvent(ev);
  347                               return null;
  348                           }
  349                       }
  350                   );
  351               } catch( PrivilegedActionException pe) {
  352                   Exception e = pe.getException();
  353                   if (e instanceof ServletException)
  354                       throw (ServletException) e;
  355                   else if (e instanceof IOException)
  356                       throw (IOException) e;
  357                   else if (e instanceof RuntimeException)
  358                       throw (RuntimeException) e;
  359                   else
  360                       throw new ServletException(e.getMessage(), e);
  361               }
  362           } else {
  363               internalDoFilterEvent(event);
  364           }
  365       }
  366   
  367       
  368       /**
  369        * The last request passed to a servlet for servicing from the current
  370        * thread.
  371        * 
  372        * @return The last request to be serviced. 
  373        */
  374       public static ServletRequest getLastServicedRequest() {
  375           return (ServletRequest) lastServicedRequest.get();
  376       }
  377   
  378       
  379       /**
  380        * The last response passed to a servlet for servicing from the current
  381        * thread.
  382        * 
  383        * @return The last response to be serviced. 
  384        */
  385       public static ServletResponse getLastServicedResponse() {
  386           return (ServletResponse) lastServicedResponse.get();
  387       }
  388       
  389       
  390       private void internalDoFilterEvent(CometEvent event)
  391           throws IOException, ServletException {
  392   
  393           // Call the next filter if there is one
  394           if (pos < n) {
  395               ApplicationFilterConfig filterConfig = filters[pos++];
  396               CometFilter filter = null;
  397               try {
  398                   filter = (CometFilter) filterConfig.getFilter();
  399                   // FIXME: No instance listener processing for events for now
  400                   /*
  401                   support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
  402                           filter, event);
  403                           */
  404   
  405                   if( Globals.IS_SECURITY_ENABLED ) {
  406                       final CometEvent ev = event;
  407                       Principal principal = 
  408                           ev.getHttpServletRequest().getUserPrincipal();
  409   
  410                       Object[] args = new Object[]{ev, this};
  411                       SecurityUtil.doAsPrivilege("doFilterEvent", filter,
  412                               cometClassType, args, principal);
  413   
  414                       args = null;
  415                   } else {  
  416                       filter.doFilterEvent(event, this);
  417                   }
  418   
  419                   /*support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  420                           filter, event);*/
  421               } catch (IOException e) {
  422                   /*
  423                   if (filter != null)
  424                       support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  425                               filter, event, e);
  426                               */
  427                   throw e;
  428               } catch (ServletException e) {
  429                   /*
  430                   if (filter != null)
  431                       support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  432                               filter, event, e);
  433                               */
  434                   throw e;
  435               } catch (RuntimeException e) {
  436                   /*
  437                   if (filter != null)
  438                       support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  439                               filter, event, e);
  440                               */
  441                   throw e;
  442               } catch (Throwable e) {
  443                   /*if (filter != null)
  444                       support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
  445                               filter, event, e);*/
  446                   throw new ServletException
  447                       (sm.getString("filterChain.filter"), e);
  448               }
  449               return;
  450           }
  451   
  452           // We fell off the end of the chain -- call the servlet instance
  453           try {
  454               /*
  455               support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
  456                       servlet, request, response);
  457                       */
  458               if( Globals.IS_SECURITY_ENABLED ) {
  459                   final CometEvent ev = event;
  460                   Principal principal = 
  461                       ev.getHttpServletRequest().getUserPrincipal();
  462                   Object[] args = new Object[]{ ev };
  463                   SecurityUtil.doAsPrivilege("event",
  464                           servlet,
  465                           classTypeUsedInEvent, 
  466                           args,
  467                           principal);
  468                   args = null;
  469               } else {  
  470                   ((CometProcessor) servlet).event(event);
  471               }
  472               /*
  473               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  474                       servlet, request, response);*/
  475           } catch (IOException e) {
  476               /*
  477               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  478                       servlet, request, response, e);
  479                       */
  480               throw e;
  481           } catch (ServletException e) {
  482               /*
  483               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  484                       servlet, request, response, e);
  485                       */
  486               throw e;
  487           } catch (RuntimeException e) {
  488               /*
  489               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  490                       servlet, request, response, e);
  491                       */
  492               throw e;
  493           } catch (Throwable e) {
  494               /*
  495               support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
  496                       servlet, request, response, e);
  497                       */
  498               throw new ServletException
  499                   (sm.getString("filterChain.servlet"), e);
  500           }
  501   
  502       }
  503   
  504   
  505       // -------------------------------------------------------- Package Methods
  506   
  507   
  508   
  509       /**
  510        * Add a filter to the set of filters that will be executed in this chain.
  511        *
  512        * @param filterConfig The FilterConfig for the servlet to be executed
  513        */
  514       void addFilter(ApplicationFilterConfig filterConfig) {
  515   
  516           if (n == filters.length) {
  517               ApplicationFilterConfig[] newFilters =
  518                   new ApplicationFilterConfig[n + INCREMENT];
  519               System.arraycopy(filters, 0, newFilters, 0, n);
  520               filters = newFilters;
  521           }
  522           filters[n++] = filterConfig;
  523   
  524       }
  525   
  526   
  527       /**
  528        * Release references to the filters and wrapper executed by this chain.
  529        */
  530       void release() {
  531   
  532           for (int i = 0; i < n; i++) {
  533               filters[i] = null;
  534           }
  535           n = 0;
  536           pos = 0;
  537           servlet = null;
  538           support = null;
  539   
  540       }
  541   
  542   
  543       /**
  544        * Prepare for reuse of the filters and wrapper executed by this chain.
  545        */
  546       void reuse() {
  547           pos = 0;
  548       }
  549   
  550   
  551       /**
  552        * Set the servlet that will be executed at the end of this chain.
  553        *
  554        * @param servlet The Wrapper for the servlet to be executed
  555        */
  556       void setServlet(Servlet servlet) {
  557   
  558           this.servlet = servlet;
  559   
  560       }
  561   
  562   
  563       /**
  564        * Set the InstanceSupport object used for event notifications
  565        * for this filter chain.
  566        *
  567        * @param support The InstanceSupport object for our Wrapper
  568        */
  569       void setSupport(InstanceSupport support) {
  570   
  571           this.support = support;
  572   
  573       }
  574   
  575   
  576   }

Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » core » [javadoc | source]