2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

Coverage Report - org.apache.shale.view.faces.ViewViewHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
ViewViewHandler
0% 
0% 
3.154
 
 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  
 package org.apache.shale.view.faces;
 19  
 
 20  
 import java.io.IOException;
 21  
 import java.util.ArrayList;
 22  
 import java.util.List;
 23  
 import java.util.Locale;
 24  
 import java.util.Map;
 25  
 
 26  
 import javax.faces.FacesException;
 27  
 import javax.faces.application.ViewHandler;
 28  
 import javax.faces.component.UIViewRoot;
 29  
 import javax.faces.context.FacesContext;
 30  
 import javax.faces.el.EvaluationException;
 31  
 import javax.faces.el.ValueBinding;
 32  
 import javax.faces.el.VariableResolver;
 33  
 
 34  
 import org.apache.commons.logging.Log;
 35  
 import org.apache.commons.logging.LogFactory;
 36  
 import org.apache.shale.util.Messages;
 37  
 import org.apache.shale.view.Constants;
 38  
 import org.apache.shale.view.ViewController;
 39  
 import org.apache.shale.view.ViewControllerMapper;
 40  
 
 41  
 /**
 42  
  * <p>{@link ViewViewHandler} is a custom implementation of <code>ViewHandler</code>
 43  
  * that adds support for on-demand creation and configuration of {@link ViewController}
 44  
  * instances, and other view related functionality.</p>
 45  
  *
 46  
  * $Id: ViewViewHandler.java 464373 2006-10-16 04:21:54Z rahul $
 47  
  */
 48  
 
 49  
 public class ViewViewHandler extends ViewHandler {
 50  
 
 51  
 
 52  
     // ------------------------------------------------------------- Constructor
 53  
 
 54  
 
 55  
     /**
 56  
      * <p>Create a {@link ViewViewHandler} instance that decorates the
 57  
      * specified <code>ViewHandler</code> provided by the JSF runtime
 58  
      * implementation.</p>
 59  
      *
 60  
      * @param original Original <code>ViewHandler</code> to be decorated
 61  
      */
 62  0
     public ViewViewHandler(ViewHandler original) {
 63  0
         this.original = original;
 64  0
     }
 65  
 
 66  
 
 67  
     // -------------------------------------------------------- Static Variables
 68  
 
 69  
 
 70  
     /**
 71  
      * <p>Log instance for this class.</p>
 72  
      */
 73  0
     private static final Log log = LogFactory.getLog(ViewViewHandler.class);
 74  
 
 75  
 
 76  
     /**
 77  
      * <p>Message resources for this class.</p>
 78  
      */
 79  0
     private static Messages messages =
 80  
       new Messages("org.apache.shale.view.resources.Bundle",
 81  
                    ViewViewHandler.class.getClassLoader());
 82  
 
 83  
 
 84  
     // ------------------------------------------------------ Instance Variables
 85  
 
 86  
 
 87  
     /**
 88  
      * <p>Cached {@link ViewControllerMapper} we will use to translate
 89  
      * view identifiers to the class name of a {@link ViewController}.</p>
 90  
      */
 91  0
     private ViewControllerMapper mapper = null;
 92  
 
 93  
 
 94  
     /**
 95  
      * <p>The <code>ViewHandler</code> instance we are decorating.  All requests
 96  
      * are delegated to this instance, before or after any special handling that
 97  
      * is required.</p>
 98  
      */
 99  0
     private ViewHandler original = null;
 100  
 
 101  
 
 102  
     // ----------------------------------------------------- ViewHandler Methods
 103  
 
 104  
 
 105  
     /** {@inheritDoc} */
 106  
     public Locale calculateLocale(FacesContext context) {
 107  0
         return original.calculateLocale(context);
 108  
     }
 109  
 
 110  
 
 111  
     /** {@inheritDoc} */
 112  
     public String calculateRenderKitId(FacesContext context) {
 113  0
         return original.calculateRenderKitId(context);
 114  
     }
 115  
 
 116  
 
 117  
     /**
 118  
      * <p>After delegating to our original <code>ViewHandler</code>,
 119  
      * create and initialize any {@link ViewController} associated with
 120  
      * the specified view identifier.</p>
 121  
      *
 122  
      * @param context <code>FacesContext</code> for the current request
 123  
      * @param viewId View identifier of the view to be created
 124  
      */
 125  
     public UIViewRoot createView(FacesContext context, String viewId) {
 126  0
         UIViewRoot view = original.createView(context, viewId);
 127  0
         setupViewController(context, view, viewId, false);
 128  0
         return view;
 129  
     }
 130  
 
 131  
 
 132  
     /** {@inheritDoc} */
 133  
     public String getActionURL(FacesContext context, String viewId) {
 134  0
         return original.getActionURL(context, viewId);
 135  
     }
 136  
 
 137  
 
 138  
     /** {@inheritDoc} */
 139  
     public String getResourceURL(FacesContext context, String path) {
 140  0
         return original.getResourceURL(context, path);
 141  
     }
 142  
 
 143  
 
 144  
     /** {@inheritDoc} */
 145  
     public void renderView(FacesContext context, UIViewRoot view)
 146  
       throws IOException, FacesException {
 147  0
         original.renderView(context, view);
 148  0
     }
 149  
 
 150  
 
 151  
     /**
 152  
      * <p>After delegating to our original <code>ViewHandler</code>,
 153  
      * create and initialize any {@link ViewController} associated with
 154  
      * the specified view identifier.</p>
 155  
      *
 156  
      * @param context <code>FacesContext</code> for the current request
 157  
      * @param viewId View identifier of the view to be restored
 158  
      */
 159  
     public UIViewRoot restoreView(FacesContext context, String viewId) {
 160  0
         UIViewRoot view = original.restoreView(context, viewId);
 161  0
         setupViewController(context, view, viewId, true);
 162  0
         return view;
 163  
     }
 164  
 
 165  
 
 166  
     /** {@inheritDoc} */
 167  
     public void writeState(FacesContext context) throws IOException {
 168  0
         original.writeState(context);
 169  0
     }
 170  
 
 171  
 
 172  
     // --------------------------------------------------------- Private Methods
 173  
 
 174  
 
 175  
     /**
 176  
      * <p>Return the {@link ViewControllerMapper} instance we will use to
 177  
      * map view identifiers to class names of the corresponding
 178  
      * {@link ViewController} class.</p>
 179  
      *
 180  
      * @param context <code>FacesContext</code> for the current request
 181  
      */
 182  
     private ViewControllerMapper getViewControllerMapper(FacesContext context) {
 183  
 
 184  
         // DEPRECATED - respect the context init parameter if specified
 185  0
         if (mapper == null) {
 186  0
             mapper = getViewControllerMapperInstance(context);
 187  
         }
 188  
 
 189  
         // DEPRECATED - return cached instance from context init parameter
 190  0
         if (mapper != null) {
 191  0
             return mapper;
 192  
         }
 193  
 
 194  
         // Live lookup of the appropriate mapper as a managed bean
 195  0
         ValueBinding vb = context.getApplication().createValueBinding
 196  
           ("#{" + Constants.VIEW_MAPPER + "}");
 197  0
         ViewControllerMapper vcm = (ViewControllerMapper) vb.getValue(context);
 198  0
         return vcm;
 199  
 
 200  
     }
 201  
 
 202  
 
 203  
     /**
 204  
      * <p>Create and return the custom configured {@link ViewControllerMapper}
 205  
      * instance we will use for this application, or <code>null</code>
 206  
      * if there is no such instance.</p>
 207  
      *
 208  
      * @param context <code>FacesContext</code> for the current request
 209  
      *
 210  
      * @deprecated As of version 1.0.3, replace the application scoped
 211  
      *  managed bean at FacesConstants.VIEW_MAPPER instead of using the
 212  
      *  deprecated context initialization parameter mentioned here
 213  
      */
 214  
     private ViewControllerMapper getViewControllerMapperInstance
 215  
             (FacesContext context) {
 216  
 
 217  0
         String className =
 218  
           context.getExternalContext().getInitParameter(Constants.VIEW_CONTROLLER_MAPPER);
 219  0
         if (className == null) {
 220  0
             return null;
 221  
         }
 222  0
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
 223  0
         if (cl == null) {
 224  0
             cl = this.getClass().getClassLoader();
 225  
         }
 226  
         try {
 227  0
             Class clazz = cl.loadClass(className);
 228  0
             return (ViewControllerMapper) clazz.newInstance();
 229  0
         } catch (ClassCastException e) {
 230  0
             throw new FacesException
 231  
               (messages.getMessage("view.vcmCast",
 232  
                                    new Object[] { className }), e);
 233  0
         } catch (ClassNotFoundException e) {
 234  0
             throw new FacesException
 235  
               (messages.getMessage("view.vcmClass",
 236  
                                    new Object[] { className }), e);
 237  0
         } catch (IllegalAccessException e) {
 238  0
             throw new FacesException
 239  
               (messages.getMessage("view.vcmAccess",
 240  
                                    new Object[] { className }), e);
 241  0
         } catch (InstantiationException e) {
 242  0
             throw new FacesException
 243  
               (messages.getMessage("view.vcmInstantiate",
 244  
                                    new Object[] { className }), e);
 245  
         }
 246  
 
 247  
     }
 248  
 
 249  
 
 250  
     /**
 251  
      * <p>Create and initialize an appropriate {@link ViewController} instance
 252  
      * associated with the specified view, which was just created or just
 253  
      * restored.</p>
 254  
      *
 255  
      * @param context <code>FacesContext</code> for the current request
 256  
      * @param view <code>UIViewRoot</code> just created or restored
 257  
      *  (or <code>null</code> if there was no such view)
 258  
      * @param viewId of the <code>UIViewRoot</code> just created or
 259  
      *  restored
 260  
      * @param postBack <code>true</code> if this is a post back to
 261  
      *  an existing view
 262  
      */
 263  
     private void setupViewController(FacesContext context, UIViewRoot view,
 264  
                                      String viewId, boolean postBack) {
 265  
 
 266  
         // Is there actually a view for us to procses?
 267  0
         if (view == null) {
 268  0
             return;
 269  
         }
 270  
 
 271  
         // Cache the postback flag so that it can be used inside
 272  
         // the AbstractViewcontroller implementation
 273  0
         if (postBack) {
 274  0
             context.getExternalContext().getRequestMap().
 275  
               put(FacesConstants.VIEW_POSTBACK, Boolean.TRUE);
 276  
         }
 277  
 
 278  
         // Its not the responsibilty of createView method to set the viewId of the view
 279  
         // (See JSF 1.1 spec. pg. 7-16)
 280  
         //String viewId = view.getViewId();
 281  0
         if (log.isDebugEnabled()) {
 282  0
             log.debug("setupViewController(" + viewId + "," + postBack + ")");
 283  
         }
 284  
 
 285  
         // Map our view identifier to a corresponding managed bean name
 286  0
         ViewControllerMapper viewControllerMapper = getViewControllerMapper(context);
 287  0
         if (viewControllerMapper == null) {
 288  0
             log.warn(messages.getMessage("view.noViewControllerMapper"));
 289  0
             return;
 290  
         }
 291  0
         String viewName = viewControllerMapper.mapViewId(viewId);
 292  
 
 293  
         // Retrieve an existing instance, or one created and configured by
 294  
         // the managed bean facility
 295  0
         Object vc = null;
 296  0
         VariableResolver vr =
 297  
             context.getApplication().getVariableResolver();
 298  
         try {
 299  0
             vc = vr.resolveVariable(context, viewName);
 300  0
             if (vc == null) {
 301  0
                 if (log.isDebugEnabled()) {
 302  0
                     log.debug(messages.getMessage("view.noViewController",
 303  
                                                   new Object[] { viewId, viewName }));
 304  
                 }
 305  0
                 return;
 306  
             }
 307  0
         } catch (EvaluationException e) {
 308  0
             log.warn(messages.getMessage("view.evalException",
 309  
                                           new Object[] { viewId, viewName }), e);
 310  0
             return;
 311  0
         }
 312  
 
 313  
         // Set the postBack property on a ViewController instance
 314  0
         if (vc instanceof ViewController) {
 315  0
             ((ViewController) vc).setPostBack(postBack);
 316  
         }
 317  
 
 318  
         // Schedule this instance for later processing as needed
 319  0
         Map map = context.getExternalContext().getRequestMap();
 320  0
         map.put(FacesConstants.VIEW_NAME_RENDERED, viewName);
 321  0
         List list = (List) map.get(FacesConstants.VIEWS_INITIALIZED);
 322  0
         if (list == null) {
 323  0
             list = new ArrayList();
 324  0
             map.put(FacesConstants.VIEWS_INITIALIZED, list);
 325  
         }
 326  0
         list.add(vc);
 327  
 
 328  0
     }
 329  
 
 330  
 
 331  
     /**
 332  
      * <p>Return the {@link ViewControllerCallbacks} instance we
 333  
      * will use.</p>
 334  
      *
 335  
      * @param context <code>FacesContext</code> for the current request
 336  
      *
 337  
      * @since 1.0.1
 338  
      */
 339  
     private ViewControllerCallbacks getViewControllerCallbacks(FacesContext context) {
 340  
 
 341  0
         ValueBinding vb = context.getApplication().createValueBinding
 342  
           ("#{" + FacesConstants.VIEW_CALLBACKS + "}");
 343  0
         return (ViewControllerCallbacks) vb.getValue(context);
 344  
 
 345  
     }
 346  
 
 347  
 
 348  
 }