Coverage Report - javax.faces.application.ViewHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
ViewHandler
69%
23/33
87%
14/16
1.5
 
 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 javax.faces.application;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.io.UnsupportedEncodingException;
 23  
 import java.util.Collections;
 24  
 import java.util.List;
 25  
 import java.util.Locale;
 26  
 import java.util.Map;
 27  
 import java.util.Set;
 28  
 
 29  
 import javax.faces.FacesException;
 30  
 import javax.faces.component.UIViewRoot;
 31  
 import javax.faces.context.ExternalContext;
 32  
 import javax.faces.context.FacesContext;
 33  
 import javax.faces.view.ViewDeclarationLanguage;
 34  
 
 35  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 36  
 
 37  
 /**
 38  
  * A ViewHandler manages the component-tree-creation and component-tree-rendering parts of a request lifecycle (ie
 39  
  * "create view", "restore view" and "render response").
 40  
  * <p>
 41  
  * A ViewHandler is responsible for generating the component tree when a new view is requested; see method "createView".
 42  
  * <p>
 43  
  * When the user performs a "postback", ie activates a UICommand component within a view, then the ViewHandler is
 44  
  * responsible for recreating a view tree identical to the one used previously to render that view; see method
 45  
  * "restoreView".
 46  
  * <p>
 47  
  * And the ViewHandler is also responsible for rendering the final output to be sent to the user by invoking the
 48  
  * rendering methods on components; see method "renderView".
 49  
  * <p>
 50  
  * This class also isolates callers from the underlying request/response system. In particular, this class does not
 51  
  * explicitly depend upon the javax.servlet apis. This allows JSF to be used on servers that do not implement the
 52  
  * servlet API (for example, plain CGI).
 53  
  * <p>
 54  
  * Examples:
 55  
  * <ul>
 56  
  * <li>A JSP ViewHandler exists for using "jsp" pages as the presentation technology. This class then works together
 57  
  * with a taghandler class and a jsp servlet class to implement the methods on this abstract class definition.
 58  
  * <li>A Facelets ViewHandler instead uses an xml file to define the components and non-component data that make up a
 59  
  * specific view.
 60  
  * </ul>
 61  
  * Of course there is no reason why the "template" needs to be a textual file. A view could be generated based on data
 62  
  * in a database, or many other mechanisms.
 63  
  * <p>
 64  
  * This class is expected to be invoked via the concrete implementation of {@link javax.faces.lifecycle.Lifecycle}.
 65  
  * <p>
 66  
  * For the official specification for this class, see <a
 67  
  * href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>.
 68  
  */
 69  1052
 public abstract class ViewHandler
 70  
 {
 71  
     public static final String CHARACTER_ENCODING_KEY = "javax.faces.request.charset";
 72  
     public static final String DEFAULT_FACELETS_SUFFIX = ".xhtml";
 73  
     public static final String DEFAULT_SUFFIX = ".xhtml .view.xml .jsp";
 74  
     
 75  
     /**
 76  
      * Indicate the default suffixes, separated by spaces to derive the default file URI 
 77  
      * used by JSF to create views and render pages. 
 78  
      */
 79  
     @JSFWebConfigParam(defaultValue=".xhtml .view.xml .jsp", since="1.1", group="viewhandler")
 80  
     public static final String DEFAULT_SUFFIX_PARAM_NAME = "javax.faces.DEFAULT_SUFFIX";
 81  
     
 82  
     /**
 83  
      * The default extension used to handle facelets pages.
 84  
      */
 85  
     @JSFWebConfigParam(defaultValue=".xhtml", since="2.0", group="viewhandler")
 86  
     public static final String FACELETS_SUFFIX_PARAM_NAME = "javax.faces.FACELETS_SUFFIX";
 87  
     
 88  
     /**
 89  
      * Set of extensions handled by facelets, separated by ';'.
 90  
      */
 91  
     @JSFWebConfigParam(since="2.0", group="viewhandler")
 92  
     public static final String FACELETS_VIEW_MAPPINGS_PARAM_NAME = "javax.faces.FACELETS_VIEW_MAPPINGS";
 93  
     // TODO: Notify EG on that last constant. Using the Facelets' param as well for backward compatiblity is 
 94  
     //       silly. If an application uses Facelets then they'll be using facelets.jar. Once they chose to 
 95  
     //       remove that JAR, they ought to be aware that some changes could be needed, like fixing their 
 96  
     //       context-param. -= Simon Lessard =-
 97  
 
 98  
     @JSFWebConfigParam(since="2.2")
 99  
     public static final java.lang.String DISABLE_FACELET_JSF_VIEWHANDLER_PARAM_NAME = 
 100  
         "DISABLE_FACELET_JSF_VIEWHANDLER";
 101  
     
 102  
     /**
 103  
      * Define the default buffer size value passed to ExternalContext.setResponseBufferResponse() and in a
 104  
      * servlet environment to HttpServletResponse.setBufferSize().
 105  
      */
 106  
     @JSFWebConfigParam(since = "2.0", alias = "facelets.BUFFER_SIZE", classType = "java.lang.Integer",
 107  
             tags = "performance", defaultValue="1024",
 108  
             desc = "Define the default buffer size value passed to ExternalContext.setResponseBufferResponse() and in "
 109  
                    + "a servlet environment to HttpServletResponse.setBufferSize()")
 110  
     public static final java.lang.String FACELETS_BUFFER_SIZE_PARAM_NAME = "javax.faces.FACELETS_BUFFER_SIZE";
 111  
     
 112  
     /**
 113  
      * Set of class names, separated by ';', implementing TagDecorator interface, used to transform
 114  
      * a view definition in a facelet abstract syntax tree, that is used later to generate a component tree.
 115  
      */
 116  
     @JSFWebConfigParam(since = "2.0", alias = "facelets.DECORATORS")
 117  
     public static final java.lang.String FACELETS_DECORATORS_PARAM_NAME = "javax.faces.FACELETS_DECORATORS";
 118  
     
 119  
     /**
 120  
      * Set of .taglib.xml files, separated by ';' that should be loaded by facelet engine.
 121  
      */
 122  
     @JSFWebConfigParam(since = "2.0",
 123  
             desc = "Set of .taglib.xml files, separated by ';' that should be loaded by facelet engine.",
 124  
             alias = "facelets.LIBRARIES")
 125  
     public static final java.lang.String FACELETS_LIBRARIES_PARAM_NAME = "javax.faces.FACELETS_LIBRARIES";
 126  
     
 127  
     /**
 128  
      * Define the period used to refresh the facelet abstract syntax tree from the view definition file. 
 129  
      *
 130  
      * <p>By default is infinite (no active).</p>
 131  
      */
 132  
     @JSFWebConfigParam(since = "2.0", defaultValue = "-1", alias = "facelets.REFRESH_PERIOD",
 133  
             classType = "java.lang.Long", tags = "performance")
 134  
     public static final java.lang.String FACELETS_REFRESH_PERIOD_PARAM_NAME = "javax.faces.FACELETS_REFRESH_PERIOD";
 135  
 
 136  
     /**
 137  
      * Skip comments found on a facelet file.
 138  
      */
 139  
     @JSFWebConfigParam(since = "2.0", alias = "facelets.SKIP_COMMENTS")
 140  
     public static final java.lang.String FACELETS_SKIP_COMMENTS_PARAM_NAME = "javax.faces.FACELETS_SKIP_COMMENTS";
 141  
     
 142  
     /**
 143  
      * @since JSF 1.2
 144  
      */
 145  
     public String calculateCharacterEncoding(FacesContext context)
 146  
     {
 147  8
         String encoding = null;
 148  8
         ExternalContext externalContext = context.getExternalContext();
 149  8
         String contentType = externalContext.getRequestHeaderMap().get("Content-Type");
 150  8
         int indexOf = contentType == null ? -1 : contentType.indexOf("charset");
 151  8
         if (indexOf != -1)
 152  
         {
 153  2
             String tempEnc = contentType.substring(indexOf); // charset=UTF-8
 154  2
             encoding = tempEnc.substring(tempEnc.indexOf("=") + 1); // UTF-8
 155  2
             if (encoding.length() == 0)
 156  
             {
 157  0
                 encoding = null;
 158  
             }
 159  
         }
 160  8
         if (encoding == null)
 161  
         {
 162  6
             boolean sessionAvailable = externalContext.getSession(false) != null;
 163  6
             if (sessionAvailable)
 164  
             {
 165  4
                 Object sessionParam = externalContext.getSessionMap().get(CHARACTER_ENCODING_KEY);
 166  4
                 if (sessionParam != null)
 167  
                 {
 168  2
                     encoding = sessionParam.toString();
 169  
                 }
 170  
             }
 171  
         }
 172  
 
 173  8
         return encoding;
 174  
     }
 175  
 
 176  
     /**
 177  
      * Return the Locale object that should be used when rendering this view to the current user.
 178  
      * <p>
 179  
      * Some request protocols allow an application user to specify what locale they prefer the response to be in. For
 180  
      * example, HTTP requests can specify the "accept-language" header.
 181  
      * <p>
 182  
      * Method {@link javax.faces.application.Application#getSupportedLocales()} defines what locales this JSF
 183  
      * application is capable of supporting.
 184  
      * <p>
 185  
      * This method should match such sources of data up and return the Locale object that is the best choice for
 186  
      * rendering the current application to the current user.
 187  
      */
 188  
     public abstract Locale calculateLocale(FacesContext context);
 189  
 
 190  
     /**
 191  
      * Return the id of an available render-kit that should be used to map the JSF components into user presentation.
 192  
      * <p>
 193  
      * The render-kit selected (eg html, xhtml, pdf, xul, ...) may depend upon the user, properties associated with the
 194  
      * request, etc.
 195  
      */
 196  
     public abstract String calculateRenderKitId(FacesContext context);
 197  
 
 198  
     /**
 199  
      * Build a root node for a component tree.
 200  
      * <p>
 201  
      * When a request is received, this method is called if restoreView returns null, ie this is not a "postback". In
 202  
      * this case, a root node is created and then renderView is invoked. It is the responsibility of the renderView
 203  
      * method to build the full component tree (ie populate the UIViewRoot with descendant nodes).
 204  
      * <p>
 205  
      * This method is also invoked when navigation occurs from one view to another, where the viewId passed is the id of
 206  
      * the new view to be displayed. Again it is the responsibility of renderView to then populate the viewroot with
 207  
      * descendants.
 208  
      * <p>
 209  
      * The locale and renderKit settings are inherited from the current UIViewRoot that is configured before this method
 210  
      * is called. That means of course that they do NOT get set for GET requests, including navigation that has the
 211  
      * redirect flag set.
 212  
      */
 213  
     public abstract UIViewRoot createView(FacesContext context, String viewId);
 214  
 
 215  
     /**
 216  
      * @param context
 217  
      * @param input
 218  
      * @return
 219  
      * 
 220  
      * @since 2.0
 221  
      */
 222  
     public String deriveViewId(FacesContext context, String input)
 223  
     {
 224  
         //The default implementation of this method simply returns rawViewId unchanged.
 225  0
         return input;
 226  
     }
 227  
     
 228  
     /**
 229  
      * 
 230  
      * @param context
 231  
      * @param rawViewId
 232  
      * @return
 233  
      * @since 2.1
 234  
      */
 235  
     public String deriveLogicalViewId(FacesContext context, String rawViewId)
 236  
     {
 237  0
         return rawViewId;
 238  
     }
 239  
 
 240  
     /**
 241  
      * Returns a URL, suitable for encoding and rendering, that (if activated) will cause the JSF
 242  
      * request processing lifecycle for the specified viewId to be executed
 243  
      */
 244  
     public abstract String getActionURL(FacesContext context, String viewId);
 245  
 
 246  
     /**
 247  
      * Return a JSF action URL derived from the viewId argument that is suitable to be used as
 248  
      * the target of a link in a JSF response. Compiliant implementations must implement this method
 249  
      * as specified in section JSF.7.5.2. The default implementation simply calls through to
 250  
      * getActionURL(javax.faces.context.FacesContext, java.lang.String), passing the arguments context and viewId.
 251  
      * 
 252  
      * @param context
 253  
      * @param viewId
 254  
      * @param parameters
 255  
      * @param includeViewParams
 256  
      * @return
 257  
      * 
 258  
      * @since 2.0
 259  
      */
 260  
     public String getBookmarkableURL(FacesContext context, String viewId, Map<String, List<String>> parameters,
 261  
                                      boolean includeViewParams)
 262  
     {
 263  0
         return getActionURL(context, viewId);
 264  
     }
 265  
 
 266  
     /**
 267  
      * Return the ViewDeclarationLanguage instance used for this ViewHandler  instance.
 268  
      * <P>
 269  
      * The default implementation of this method returns null.
 270  
      * 
 271  
      * @param context
 272  
      * @param viewId
 273  
      * @return
 274  
      * 
 275  
      * @since 2.0
 276  
      */
 277  
     public ViewDeclarationLanguage getViewDeclarationLanguage(FacesContext context, String viewId)
 278  
     {
 279  
         // TODO: In some places like RestoreViewExecutor, we are calling deriveViewId
 280  
         // TODO: after call restoreViewSupport.calculateViewId
 281  
         // Maybe this method should be called from here, because it is supposed that
 282  
         // calculateViewId "calculates the view id!"
 283  
         
 284  
         // here we return null to support pre jsf 2.0 ViewHandlers (e.g. com.sun.facelets.FaceletViewHandler),
 285  
         // because they don't provide any ViewDeclarationLanguage,
 286  
         // but in the default implementation (ViewHandlerImpl) we return vdlFactory.getViewDeclarationLanguage(viewId)
 287  0
         return null;
 288  
     }
 289  
 
 290  
     /**
 291  
      * Return a JSF action URL derived from the viewId argument that is suitable to be used by
 292  
      * the NavigationHandler to issue a redirect request to the URL using a NonFaces request.
 293  
      * Compiliant implementations must implement this method as specified in section JSF.7.5.2.
 294  
      * The default implementation simply calls through to
 295  
      * getActionURL(javax.faces.context.FacesContext, java.lang.String), passing the arguments context and viewId.
 296  
      * 
 297  
      * @param context
 298  
      * @param viewId
 299  
      * @param parameters
 300  
      * @param includeViewParams
 301  
      * @return
 302  
      * 
 303  
      * @since 2.0
 304  
      */
 305  
     public String getRedirectURL(FacesContext context, String viewId, Map<String, List<String>> parameters,
 306  
                                  boolean includeViewParams)
 307  
     {
 308  0
         return getActionURL(context, viewId);
 309  
     }
 310  
 
 311  
     /**
 312  
      * Returns a URL, suitable for encoding and rendering, that (if activated)
 313  
      * will retrieve the specified web application resource.
 314  
      */
 315  
     public abstract String getResourceURL(FacesContext context, String path);
 316  
 
 317  
     /**
 318  
      * Initialize the view for the request processing lifecycle.
 319  
      * <P>
 320  
      * This method must be called at the beginning of the Restore View Phase of the Request
 321  
      * Processing Lifecycle. It is responsible for performing any per-request initialization
 322  
      * necessary to the operation of the lifycecle.
 323  
      * <P>
 324  
      * The default implementation must perform the following actions. If
 325  
      * ExternalContext.getRequestCharacterEncoding() returns null, call
 326  
      * calculateCharacterEncoding(javax.faces.context.FacesContext) and pass the result,
 327  
      * if non-null, into the ExternalContext.setRequestCharacterEncoding(java.lang.String) method.
 328  
      * If ExternalContext.getRequestCharacterEncoding() returns non-null take no action.
 329  
      * 
 330  
      * @since JSF 1.2
 331  
      */
 332  
     public void initView(FacesContext context) throws FacesException
 333  
     {
 334  4
         String encoding = this.calculateCharacterEncoding(context);
 335  4
         if (encoding != null)
 336  
         {
 337  
             try
 338  
             {
 339  4
                 context.getExternalContext().setRequestCharacterEncoding(encoding);
 340  
             }
 341  2
             catch (UnsupportedEncodingException uee)
 342  
             {
 343  2
                 throw new FacesException(uee);
 344  2
             }
 345  
         }
 346  2
     }
 347  
 
 348  
     /**
 349  
      *  Perform whatever actions are required to render the response view to the
 350  
      *  response object associated with the current FacesContext.
 351  
      *  <P>
 352  
      *  Otherwise, the default implementation must obtain a reference to the
 353  
      *  ViewDeclarationLanguage for the viewId of the argument viewToRender and call its
 354  
      *  ViewDeclarationLanguage.renderView(javax.faces.context.FacesContext, javax.faces.component.UIViewRoot)
 355  
      *  method, returning the result and not swallowing any exceptions thrown by that method.
 356  
      */
 357  
     public abstract void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException;
 358  
 
 359  
     /**
 360  
      * Perform whatever actions are required to restore the view associated with the
 361  
      * specified FacesContext and viewId. It may delegate to the restoreView of the
 362  
      * associated StateManager to do the actual work of restoring the view. If there
 363  
      * is no available state for the specified viewId, return null.
 364  
      * <P>
 365  
      * Otherwise, the default implementation must obtain a reference to the
 366  
      * ViewDeclarationLanguage for this viewId and call its
 367  
      * ViewDeclarationLanguage.restoreView(javax.faces.context.FacesContext, java.lang.String)
 368  
      * method, returning the result and not swallowing any exceptions thrown by that method.
 369  
      */
 370  
     public abstract UIViewRoot restoreView(FacesContext context, String viewId);
 371  
 
 372  
     /**
 373  
      * Take any appropriate action to either immediately write out the current state information
 374  
      * (by calling StateManager.writeState(javax.faces.context.FacesContext, java.lang.Object),
 375  
      * or noting where state information should later be written.
 376  
      * <P>
 377  
      * This method must do nothing if the current request is an Ajax request. When responding
 378  
      * to Ajax requests, the state is obtained by calling StateManager.getViewState(javax.faces.context.FacesContext)
 379  
      * and then written into the Ajax response during
 380  
      * final encoding (UIViewRoot.encodeEnd(javax.faces.context.FacesContext).
 381  
      */
 382  
     public abstract void writeState(FacesContext context) throws IOException;
 383  
 
 384  
     /**
 385  
      * @since 2.2
 386  
      * @param urlPattern 
 387  
      */
 388  
     public void addProtectedView(String urlPattern)
 389  
     {
 390  0
     }
 391  
     
 392  
     /**
 393  
      * @since 2.2
 394  
      * @param urlPattern 
 395  
      */
 396  
     public boolean removeProtectedView(String urlPattern)
 397  
     {
 398  0
         return false;
 399  
     }
 400  
 
 401  
     /**
 402  
      * @since 2.2
 403  
      * @return 
 404  
      */
 405  
     public Set<String> getProtectedViewsUnmodifiable()
 406  
     {
 407  0
         Set<String> set = Collections.emptySet();
 408  0
         return Collections.unmodifiableSet(set);
 409  
     }
 410  
 }