Save This Page
Home » trinidad-1.2.8-src-all » org.apache.myfaces.trinidadinternal » webapp » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    * 
   10    *  http://www.apache.org/licenses/LICENSE-2.0
   11    * 
   12    *  Unless required by applicable law or agreed to in writing,
   13    *  software distributed under the License is distributed on an
   14    *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    *  KIND, either express or implied.  See the License for the
   16    *  specific language governing permissions and limitations
   17    *  under the License.
   18    */
   19   package org.apache.myfaces.trinidadinternal.webapp;
   20   
   21   import java.io.IOException;
   22   import java.util.List;
   23   import java.util.Map;
   24   
   25   import javax.faces.context.ExternalContext;
   26   import javax.faces.context.FacesContext;
   27   import javax.servlet.Filter;
   28   import javax.servlet.FilterChain;
   29   import javax.servlet.FilterConfig;
   30   import javax.servlet.ServletContext;
   31   import javax.servlet.ServletException;
   32   import javax.servlet.ServletRequest;
   33   import javax.servlet.ServletResponse;
   34   import javax.servlet.http.HttpServletRequest;
   35   import javax.servlet.http.HttpServletResponse;
   36   
   37   import org.apache.myfaces.trinidad.logging.TrinidadLogger;
   38   import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
   39   import org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl;
   40   import org.apache.myfaces.trinidadinternal.config.dispatch.DispatchResponseConfiguratorImpl;
   41   import org.apache.myfaces.trinidadinternal.config.dispatch.DispatchServletResponse;
   42   import org.apache.myfaces.trinidadinternal.config.upload.FileUploadConfiguratorImpl;
   43   import org.apache.myfaces.trinidadinternal.config.upload.UploadRequestWrapper;
   44   import org.apache.myfaces.trinidadinternal.config.xmlHttp.XmlHttpConfigurator;
   45   import org.apache.myfaces.trinidadinternal.context.RequestContextImpl;
   46   import org.apache.myfaces.trinidadinternal.context.external.ServletExternalContext;
   47   import org.apache.myfaces.trinidadinternal.renderkit.core.CoreRenderKit;
   48   
   49   /**
   50    * Actual implementation of the Trinidad servlet filter.
   51    * <p>
   52    * @version $Name:  $ ($Revision: adfrt/faces/adf-faces-impl/src/main/java/oracle/adfinternal/view/faces/webapp/AdfFacesFilterImpl.java#0 $) $Date: 10-nov-2005.18:48:59 $
   53    * @todo Allow configuration of the maximum allowed number of bytes in
   54    *   an entire request
   55    */
   56   public class TrinidadFilterImpl implements Filter
   57   {
   58     static public void verifyFilterIsInstalled(FacesContext context)
   59     {
   60       Object isInstalled =
   61         context.getExternalContext().getRequestMap().get(_FILTER_EXECUTED_KEY);
   62       if (!Boolean.TRUE.equals(isInstalled))
   63       {
   64         _LOG.warning("REQUIRED_TRINIDADFILTER_NOT_INSTALLED");
   65   
   66       }
   67     }
   68   
   69     static public FacesContext getPseudoFacesContext()
   70     {
   71       return _PSEUDO_FACES_CONTEXT.get();
   72     }
   73   
   74     /**
   75      * Returns true if the filter is in the middle of executing the
   76      * "return from dialog"
   77      */
   78     static public boolean isExecutingDialogReturn(FacesContext context)
   79     {
   80       return Boolean.TRUE.equals(
   81         context.getExternalContext().getRequestMap().get(_IS_RETURNING_KEY));
   82     }
   83   
   84     public void init(FilterConfig filterConfig) throws ServletException
   85     {
   86       _servletContext = filterConfig.getServletContext();
   87               
   88       //There is some functionality that still might require servlet-only filter services.
   89       _filters = ClassLoaderUtils.getServices(TrinidadFilterImpl.class.getName());
   90       for(Filter f:_filters)
   91       {
   92         f.init(filterConfig);
   93       }
   94     }
   95   
   96     public void destroy()
   97     {
   98       //Destroy filter services
   99       for(Filter f:_filters)
  100       {
  101         f.destroy();
  102       }
  103   
  104       _filters = null;
  105     }
  106   
  107   
  108     @SuppressWarnings("unchecked")
  109     public void doFilter(
  110       ServletRequest  request,
  111       ServletResponse response,
  112       FilterChain     chain) throws IOException, ServletException
  113     {
  114       //Execute the filter services
  115       if (!_filters.isEmpty())
  116         chain = new FilterListChain(_filters, chain);
  117   
  118       // Set a flag so that we can detect if the filter has been
  119       // properly installed.
  120       request.setAttribute(_FILTER_EXECUTED_KEY, Boolean.TRUE);
  121   
  122       ExternalContext externalContext = new ServletExternalContext(_servletContext, request, response);    
  123       GlobalConfiguratorImpl config = GlobalConfiguratorImpl.getInstance();
  124       config.beginRequest(externalContext);
  125       
  126       //To maintain backward compatibilty, wrap the request at the filter level
  127       Map<String, String[]> addedParams = FileUploadConfiguratorImpl.getAddedParameters(externalContext);
  128       
  129       if(addedParams != null)
  130       {
  131         FileUploadConfiguratorImpl.apply(externalContext);
  132         request = new UploadRequestWrapper((HttpServletRequest)request, addedParams);
  133       }
  134   
  135       try
  136       {
  137         
  138         _doFilterImpl(request, response, chain);
  139       }
  140       // For PPR errors, handle the request specially
  141       catch (Throwable t)
  142       {
  143         boolean isPartialRequest;
  144         if (addedParams != null)
  145         {
  146           isPartialRequest = CoreRenderKit.isPartialRequest(addedParams);
  147         }
  148         else
  149         {
  150           isPartialRequest = CoreRenderKit.isPartialRequest(externalContext);
  151         }
  152   
  153         if (isPartialRequest)
  154         {
  155           XmlHttpConfigurator.handleError(externalContext, t);
  156         }
  157         else
  158         {
  159           // For non-partial requests, just re-throw.  It is not
  160           // our responsibility to catch these
  161           if (t instanceof RuntimeException)
  162             throw ((RuntimeException) t);
  163           if (t instanceof Error)
  164             throw ((Error) t);
  165           if (t instanceof IOException)
  166             throw ((IOException) t);
  167           if (t instanceof ServletException)
  168             throw ((ServletException) t);
  169   
  170           // Should always be one of those four types to have
  171           // gotten here.
  172           _LOG.severe(t);
  173         }
  174   
  175       }
  176       finally
  177       {
  178         config.endRequest(externalContext);
  179       }
  180     }
  181   
  182   
  183     @SuppressWarnings("unchecked")
  184     private void _doFilterImpl(
  185       ServletRequest  request,
  186       ServletResponse response,
  187       FilterChain     chain) throws IOException, ServletException
  188     {
  189       // -= Scott O'Bryan =-
  190       // Added for backward compatibility
  191       ExternalContext ec = new ServletExternalContext(_servletContext, request, response);
  192       HttpServletResponse dispatch = new DispatchServletResponse(ec);
  193       DispatchResponseConfiguratorImpl.apply(ec);
  194   
  195       _invokeDoFilter(request, dispatch, chain);
  196   
  197       // If there are existing "launchParameters", then that means
  198       // we've returned from a "launch", and we need to re-execute the
  199       // faces lifecycle.  ViewHandlerImpl will be responsible for ensuring
  200       // that we re-execute the lifecycle on the correct page.
  201       // -= Simon Lessard =-
  202       // FIXME: Using <String, String[]> for now to accomodate ReplaceParametersRequestWrapper.
  203       //        However, the Servlet specification suggest <String, Object> so this 
  204       //        could lead to some nasty problems one day. Especially if JEE spec includes 
  205       //        generics for its Servlet API soon.
  206       //
  207       // -= Scott O'Bryan =- 
  208       // TODO: The following should be made available to the Portal.  This is not trivial 
  209       //       because this just re-invokes the filter chain with a new set of parameters.
  210       //       In the portal environment, this must rerun the portlet without the use of 
  211       //       filters until Portlet 2.0.
  212       Map<String, String[]> launchParameters = (Map<String, String[]>)
  213         request.getAttribute(RequestContextImpl.LAUNCH_PARAMETERS);
  214       if (launchParameters != null)
  215       {
  216         request.removeAttribute(RequestContextImpl.LAUNCH_PARAMETERS);
  217         request.setAttribute(_IS_RETURNING_KEY, Boolean.TRUE);
  218         request = new ReplaceParametersRequestWrapper(
  219                  (HttpServletRequest) request, launchParameters);
  220         _invokeDoFilter(request, dispatch, chain);
  221         request.removeAttribute(_IS_RETURNING_KEY);
  222       }
  223     }
  224   
  225     private void _invokeDoFilter(
  226       ServletRequest  request,
  227       ServletResponse response,
  228       FilterChain     chain) throws IOException, ServletException
  229     {
  230       // Set up a PseudoFacesContext with the actual request and response
  231       // so that RequestContext can be more functional in the interval
  232       // between now and when the FacesServlet starts.
  233       PseudoFacesContext pfc = new PseudoFacesContext(
  234         new ServletExternalContext(_servletContext, request, response));
  235       _PSEUDO_FACES_CONTEXT.set(pfc);
  236       try
  237       {
  238         chain.doFilter(request, response);
  239       }
  240       finally
  241       {
  242         _PSEUDO_FACES_CONTEXT.remove();
  243       }
  244     }
  245   
  246   
  247     private static final class FilterListChain implements FilterChain
  248     {
  249       private final List<Filter> _filters;
  250       private final FilterChain _last;
  251       private final int _index;
  252       
  253       public FilterListChain(List<Filter> filters, FilterChain last)
  254       {
  255         this(filters, last, 0);
  256       }
  257   
  258       private FilterListChain(List<Filter> filters, FilterChain last, int index)
  259       {
  260         assert index < filters.size();
  261         _filters = filters;
  262         _last = last;
  263         _index = index;
  264       }
  265       
  266       public void doFilter(ServletRequest request, ServletResponse response)
  267         throws IOException, ServletException
  268       {
  269         int nextIndex = _index+1;
  270         final FilterChain next;
  271         // if there are more filters to chain, then keep using
  272         // FilterListChain; otherwise, just use the last chain:
  273         if (nextIndex < _filters.size())
  274           next = new FilterListChain(_filters, _last, nextIndex);
  275         else
  276           next = _last;
  277   
  278         _filters.get(_index).doFilter(request, response, next);
  279       }
  280     }
  281   
  282     private ServletContext _servletContext;
  283     private List<Filter> _filters = null;
  284   
  285     private static final String _IS_RETURNING_KEY =
  286       "org.apache.myfaces.trinidadinternal.webapp.AdfacesFilterImpl.IS_RETURNING";
  287     private static final String _FILTER_EXECUTED_KEY =
  288       "org.apache.myfaces.trinidadinternal.webapp.AdfacesFilterImpl.EXECUTED";
  289   
  290     private static ThreadLocal<PseudoFacesContext> _PSEUDO_FACES_CONTEXT = 
  291       new ThreadLocal<PseudoFacesContext>()
  292     {
  293       @Override
  294       protected PseudoFacesContext initialValue() { return null; }
  295     };
  296   
  297     private static final TrinidadLogger _LOG =
  298       TrinidadLogger.createTrinidadLogger(TrinidadFilterImpl.class);
  299   }

Save This Page
Home » trinidad-1.2.8-src-all » org.apache.myfaces.trinidadinternal » webapp » [javadoc | source]