View Javadoc

    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.orchestra.requestParameterProvider.jsf;
    20
    21  import javax.faces.FacesException;
    22  import javax.faces.context.FacesContext;
    23  import javax.faces.context.FacesContextFactory;
    24  import javax.faces.lifecycle.Lifecycle;
    25  import javax.servlet.http.HttpServletRequest;
    26  import javax.servlet.http.HttpServletResponse;
    27
    28  import org.apache.myfaces.orchestra.lib.jsf.ExternalContextUtils;
    29  import org.apache.myfaces.orchestra.requestParameterProvider.RequestParameterResponseWrapper;
    30  import org.apache.myfaces.orchestra.requestParameterProvider.RequestParameterServletFilter;
    31
    32  /**
    33   * Ensure that a custom wrapper is put around the HttpServletResponse so that encodeURL can be
    34   * intercepted and modified.
    35   * <p>
    36   * There is a servlet filter (RequestParameterServletFilter) that does this in the obvious way, but
    37   * it is a nuisance to have to set up filters in the web.xml. This class implements a sneaky hack
    38   * to get this to happen automatically for JSF applications, ie no servlet filter is needed when
    39   * this is specified in the faces-config.xml file as the FacesContextFactory.
    40   * <p>
    41   * If you have to deal with a mixed environment e.g. JSP/JSF it would be better to use the
    42   * {@link org.apache.myfaces.orchestra.requestParameterProvider.RequestParameterServletFilter}.
    43   */
    44  public class RequestParameterFacesContextFactory extends FacesContextFactory
    45  {
    46      private final FacesContextFactory original;
    47
    48      public RequestParameterFacesContextFactory(FacesContextFactory original)
    49      {
    50          this.original = original;
    51      }
    52
    53      /**
    54       * Invokes the getFacesContext method on the original factory in order to return a
    55       * perfectly normal FacesContext instance. However the ServletResponse object passed
    56       * to that FacesContext instance is a modified one that tweaks every url that is
    57       * processed by the ServletResponse.encodeUrl method.
    58       */
    59      public FacesContext getFacesContext(Object context, Object request, Object response, Lifecycle lifecycle)
    60      throws FacesException
    61      {
    62          if (!ExternalContextUtils.getRequestType(context, request).isPortlet())
    63          {
    64              HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    65
    66              // Wrap this request only if something else (eg a RequestParameterServletFilter)
    67              // has not already wrapped it.
    68              if (!Boolean.TRUE.equals(httpServletRequest.getAttribute(
    69                      RequestParameterServletFilter.REQUEST_PARAM_FILTER_CALLED)))
    70              {
    71                  // No servlet filter has wrapped the response, so do it now for the response
    72                  // referenced by this FacesContext. Note that this wrapper will therefore
    73                  // apply to all output generated via the FacesContext, but not to anything
    74                  // that might be written by filters etc.
    75                  response = new RequestParameterResponseWrapper((HttpServletResponse) response);
    76
    77                  // We now need to reassure the RequestParameterProviderManager that the response has indeed been
    78                  // wrapped; it checks and reports an error if not as it is easy to stuff up this configuration.
    79                  //
    80                  // However we can not just set the REQUEST_PARAMETER_FILTER_CALLED flag here. If code creates its own
    81                  // FacesContext instance for any reason while a request is running, then this method is called again.
    82                  // On the second call this flag would already be set and the response would not be wrapped as required.
    83                  //
    84                  // Therefore we have two separate flags; RequestParameterProviderManager checks whether either
    85                  // REQUEST_PARAM_FILTER_CALLED or REQUEST_PARAM_RESPONSE_WRAPPED has been set.
    86
    87                  httpServletRequest.setAttribute(
    88                      RequestParameterServletFilter.REQUEST_PARAM_RESPONSE_WRAPPED, Boolean.TRUE);
    89
    90              }
    91          }
    92
    93          return original.getFacesContext(context, request, response, lifecycle);
    94      }
    95  }