Coverage Report - org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage
 
Classes in this File Line Coverage Branch Coverage Complexity
FaceletViewDeclarationLanguage
0%
0/798
0%
0/548
5.406
FaceletViewDeclarationLanguage$FaceletViewMetadata
0%
0/19
0%
0/2
5.406
 
 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.view.facelets;
 20  
 
 21  
 import java.beans.BeanDescriptor;
 22  
 import java.beans.BeanInfo;
 23  
 import java.beans.PropertyDescriptor;
 24  
 import java.io.FileNotFoundException;
 25  
 import java.io.IOException;
 26  
 import java.io.Writer;
 27  
 import java.util.ArrayList;
 28  
 import java.util.Collections;
 29  
 import java.util.EnumSet;
 30  
 import java.util.HashMap;
 31  
 import java.util.HashSet;
 32  
 import java.util.List;
 33  
 import java.util.Map;
 34  
 import java.util.Set;
 35  
 import java.util.logging.Level;
 36  
 import java.util.logging.Logger;
 37  
 
 38  
 import javax.el.ELContext;
 39  
 import javax.el.ELException;
 40  
 import javax.el.MethodExpression;
 41  
 import javax.el.ValueExpression;
 42  
 import javax.el.VariableMapper;
 43  
 import javax.faces.FacesException;
 44  
 import javax.faces.FacesWrapper;
 45  
 import javax.faces.FactoryFinder;
 46  
 import javax.faces.application.Application;
 47  
 import javax.faces.application.ProjectStage;
 48  
 import javax.faces.application.Resource;
 49  
 import javax.faces.application.StateManager;
 50  
 import javax.faces.application.ViewHandler;
 51  
 import javax.faces.component.ActionSource2;
 52  
 import javax.faces.component.EditableValueHolder;
 53  
 import javax.faces.component.UIComponent;
 54  
 import javax.faces.component.UINamingContainer;
 55  
 import javax.faces.component.UIPanel;
 56  
 import javax.faces.component.UIViewRoot;
 57  
 import javax.faces.component.visit.VisitContext;
 58  
 import javax.faces.component.visit.VisitHint;
 59  
 import javax.faces.context.ExternalContext;
 60  
 import javax.faces.context.FacesContext;
 61  
 import javax.faces.context.ResponseWriter;
 62  
 import javax.faces.event.ActionEvent;
 63  
 import javax.faces.event.ActionListener;
 64  
 import javax.faces.event.MethodExpressionActionListener;
 65  
 import javax.faces.event.MethodExpressionValueChangeListener;
 66  
 import javax.faces.event.PhaseId;
 67  
 import javax.faces.event.PostAddToViewEvent;
 68  
 import javax.faces.event.PostRestoreStateEvent;
 69  
 import javax.faces.event.ValueChangeEvent;
 70  
 import javax.faces.event.ValueChangeListener;
 71  
 import javax.faces.render.RenderKit;
 72  
 import javax.faces.render.RenderKitFactory;
 73  
 import javax.faces.render.ResponseStateManager;
 74  
 import javax.faces.validator.MethodExpressionValidator;
 75  
 import javax.faces.validator.Validator;
 76  
 import javax.faces.view.ActionSource2AttachedObjectHandler;
 77  
 import javax.faces.view.ActionSource2AttachedObjectTarget;
 78  
 import javax.faces.view.AttachedObjectHandler;
 79  
 import javax.faces.view.AttachedObjectTarget;
 80  
 import javax.faces.view.BehaviorHolderAttachedObjectHandler;
 81  
 import javax.faces.view.BehaviorHolderAttachedObjectTarget;
 82  
 import javax.faces.view.EditableValueHolderAttachedObjectHandler;
 83  
 import javax.faces.view.EditableValueHolderAttachedObjectTarget;
 84  
 import javax.faces.view.StateManagementStrategy;
 85  
 import javax.faces.view.ValueHolderAttachedObjectHandler;
 86  
 import javax.faces.view.ValueHolderAttachedObjectTarget;
 87  
 import javax.faces.view.ViewDeclarationLanguage;
 88  
 import javax.faces.view.ViewMetadata;
 89  
 import javax.faces.view.facelets.Facelet;
 90  
 import javax.faces.view.facelets.FaceletContext;
 91  
 import javax.faces.view.facelets.ResourceResolver;
 92  
 import javax.servlet.http.HttpServletResponse;
 93  
 import org.apache.myfaces.application.StateManagerImpl;
 94  
 
 95  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 96  
 import org.apache.myfaces.config.RuntimeConfig;
 97  
 import org.apache.myfaces.shared.application.DefaultViewHandlerSupport;
 98  
 import org.apache.myfaces.shared.application.ViewHandlerSupport;
 99  
 import org.apache.myfaces.shared.config.MyfacesConfig;
 100  
 import org.apache.myfaces.shared.util.ClassUtils;
 101  
 import org.apache.myfaces.shared.util.StringUtils;
 102  
 import org.apache.myfaces.shared.util.WebConfigParamUtils;
 103  
 import org.apache.myfaces.view.ViewDeclarationLanguageStrategy;
 104  
 import org.apache.myfaces.view.ViewMetadataBase;
 105  
 import org.apache.myfaces.view.facelets.compiler.Compiler;
 106  
 import org.apache.myfaces.view.facelets.compiler.SAXCompiler;
 107  
 import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
 108  
 import org.apache.myfaces.view.facelets.el.LocationMethodExpression;
 109  
 import org.apache.myfaces.view.facelets.el.LocationValueExpression;
 110  
 import org.apache.myfaces.view.facelets.el.MethodExpressionMethodExpression;
 111  
 import org.apache.myfaces.view.facelets.el.RedirectMethodExpressionValueExpressionActionListener;
 112  
 import org.apache.myfaces.view.facelets.el.RedirectMethodExpressionValueExpressionValidator;
 113  
 import org.apache.myfaces.view.facelets.el.RedirectMethodExpressionValueExpressionValueChangeListener;
 114  
 import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression;
 115  
 import org.apache.myfaces.view.facelets.el.VariableMapperWrapper;
 116  
 import org.apache.myfaces.view.facelets.impl.DefaultFaceletFactory;
 117  
 import org.apache.myfaces.view.facelets.impl.DefaultResourceResolver;
 118  
 import org.apache.myfaces.view.facelets.tag.composite.ClientBehaviorAttachedObjectTarget;
 119  
 import org.apache.myfaces.view.facelets.tag.composite.ClientBehaviorRedirectBehaviorAttachedObjectHandlerWrapper;
 120  
 import org.apache.myfaces.view.facelets.tag.composite.ClientBehaviorRedirectEventComponentWrapper;
 121  
 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 122  
 import org.apache.myfaces.view.facelets.tag.jsf.core.AjaxHandler;
 123  
 import org.apache.myfaces.view.facelets.tag.ui.UIDebug;
 124  
 
 125  
 import static org.apache.myfaces.view.facelets.DefaultFaceletsStateManagementStrategy.*;
 126  
 import org.apache.myfaces.view.facelets.compiler.FaceletsCompilerSupport;
 127  
 import org.apache.myfaces.view.facelets.compiler.RefreshDynamicComponentListener;
 128  
 import org.apache.myfaces.view.facelets.impl.SectionUniqueIdCounter;
 129  
 import org.apache.myfaces.view.facelets.pool.RestoreViewFromPoolResult;
 130  
 import org.apache.myfaces.view.facelets.pool.ViewEntry;
 131  
 import org.apache.myfaces.view.facelets.pool.ViewPool;
 132  
 import org.apache.myfaces.view.facelets.pool.ViewStructureMetadata;
 133  
 import org.apache.myfaces.view.facelets.tag.composite.CreateDynamicCompositeComponentListener;
 134  
 import org.apache.myfaces.view.facelets.tag.jsf.PartialMethodExpressionActionListener;
 135  
 import org.apache.myfaces.view.facelets.tag.jsf.PartialMethodExpressionValidator;
 136  
 import org.apache.myfaces.view.facelets.tag.jsf.PartialMethodExpressionValueChangeListener;
 137  
 import org.apache.myfaces.view.facelets.util.FaceletsViewDeclarationLanguageUtils;
 138  
 
 139  
 /**
 140  
  * This class represents the abstraction of Facelets as a ViewDeclarationLanguage.
 141  
  *
 142  
  * @author Simon Lessard (latest modification by $Author$)
 143  
  * @version $Revision$ $Date$
 144  
  *
 145  
  * @since 2.0
 146  
  */
 147  0
 public class FaceletViewDeclarationLanguage extends FaceletViewDeclarationLanguageBase
 148  
 {
 149  
     //private static final Log log = LogFactory.getLog(FaceletViewDeclarationLanguage.class);
 150  0
     private static final Logger log = Logger.getLogger(FaceletViewDeclarationLanguage.class.getName());
 151  
 
 152  0
     private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
 153  
 
 154  0
     private static final Class<?>[] VALUE_CHANGE_LISTENER_SIGNATURE = new Class[]{ValueChangeEvent.class};
 155  
 
 156  0
     private static final Class<?>[] ACTION_LISTENER_SIGNATURE = new Class[]{ActionEvent.class};
 157  
 
 158  0
     private static final Class<?>[] VALIDATOR_SIGNATURE
 159  
             = new Class[]{FacesContext.class, UIComponent.class, Object.class};
 160  
 
 161  
     public static final String CHARACTER_ENCODING_KEY = "javax.faces.request.charset";
 162  
 
 163  
     public final static long DEFAULT_REFRESH_PERIOD = 0;
 164  
     public final static long DEFAULT_REFRESH_PERIOD_PRODUCTION = -1;
 165  
 
 166  
     public final static String DEFAULT_CHARACTER_ENCODING = "UTF-8";
 167  
 
 168  
     /**
 169  
      * Define the default buffer size value passed to ExternalContext.setResponseBufferResponse() and in a
 170  
      * servlet environment to HttpServletResponse.setBufferSize().
 171  
      */
 172  
     @JSFWebConfigParam(since = "2.0", deprecated = true, classType = "java.lang.Integer")
 173  
     private final static String PARAM_BUFFER_SIZE_DEPRECATED = "facelets.BUFFER_SIZE";
 174  
 
 175  0
     private final static String[] PARAMS_BUFFER_SIZE = {ViewHandler.FACELETS_BUFFER_SIZE_PARAM_NAME,
 176  
         PARAM_BUFFER_SIZE_DEPRECATED};
 177  
 
 178  
     //private final static String PARAM_BUILD_BEFORE_RESTORE = "facelets.BUILD_BEFORE_RESTORE";
 179  
 
 180  
     /**
 181  
      * Constant used by EncodingHandler to indicate the current encoding of the page being built,
 182  
      * and indicate which one is the response encoding on getResponseEncoding(FacesContext, String) method.
 183  
      */
 184  
     public final static String PARAM_ENCODING = "facelets.Encoding";
 185  
 
 186  
     /**
 187  
      * Define the period used to refresh the facelet abstract syntax tree from the view definition file. 
 188  
      *
 189  
      * <p>By default is infinite (no active).</p>
 190  
      */
 191  
     @JSFWebConfigParam(since = "2.0", defaultValue = "-1", deprecated = true)
 192  
     public final static String PARAM_REFRESH_PERIOD_DEPRECATED = "facelets.REFRESH_PERIOD";
 193  
 
 194  0
     public final static String[] PARAMS_REFRESH_PERIOD = {ViewHandler.FACELETS_REFRESH_PERIOD_PARAM_NAME,
 195  
         PARAM_REFRESH_PERIOD_DEPRECATED};
 196  
 
 197  
     /**
 198  
      * Class implementing ResourceResolver interface used to locate facelet resources. 
 199  
      */
 200  
     @JSFWebConfigParam(since = "2.0", alias = "facelets.RESOURCE_RESOLVER")
 201  
     public final static String PARAM_RESOURCE_RESOLVER = "javax.faces.FACELETS_RESOURCE_RESOLVER";
 202  
 
 203  
     /**
 204  
      * Class implementing ResourceResolver interface used to locate facelet resources.
 205  
      */
 206  
     @JSFWebConfigParam(since = "2.0", deprecated = true)
 207  
     private final static String PARAM_RESOURCE_RESOLVER_DEPRECATED = "facelets.RESOURCE_RESOLVER";
 208  
 
 209  0
     private final static String[] PARAMS_RESOURCE_RESOLVER
 210  
             = {PARAM_RESOURCE_RESOLVER, PARAM_RESOURCE_RESOLVER_DEPRECATED};
 211  
 
 212  
     @JSFWebConfigParam(since = "2.1", defaultValue = "false", expectedValues = "true, false", tags = "performance")
 213  
     private final static String PARAM_MARK_INITIAL_STATE_WHEN_APPLY_BUILD_VIEW
 214  
             = "org.apache.myfaces.MARK_INITIAL_STATE_WHEN_APPLY_BUILD_VIEW";
 215  
 
 216  
     public final static String FILLED_VIEW = "org.apache.myfaces.FILLED_VIEW";
 217  
 
 218  
     //BEGIN CONSTANTS SET ON BUILD VIEW
 219  
 
 220  
     public final static String BUILDING_VIEW_METADATA = "org.apache.myfaces.BUILDING_VIEW_METADATA";
 221  
 
 222  
     public final static String REFRESHING_TRANSIENT_BUILD = "org.apache.myfaces.REFRESHING_TRANSIENT_BUILD";
 223  
 
 224  
     public final static String REFRESH_TRANSIENT_BUILD_ON_PSS = "org.apache.myfaces.REFRESH_TRANSIENT_BUILD_ON_PSS";
 225  
 
 226  
     public final static String USING_PSS_ON_THIS_VIEW = "org.apache.myfaces.USING_PSS_ON_THIS_VIEW";
 227  
 
 228  
     public final static String REMOVING_COMPONENTS_BUILD = "org.apache.myfaces.REMOVING_COMPONENTS_BUILD";
 229  
     //END CONSTANTS SET ON BUILD VIEW
 230  
 
 231  
     /**
 232  
      * Marker to indicate tag handlers the view currently being built is using
 233  
      * partial state saving and it is necessary to call UIComponent.markInitialState
 234  
      * after component instances are populated. 
 235  
      */
 236  
     public final static String MARK_INITIAL_STATE_KEY = "org.apache.myfaces.MARK_INITIAL_STATE";
 237  
     
 238  
     public final static String IS_BUILDING_INITIAL_STATE_KEY_ALIAS
 239  
             = "javax.faces.view.ViewDeclarationLanguage.IS_BUILDING_INITIAL_STATE";
 240  
 
 241  
     public final static String CLEAN_TRANSIENT_BUILD_ON_RESTORE
 242  
             = "org.apache.myfaces.CLEAN_TRANSIENT_BUILD_ON_RESTORE";
 243  
 
 244  
     private final static String STATE_KEY = "<!--@@JSF_FORM_STATE_MARKER@@-->";
 245  
 
 246  0
     private final static int STATE_KEY_LEN = STATE_KEY.length();
 247  
     
 248  0
     private static final Set<VisitHint> VISIT_HINTS_DYN_REFRESH = Collections.unmodifiableSet( 
 249  
             EnumSet.of(VisitHint.SKIP_ITERATION));
 250  
     
 251  
     /**
 252  
      * Key used to cache component ids for the counter
 253  
      */
 254  
     public final static String CACHED_COMPONENT_IDS = "oam.CACHED_COMPONENT_IDS"; 
 255  
     
 256  
     private static final String ASTERISK = "*";
 257  
 
 258  
     private int _bufferSize;
 259  
 
 260  
     // This param evolve in jsf 2.0 to partial state saving
 261  
     //private boolean _buildBeforeRestore = false;
 262  
 
 263  
     private ViewHandlerSupport _cachedViewHandlerSupport;
 264  
 
 265  
     private String _defaultSuffix;
 266  
 
 267  
     private FaceletFactory _faceletFactory;
 268  
 
 269  
     private StateManagementStrategy _stateMgmtStrategy;
 270  
     
 271  0
     private RenderKitFactory _renderKitFactory = null;
 272  
 
 273  
     private boolean _partialStateSaving;
 274  
 
 275  
     private boolean _refreshTransientBuildOnPSS;
 276  
 
 277  
     private boolean _refreshTransientBuildOnPSSAuto;
 278  
 
 279  
     private Set<String> _viewIds;
 280  
 
 281  
     private boolean _markInitialStateWhenApplyBuildView;
 282  
 
 283  
     private final ViewDeclarationLanguageStrategy _strategy;
 284  
 
 285  
     private ResourceResolver _resourceResolver;
 286  
     
 287  
     private Map<String, List<String>> _contractMappings;
 288  
     private List<String> _prefixWildcardKeys;
 289  
     
 290  
     private FaceletsCompilerSupport _faceletsCompilerSupport;
 291  
     
 292  
     private MyfacesConfig _config;
 293  
     
 294  
     private ViewPoolProcessor _viewPoolProcessor;
 295  
 
 296  
     /**
 297  
      *
 298  
      */
 299  
     public FaceletViewDeclarationLanguage(FacesContext context)
 300  0
     {
 301  0
         _config = MyfacesConfig.getCurrentInstance(context.getExternalContext());
 302  0
         initialize(context);
 303  0
         _strategy = new FaceletViewDeclarationLanguageStrategy();
 304  0
     }
 305  
 
 306  
     public FaceletViewDeclarationLanguage(FacesContext context, ViewDeclarationLanguageStrategy strategy)
 307  0
     {
 308  0
         _config = MyfacesConfig.getCurrentInstance(context.getExternalContext());
 309  0
         initialize(context);
 310  0
         _strategy = strategy;
 311  0
     }
 312  
 
 313  
 
 314  
     @Override
 315  
     public String getId()
 316  
     {
 317  0
         return ViewDeclarationLanguage.FACELETS_VIEW_DECLARATION_LANGUAGE_ID;
 318  
     }
 319  
 
 320  
     @Override
 321  
     public boolean viewExists(FacesContext facesContext, String viewId)
 322  
     {
 323  0
         if (_strategy.handles(viewId))
 324  
         {
 325  0
             return _resourceResolver.resolveUrl(viewId) != null;
 326  
         }
 327  0
         return false;
 328  
     }
 329  
 
 330  
     private RestoreViewFromPoolResult tryRestoreViewFromCache(FacesContext context, UIViewRoot view)
 331  
     {
 332  0
         if (_viewPoolProcessor != null)
 333  
         {
 334  0
             ViewPool viewPool = _viewPoolProcessor.getViewPool(context, view);
 335  0
             if (viewPool != null)
 336  
             {
 337  0
                 ViewStructureMetadata metadata = viewPool.retrieveStaticViewStructureMetadata(context, view);
 338  0
                 if (metadata != null)
 339  
                 {
 340  0
                     ViewEntry entry = viewPool.popStaticOrPartialStructureView(context, view);
 341  0
                     if (entry != null)
 342  
                     {
 343  0
                         _viewPoolProcessor.cloneAndRestoreView(context, view, entry, metadata);
 344  0
                         return entry.getResult();
 345  
                     }
 346  
                 }
 347  
             }
 348  
         }
 349  0
         return null;
 350  
     }
 351  
 
 352  
     /**
 353  
      * {@inheritDoc}
 354  
      */
 355  
     @Override
 356  
     public void buildView(FacesContext context, UIViewRoot view) throws IOException
 357  
     {
 358  0
         if (isFilledView(context, view))
 359  
         {
 360  0
             if (view != null && 
 361  
                 FaceletViewDeclarationLanguageBase.isDynamicComponentRefreshTransientBuildActive(context, view))
 362  
             {
 363  
                 // don't return
 364  
             }
 365  
             else
 366  
             {
 367  0
                 return;
 368  
             }
 369  
         }
 370  
 
 371  
         // setup our viewId
 372  0
         String previousViewId = view.getViewId();
 373  0
         String renderedViewId = getRenderedViewId(context, previousViewId);
 374  
 
 375  0
         if (renderedViewId == null)
 376  
         {
 377  0
             view.setViewId(renderedViewId);
 378  
         }
 379  0
         else if (!renderedViewId.equals(previousViewId))
 380  
         {
 381  0
             view.setViewId(renderedViewId);
 382  
         }
 383  
 
 384  0
         if (log.isLoggable(Level.FINEST))
 385  
         {
 386  0
             log.finest("Building View: " + renderedViewId);
 387  
         }
 388  
 
 389  0
         boolean usePartialStateSavingOnThisView = _usePartialStateSavingOnThisView(renderedViewId);
 390  0
         boolean refreshTransientBuild = (view.getChildCount() > 0);
 391  0
         boolean refreshTransientBuildOnPSS = (usePartialStateSavingOnThisView && _refreshTransientBuildOnPSS);
 392  0
         boolean refreshPartialView = false;
 393  
 
 394  0
         if (_viewPoolProcessor != null && !refreshTransientBuild)
 395  
         {
 396  0
             RestoreViewFromPoolResult result = tryRestoreViewFromCache(context, view);
 397  0
             if (result != null)
 398  
             {
 399  
                 // Since all transient stuff has been removed, add listeners that keep
 400  
                 // track of tree updates.
 401  0
                 if (RestoreViewFromPoolResult.COMPLETE.equals(result))
 402  
                 {
 403  0
                     if (!PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId()))
 404  
                     {
 405  0
                         ((DefaultFaceletsStateManagementStrategy) 
 406  
                                 getStateManagementStrategy(context, view.getViewId())).
 407  
                                 suscribeListeners(view);
 408  
                     }
 409  
                     // If the result is complete, the view restored here is static. 
 410  
                     // static views can be marked as filled.
 411  0
                     if (!refreshTransientBuildOnPSS)
 412  
                     {
 413  
                         // This option will be true on this cases:
 414  
                         // -pss is true and refresh is not active
 415  0
                         setFilledView(context, view);
 416  
                     }
 417  
                     //At this point refreshTransientBuild = false && refreshTransientBuildOnPSS is true
 418  0
                     else if (_refreshTransientBuildOnPSSAuto &&
 419  
                              !context.getAttributes().containsKey(CLEAN_TRANSIENT_BUILD_ON_RESTORE))
 420  
                     {
 421  0
                         setFilledView(context, view);
 422  
                     }
 423  0
                     return;
 424  
                 }
 425  
                 else
 426  
                 {
 427  
                     // We need to refresh a partial view.
 428  0
                     refreshTransientBuild = true;
 429  0
                     refreshPartialView = true;
 430  
                 }
 431  
             }
 432  
         }
 433  
         
 434  0
         if (usePartialStateSavingOnThisView)
 435  
         {
 436  
             // Before apply we need to make sure the current view has
 437  
             // a clientId that will be used as a key to save and restore
 438  
             // the current view. Note that getClientId is never called (or used)
 439  
             // from UIViewRoot.
 440  0
             if (view.getId() == null)
 441  
             {
 442  0
                 view.setId(view.createUniqueId(context, null));
 443  
             }
 444  
 
 445  0
             context.getAttributes().put(USING_PSS_ON_THIS_VIEW, Boolean.TRUE);
 446  
             //Add a key to indicate ComponentTagHandlerDelegate to 
 447  
             //call UIComponent.markInitialState after it is populated
 448  0
             if (!refreshTransientBuild || refreshPartialView)
 449  
             {
 450  0
                 context.getAttributes().put(StateManager.IS_BUILDING_INITIAL_STATE, Boolean.TRUE);
 451  0
                 context.getAttributes().put(IS_BUILDING_INITIAL_STATE_KEY_ALIAS, Boolean.TRUE);
 452  
             }
 453  0
             if (!refreshTransientBuild && _markInitialStateWhenApplyBuildView)
 454  
             {
 455  0
                 context.getAttributes().put(MARK_INITIAL_STATE_KEY, Boolean.TRUE);
 456  
             }
 457  0
             if (refreshTransientBuildOnPSS)
 458  
             {
 459  
                 //This value is only set when _refreshTransientBuildOnPSSMode is "auto" or "true" 
 460  0
                 context.getAttributes().put(REFRESH_TRANSIENT_BUILD_ON_PSS,
 461  
                                             _refreshTransientBuildOnPSSAuto ? "auto" : "true");
 462  
             }
 463  
         }
 464  
 
 465  
         try
 466  
         {
 467  0
             if (refreshTransientBuild)
 468  
             {
 469  0
                 context.getAttributes().put(REFRESHING_TRANSIENT_BUILD, Boolean.TRUE);
 470  
 
 471  
                 // In theory, this should be disabled on ComponentTagHandlerDelegate,
 472  
                 // otherwise we could lost PostAddToViewEvent / PreRemoveFromViewEvent
 473  
                 // caused by c:if effect or facelets cleanup algorithm
 474  
                 //context.setProcessingEvents(false);
 475  
             }
 476  
             // populate UIViewRoot
 477  0
             _getFacelet(context, renderedViewId).apply(context, view);
 478  
         }
 479  
         finally
 480  
         {
 481  0
             if (refreshTransientBuildOnPSS)
 482  
             {
 483  0
                 context.getAttributes().remove(REFRESH_TRANSIENT_BUILD_ON_PSS);
 484  
             }
 485  0
             if (refreshTransientBuild)
 486  
             {
 487  
                 //context.setProcessingEvents(true);
 488  0
                 if (FaceletViewDeclarationLanguageBase.isDynamicComponentRefreshTransientBuildActive(context))
 489  
                 {
 490  0
                     VisitContext visitContext = (VisitContext) getVisitContextFactory().
 491  
                         getVisitContext(context, null, VISIT_HINTS_DYN_REFRESH);
 492  0
                     view.visitTree(visitContext, new PublishDynamicComponentRefreshTransientBuildCallback());
 493  
                 }
 494  0
                 if (!usePartialStateSavingOnThisView || refreshTransientBuildOnPSS)
 495  
                 {
 496  
                     // When the facelet is applied, all components are removed and added from view,
 497  
                     // but the difference resides in the ordering. Since the view is
 498  
                     // being refreshed, if we don't do this manually, some tags like
 499  
                     // cc:insertChildren or cc:insertFacet will not work correctly, because
 500  
                     // we expect PostAddToViewEvent will be propagated from parent to child, and
 501  
                     // facelets refreshing algorithm do the opposite.
 502  
                     //FaceletViewDeclarationLanguage._publishPreRemoveFromViewEvent(context, view);
 503  
                     //FaceletViewDeclarationLanguage._publishPostAddToViewEvent(context, view);
 504  0
                     FaceletViewDeclarationLanguage._publishPostBuildComponentTreeOnRestoreViewEvent(context, view);
 505  
                 }
 506  
 
 507  0
                 context.getAttributes().remove(REFRESHING_TRANSIENT_BUILD);
 508  
             }
 509  
             else
 510  
             {
 511  
                 // Publish PostAddToView over UIViewRoot, because this is not done automatically.
 512  0
                 context.getApplication().publishEvent(context, PostAddToViewEvent.class, UIViewRoot.class, view);
 513  
             }
 514  0
         }
 515  
 
 516  
         // set this view as filled
 517  0
         if (refreshTransientBuild)
 518  
         {
 519  
             //This option will be true on this cases:
 520  
             //- pss is false, but we are refreshing
 521  
             //- pss is true, and we are refreshing a view already filled
 522  0
             setFilledView(context, view);
 523  
         }
 524  0
         else if (!refreshTransientBuildOnPSS)
 525  
         {
 526  
             // This option will be true on this cases:
 527  
             // -pss is true and refresh is not active
 528  0
             setFilledView(context, view);
 529  
         }
 530  
         //At this point refreshTransientBuild = false && refreshTransientBuildOnPSS is true
 531  0
         else if (_refreshTransientBuildOnPSSAuto &&
 532  
                  !context.getAttributes().containsKey(CLEAN_TRANSIENT_BUILD_ON_RESTORE))
 533  
         {
 534  0
             setFilledView(context, view);
 535  
         }
 536  
 
 537  
         // Suscribe listeners if we are using partialStateSaving
 538  0
         if (usePartialStateSavingOnThisView)
 539  
         {
 540  
             // UIViewRoot.markInitialState() is not called because it does
 541  
             // not have a facelet tag handler class that create it, instead
 542  
             // new instances are created programatically.
 543  0
             if (!refreshTransientBuild || refreshPartialView)
 544  
             {
 545  
                 // Save the state
 546  0
                 if (_viewPoolProcessor != null &&
 547  
                     _viewPoolProcessor.isViewPoolEnabledForThisView(context, view))
 548  
                 {
 549  0
                     _viewPoolProcessor.storeViewStructureMetadata(context, view);
 550  
                 }
 551  0
                 if (_markInitialStateWhenApplyBuildView)
 552  
                 {
 553  0
                     if (!refreshTransientBuildOnPSS ||
 554  
                         !view.getAttributes().containsKey(COMPONENT_ADDED_AFTER_BUILD_VIEW))
 555  
                     {
 556  0
                         view.markInitialState();
 557  
                     }
 558  
 
 559  
                     //Remove the key that indicate we need to call UIComponent.markInitialState
 560  
                     //on the current tree
 561  0
                     context.getAttributes().remove(MARK_INITIAL_STATE_KEY);
 562  
                 }
 563  
                 else
 564  
                 {
 565  0
                     context.getAttributes().put(MARK_INITIAL_STATE_KEY, Boolean.TRUE);
 566  0
                     _markInitialStateOnView(view, refreshTransientBuildOnPSS);
 567  0
                     context.getAttributes().remove(MARK_INITIAL_STATE_KEY);
 568  
                 }
 569  0
                 context.getAttributes().remove(StateManager.IS_BUILDING_INITIAL_STATE);
 570  0
                 context.getAttributes().remove(IS_BUILDING_INITIAL_STATE_KEY_ALIAS);
 571  
             }
 572  
 
 573  
             // We need to suscribe the listeners of changes in the component tree
 574  
             // only the first time here. Later we suscribe this listeners on
 575  
             // DefaultFaceletsStateManagement.restoreView after calling 
 576  
             // _publishPostBuildComponentTreeOnRestoreViewEvent(), to ensure 
 577  
             // relocated components are not retrieved later on getClientIdsRemoved().
 578  0
             if (!(refreshTransientBuild && PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId())) &&
 579  
                 !view.isTransient())
 580  
             {
 581  0
                 ((DefaultFaceletsStateManagementStrategy) getStateManagementStrategy(context, view.getViewId())).
 582  
                         suscribeListeners(view);
 583  
             }
 584  
 
 585  0
             context.getAttributes().remove(USING_PSS_ON_THIS_VIEW);
 586  
         }
 587  
 
 588  
         // Remove this var from faces context because this one prevent AjaxHandler
 589  
         // register the standard script library on Post-Redirect-Get pattern or
 590  
         // in the next view
 591  0
         context.getAttributes().remove(AjaxHandler.STANDARD_JSF_AJAX_LIBRARY_LOADED);
 592  0
     }
 593  
 
 594  
     private void _markInitialStateOnView(final UIViewRoot view, final boolean refreshTransientBuildOnPSS)
 595  
     {
 596  0
         if (!refreshTransientBuildOnPSS ||
 597  
                 !view.getAttributes().containsKey(COMPONENT_ADDED_AFTER_BUILD_VIEW))
 598  
         {
 599  0
             if (!view.isTransient())
 600  
             {
 601  0
                 view.markInitialState();
 602  
             }
 603  
         }
 604  
 
 605  0
         int childCount = view.getChildCount();
 606  0
         if (childCount > 0)
 607  
         {
 608  0
             for (int i = 0; i < childCount; i++)
 609  
             {
 610  0
                 UIComponent child = view.getChildren().get(i);
 611  0
                 if (!child.isTransient())
 612  
                 {
 613  0
                     _markInitialState(child);
 614  
                 }
 615  
             }
 616  
         }
 617  0
         if (view.getFacetCount() > 0)
 618  
         {
 619  0
             Map<String, UIComponent> facetMap = view.getFacets();
 620  0
             for (Map.Entry<String, UIComponent> entry : facetMap.entrySet())
 621  
             {
 622  0
                 UIComponent child = entry.getValue();
 623  0
                 if (!child.isTransient())
 624  
                 {
 625  0
                     _markInitialState(child);
 626  
                 }
 627  0
             }
 628  
 
 629  
         }
 630  0
     }
 631  
 
 632  
     private void _markInitialState(final UIComponent component)
 633  
     {
 634  0
         component.markInitialState();
 635  
 
 636  0
         final int childCount = component.getChildCount();
 637  0
         if (childCount > 0)
 638  
         {
 639  0
             for (int i = 0; i < childCount; i++)
 640  
             {
 641  0
                 UIComponent child = component.getChildren().get(i);
 642  0
                 if (!child.isTransient())
 643  
                 {
 644  0
                     _markInitialState(child);
 645  
                 }
 646  
             }
 647  
         }
 648  0
         if (component.getFacetCount() > 0)
 649  
         {
 650  0
             Map<String, UIComponent> facetMap = component.getFacets();
 651  0
             for (Map.Entry<String, UIComponent> entry : facetMap.entrySet())
 652  
             {
 653  0
                 UIComponent child = entry.getValue();
 654  0
                 if (!child.isTransient())
 655  
                 {
 656  0
                     _markInitialState(child);
 657  
                 }
 658  0
             }
 659  
 
 660  
         }
 661  0
     }
 662  
 
 663  
     public static void _publishPostBuildComponentTreeOnRestoreViewEvent(FacesContext context, UIComponent component)
 664  
     {
 665  0
         context.getApplication().publishEvent(context, PostBuildComponentTreeOnRestoreViewEvent.class,
 666  
                                               component.getClass(), component);
 667  
 
 668  0
         if (component.getChildCount() > 0)
 669  
         {
 670  
             // PostAddToViewEvent could cause component relocation
 671  
             // (h:outputScript, h:outputStylesheet, composite:insertChildren, composite:insertFacet)
 672  
             // so we need to check if the component was relocated or not
 673  0
             List<UIComponent> children = component.getChildren();
 674  0
             UIComponent child = null;
 675  0
             UIComponent currentChild = null;
 676  0
             int i = 0;
 677  0
             while (i < children.size())
 678  
             {
 679  0
                 child = children.get(i);
 680  
                 // Iterate over the same index if the component was removed
 681  
                 // This prevents skip components when processing
 682  
                 do
 683  
                 {
 684  0
                     _publishPostBuildComponentTreeOnRestoreViewEvent(context, child);
 685  0
                     currentChild = child;
 686  0
                     child = children.get(i);
 687  
                 }
 688  0
                 while ((i < children.size()) && child != currentChild);
 689  0
                 i++;
 690  
             }
 691  
         }
 692  0
         if (component.getFacetCount() > 0)
 693  
         {
 694  0
             for (UIComponent child : component.getFacets().values())
 695  
             {
 696  0
                 _publishPostBuildComponentTreeOnRestoreViewEvent(context, child);
 697  0
             }
 698  
         }
 699  0
     }
 700  
 
 701  
     private boolean isFilledView(FacesContext context, UIViewRoot view)
 702  
     {
 703  
         // The view is only built on restoreView or renderView, but if
 704  
         // we are not using partial state saving, we need to mark the current
 705  
         // view as filled, otherwise it will be filled again on renderView.
 706  0
         return context.getAttributes().containsKey(view);
 707  
         // -= Leonardo Uribe =- save this key on view cause render fail, because the view
 708  
         // is built before render view to "restore" the transient components that has
 709  
         // facelet markup (facelets UIInstructions ...) This effect is only notice when
 710  
         // partial state saving is not used. 
 711  
         //return view.getAttributes().containsKey(FILLED_VIEW);
 712  
     }
 713  
 
 714  
     private void setFilledView(FacesContext context, UIViewRoot view)
 715  
     {
 716  0
         context.getAttributes().put(view, Boolean.TRUE);
 717  
         // -= Leonardo Uribe =- save this key on view cause render fail, because the view
 718  
         // is built before render view to "restore" the transient components that has
 719  
         // facelet markup (facelets UIInstructions ...) This effect is only notice when
 720  
         // partial state saving is not used. 
 721  
         // view.getAttributes().put(FILLED_VIEW, Boolean.TRUE);
 722  0
     }
 723  
 
 724  
     /**
 725  
      * retargetMethodExpressions(FacesContext, UIComponent) has some clues about the behavior of this method
 726  
      *
 727  
      * {@inheritDoc}
 728  
      */
 729  
     @Override
 730  
     public BeanInfo getComponentMetadata(FacesContext context, Resource componentResource)
 731  
     {
 732  0
         BeanInfo beanInfo = null;
 733  
 
 734  0
         checkNull(context, "context");
 735  
 
 736  
         try
 737  
         {
 738  
             Facelet compositeComponentFacelet;
 739  0
             FaceletFactory.setInstance(_faceletFactory);
 740  
             try
 741  
             {
 742  0
                 compositeComponentFacelet
 743  
                         = _faceletFactory.getCompositeComponentMetadataFacelet(componentResource.getURL());
 744  
             }
 745  
             finally
 746  
             {
 747  0
                 FaceletFactory.setInstance(null);
 748  0
             }
 749  
             //context.getAttributes().put(BUILDING_COMPOSITE_COMPONENT_METADATA, Boolean.TRUE);
 750  
 
 751  
             // Create a temporal tree where all components will be put, but we are only
 752  
             // interested in metadata.
 753  0
             UINamingContainer compositeComponentBase
 754  
                     = (UINamingContainer) context.getApplication().createComponent(
 755  
                     context, UINamingContainer.COMPONENT_TYPE, null);
 756  
 
 757  
             // Fill the component resource key, because this information should be available
 758  
             // on metadata to recognize which is the component used as composite component base.
 759  
             // Since this method is called from Application.createComponent(FacesContext,Resource),
 760  
             // and in that specific method this key is updated, this is the best option we
 761  
             // have for recognize it (also this key is used by UIComponent.isCompositeComponent)
 762  0
             compositeComponentBase.getAttributes().put(Resource.COMPONENT_RESOURCE_KEY, componentResource);
 763  
 
 764  
             // According to UserTagHandler, in this point we need to wrap the facelet
 765  
             // VariableMapper, so local changes are applied on "page context", but
 766  
             // data is retrieved from full context
 767  0
             FaceletContext faceletContext = (FaceletContext) context.
 768  
                     getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
 769  0
             VariableMapper orig = faceletContext.getVariableMapper();
 770  
             try
 771  
             {
 772  0
                 faceletContext.setVariableMapper(new VariableMapperWrapper(orig));
 773  
 
 774  0
                 compositeComponentBase.pushComponentToEL(context, compositeComponentBase);
 775  
 
 776  0
                 compositeComponentFacelet.apply(context, compositeComponentBase);
 777  
 
 778  0
                 compositeComponentBase.popComponentFromEL(context);
 779  
             }
 780  
             finally
 781  
             {
 782  0
                 faceletContext.setVariableMapper(orig);
 783  0
             }
 784  
 
 785  0
             beanInfo = (BeanInfo) compositeComponentBase.getAttributes().get(UIComponent.BEANINFO_KEY);
 786  
         }
 787  0
         catch (IOException e)
 788  
         {
 789  0
             throw new FacesException(e);
 790  0
         }
 791  
         //finally
 792  
         //{
 793  
         //context.getAttributes().remove(BUILDING_COMPOSITE_COMPONENT_METADATA);
 794  
         //}
 795  
 
 796  0
         return beanInfo;
 797  
     }
 798  
 
 799  
     /**
 800  
      * Check if the current facelet applied is used to build composite component metadata.
 801  
      *
 802  
      * @param context
 803  
      * @return
 804  
      */
 805  
     //public static boolean isBuildingCompositeComponentMetadata(FacesContext context)
 806  
     //{
 807  
     //    return context.getAttributes().containsKey(BUILDING_COMPOSITE_COMPONENT_METADATA);
 808  
     //}
 809  
 
 810  
     /**
 811  
      * Check if the current facelet applied is used to build view metadata.
 812  
      *
 813  
      * @param context
 814  
      * @return
 815  
      */
 816  
     public static boolean isBuildingViewMetadata(FacesContext context)
 817  
     {
 818  0
         return context.getAttributes().containsKey(BUILDING_VIEW_METADATA);
 819  
     }
 820  
 
 821  
     public static boolean isRefreshingTransientBuild(FacesContext context)
 822  
     {
 823  0
         return context.getAttributes().containsKey(REFRESHING_TRANSIENT_BUILD);
 824  
     }
 825  
 
 826  
     public static boolean isRemovingComponentBuild(FacesContext context)
 827  
     {
 828  0
         return context.getAttributes().containsKey(REMOVING_COMPONENTS_BUILD);
 829  
     }
 830  
 
 831  
     public static boolean isMarkInitialState(FacesContext context)
 832  
     {
 833  0
         return Boolean.TRUE.equals(context.getAttributes().get(MARK_INITIAL_STATE_KEY));
 834  
     }
 835  
 
 836  
     public static boolean isRefreshTransientBuildOnPSS(FacesContext context)
 837  
     {
 838  
         //this include both "true" and "auto"
 839  0
         return context.getAttributes().containsKey(REFRESH_TRANSIENT_BUILD_ON_PSS);
 840  
     }
 841  
 
 842  
     public static boolean isRefreshTransientBuildOnPSSAuto(FacesContext context)
 843  
     {
 844  0
         return "auto".equalsIgnoreCase((String) context.getAttributes().get(REFRESH_TRANSIENT_BUILD_ON_PSS));
 845  
     }
 846  
 
 847  
     public static boolean isCleanTransientBuildOnRestore(FacesContext context)
 848  
     {
 849  0
         return context.getAttributes().containsKey(CLEAN_TRANSIENT_BUILD_ON_RESTORE);
 850  
     }
 851  
 
 852  
     public static void cleanTransientBuildOnRestore(FacesContext context)
 853  
     {
 854  0
         context.getAttributes().put(CLEAN_TRANSIENT_BUILD_ON_RESTORE, Boolean.TRUE);
 855  0
     }
 856  
 
 857  
     public static boolean isUsingPSSOnThisView(FacesContext context)
 858  
     {
 859  0
         return context.getAttributes().containsKey(USING_PSS_ON_THIS_VIEW);
 860  
     }
 861  
 
 862  
     /**
 863  
      * In short words, this method take care of "target" an "attached object".
 864  
      * <ul>
 865  
      * <li>The "attached object" is instantiated by a tag handler.</li> 
 866  
      * <li>The "target" is an object used as "marker", that exposes a List<UIComponent></li>
 867  
      * </ul>
 868  
      * This method should be called from some composite component tag handler, after
 869  
      * all children of composite component has been applied.
 870  
      */
 871  
     @Override
 872  
     @SuppressWarnings("unchecked")
 873  
     public void retargetAttachedObjects(FacesContext context,
 874  
                                         UIComponent topLevelComponent, List<AttachedObjectHandler> handlerList)
 875  
     {
 876  0
         checkNull(context, "context");
 877  0
         checkNull(topLevelComponent, "topLevelComponent");
 878  0
         checkNull(handlerList, "handlerList");
 879  
 
 880  0
         BeanInfo compositeComponentMetadata
 881  
                 = (BeanInfo) topLevelComponent.getAttributes().get(UIComponent.BEANINFO_KEY);
 882  
 
 883  0
         if (compositeComponentMetadata == null)
 884  
         {
 885  0
             log.severe("Composite component metadata not found for: " + topLevelComponent.getClientId(context));
 886  0
             return;
 887  
         }
 888  
 
 889  0
         BeanDescriptor compositeComponentDescriptor = compositeComponentMetadata.getBeanDescriptor();
 890  
 
 891  0
         List<AttachedObjectTarget> targetList = (List<AttachedObjectTarget>)
 892  
                 compositeComponentDescriptor.getValue(AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
 893  
 
 894  0
         if (targetList == null || targetList.isEmpty())
 895  
         {
 896  0
             return;
 897  
         }
 898  
 
 899  0
         for (int i = 0, size = handlerList.size(); i < size; i++)
 900  
         {
 901  0
             AttachedObjectHandler currentHandler = handlerList.get(i);
 902  
             // In the spec javadoc this variable is referred as forAttributeValue, but
 903  
             // note it is also called curTargetName
 904  0
             String forValue = currentHandler.getFor();
 905  
             
 906  
             // perf: targetList is always arrayList: see AttachedObjectTargetHandler.apply 
 907  
             // and ClientBehaviorHandler.apply 
 908  0
             for (int k = 0, targetsSize = targetList.size(); k < targetsSize; k++)
 909  
             {
 910  0
                 AttachedObjectTarget currentTarget = targetList.get(k);
 911  0
                 FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance();
 912  
 
 913  0
                 if ((forValue != null && forValue.equals(currentTarget.getName())) &&
 914  
                         ((currentTarget instanceof ActionSource2AttachedObjectTarget &&
 915  
                                 currentHandler instanceof ActionSource2AttachedObjectHandler) ||
 916  
                                 (currentTarget instanceof EditableValueHolderAttachedObjectTarget &&
 917  
                                         currentHandler instanceof EditableValueHolderAttachedObjectHandler) ||
 918  
                                 (currentTarget instanceof ValueHolderAttachedObjectTarget &&
 919  
                                         currentHandler instanceof ValueHolderAttachedObjectHandler)))
 920  
                 {
 921  
                     // perf: getTargets return ArrayList - see getTargets implementations
 922  0
                     List<UIComponent> targets = currentTarget.getTargets(topLevelComponent);
 923  0
                     for (int l = 0, targetsCount = targets.size(); l < targetsCount; l++)
 924  
                     {
 925  0
                         UIComponent component = targets.get(l);
 926  
                         // If we found composite components when traverse the tree
 927  
                         // we have to call this one recursively, because each composite component
 928  
                         // should have its own AttachedObjectHandler list, filled earlier when
 929  
                         // its tag handler is applied.
 930  0
                         if (UIComponent.isCompositeComponent(component))
 931  
                         {
 932  
                             // How we obtain the list of AttachedObjectHandler for
 933  
                             // the current composite component? It should be a component
 934  
                             // attribute or retrieved by a key inside component.getAttributes
 935  
                             // map. Since api does not specify any attribute, we suppose
 936  
                             // this is an implementation detail and it should be retrieved
 937  
                             // from component attribute map.
 938  
                             // But this is only the point of the iceberg, because we should
 939  
                             // define how we register attached object handlers in this list.
 940  
                             // ANS: see CompositeComponentResourceTagHandler.
 941  
                             // The current handler should be added to the list, to be chained.
 942  
                             // Note that the inner component should have a target with the same name
 943  
                             // as "for" attribute
 944  0
                             mctx.addAttachedObjectHandler(component, currentHandler);
 945  
 
 946  0
                             List<AttachedObjectHandler> handlers = mctx.getAttachedObjectHandlers(component);
 947  
 
 948  0
                             retargetAttachedObjects(context, component, handlers);
 949  
 
 950  0
                             handlers.remove(currentHandler);
 951  0
                         }
 952  
                         else
 953  
                         {
 954  0
                             currentHandler.applyAttachedObject(context, component);
 955  
                         }
 956  0
                         if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 957  
                         {
 958  0
                             component.markInitialState();
 959  
                         }
 960  
                     }
 961  0
                 }
 962  0
                 else if ((currentTarget instanceof BehaviorHolderAttachedObjectTarget &&
 963  
                         currentHandler instanceof BehaviorHolderAttachedObjectHandler))
 964  
                 {
 965  0
                     String eventName = ((BehaviorHolderAttachedObjectHandler) currentHandler).getEventName();
 966  0
                     boolean isDefaultEvent = ((BehaviorHolderAttachedObjectTarget) currentTarget).isDefaultEvent();
 967  
 
 968  0
                     if ((eventName != null && eventName.equals(currentTarget.getName())) ||
 969  
                             (eventName == null && isDefaultEvent))
 970  
                     {
 971  0
                         List<UIComponent> targets = currentTarget.getTargets(topLevelComponent);
 972  0
                         for (int j = 0, targetssize = targets.size(); j < targetssize; j++)
 973  
                         {
 974  0
                             UIComponent component = targets.get(j);
 975  
                             // If we found composite components when traverse the tree
 976  
                             // we have to call this one recursively, because each composite component
 977  
                             // should have its own AttachedObjectHandler list, filled earlier when
 978  
                             // its tag handler is applied.
 979  0
                             if (UIComponent.isCompositeComponent(component))
 980  
                             {
 981  0
                                 if (currentTarget instanceof ClientBehaviorAttachedObjectTarget)
 982  
                                 {
 983  0
                                     mctx.addAttachedObjectHandler(component,
 984  
                                             new ClientBehaviorRedirectBehaviorAttachedObjectHandlerWrapper(
 985  
                                                     (BehaviorHolderAttachedObjectHandler) currentHandler,
 986  
                                                     ((ClientBehaviorAttachedObjectTarget) currentTarget).getEvent()));
 987  
                                 }
 988  
                                 else
 989  
                                 {
 990  0
                                     mctx.addAttachedObjectHandler(component, currentHandler);
 991  
                                 }
 992  
 
 993  0
                                 List<AttachedObjectHandler> handlers = mctx.getAttachedObjectHandlers(component);
 994  
 
 995  0
                                 retargetAttachedObjects(context, component, handlers);
 996  
 
 997  0
                                 handlers.remove(currentHandler);
 998  0
                             }
 999  
                             else
 1000  
                             {
 1001  0
                                 if (currentHandler instanceof
 1002  
                                         ClientBehaviorRedirectBehaviorAttachedObjectHandlerWrapper)
 1003  
                                 {
 1004  0
                                     currentHandler.applyAttachedObject(context,
 1005  
                                             new ClientBehaviorRedirectEventComponentWrapper(component,
 1006  
                                             ((ClientBehaviorRedirectBehaviorAttachedObjectHandlerWrapper)
 1007  
                                                     currentHandler).getWrappedEventName(), eventName));
 1008  
                                 }
 1009  
                                 else
 1010  
                                 {
 1011  0
                                     currentHandler.applyAttachedObject(context, component);
 1012  
                                 }
 1013  
                             }
 1014  0
                             if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 1015  
                             {
 1016  0
                                 component.markInitialState();
 1017  
                             }
 1018  
                         }
 1019  
                     }
 1020  
                 }
 1021  
             }
 1022  
         }
 1023  0
     }
 1024  
 
 1025  
     @Override
 1026  
     public void retargetMethodExpressions(FacesContext context, UIComponent topLevelComponent)
 1027  
     {
 1028  0
         checkNull(context, "context");
 1029  
 
 1030  0
         BeanInfo compositeComponentMetadata
 1031  
                 = (BeanInfo) topLevelComponent.getAttributes().get(UIComponent.BEANINFO_KEY);
 1032  
 
 1033  0
         if (compositeComponentMetadata == null)
 1034  
         {
 1035  0
             log.severe("Composite component metadata not found for: " + topLevelComponent.getClientId(context));
 1036  0
             return;
 1037  
         }
 1038  
 
 1039  
         // "...For each attribute that is a MethodExpression..." This means we have to scan
 1040  
         // all attributes with "method-signature" attribute and no "type" attribute
 1041  
         // javax.faces.component._ComponentAttributesMap uses BeanInfo.getPropertyDescriptors to
 1042  
         // traverse over it, but here the metadata returned by UIComponent.BEANINFO_KEY is available
 1043  
         // only for composite components.
 1044  
         // That means somewhere we need to create a custom BeanInfo object for composite components
 1045  
         // that will be filled somewhere (theorically in ViewDeclarationLanguage.getComponentMetadata())
 1046  
 
 1047  0
         PropertyDescriptor[] propertyDescriptors = compositeComponentMetadata.getPropertyDescriptors();
 1048  
 
 1049  0
         ELContext elContext = (ELContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
 1050  
 
 1051  0
         for (PropertyDescriptor propertyDescriptor : propertyDescriptors)
 1052  
         {
 1053  0
             if (propertyDescriptor.getValue("type") != null)
 1054  
             {
 1055  
                 // This check is necessary if we have both "type" and "method-signature" set.
 1056  
                 // In that case, "method-signature" is ignored
 1057  0
                 continue;
 1058  
             }
 1059  
 
 1060  0
             String attributeName = propertyDescriptor.getName();
 1061  
             //boolean isKnownMethod = "action".equals(attributeName) || "actionListener".equals(attributeName)  
 1062  
             //        || "validator".equals(attributeName) || "valueChangeListener".equals(attributeName);
 1063  
 
 1064  
             // <composite:attribute> method-signature attribute is 
 1065  
             // ValueExpression that must evaluate to String
 1066  0
             ValueExpression methodSignatureExpression
 1067  
                     = (ValueExpression) propertyDescriptor.getValue("method-signature");
 1068  0
             String methodSignature = null;
 1069  0
             if (methodSignatureExpression != null)
 1070  
             {
 1071  
                 // Check if the value expression holds a method signature
 1072  
                 // Note that it could be null, so in that case we don't have to do anything
 1073  0
                 methodSignature = (String) methodSignatureExpression.getValue(elContext);
 1074  
             }
 1075  
 
 1076  0
             String targetAttributeName = null;
 1077  0
             ValueExpression targetAttributeNameVE
 1078  
                     = (ValueExpression) propertyDescriptor.getValue("targetAttributeName");
 1079  0
             if (targetAttributeNameVE != null)
 1080  
             {
 1081  0
                 targetAttributeName = (String) targetAttributeNameVE.getValue(context.getELContext());
 1082  0
                 if (targetAttributeName == null)
 1083  
                 {
 1084  0
                     targetAttributeName = attributeName;
 1085  
                 }
 1086  
             }
 1087  
             else
 1088  
             {
 1089  0
                 targetAttributeName = attributeName;
 1090  
             }
 1091  
 
 1092  0
             boolean isKnownTargetAttributeMethod
 1093  
                     = "action".equals(targetAttributeName) || "actionListener".equals(targetAttributeName)
 1094  
                       || "validator".equals(targetAttributeName) || "valueChangeListener".equals(targetAttributeName);
 1095  
 
 1096  
             // either the attributeName has to be a knownMethod or there has to be a method-signature
 1097  0
             if (isKnownTargetAttributeMethod || methodSignature != null)
 1098  
             {
 1099  0
                 ValueExpression targetsExpression =
 1100  
                         (ValueExpression) propertyDescriptor.getValue("targets");
 1101  
 
 1102  0
                 String targets = null;
 1103  
                 // <composite:attribute> targets attribute is 
 1104  
                 // ValueExpression that must evaluate to String
 1105  0
                 if (targetsExpression != null)
 1106  
                 {
 1107  0
                     targets = (String) targetsExpression.getValue(elContext);
 1108  
                 }
 1109  
 
 1110  0
                 if (targets == null)
 1111  
                 {
 1112  
                     // "...let the name of the metadata element be the 
 1113  
                     // evaluated value of the targets attribute..."
 1114  0
                     targets = attributeName;
 1115  
                 }
 1116  
 
 1117  0
                 FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance();
 1118  
 
 1119  
                 // If the MethodExpression attribute has been already applied, there is no need to
 1120  
                 // handle it and it is probably a MethodExpression instance is on attribute map, so the
 1121  
                 // inner code will cause a ClassCastException.
 1122  0
                 if (!mctx.isMethodExpressionAttributeApplied(topLevelComponent, attributeName))
 1123  
                 {
 1124  
 
 1125  0
                     ValueExpression attributeNameValueExpression =
 1126  
                             (ValueExpression) topLevelComponent.getAttributes().get(attributeName);
 1127  
 
 1128  0
                     if (attributeNameValueExpression == null)
 1129  
                     {
 1130  
                         // composite:attribute has a default property, so if we can't found on the
 1131  
                         // component attribute map, we should get the default as CompositeComponentELResolver
 1132  
                         // does.
 1133  0
                         attributeNameValueExpression = (ValueExpression) propertyDescriptor.getValue("default");
 1134  0
                         if (attributeNameValueExpression == null)
 1135  
                         {
 1136  
                             // It is only valid to log an error if the attribute is required
 1137  0
                             ValueExpression ve = (ValueExpression) propertyDescriptor.getValue("required");
 1138  0
                             if (ve != null)
 1139  
                             {
 1140  0
                                 Object requiredValue = ve.getValue(elContext);
 1141  0
                                 Boolean required = null;
 1142  0
                                 if (requiredValue instanceof Boolean)
 1143  
                                 {
 1144  0
                                     required = (Boolean) requiredValue;
 1145  
                                 }
 1146  
                                 else
 1147  
                                 {
 1148  0
                                     required = Boolean.valueOf(requiredValue.toString());
 1149  
                                 }
 1150  
 
 1151  0
                                 if (required != null && required.booleanValue())
 1152  
                                 {
 1153  0
                                     if (log.isLoggable(Level.SEVERE))
 1154  
                                     {
 1155  0
                                         log.severe("attributeValueExpression not found under the key \""
 1156  
                                                    + attributeName
 1157  
                                                    + "\". Looking for the next attribute");
 1158  
                                     }
 1159  
                                 }
 1160  0
                             }
 1161  
                             continue;
 1162  
                         }
 1163  
                     }
 1164  
 
 1165  0
                     String[] targetsArray = StringUtils.splitShortString(targets, ' ');
 1166  0
                     String attributeExpressionString = attributeNameValueExpression.getExpressionString();
 1167  
 
 1168  
                     //Check if the stored valueExpression is a ccRedirection, to handle it properly later.
 1169  0
                     boolean ccAttrMeRedirection =
 1170  
                             attributeNameValueExpression instanceof LocationValueExpression &&
 1171  
                                     CompositeComponentELUtils.isCompositeComponentAttrsMethodExpression(
 1172  
                                             attributeNameValueExpression.getExpressionString());
 1173  
 
 1174  0
                     if (isKnownTargetAttributeMethod)
 1175  
                     {
 1176  
                         // To add support to #{cc.attrs.action}, #{cc.attrs.actionListener}, #{cc.attrs.validator} or
 1177  
                         // #{cc.attrs.valueChangeListener} it is necessary to put a MethodExpression or a 
 1178  
                         // ValueExpression pointing to the associated java method in the component attribute map.
 1179  
                         // org.apache.myfaces.view.facelets.tag.composite.RetargetMethodExpressionRule already put
 1180  
                         // a ValueExpression, so we only need to put a MethodExpression when a non redirecting
 1181  
                         // expression is used (for example when a nested #{cc.attrs.xxx} is used).
 1182  0
                         if ("action".equals(targetAttributeName))
 1183  
                         {
 1184  0
                             applyActionMethodExpressionEL(context, elContext,
 1185  
                                     topLevelComponent, attributeName,
 1186  
                                     attributeExpressionString, attributeNameValueExpression,
 1187  
                                     ccAttrMeRedirection);
 1188  
                         }
 1189  0
                         else if ("actionListener".equals(targetAttributeName))
 1190  
                         {
 1191  0
                             applyActionListenerMethodExpressionEL(context, elContext,
 1192  
                                     topLevelComponent, attributeName, 
 1193  
                                     attributeExpressionString, attributeNameValueExpression, 
 1194  
                                     ccAttrMeRedirection);
 1195  
                         }
 1196  0
                         else if ("validator".equals(targetAttributeName))
 1197  
                         {
 1198  0
                             applyValidatorMethodExpressionEL(context, elContext,
 1199  
                                     topLevelComponent, attributeName,
 1200  
                                     attributeExpressionString, attributeNameValueExpression, 
 1201  
                                     ccAttrMeRedirection);
 1202  
                         }
 1203  0
                         else if ("valueChangeListener".equals(targetAttributeName))
 1204  
                         {
 1205  0
                             applyValueChangeListenerMethodExpressionEL(context, elContext,
 1206  
                                     topLevelComponent, attributeName, 
 1207  
                                     attributeExpressionString, attributeNameValueExpression,
 1208  
                                     ccAttrMeRedirection);
 1209  
                         }
 1210  
 
 1211  0
                         UIComponent topLevelComponentBase = 
 1212  
                             topLevelComponent.getFacet(UIComponent.COMPOSITE_FACET_NAME);
 1213  
 
 1214  0
                         for (String target : targetsArray)
 1215  
                         {
 1216  0
                             UIComponent innerComponent
 1217  
                                     = ComponentSupport.findComponentChildOrFacetFrom(context, topLevelComponentBase,
 1218  
                                                                                      target);
 1219  
 
 1220  0
                             if (innerComponent == null)
 1221  
                             {
 1222  0
                                 continue;
 1223  
                             }
 1224  
 
 1225  0
                             if (isCompositeComponentRetarget(context, innerComponent, targetAttributeName))
 1226  
                             {
 1227  0
                                 innerComponent.getAttributes().put(targetAttributeName, attributeNameValueExpression);
 1228  
 
 1229  0
                                 mctx.clearMethodExpressionAttribute(innerComponent, targetAttributeName);
 1230  
 
 1231  0
                                 retargetMethodExpressions(context, innerComponent);
 1232  0
                                 if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 1233  
                                 {
 1234  0
                                     innerComponent.markInitialState();
 1235  
                                 }
 1236  
                             }
 1237  
                             else
 1238  
                             {
 1239  0
                                 if ("action".equals(targetAttributeName))
 1240  
                                 {
 1241  0
                                     applyActionMethodExpressionTarget(context, mctx, elContext,
 1242  
                                             topLevelComponentBase, innerComponent, 
 1243  
                                             attributeName, targetAttributeName, 
 1244  
                                             attributeExpressionString, attributeNameValueExpression, 
 1245  
                                             ccAttrMeRedirection);
 1246  0
                                     if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 1247  
                                     {
 1248  0
                                         innerComponent.markInitialState();
 1249  
                                     }
 1250  
                                 }
 1251  0
                                 else if ("actionListener".equals(targetAttributeName))
 1252  
                                 {
 1253  0
                                     applyActionListenerMethodExpressionTarget(context, mctx, elContext, 
 1254  
                                             topLevelComponentBase, innerComponent, 
 1255  
                                             attributeName, targetAttributeName, 
 1256  
                                             attributeExpressionString, attributeNameValueExpression, 
 1257  
                                             ccAttrMeRedirection);
 1258  0
                                     if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 1259  
                                     {
 1260  0
                                         innerComponent.markInitialState();
 1261  
                                     }
 1262  
                                 }
 1263  0
                                 else if ("validator".equals(targetAttributeName))
 1264  
                                 {
 1265  0
                                     applyValidatorMethodExpressionTarget(context, mctx, elContext,
 1266  
                                             topLevelComponentBase, innerComponent, 
 1267  
                                             attributeName, targetAttributeName, 
 1268  
                                             attributeExpressionString, attributeNameValueExpression, 
 1269  
                                             ccAttrMeRedirection);
 1270  0
                                     if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 1271  
                                     {
 1272  0
                                         innerComponent.markInitialState();
 1273  
                                     }
 1274  
                                 }
 1275  0
                                 else if ("valueChangeListener".equals(targetAttributeName))
 1276  
                                 {
 1277  0
                                     applyValueChangeListenerMethodExpressionTarget(context, mctx, elContext,
 1278  
                                             topLevelComponentBase, innerComponent, 
 1279  
                                             attributeName, targetAttributeName,
 1280  
                                             attributeExpressionString, attributeNameValueExpression,
 1281  
                                             ccAttrMeRedirection);
 1282  0
                                     if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 1283  
                                     {
 1284  0
                                         innerComponent.markInitialState();
 1285  
                                     }
 1286  
                                 }
 1287  
                             }
 1288  
                         }
 1289  0
                     }
 1290  
                     else
 1291  
                     {
 1292  0
                         MethodExpression methodExpression = null;
 1293  
                         // composite:attribute targets property only has sense for action, actionListener,
 1294  
                         // validator or valueChangeListener. This means we have to retarget the method expression
 1295  
                         // to the topLevelComponent.
 1296  
 
 1297  
                         // Since a MethodExpression has no state, we can use it multiple times without problem, so
 1298  
                         // first create it here.
 1299  0
                         methodSignature = methodSignature.trim();
 1300  0
                         methodExpression = context.getApplication().getExpressionFactory().
 1301  
                                 createMethodExpression(elContext,
 1302  
                                         attributeExpressionString, 
 1303  
                                         FaceletsViewDeclarationLanguageUtils.getReturnType(methodSignature),
 1304  
                                         FaceletsViewDeclarationLanguageUtils.getParameters(methodSignature));
 1305  
 
 1306  0
                         methodExpression = reWrapMethodExpression(methodExpression, attributeNameValueExpression);
 1307  
 
 1308  0
                         applyMethodExpression(context, mctx, topLevelComponent, attributeName, 
 1309  
                                 targetAttributeName, attributeNameValueExpression, methodExpression, 
 1310  
                                 ccAttrMeRedirection, targetsArray);
 1311  
                     }
 1312  0
                     mctx.markMethodExpressionAttribute(topLevelComponent, attributeName);
 1313  
                 }
 1314  
 
 1315  
                 // We need to remove the previous ValueExpression, to prevent some possible
 1316  
                 // confusion when the same value is retrieved from the attribute map.
 1317  0
                 topLevelComponent.setValueExpression(attributeName, null);
 1318  
             }
 1319  
         }
 1320  0
     }
 1321  
     
 1322  
     private void applyActionMethodExpressionEL(FacesContext context, 
 1323  
                                                ELContext elContext, 
 1324  
                                                UIComponent topLevelComponent, 
 1325  
                                                String attributeName,
 1326  
                                                String attributeExpressionString, 
 1327  
                                                ValueExpression attributeNameValueExpression, 
 1328  
                                                boolean ccAttrMeRedirection)
 1329  
     {
 1330  
         // target is ActionSource2
 1331  0
         MethodExpression methodExpression = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1332  
                 createMethodExpression(elContext,
 1333  
                         attributeExpressionString, null,
 1334  
                         EMPTY_CLASS_ARRAY), attributeNameValueExpression);
 1335  
 
 1336  
         //Store the method expression to the topLevelComponent to allow reference it through EL
 1337  0
         if (!ccAttrMeRedirection)
 1338  
         {
 1339  
             //Replace it with a method expression
 1340  0
             topLevelComponent.getAttributes().put(attributeName, methodExpression);
 1341  
         }
 1342  
         // Otherwise keep the current ValueExpression,
 1343  
         // because it will be used chain other value expressions
 1344  0
     }
 1345  
 
 1346  
     private void applyActionListenerMethodExpressionEL(FacesContext context, 
 1347  
                                                        ELContext elContext, 
 1348  
                                                        UIComponent topLevelComponent, 
 1349  
                                                        String attributeName,
 1350  
                                                        String attributeExpressionString, 
 1351  
                                                        ValueExpression attributeNameValueExpression, 
 1352  
                                                        boolean ccAttrMeRedirection)
 1353  
     {
 1354  
         // target is ActionSource2
 1355  0
         MethodExpression methodExpression = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1356  
                 createMethodExpression(elContext,
 1357  
                         attributeExpressionString, Void.TYPE, ACTION_LISTENER_SIGNATURE),
 1358  
                         attributeNameValueExpression);
 1359  
 
 1360  0
         MethodExpression methodExpression2 = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1361  
                 createMethodExpression(elContext,
 1362  
                         attributeExpressionString, Void.TYPE, EMPTY_CLASS_ARRAY),
 1363  
                         attributeNameValueExpression);
 1364  
 
 1365  
         //Store the method expression to the topLevelComponent to allow reference it through EL
 1366  0
         if (!ccAttrMeRedirection)
 1367  
         {
 1368  
             //Replace it with a method expression
 1369  0
             topLevelComponent.getAttributes().put(attributeName,
 1370  
                     new MethodExpressionMethodExpression(methodExpression, methodExpression2));
 1371  
         }
 1372  
         // Otherwise keep the current ValueExpression,
 1373  
         // because it will be used chain other value expressions
 1374  0
     }
 1375  
     
 1376  
     private void applyValidatorMethodExpressionEL(FacesContext context, 
 1377  
                                                   ELContext elContext, 
 1378  
                                                   UIComponent topLevelComponent, 
 1379  
                                                   String attributeName,
 1380  
                                                   String attributeExpressionString, 
 1381  
                                                   ValueExpression attributeNameValueExpression, 
 1382  
                                                   boolean ccAttrMeRedirection)
 1383  
     {
 1384  
         // target is EditableValueHolder
 1385  0
         MethodExpression methodExpression = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1386  
                 createMethodExpression(elContext,
 1387  
                         attributeExpressionString, Void.TYPE,
 1388  
                         VALIDATOR_SIGNATURE), attributeNameValueExpression);
 1389  
 
 1390  
         //Store the method expression to the topLevelComponent to allow reference it through EL
 1391  0
         if (!ccAttrMeRedirection)
 1392  
         {
 1393  
             //Replace it with a method expression
 1394  0
             topLevelComponent.getAttributes().put(attributeName, methodExpression);
 1395  
         }
 1396  
         // Otherwise keep the current ValueExpression,
 1397  
         // because it will be used chain other value expressions
 1398  0
     }
 1399  
     
 1400  
     private void applyValueChangeListenerMethodExpressionEL(FacesContext context, 
 1401  
                                                             ELContext elContext, 
 1402  
                                                             UIComponent topLevelComponent, 
 1403  
                                                             String attributeName,
 1404  
                                                             String attributeExpressionString, 
 1405  
                                                             ValueExpression attributeNameValueExpression, 
 1406  
                                                             boolean ccAttrMeRedirection)
 1407  
     {
 1408  
         // target is EditableValueHolder
 1409  0
         MethodExpression methodExpression = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1410  
                 createMethodExpression(elContext,
 1411  
                         attributeExpressionString, Void.TYPE,
 1412  
                         VALUE_CHANGE_LISTENER_SIGNATURE), attributeNameValueExpression);
 1413  
 
 1414  0
         MethodExpression methodExpression2 = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1415  
                 createMethodExpression(elContext,
 1416  
                         attributeExpressionString, Void.TYPE,
 1417  
                         EMPTY_CLASS_ARRAY), attributeNameValueExpression);
 1418  
 
 1419  
         //Store the method expression to the topLevelComponent to allow reference it through EL
 1420  0
         if (!ccAttrMeRedirection)
 1421  
         {
 1422  
             //Replace it with a method expression
 1423  0
             topLevelComponent.getAttributes().put(attributeName,
 1424  
                     new MethodExpressionMethodExpression(methodExpression, methodExpression2));
 1425  
         }
 1426  
         // Otherwise keep the current ValueExpression, because it will be used chain other value expressions
 1427  0
     }
 1428  
     
 1429  
     private void applyActionMethodExpressionTarget(FacesContext context, FaceletCompositionContext mctx,
 1430  
                                                    ELContext elContext, 
 1431  
                                                    UIComponent topLevelComponent,
 1432  
                                                    UIComponent innerComponent,
 1433  
                                                    String attributeName,
 1434  
                                                    String targetAttributeName,
 1435  
                                                    String attributeExpressionString,
 1436  
                                                    ValueExpression attributeNameValueExpression,
 1437  
                                                    boolean ccAttrMeRedirection)
 1438  
     {
 1439  
         // target is ActionSource2
 1440  0
         MethodExpression methodExpression
 1441  
                 = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1442  
                 createMethodExpression(elContext,
 1443  
                         attributeExpressionString, null, EMPTY_CLASS_ARRAY),
 1444  
                         attributeNameValueExpression);
 1445  
 
 1446  
         // If it is a redirection, a wrapper is used to
 1447  
         // locate the right instance and call it properly.
 1448  0
         if (ccAttrMeRedirection)
 1449  
         {
 1450  0
             ((ActionSource2) innerComponent).setActionExpression(
 1451  
                     new ValueExpressionMethodExpression(attributeNameValueExpression));
 1452  
         }
 1453  
         else
 1454  
         {
 1455  0
             ((ActionSource2) innerComponent).setActionExpression(methodExpression);
 1456  
         }
 1457  0
     }
 1458  
 
 1459  
     private void applyActionListenerMethodExpressionTarget(FacesContext context, FaceletCompositionContext mctx,
 1460  
             ELContext elContext, 
 1461  
             UIComponent topLevelComponent,
 1462  
             UIComponent innerComponent,
 1463  
             String attributeName,
 1464  
             String targetAttributeName,
 1465  
             String attributeExpressionString,
 1466  
             ValueExpression attributeNameValueExpression,
 1467  
             boolean ccAttrMeRedirection)
 1468  
     {
 1469  
         //First try to remove any prevous target if any
 1470  0
         ActionListener o = (ActionListener)
 1471  
                 mctx.removeMethodExpressionTargeted(innerComponent, targetAttributeName);
 1472  0
         if (o != null)
 1473  
         {
 1474  0
             ((ActionSource2) innerComponent).removeActionListener(o);
 1475  
         }
 1476  
 
 1477  
         // target is ActionSource2
 1478  0
         ActionListener actionListener = null;
 1479  
         // If it is a redirection, a wrapper is used to locate the right instance and call
 1480  
         //it properly.
 1481  0
         if (ccAttrMeRedirection)
 1482  
         {
 1483  0
             actionListener = new RedirectMethodExpressionValueExpressionActionListener(
 1484  
                                          attributeNameValueExpression);
 1485  
         }
 1486  
         else
 1487  
         {
 1488  0
             MethodExpression methodExpression = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1489  
                     createMethodExpression(elContext,
 1490  
                        attributeExpressionString, Void.TYPE, ACTION_LISTENER_SIGNATURE), attributeNameValueExpression);
 1491  
 
 1492  0
             MethodExpression methodExpression2 = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1493  
                     createMethodExpression(elContext,
 1494  
                             attributeExpressionString, Void.TYPE, EMPTY_CLASS_ARRAY), attributeNameValueExpression);
 1495  
 
 1496  0
             if (mctx.isUsingPSSOnThisView())
 1497  
             {
 1498  0
                 actionListener = new PartialMethodExpressionActionListener(methodExpression, methodExpression2);
 1499  
             }
 1500  
             else
 1501  
             {
 1502  0
                 actionListener = new MethodExpressionActionListener(methodExpression, methodExpression2);
 1503  
             }
 1504  
         }
 1505  0
         ((ActionSource2) innerComponent).addActionListener(actionListener);
 1506  0
         mctx.addMethodExpressionTargeted(innerComponent, targetAttributeName, actionListener);
 1507  0
     }
 1508  
     
 1509  
     private void applyValidatorMethodExpressionTarget(FacesContext context, FaceletCompositionContext mctx,
 1510  
             ELContext elContext, 
 1511  
             UIComponent topLevelComponent,
 1512  
             UIComponent innerComponent,
 1513  
             String attributeName,
 1514  
             String targetAttributeName,
 1515  
             String attributeExpressionString,
 1516  
             ValueExpression attributeNameValueExpression,
 1517  
             boolean ccAttrMeRedirection)
 1518  
     {
 1519  
         //First try to remove any prevous target if any
 1520  0
         Validator o = (Validator) mctx.removeMethodExpressionTargeted(innerComponent, targetAttributeName);
 1521  0
         if (o != null)
 1522  
         {
 1523  0
             ((EditableValueHolder) innerComponent).removeValidator(o);
 1524  
         }
 1525  
 
 1526  
         // target is EditableValueHolder
 1527  0
         Validator validator = null;
 1528  
         // If it is a redirection, a wrapper is used to locate the right instance and call it properly.
 1529  0
         if (ccAttrMeRedirection)
 1530  
         {
 1531  0
             validator = new RedirectMethodExpressionValueExpressionValidator(attributeNameValueExpression);
 1532  
         }
 1533  
         else
 1534  
         {
 1535  0
             MethodExpression methodExpression = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1536  
                     createMethodExpression(elContext,
 1537  
                             attributeExpressionString, Void.TYPE,
 1538  
                             VALIDATOR_SIGNATURE), attributeNameValueExpression);
 1539  
 
 1540  0
             if (mctx.isUsingPSSOnThisView())
 1541  
             {
 1542  0
                 validator = new PartialMethodExpressionValidator(methodExpression);
 1543  
             }
 1544  
             else
 1545  
             {
 1546  0
                 validator = new MethodExpressionValidator(methodExpression);
 1547  
             }
 1548  
         }
 1549  0
         ((EditableValueHolder) innerComponent).addValidator(validator);
 1550  0
         mctx.addMethodExpressionTargeted(innerComponent, targetAttributeName, validator);
 1551  0
     }
 1552  
     
 1553  
     private void applyValueChangeListenerMethodExpressionTarget(FacesContext context, FaceletCompositionContext mctx,
 1554  
             ELContext elContext, 
 1555  
             UIComponent topLevelComponent,
 1556  
             UIComponent innerComponent,
 1557  
             String attributeName,
 1558  
             String targetAttributeName,
 1559  
             String attributeExpressionString,
 1560  
             ValueExpression attributeNameValueExpression,
 1561  
             boolean ccAttrMeRedirection)
 1562  
     {
 1563  0
         ValueChangeListener o = (ValueChangeListener) mctx.removeMethodExpressionTargeted(
 1564  
                 innerComponent, targetAttributeName);
 1565  0
         if (o != null)
 1566  
         {
 1567  0
             ((EditableValueHolder) innerComponent).removeValueChangeListener(o);
 1568  
         }
 1569  
 
 1570  
         // target is EditableValueHolder
 1571  0
         ValueChangeListener valueChangeListener = null;
 1572  
         // If it is a redirection, a wrapper is used to locate the right instance and call it properly.
 1573  0
         if (ccAttrMeRedirection)
 1574  
         {
 1575  0
             valueChangeListener = new RedirectMethodExpressionValueExpressionValueChangeListener(
 1576  
                     attributeNameValueExpression);
 1577  
         }
 1578  
         else
 1579  
         {
 1580  0
             MethodExpression methodExpression = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1581  
                     createMethodExpression(elContext,
 1582  
                             attributeExpressionString, Void.TYPE,
 1583  
                             VALUE_CHANGE_LISTENER_SIGNATURE), attributeNameValueExpression);
 1584  
 
 1585  0
             MethodExpression methodExpression2 = reWrapMethodExpression(context.getApplication().getExpressionFactory().
 1586  
                     createMethodExpression(elContext,
 1587  
                             attributeExpressionString, Void.TYPE,
 1588  
                             EMPTY_CLASS_ARRAY), attributeNameValueExpression);
 1589  
 
 1590  0
             if (mctx.isUsingPSSOnThisView())
 1591  
             {
 1592  0
                 valueChangeListener = new PartialMethodExpressionValueChangeListener(
 1593  
                         methodExpression, methodExpression2);
 1594  
             }
 1595  
             else
 1596  
             {
 1597  0
                 valueChangeListener = new MethodExpressionValueChangeListener(methodExpression, methodExpression2);
 1598  
             }
 1599  
         }
 1600  0
         ((EditableValueHolder) innerComponent).addValueChangeListener(valueChangeListener);
 1601  0
         mctx.addMethodExpressionTargeted(innerComponent, targetAttributeName, valueChangeListener);
 1602  0
     }
 1603  
     
 1604  
     private void applyMethodExpression(FacesContext context, FaceletCompositionContext mctx, 
 1605  
             UIComponent topLevelComponent,
 1606  
             String attributeName,
 1607  
             String targetAttributeName,
 1608  
             ValueExpression attributeNameValueExpression,
 1609  
             MethodExpression methodExpression,
 1610  
             boolean ccAttrMeRedirection,
 1611  
             String[] targetsArray)
 1612  
     {
 1613  0
         UIComponent topLevelComponentBase = topLevelComponent.getFacet(
 1614  
                 UIComponent.COMPOSITE_FACET_NAME);
 1615  
 
 1616  0
         for (String target : targetsArray)
 1617  
         {
 1618  0
             UIComponent innerComponent = ComponentSupport.findComponentChildOrFacetFrom(context, 
 1619  
                     topLevelComponentBase, target);
 1620  
 
 1621  0
             if (innerComponent == null)
 1622  
             {
 1623  0
                 continue;
 1624  
             }
 1625  
 
 1626  
             // If a component is found, that means the expression should be retarget to the
 1627  
             // components related
 1628  0
             if (isCompositeComponentRetarget(context, innerComponent, targetAttributeName))
 1629  
             {
 1630  0
                 innerComponent.getAttributes().put(targetAttributeName, attributeNameValueExpression);
 1631  
 
 1632  0
                 mctx.clearMethodExpressionAttribute(innerComponent, targetAttributeName);
 1633  
 
 1634  0
                 retargetMethodExpressions(context, innerComponent);
 1635  
                 
 1636  0
                 if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 1637  
                 {
 1638  
                     //retargetMethodExpression occur on build view time, so it is safe to call markInitiaState here
 1639  0
                     innerComponent.markInitialState();
 1640  
                 }
 1641  
             }
 1642  
             else
 1643  
             {
 1644  
                 //Put the retarget
 1645  0
                 if (ccAttrMeRedirection)
 1646  
                 {
 1647  
                     // Since we require here a method expression, it is necessary to wrap 
 1648  
                     // the ValueExpression into a MethodExpression that handles redirection.
 1649  0
                     innerComponent.getAttributes().put(targetAttributeName, 
 1650  
                             new ValueExpressionMethodExpression(attributeNameValueExpression));
 1651  
                 }
 1652  
                 else
 1653  
                 {
 1654  0
                     innerComponent.getAttributes().put(targetAttributeName, methodExpression);
 1655  
                 }
 1656  0
                 if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
 1657  
                 {
 1658  0
                     innerComponent.markInitialState();
 1659  
                 }
 1660  
             }
 1661  
         }
 1662  
         //Store the method expression to the topLevelComponent to allow reference it through EL
 1663  0
         if (!ccAttrMeRedirection)
 1664  
         {
 1665  
             //Replace it with a method expression
 1666  0
             topLevelComponent.getAttributes().put(attributeName, methodExpression);
 1667  
         }
 1668  
         // Othewise keep the current ValueExpression, because it will be used chain other value 
 1669  
         // expressions
 1670  0
     }
 1671  
 
 1672  
 
 1673  
     private boolean isCompositeComponentRetarget(FacesContext context, UIComponent component, String attributeName)
 1674  
     {
 1675  0
         if (UIComponent.isCompositeComponent(component))
 1676  
         {
 1677  0
             BeanInfo compositeComponentMetadata = (BeanInfo) component.getAttributes().get(UIComponent.BEANINFO_KEY);
 1678  
 
 1679  0
             PropertyDescriptor[] propertyDescriptors = compositeComponentMetadata.getPropertyDescriptors();
 1680  
 
 1681  0
             ELContext elContext = (ELContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
 1682  
 
 1683  0
             for (PropertyDescriptor propertyDescriptor : propertyDescriptors)
 1684  
             {
 1685  0
                 if (propertyDescriptor.getValue("type") != null)
 1686  
                 {
 1687  
                     // This check is necessary if we have both "type" and "method-signature" set.
 1688  
                     // In that case, "method-signature" is ignored
 1689  0
                     continue;
 1690  
                 }
 1691  
 
 1692  0
                 if (attributeName.equals(propertyDescriptor.getName()))
 1693  
                 {
 1694  
                     //boolean isKnownMethod = "action".equals(attributeName) || "actionListener".equals(attributeName)  
 1695  
                     //|| "validator".equals(attributeName) || "valueChangeListener".equals(attributeName);
 1696  
 
 1697  
                     // <composite:attribute> method-signature attribute is 
 1698  
                     // ValueExpression that must evaluate to String
 1699  0
                     ValueExpression methodSignatureExpression
 1700  
                             = (ValueExpression) propertyDescriptor.getValue("method-signature");
 1701  0
                     String methodSignature = null;
 1702  0
                     if (methodSignatureExpression != null)
 1703  
                     {
 1704  
                         // Check if the value expression holds a method signature
 1705  
                         // Note that it could be null, so in that case we don't have to do anything
 1706  0
                         methodSignature = (String) methodSignatureExpression.getValue(elContext);
 1707  
                     }
 1708  
 
 1709  0
                     String targetAttributeName = null;
 1710  0
                     ValueExpression targetAttributeNameVE = (ValueExpression) 
 1711  
                         propertyDescriptor.getValue("targetAttributeName");
 1712  0
                     if (targetAttributeNameVE != null)
 1713  
                     {
 1714  0
                         targetAttributeName = (String) targetAttributeNameVE.getValue(context.getELContext());
 1715  0
                         if (targetAttributeName == null)
 1716  
                         {
 1717  0
                             targetAttributeName = attributeName;
 1718  
                         }
 1719  
                     }
 1720  
                     else
 1721  
                     {
 1722  0
                         targetAttributeName = attributeName;
 1723  
                     }
 1724  
 
 1725  0
                     boolean isKnownTargetAttributeMethod = "action".equals(targetAttributeName)
 1726  
                             || "actionListener".equals(targetAttributeName)
 1727  
                             || "validator".equals(targetAttributeName)
 1728  
                             || "valueChangeListener".equals(targetAttributeName);
 1729  
 
 1730  
                     // either the attributeName has to be a knownMethod or there has to be a method-signature
 1731  0
                     if (isKnownTargetAttributeMethod || methodSignature != null)
 1732  
                     {
 1733  0
                         if ("action".equals(targetAttributeName))
 1734  
                         {
 1735  0
                             return !(component instanceof ActionSource2);
 1736  
                         }
 1737  0
                         else if ("actionListener".equals(targetAttributeName))
 1738  
                         {
 1739  0
                             return !(component instanceof ActionSource2);
 1740  
                         }
 1741  0
                         else if ("validator".equals(targetAttributeName))
 1742  
                         {
 1743  0
                             return !(component instanceof EditableValueHolder);
 1744  
                         }
 1745  0
                         else if ("valueChangeListener".equals(targetAttributeName))
 1746  
                         {
 1747  0
                             return !(component instanceof EditableValueHolder);
 1748  
                         }
 1749  
                         else
 1750  
                         {
 1751  0
                             return true;
 1752  
                         }
 1753  
                     }
 1754  
                 }
 1755  
             }
 1756  0
             return false;
 1757  
         }
 1758  
         else
 1759  
         {
 1760  0
             return false;
 1761  
         }
 1762  
     }
 1763  
 
 1764  
     @SuppressWarnings("unchecked")
 1765  
     private MethodExpression reWrapMethodExpression(MethodExpression createdMethodExpression,
 1766  
                                                     ValueExpression originalValueExpression)
 1767  
     {
 1768  0
         if (originalValueExpression instanceof LocationValueExpression)
 1769  
         {
 1770  0
             return new LocationMethodExpression(
 1771  
                     ((LocationValueExpression) originalValueExpression).getLocation(),
 1772  
                     reWrapMethodExpression(createdMethodExpression,
 1773  
                             ((LocationValueExpression) originalValueExpression).getWrapped()),
 1774  
                     ((LocationValueExpression) originalValueExpression).getCCLevel());
 1775  
         }
 1776  0
         else if (originalValueExpression instanceof FacesWrapper &&
 1777  
                 ((FacesWrapper) originalValueExpression).getWrapped() instanceof ValueExpression)
 1778  
         {
 1779  0
             return reWrapMethodExpression(createdMethodExpression,
 1780  
                     (ValueExpression) ((FacesWrapper) originalValueExpression).getWrapped());
 1781  
         }
 1782  
         else
 1783  
         {
 1784  0
             return createdMethodExpression;
 1785  
         }
 1786  
     }
 1787  
 
 1788  
     /**
 1789  
      * {@inheritDoc}
 1790  
      */
 1791  
     @Override
 1792  
     public Resource getScriptComponentResource(FacesContext context, Resource componentResource)
 1793  
     {
 1794  0
         checkNull(context, "context");
 1795  0
         checkNull(componentResource, "componentResource");
 1796  
         // TODO Auto-generated method stub
 1797  0
         return null;
 1798  
     }
 1799  
 
 1800  
     /**
 1801  
      * {@inheritDoc}
 1802  
      */
 1803  
     @Override
 1804  
     public StateManagementStrategy getStateManagementStrategy(FacesContext context, String viewId)
 1805  
     {
 1806  
         // Use partial state saving strategy only if javax.faces.PARTIAL_STATE_SAVING is "true" and
 1807  
         // the current view is not on javax.faces.FULL_STATE_SAVING_VIEW_IDS.
 1808  0
         if (_partialStateSaving && _stateMgmtStrategy == null)
 1809  
         {
 1810  0
             _stateMgmtStrategy = new DefaultFaceletsStateManagementStrategy(context);
 1811  
         }
 1812  
 
 1813  0
         return _usePartialStateSavingOnThisView(viewId) ? _stateMgmtStrategy : null;
 1814  
     }
 1815  
 
 1816  
     /**
 1817  
      * {@inheritDoc}
 1818  
      */
 1819  
     @Override
 1820  
     public ViewMetadata getViewMetadata(FacesContext context, String viewId)
 1821  
     {
 1822  0
         checkNull(context, "facesContext");
 1823  0
         checkNull(viewId, "viewId");
 1824  0
         return new FaceletViewMetadata(viewId);
 1825  
     }
 1826  
 
 1827  
     /**
 1828  
      * {@inheritDoc}
 1829  
      */
 1830  
     @Override
 1831  
     public void renderView(FacesContext context, UIViewRoot view) throws IOException
 1832  
     {
 1833  0
         if (!view.isRendered())
 1834  
         {
 1835  0
             return;
 1836  
         }
 1837  
 
 1838  
         // log request
 1839  0
         if (log.isLoggable(Level.FINE))
 1840  
         {
 1841  0
             log.fine("Rendering View: " + view.getViewId());
 1842  
         }
 1843  
 
 1844  
         try
 1845  
         {
 1846  
             // build view - but not if we're in "buildBeforeRestore"
 1847  
             // land and we've already got a populated view. Note
 1848  
             // that this optimizations breaks if there's a "c:if" in
 1849  
             // the page that toggles as a result of request processing -
 1850  
             // should that be handled? Or
 1851  
             // is this optimization simply so minor that it should just
 1852  
             // be trimmed altogether?
 1853  
             // See JSF 2.0 spec section 2.2.6, buildView is called before
 1854  
             // Render Response
 1855  
             //if (!isFilledView(context, view))
 1856  
             //{
 1857  
             //    buildView(context, view);
 1858  
             //}
 1859  
 
 1860  
             // setup writer and assign it to the context
 1861  0
             ResponseWriter origWriter = createResponseWriter(context);
 1862  
 
 1863  0
             ExternalContext extContext = context.getExternalContext();
 1864  0
             Writer outputWriter = extContext.getResponseOutputWriter();
 1865  
 
 1866  0
             StateWriter stateWriter = new StateWriter(outputWriter, 1024, context);
 1867  
             try
 1868  
             {
 1869  0
                 ResponseWriter writer = origWriter.cloneWithWriter(stateWriter);
 1870  
                 try
 1871  
                 {
 1872  0
                     context.setResponseWriter(writer);
 1873  
 
 1874  0
                     StateManager stateMgr = context.getApplication().getStateManager();
 1875  
                     // force creation of session if saving state there
 1876  
                     // -= Leonardo Uribe =- Do this does not have any sense!. The only reference
 1877  
                     // about these lines are on http://java.net/projects/facelets/sources/svn/revision/376
 1878  
                     // and it says: "fixed lazy session instantiation with eager response commit"
 1879  
                     // This code is obviously to prevent this exception:
 1880  
                     // java.lang.IllegalStateException: Cannot create a session after the response has been committed
 1881  
                     // But in theory if that so, StateManager.saveState must happen before writer.close() is called,
 1882  
                     // which can be done very easily.
 1883  
                     //if (!stateMgr.isSavingStateInClient(context))
 1884  
                     //{
 1885  
                     //    extContext.getSession(true);
 1886  
                     //}
 1887  
 
 1888  
                     // render the view to the response
 1889  0
                     writer.startDocument();
 1890  
 
 1891  0
                     view.encodeAll(context);
 1892  
 
 1893  0
                     writer.endDocument();
 1894  
 
 1895  
                     // finish writing
 1896  
                     // -= Leonardo Uribe =- This does not has sense too, because that's the reason
 1897  
                     // of the try/finally block. In practice, it only forces the close of the tag 
 1898  
                     // in HtmlResponseWriter if necessary, but according to the spec, this should
 1899  
                     // be done using writer.flush() instead.
 1900  
                     // writer.close();
 1901  
 
 1902  
                     // flush to origWriter
 1903  0
                     if (stateWriter.isStateWritten())
 1904  
                     {
 1905  
                         // Call this method to force close the tag if necessary.
 1906  
                         // The spec javadoc says this: 
 1907  
                         // "... Flush any ouput buffered by the output method to the underlying 
 1908  
                         // Writer or OutputStream. This method will not flush the underlying 
 1909  
                         // Writer or OutputStream; it simply clears any values buffered by this 
 1910  
                         // ResponseWriter. ..."
 1911  0
                         writer.flush();
 1912  
 
 1913  
                         // =-= markoc: STATE_KEY is in output ONLY if 
 1914  
                         // stateManager.isSavingStateInClient(context)is true - see
 1915  
                         // org.apache.myfaces.application.ViewHandlerImpl.writeState(FacesContext)
 1916  
                         // TODO this class and ViewHandlerImpl contain same constant <!--@@JSF_FORM_STATE_MARKER@@-->
 1917  0
                         Object stateObj = stateMgr.saveView(context);
 1918  0
                         String content = stateWriter.getAndResetBuffer();
 1919  0
                         int end = content.indexOf(STATE_KEY);
 1920  
                         // See if we can find any trace of the saved state.
 1921  
                         // If so, we need to perform token replacement
 1922  0
                         if (end >= 0)
 1923  
                         {
 1924  
                             // save state
 1925  
                             String stateStr;
 1926  0
                             if (view.isTransient())
 1927  
                             {
 1928  
                                 // Force state saving
 1929  0
                                 stateMgr.writeState(context, stateObj);
 1930  0
                                 stateStr = stateWriter.getAndResetBuffer();
 1931  
                             }
 1932  0
                             else if (stateObj == null)
 1933  
                             {
 1934  0
                                 stateStr = null;
 1935  
                             }
 1936  
                             else
 1937  
                             {
 1938  0
                                 stateMgr.writeState(context, stateObj);
 1939  0
                                 stateStr = stateWriter.getAndResetBuffer();
 1940  
                             }
 1941  
 
 1942  0
                             int start = 0;
 1943  
 
 1944  0
                             while (end != -1)
 1945  
                             {
 1946  0
                                 origWriter.write(content, start, end - start);
 1947  0
                                 if (stateStr != null)
 1948  
                                 {
 1949  0
                                     origWriter.write(stateStr);
 1950  
                                 }
 1951  0
                                 start = end + STATE_KEY_LEN;
 1952  0
                                 end = content.indexOf(STATE_KEY, start);
 1953  
                             }
 1954  
 
 1955  0
                             origWriter.write(content, start, content.length() - start);
 1956  
                             // No trace of any saved state, so we just need to flush
 1957  
                             // the buffer
 1958  0
                         }
 1959  
                         else
 1960  
                         {
 1961  0
                             origWriter.write(content);
 1962  
                         }
 1963  0
                     }
 1964  0
                     else if (stateWriter.isStateWrittenWithoutWrapper())
 1965  
                     {
 1966  
                         // The state token has been written but the state has not been
 1967  
                         // saved yet.
 1968  0
                         stateMgr.saveView(context);
 1969  
                     }
 1970  
                     else
 1971  
                     {
 1972  
                         // GET case without any form that trigger state saving.
 1973  
                         // Try to store it into cache.
 1974  0
                         if (_viewPoolProcessor != null && 
 1975  
                             _viewPoolProcessor.isViewPoolEnabledForThisView(context, view))
 1976  
                         {
 1977  0
                             ViewDeclarationLanguage vdl = context.getApplication().
 1978  
                                     getViewHandler().getViewDeclarationLanguage(
 1979  
                                         context, view.getViewId());
 1980  
 
 1981  0
                             if (ViewDeclarationLanguage.FACELETS_VIEW_DECLARATION_LANGUAGE_ID.equals(
 1982  
                                     vdl.getId()))
 1983  
                             {
 1984  0
                                 StateManagementStrategy sms = vdl.getStateManagementStrategy(
 1985  
                                         context, view.getId());
 1986  0
                                 if (sms != null)
 1987  
                                 {
 1988  0
                                     context.getAttributes().put(ViewPoolProcessor.FORCE_HARD_RESET, Boolean.TRUE);
 1989  
 
 1990  
                                     // Force indirectly to store the map in the cache
 1991  
                                     try
 1992  
                                     {
 1993  0
                                         Object state = sms.saveView(context);
 1994  
                                     }
 1995  
                                     finally
 1996  
                                     {
 1997  0
                                         context.getAttributes().remove(ViewPoolProcessor.FORCE_HARD_RESET);
 1998  0
                                     }
 1999  
 
 2000  
                                     // Clear the calculated value from the application map
 2001  0
                                     context.getAttributes().remove(SERIALIZED_VIEW_REQUEST_ATTR);
 2002  
                                 }
 2003  
                             }
 2004  
                         }
 2005  
                     }
 2006  
                 }
 2007  
                 finally
 2008  
                 {
 2009  
                     // The Facelets implementation must close the writer used to write the response
 2010  0
                     writer.close();
 2011  0
                 }
 2012  
             }
 2013  
             finally
 2014  
             {
 2015  0
                 stateWriter.release(context);
 2016  0
             }
 2017  
         }
 2018  0
         catch (FileNotFoundException fnfe)
 2019  
         {
 2020  0
             handleFaceletNotFound(context, view.getViewId());
 2021  
         }
 2022  0
         catch (Exception e)
 2023  
         {
 2024  0
             handleRenderException(context, e);
 2025  0
         }
 2026  0
     }
 2027  
     
 2028  0
     private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
 2029  
         StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
 2030  
 
 2031  
     /**
 2032  
      * {@inheritDoc}
 2033  
      */
 2034  
     @Override
 2035  
     public UIViewRoot createView(FacesContext context, String viewId)
 2036  
     {
 2037  0
         checkNull(viewId, "viewId");
 2038  
         // we have to check for a possible debug request
 2039  0
         if (UIDebug.debugRequest(context))
 2040  
         {
 2041  
             // the current request is a debug request, so we don't need
 2042  
             // to create a view, since the output has already been written
 2043  
             // in UIDebug.debugRequest() and facesContext.responseComplete()
 2044  
             // has been called.
 2045  0
             return null;
 2046  
         }
 2047  
         else
 2048  
         {
 2049  0
             UIViewRoot root = super.createView(context, viewId);
 2050  0
             if (root != null)
 2051  
             {
 2052  
                 //Ensure calculateResourceLibraryContracts() can be decorated
 2053  0
                 ViewDeclarationLanguage vdl = context.getApplication().getViewHandler().
 2054  
                     getViewDeclarationLanguage(context, viewId);
 2055  0
                 List<String> contracts = vdl.calculateResourceLibraryContracts(
 2056  
                     context, root.getViewId() != null ? root.getViewId() : viewId);
 2057  0
                 context.setResourceLibraryContracts(contracts);
 2058  
             }
 2059  0
             return root;
 2060  
         }
 2061  
     }
 2062  
 
 2063  
     /**
 2064  
      * {@inheritDoc}
 2065  
      */
 2066  
     @Override
 2067  
     public UIViewRoot restoreView(FacesContext context, String viewId)
 2068  
     {
 2069  0
         checkNull(viewId, "viewId");
 2070  
         // Currently there is no way, in which UIDebug.debugRequest(context)
 2071  
         // can create debug information and return true at this point,
 2072  
         // because this method is only accessed if the current request
 2073  
         // is a postback, which will never be true for a debug page.
 2074  
         // The only point where valid debug output can be produced by now
 2075  
         // is in createView() -= Jakob Korherr =-
 2076  
         //if (UIDebug.debugRequest(context))
 2077  
         //{
 2078  
         //    return new UIViewRoot();
 2079  
         //}
 2080  
 
 2081  
         //else if (!_buildBeforeRestore)
 2082  
         //{
 2083  
         
 2084  
         // When partial state saving is not used, createView() is not called. To ensure
 2085  
         // everything is in place it is necessary to calculate the resource library 
 2086  
         // contracts and set them into facesContext.
 2087  0
         ViewDeclarationLanguage vdl = context.getApplication().getViewHandler().
 2088  
             getViewDeclarationLanguage(context, viewId);
 2089  0
         List<String> contracts = vdl.calculateResourceLibraryContracts(
 2090  
             context, viewId);
 2091  0
         context.setResourceLibraryContracts(contracts);
 2092  
         
 2093  
         // JSF 2.2 stateless views
 2094  
         // We need to check if the incoming view is stateless or not and if that so rebuild it here
 2095  
         // note we cannot do this in DefaultFaceletsStateManagementStrategy because it is only used
 2096  
         // when PSS is enabled, but stateless views can be used without PSS. If the view is stateless,
 2097  
         // there is no need to ask to the StateManager.
 2098  0
         Application application = context.getApplication();
 2099  0
         ViewHandler applicationViewHandler = application.getViewHandler();
 2100  0
         String renderKitId = applicationViewHandler.calculateRenderKitId(context);
 2101  
 
 2102  0
         ResponseStateManager manager = getRenderKitFactory().getRenderKit(
 2103  
             context, renderKitId).getResponseStateManager();
 2104  
         
 2105  0
         if (manager.isStateless(context, viewId))
 2106  
         {
 2107  
             // Per the spec: build the view.
 2108  0
             UIViewRoot view = null;
 2109  
             try
 2110  
             {
 2111  0
                 ViewMetadata metadata = vdl.getViewMetadata (context, viewId);
 2112  0
                 if (metadata != null)
 2113  
                 {
 2114  0
                     view = metadata.createMetadataView(context);
 2115  
                 }
 2116  0
                 if (view == null)
 2117  
                 {
 2118  0
                     view = context.getApplication().getViewHandler().createView(context, viewId);
 2119  
                 }
 2120  0
                 context.setViewRoot (view); 
 2121  0
                 boolean oldContextEventState = context.isProcessingEvents();
 2122  
                 try 
 2123  
                 {
 2124  0
                     context.setProcessingEvents (true);
 2125  0
                     vdl.buildView (context, view);
 2126  
                     // If the view is not transient, then something is wrong. Throw an exception.
 2127  0
                     if (!view.isTransient())
 2128  
                     {
 2129  0
                         throw new FacesException ("unable to create view \"" + viewId + "\"");
 2130  
                     } 
 2131  
                 }
 2132  
                 finally
 2133  
                 {
 2134  0
                     context.setProcessingEvents (oldContextEventState);
 2135  0
                 } 
 2136  
             }
 2137  0
             catch (Throwable e)
 2138  
             {
 2139  0
                 throw new FacesException ("unable to create view \"" + viewId + "\"", e);
 2140  0
             }
 2141  0
             return view;
 2142  
         }
 2143  
         else
 2144  
         {
 2145  0
             return super.restoreView(context, viewId);
 2146  
         }
 2147  
     }
 2148  
 
 2149  
     /**
 2150  
      * {@inheritDoc}
 2151  
      */
 2152  
     @Override
 2153  
     protected String calculateViewId(FacesContext context, String viewId)
 2154  
     {
 2155  0
         if (_cachedViewHandlerSupport == null)
 2156  
         {
 2157  0
             _cachedViewHandlerSupport = new DefaultViewHandlerSupport();
 2158  
         }
 2159  
 
 2160  0
         return _cachedViewHandlerSupport.calculateViewId(context, viewId);
 2161  
     }
 2162  
 
 2163  
     /**
 2164  
      * Creates the Facelet page compiler.
 2165  
      *
 2166  
      * @param context
 2167  
      *            the current FacesContext
 2168  
      *
 2169  
      * @return the application's Facelet page compiler
 2170  
      */
 2171  
     protected Compiler createCompiler(FacesContext context)
 2172  
     {
 2173  0
         Compiler compiler = new SAXCompiler();
 2174  
 
 2175  0
         compiler.setDevelopmentProjectStage(context.isProjectStage(ProjectStage.Development));
 2176  
 
 2177  0
         loadLibraries(context, compiler);
 2178  0
         loadDecorators(context, compiler);
 2179  0
         loadOptions(context, compiler);
 2180  
 
 2181  0
         return compiler;
 2182  
     }
 2183  
 
 2184  
     /**
 2185  
      * Creates a FaceletFactory instance using the specified compiler.
 2186  
      *
 2187  
      * @param context
 2188  
      *            the current FacesContext
 2189  
      * @param compiler
 2190  
      *            the compiler to be used by the factory
 2191  
      *
 2192  
      * @return the factory used by this VDL to load pages
 2193  
      */
 2194  
     protected FaceletFactory createFaceletFactory(FacesContext context, Compiler compiler)
 2195  
     {
 2196  0
         ExternalContext eContext = context.getExternalContext();
 2197  
 
 2198  
         // refresh period
 2199  
         long refreshPeriod;
 2200  0
         if (context.isProjectStage(ProjectStage.Production))
 2201  
         {
 2202  0
             refreshPeriod = WebConfigParamUtils.getLongInitParameter(eContext, PARAMS_REFRESH_PERIOD,
 2203  
                     DEFAULT_REFRESH_PERIOD_PRODUCTION);
 2204  
         }
 2205  
         else
 2206  
         {
 2207  0
             refreshPeriod = WebConfigParamUtils.getLongInitParameter(eContext, PARAMS_REFRESH_PERIOD,
 2208  
                     DEFAULT_REFRESH_PERIOD);
 2209  
         }
 2210  
 
 2211  
         // resource resolver
 2212  0
         ResourceResolver resolver = new DefaultResourceResolver();
 2213  0
         ArrayList<String> classNames = new ArrayList<String>();
 2214  0
         String faceletsResourceResolverClassName = WebConfigParamUtils.getStringInitParameter(eContext,
 2215  
                 PARAMS_RESOURCE_RESOLVER, null);
 2216  0
         List<String> resourceResolversFromAnnotations = RuntimeConfig.getCurrentInstance(
 2217  
             context.getExternalContext()).getResourceResolvers();
 2218  0
         if (faceletsResourceResolverClassName != null)
 2219  
         {
 2220  0
             classNames.add(faceletsResourceResolverClassName);
 2221  
         }
 2222  0
         if (!resourceResolversFromAnnotations.isEmpty())
 2223  
         {
 2224  0
             classNames.addAll(resourceResolversFromAnnotations);
 2225  
         }
 2226  0
         if (!classNames.isEmpty())
 2227  
         {
 2228  0
             resolver = ClassUtils.buildApplicationObject(ResourceResolver.class, classNames, resolver);
 2229  
         }
 2230  
 
 2231  0
         _resourceResolver = resolver;
 2232  
 
 2233  0
         return new DefaultFaceletFactory(compiler, resolver, refreshPeriod);
 2234  
     }
 2235  
 
 2236  
 
 2237  
     protected ResponseWriter createResponseWriter(FacesContext context) throws IOException, FacesException
 2238  
     {
 2239  0
         ExternalContext extContext = context.getExternalContext();
 2240  0
         RenderKit renderKit = context.getRenderKit();
 2241  
         // Avoid a cryptic NullPointerException when the renderkit ID
 2242  
         // is incorrectly set
 2243  0
         if (renderKit == null)
 2244  
         {
 2245  0
             String id = context.getViewRoot().getRenderKitId();
 2246  0
             throw new IllegalStateException("No render kit was available for id \"" + id + "\"");
 2247  
         }
 2248  
 
 2249  
         // set the buffer for content
 2250  0
         if (_bufferSize != -1)
 2251  
         {
 2252  0
             extContext.setResponseBufferSize(_bufferSize);
 2253  
         }
 2254  
 
 2255  
         // get our content type
 2256  0
         String contentType = (String) context.getAttributes().get("facelets.ContentType");
 2257  
 
 2258  
         // get the encoding
 2259  0
         String encoding = (String) context.getAttributes().get("facelets.Encoding");
 2260  
 
 2261  
         // -= Leonardo Uribe =- Add */* to the contentType is a fix done from FaceletViewHandler
 2262  
         // to make old RI versions work, but since this is for JSF 2.0 it is not necessary that code.
 2263  0
         ResponseWriter writer = renderKit.createResponseWriter(FaceletsVDLUtils.NullWriter.INSTANCE,
 2264  
             contentType, encoding);
 2265  
 
 2266  
         //ResponseWriter writer;
 2267  
         // append */* to the contentType so createResponseWriter will succeed no matter
 2268  
         // the requested contentType.
 2269  
         //if (contentType != null && !contentType.equals("*/*"))
 2270  
         //{
 2271  
         //    contentType += ",*/*";
 2272  
         //}
 2273  
         // Create a dummy ResponseWriter with a bogus writer,
 2274  
         // so we can figure out what content type the ReponseWriter
 2275  
         // is really going to ask for
 2276  
         //try
 2277  
         //{
 2278  
         //    writer = renderKit.createResponseWriter(NullWriter.Instance, contentType, encoding);
 2279  
         //}
 2280  
         // catch (IllegalArgumentException e)
 2281  
         //{
 2282  
         // Added because of an RI bug prior to 1.2_05-b3. Might as well leave it in case other
 2283  
         // impls have the same problem. https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=613
 2284  
         //log.finest("The impl didn't correctly handled '*/*' in the content type list.  Trying '*/*' directly.");
 2285  
         //writer = renderKit.createResponseWriter(NullWriter.Instance, "*/*", encoding);
 2286  
         //}
 2287  
 
 2288  
         // Override the JSF provided content type if necessary
 2289  0
         contentType = getResponseContentType(context, writer.getContentType());
 2290  0
         encoding = getResponseEncoding(context, writer.getCharacterEncoding());
 2291  
 
 2292  
         // apply them to the response
 2293  0
         extContext.setResponseContentType(contentType + "; charset=" + encoding);
 2294  
 
 2295  
         // removed 2005.8.23 to comply with J2EE 1.3
 2296  
         // response.setCharacterEncoding(encoding);
 2297  
 
 2298  
         // Now, clone with the real writer
 2299  0
         writer = writer.cloneWithWriter(extContext.getResponseOutputWriter());
 2300  
 
 2301  0
         return writer;
 2302  
     }
 2303  
 
 2304  
     /**
 2305  
      * @deprecated this code is not used anymore
 2306  
      */
 2307  
     @Deprecated
 2308  
     protected String getDefaultSuffix(FacesContext context) throws FacesException
 2309  
     {
 2310  0
         if (_defaultSuffix == null)
 2311  
         {
 2312  0
             ExternalContext eContext = context.getExternalContext();
 2313  
 
 2314  0
             String viewSuffix = eContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
 2315  
 
 2316  0
             _defaultSuffix = viewSuffix == null ? ViewHandler.DEFAULT_FACELETS_SUFFIX : viewSuffix;
 2317  
         }
 2318  
 
 2319  0
         return _defaultSuffix;
 2320  
     }
 2321  
 
 2322  
     /**
 2323  
      * @deprecated
 2324  
      */
 2325  
     @Deprecated
 2326  
     protected String getRenderedViewId(FacesContext context, String actionId)
 2327  
     {
 2328  
         // The previous code comes from Facelets 1.1.x but now it becomes invalid. In JSF 2.1, it is possible
 2329  
         // to have multiple file extensions, and to make work correctly viewExists(), it is necessary to return
 2330  
         // the viewId without changes
 2331  0
         return actionId;
 2332  
     }
 2333  
 
 2334  
     /**
 2335  
      * Generate the content type
 2336  
      *
 2337  
      * @param context
 2338  
      * @param orig
 2339  
      * @return
 2340  
      */
 2341  
     protected String getResponseContentType(FacesContext context, String orig)
 2342  
     {
 2343  0
         String contentType = orig;
 2344  
 
 2345  
         // see if we need to override the contentType
 2346  0
         Map<Object, Object> m = context.getAttributes();
 2347  0
         if (m.containsKey("facelets.ContentType"))
 2348  
         {
 2349  0
             contentType = (String) m.get("facelets.ContentType");
 2350  0
             if (log.isLoggable(Level.FINEST))
 2351  
             {
 2352  0
                 log.finest("Facelet specified alternate contentType '" + contentType + "'");
 2353  
             }
 2354  
         }
 2355  
 
 2356  
         // safety check
 2357  0
         if (contentType == null)
 2358  
         {
 2359  0
             contentType = "text/html";
 2360  0
             log.finest("ResponseWriter created had a null ContentType, defaulting to text/html");
 2361  
         }
 2362  
 
 2363  0
         return contentType;
 2364  
     }
 2365  
 
 2366  
     /**
 2367  
      * Generate the encoding
 2368  
      *
 2369  
      * @param context
 2370  
      * @param orig
 2371  
      * @return
 2372  
      */
 2373  
     protected String getResponseEncoding(FacesContext context, String orig)
 2374  
     {
 2375  0
         String encoding = orig;
 2376  
 
 2377  
         // see if we need to override the encoding
 2378  0
         Map<Object, Object> m = context.getAttributes();
 2379  
 
 2380  0
         Object session = context.getExternalContext().getSession(false);
 2381  
 
 2382  
         // 1. check the request attribute
 2383  0
         if (m.containsKey(PARAM_ENCODING))
 2384  
         {
 2385  0
             encoding = (String) m.get(PARAM_ENCODING);
 2386  0
             if (encoding != null && log.isLoggable(Level.FINEST))
 2387  
             {
 2388  0
                 log.finest("Facelet specified alternate encoding '" + encoding + "'");
 2389  
             }
 2390  
 
 2391  0
             if (session != null)
 2392  
             {
 2393  0
                 context.getExternalContext().getSessionMap().put(CHARACTER_ENCODING_KEY, encoding);
 2394  
             }
 2395  
         }
 2396  
 
 2397  
         // 2. get it from request
 2398  0
         if (encoding == null)
 2399  
         {
 2400  0
             encoding = context.getExternalContext().getRequestCharacterEncoding();
 2401  
         }
 2402  
 
 2403  
         // 3. get it from the session
 2404  0
         if (encoding == null)
 2405  
         {
 2406  0
             if (session != null)
 2407  
             {
 2408  0
                 encoding = (String) context.getExternalContext().getSessionMap().get(CHARACTER_ENCODING_KEY);
 2409  0
                 if (encoding != null && log.isLoggable(Level.FINEST))
 2410  
                 {
 2411  0
                     log.finest("Session specified alternate encoding '" + encoding + '\'');
 2412  
                 }
 2413  
             }
 2414  
         }
 2415  
 
 2416  
         // 4. default it
 2417  0
         if (encoding == null)
 2418  
         {
 2419  0
             encoding = DEFAULT_CHARACTER_ENCODING;
 2420  0
             if (log.isLoggable(Level.FINEST))
 2421  
             {
 2422  0
                 log.finest("ResponseWriter created had a null CharacterEncoding, defaulting to " + encoding);
 2423  
             }
 2424  
         }
 2425  
 
 2426  0
         return encoding;
 2427  
     }
 2428  
 
 2429  
     protected void handleFaceletNotFound(FacesContext context, String viewId) throws FacesException, IOException
 2430  
     {
 2431  0
         String actualId = context.getApplication().getViewHandler().getActionURL(context, viewId);
 2432  0
         context.getExternalContext().responseSendError(HttpServletResponse.SC_NOT_FOUND, actualId);
 2433  0
         context.responseComplete();
 2434  
 
 2435  0
     }
 2436  
 
 2437  
     protected void handleRenderException(FacesContext context, Exception e)
 2438  
             throws IOException, ELException, FacesException
 2439  
     {
 2440  
         /*
 2441  
         UIViewRoot root = context.getViewRoot();
 2442  
         StringBuffer sb = new StringBuffer(64);
 2443  
         sb.append("Error Rendering View");
 2444  
         if (root != null)
 2445  
         {
 2446  
             sb.append('[');
 2447  
             sb.append(root.getViewId());
 2448  
             sb.append(']');
 2449  
         }
 2450  
         
 2451  
         log.log(Level.SEVERE, sb.toString(), e);
 2452  
         */
 2453  
 
 2454  
         // rethrow the Exception to be handled by the ExceptionHandler
 2455  0
         if (e instanceof RuntimeException)
 2456  
         {
 2457  0
             throw (RuntimeException) e;
 2458  
         }
 2459  0
         else if (e instanceof IOException)
 2460  
         {
 2461  0
             throw (IOException) e;
 2462  
         }
 2463  
         else
 2464  
         {
 2465  0
             throw new FacesException(e.getMessage(), e);
 2466  
         }
 2467  
     }
 2468  
 
 2469  
     /**
 2470  
      * Initialize the ViewHandler during its first request.
 2471  
      */
 2472  
     protected void initialize(FacesContext context)
 2473  
     {
 2474  0
         log.finest("Initializing");
 2475  
 
 2476  0
         Compiler compiler = createCompiler(context);
 2477  
 
 2478  0
         _faceletFactory = createFaceletFactory(context, compiler);
 2479  
 
 2480  0
         ExternalContext eContext = context.getExternalContext();
 2481  0
         _initializeBuffer(eContext);
 2482  0
         _initializeMode(eContext);
 2483  0
         _initializeContractMappings(eContext);
 2484  
         
 2485  
         // Create a component ids cache and store it on application map to
 2486  
         // reduce the overhead associated with create such ids over and over.
 2487  0
         MyfacesConfig mfConfig = MyfacesConfig.getCurrentInstance(eContext);
 2488  0
         if (mfConfig.getComponentUniqueIdsCacheSize() > 0)
 2489  
         {
 2490  0
             String[] componentIdsCached = SectionUniqueIdCounter.generateUniqueIdCache("_", 
 2491  
                     mfConfig.getComponentUniqueIdsCacheSize());
 2492  0
             eContext.getApplicationMap().put(
 2493  
                     CACHED_COMPONENT_IDS, componentIdsCached);
 2494  
         }
 2495  
         
 2496  0
         _viewPoolProcessor = ViewPoolProcessor.getInstance(context);
 2497  
 
 2498  0
         log.finest("Initialization Successful");
 2499  0
     }
 2500  
 
 2501  
     /**
 2502  
      * Load the various decorators for Facelets.
 2503  
      *
 2504  
      * @param context
 2505  
      *            the current FacesContext
 2506  
      * @param compiler
 2507  
      *            the page compiler
 2508  
      */
 2509  
     protected void loadDecorators(FacesContext context, Compiler compiler)
 2510  
     {
 2511  0
         getFaceletsCompilerSupport().loadDecorators(context, compiler);
 2512  0
     }
 2513  
 
 2514  
     protected FaceletsCompilerSupport getFaceletsCompilerSupport()
 2515  
     {
 2516  0
         if (_faceletsCompilerSupport == null)
 2517  
         {
 2518  0
             _faceletsCompilerSupport = new FaceletsCompilerSupport();
 2519  
         }
 2520  0
         return _faceletsCompilerSupport;
 2521  
     }
 2522  
     
 2523  
     public void setFaceletsCompilerSupport(FaceletsCompilerSupport support)
 2524  
     {
 2525  0
         _faceletsCompilerSupport = support;
 2526  0
     }
 2527  
 
 2528  
     /**
 2529  
      * Load the various tag libraries for Facelets.
 2530  
      *
 2531  
      * @param context
 2532  
      *            the current FacesContext
 2533  
      * @param compiler
 2534  
      *            the page compiler
 2535  
      */
 2536  
     protected void loadLibraries(FacesContext context, Compiler compiler)
 2537  
     {
 2538  0
         getFaceletsCompilerSupport().loadLibraries(context, compiler);
 2539  0
     }
 2540  
 
 2541  
     /**
 2542  
      * Load the various options for Facelets compiler. Currently only comment skipping is supported.
 2543  
      *
 2544  
      * @param context
 2545  
      *            the current FacesContext
 2546  
      * @param compiler
 2547  
      *            the page compiler
 2548  
      */
 2549  
     protected void loadOptions(FacesContext context, Compiler compiler)
 2550  
     {
 2551  0
         getFaceletsCompilerSupport().loadOptions(context, compiler);
 2552  0
     }
 2553  
 
 2554  
     /**
 2555  
      * {@inheritDoc}
 2556  
      */
 2557  
     @Override
 2558  
     protected void sendSourceNotFound(FacesContext context, String message)
 2559  
     {
 2560  
         try
 2561  
         {
 2562  0
             context.responseComplete();
 2563  0
             context.getExternalContext().responseSendError(HttpServletResponse.SC_NOT_FOUND, message);
 2564  
         }
 2565  0
         catch (IOException ioe)
 2566  
         {
 2567  0
             throw new FacesException(ioe);
 2568  0
         }
 2569  0
     }
 2570  
 
 2571  
     /**
 2572  
      * Gets the Facelet representing the specified view identifier.
 2573  
      *
 2574  
      * @param viewId
 2575  
      *            the view identifier
 2576  
      *
 2577  
      * @return the Facelet representing the specified view identifier
 2578  
      *
 2579  
      * @throws IOException
 2580  
      *             if a read or parsing error occurs
 2581  
      */
 2582  
     private Facelet _getFacelet(FacesContext context, String viewId) throws IOException
 2583  
     {
 2584  
         // grab our FaceletFactory and create a Facelet
 2585  0
         FaceletFactory.setInstance(_faceletFactory);
 2586  
         try
 2587  
         {
 2588  0
             return _faceletFactory.getFacelet(context, viewId);
 2589  
         }
 2590  
         finally
 2591  
         {
 2592  0
             FaceletFactory.setInstance(null);
 2593  
         }
 2594  
     }
 2595  
 
 2596  
     private Facelet _getViewMetadataFacelet(FacesContext context, String viewId) throws IOException
 2597  
     {
 2598  
         // grab our FaceletFactory and create a Facelet used to create view metadata
 2599  0
         FaceletFactory.setInstance(_faceletFactory);
 2600  
         try
 2601  
         {
 2602  0
             return _faceletFactory.getViewMetadataFacelet(context, viewId);
 2603  
         }
 2604  
         finally
 2605  
         {
 2606  0
             FaceletFactory.setInstance(null);
 2607  
         }
 2608  
     }
 2609  
 
 2610  
     private void _initializeBuffer(ExternalContext context)
 2611  
     {
 2612  0
         _bufferSize = WebConfigParamUtils.getIntegerInitParameter(context, PARAMS_BUFFER_SIZE, 1024);
 2613  0
     }
 2614  
 
 2615  
     private void _initializeMode(ExternalContext context)
 2616  
     {
 2617  0
         String facesVersion = RuntimeConfig.getCurrentInstance(context).getFacesVersion();
 2618  
         boolean partialStateSavingDefault;
 2619  
 
 2620  
         // Per spec section 11.1.3, the default value for the partial state saving feature needs
 2621  
         // to be true if 2.0, false otherwise.
 2622  
 
 2623  0
         partialStateSavingDefault = facesVersion == null
 2624  
                 || facesVersion.trim().isEmpty()
 2625  
                 || Float.parseFloat(facesVersion) >= 2;
 2626  
 
 2627  
         // In jsf 2.0 this code evolve as PartialStateSaving feature
 2628  
         //_buildBeforeRestore = _getBooleanParameter(context, PARAM_BUILD_BEFORE_RESTORE, false);
 2629  0
         _partialStateSaving = WebConfigParamUtils.getBooleanInitParameter(context,
 2630  
                 StateManager.PARTIAL_STATE_SAVING_PARAM_NAME, partialStateSavingDefault);
 2631  
 
 2632  0
         String[] viewIds = StringUtils.splitShortString(WebConfigParamUtils.getStringInitParameter(context,
 2633  
                 StateManager.FULL_STATE_SAVING_VIEW_IDS_PARAM_NAME), ',');
 2634  
 
 2635  0
         if (viewIds.length > 0)
 2636  
         {
 2637  0
             _viewIds = new HashSet<String>(viewIds.length, 1.0f);
 2638  0
             Collections.addAll(_viewIds, viewIds);
 2639  
         }
 2640  
         else
 2641  
         {
 2642  0
             _viewIds = null;
 2643  
         }
 2644  
 
 2645  0
         if (_partialStateSaving)
 2646  
         {
 2647  0
             _refreshTransientBuildOnPSS = MyfacesConfig.getCurrentInstance(context).isRefreshTransientBuildOnPSS();
 2648  
 
 2649  0
             _refreshTransientBuildOnPSSAuto
 2650  
                     = MyfacesConfig.getCurrentInstance(context).isRefreshTransientBuildOnPSSAuto();
 2651  
 
 2652  0
             _markInitialStateWhenApplyBuildView = WebConfigParamUtils.getBooleanInitParameter(context,
 2653  
                     PARAM_MARK_INITIAL_STATE_WHEN_APPLY_BUILD_VIEW, false);
 2654  
         }
 2655  0
     }
 2656  
     
 2657  
     private void _initializeContractMappings(ExternalContext context)
 2658  
     {
 2659  0
         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(context);
 2660  0
         List<String> prefixWildcardKeys = new ArrayList<String>();
 2661  0
         Map<String, List<String>> contractMappings = new HashMap<String, List<String>>();
 2662  
         
 2663  0
         for (Map.Entry<String, List<String>> entry : runtimeConfig.getContractMappings().entrySet())
 2664  
         {
 2665  0
             String urlPattern = entry.getKey().trim();
 2666  0
             if (urlPattern.endsWith(ASTERISK))
 2667  
             {
 2668  0
                 prefixWildcardKeys.add(urlPattern);
 2669  
             }
 2670  0
             contractMappings.put(entry.getKey(), new ArrayList<String>(entry.getValue()));
 2671  0
         }
 2672  
         
 2673  0
         Collections.sort(prefixWildcardKeys, new FaceletsVDLUtils.KeyComparator());
 2674  
         
 2675  0
         this._prefixWildcardKeys = prefixWildcardKeys;
 2676  0
         this._contractMappings = contractMappings;
 2677  0
     }
 2678  
 
 2679  
     private boolean _usePartialStateSavingOnThisView(String viewId)
 2680  
     {
 2681  0
         return _partialStateSaving && !(_viewIds != null && _viewIds.contains(viewId));
 2682  
     }
 2683  
 
 2684  
     @Override
 2685  
     public List<String> calculateResourceLibraryContracts(FacesContext context, String viewId)
 2686  
     {
 2687  0
         List<String> contracts = this._contractMappings.get(viewId);
 2688  0
         if (contracts == null)
 2689  
         {
 2690  
             //Check prefix mapping
 2691  0
             for (String prefix : this._prefixWildcardKeys)
 2692  
             {
 2693  0
                 if (FaceletsVDLUtils.matchPattern(viewId, prefix))
 2694  
                 {
 2695  0
                     contracts =  this._contractMappings.get(prefix);
 2696  0
                     break;
 2697  
                 }
 2698  0
             }
 2699  
         }
 2700  0
         return contracts;
 2701  
     }
 2702  
 
 2703  
     private class FaceletViewMetadata extends ViewMetadataBase
 2704  
     {
 2705  
         /**
 2706  
          * Constructor
 2707  
          *
 2708  
          * Note that this viewId is not the one after calculateViewId() method
 2709  
          */
 2710  
         public FaceletViewMetadata(String viewId)
 2711  0
         {
 2712  0
             super(viewId);
 2713  0
         }
 2714  
 
 2715  
         @Override
 2716  
         public UIViewRoot createMetadataView(FacesContext context)
 2717  
         {
 2718  
             try
 2719  
             {
 2720  0
                 context.setProcessingEvents(false);
 2721  
 
 2722  
                 // spec doesn't say that this is necessary, but we blow up later if
 2723  
                 // the viewroot isn't available from the FacesContext.
 2724  
                 // -= Leonardo Uribe =- since it is supposed when we apply view metadata
 2725  
                 // facelet we don't apply components with renderers and we don't call getRenderKit()
 2726  
                 // it is safe to let this one commented
 2727  
                 // context.setViewRoot(view);
 2728  
 
 2729  
                 // -= Leonardo Uribe =- This part is related to section 2.5.5 of jsf 2.0 spec.
 2730  
                 // In theory what we need here is fill UIViewRoot.METADATA_FACET_NAME facet
 2731  
                 // with UIViewParameter instances. Later, ViewHandlerImpl.getBookmarkableURL(),
 2732  
                 // ViewHandlerImpl.getRedirectURL() and UIViewRoot.encodeEnd uses them. 
 2733  
                 // For now, the only way to do this is call buildView(context,view) method, but 
 2734  
                 // this is a waste of resources. We need to find another way to handle facelets view metadata.
 2735  
                 // Call to buildView causes the view is not created on Render Response phase,
 2736  
                 // if buildView is called from here all components pass through current lifecycle and only
 2737  
                 // UIViewParameter instances should be taken into account.
 2738  
                 // It should be an additional call to buildView on Render Response phase.
 2739  
                 // buildView(context, view);
 2740  
 
 2741  0
                 context.getAttributes().put(BUILDING_VIEW_METADATA, Boolean.TRUE);
 2742  
 
 2743  
                 // we have to invoke createView() on the application's ViewHandler
 2744  
                 // here instead of invoking it directly in FaceletVDL, because
 2745  
                 // the ViewHandler might be wrapped and wants to do some work
 2746  
                 // in createView() (e.g. in Trinidad - see MYFACES-2641)
 2747  0
                 UIViewRoot view = context.getApplication().getViewHandler().createView(context, getViewId());
 2748  
 
 2749  0
                 if (view != null)
 2750  
                 {
 2751  
                     // inside createView(context,viewId), calculateViewId() is called and
 2752  
                     // the result is stored inside created UIViewRoot, so we can safely take the derived
 2753  
                     // viewId from there.
 2754  0
                     Facelet facelet = null;
 2755  
                     try
 2756  
                     {
 2757  0
                         facelet = _getViewMetadataFacelet(context, view.getViewId());
 2758  
                     }
 2759  0
                     catch (FileNotFoundException e)
 2760  
                     {
 2761  0
                         sendSourceNotFound(context, getViewId());
 2762  0
                         return null;
 2763  0
                     }
 2764  
 
 2765  0
                     facelet.apply(context, view);
 2766  
                 }
 2767  
 
 2768  0
                 return view;
 2769  
             }
 2770  0
             catch (IOException ioe)
 2771  
             {
 2772  0
                 throw new FacesException(ioe);
 2773  
             }
 2774  
             finally
 2775  
             {
 2776  0
                 context.getAttributes().remove(BUILDING_VIEW_METADATA);
 2777  
 
 2778  0
                 context.setProcessingEvents(true);
 2779  
             }
 2780  
         }
 2781  
     }
 2782  
     
 2783  
     public FaceletFactory getFaceletFactory()
 2784  
     {
 2785  0
         return _faceletFactory;
 2786  
     }
 2787  
 
 2788  
     @Override
 2789  
     public UIComponent createComponent(FacesContext context, 
 2790  
         String taglibURI, String tagName, Map<String, Object> attributes)
 2791  
     {
 2792  0
         checkNull(context, "context");
 2793  0
         UIComponent createdComponent = null;
 2794  
         try
 2795  
         {
 2796  
             Facelet componentFacelet;
 2797  0
             FaceletFactory.setInstance(_faceletFactory);
 2798  
             try
 2799  
             {
 2800  0
                 componentFacelet
 2801  
                         = _faceletFactory.compileComponentFacelet(taglibURI, tagName, attributes);
 2802  
             }
 2803  
             finally
 2804  
             {
 2805  0
                 FaceletFactory.setInstance(null);
 2806  0
             }
 2807  0
             if (componentFacelet == null)
 2808  
             {
 2809  0
                 return null;
 2810  
             }
 2811  
             // Create a temporal component base class where all components will be put, but we are only
 2812  
             // interested in the inner UIComponent and if multiple are created, return this one.
 2813  0
             boolean requiresDynamicRefresh = false;
 2814  0
             boolean requiresFaceletDynamicRefresh = false;
 2815  0
             UIPanel tempParent
 2816  
                     = (UIPanel) context.getApplication().createComponent(
 2817  
                     context, UIPanel.COMPONENT_TYPE, null);
 2818  0
             tempParent.setId(context.getViewRoot().createUniqueId(context, null));
 2819  0
             String baseKey = tempParent.getId();
 2820  0
             baseKey = baseKey.startsWith(UIViewRoot.UNIQUE_ID_PREFIX) ? baseKey.substring(4) : baseKey;
 2821  
 
 2822  
             try
 2823  
             {
 2824  0
                 tempParent.pushComponentToEL(context, tempParent);
 2825  0
                 ((AbstractFacelet)componentFacelet).applyDynamicComponentHandler(
 2826  
                     context, tempParent, baseKey);
 2827  
             }
 2828  
             finally
 2829  
             {
 2830  0
                 tempParent.popComponentFromEL(context);
 2831  
                 // There are two cases:
 2832  
                 // 1. If we are under facelets algorithm control (binding case), the refreshing logic will be done
 2833  
                 // outside this block. We can check that condition easily with FaceletCompositionContext
 2834  
                 // 2. If we are not under facelets algorithm control, check if the dynamic component requires refresh,
 2835  
                 // if that so, mark the view to be refreshed and reset the flag, otherwise continue. This check
 2836  
                 // allows us to decide if we add a third listener to refresh on transient build.
 2837  
                     // Check if the current component requires dynamic refresh and if that so,
 2838  0
                 FaceletCompositionContext fcc = FaceletCompositionContext.getCurrentInstance(context);
 2839  0
                 if (fcc != null)
 2840  
                 {
 2841  0
                     requiresFaceletDynamicRefresh = true;
 2842  
                 }
 2843  0
                 else if (FaceletViewDeclarationLanguageBase.isDynamicComponentNeedsRefresh(context))
 2844  
                 {
 2845  0
                     FaceletViewDeclarationLanguageBase.activateDynamicComponentRefreshTransientBuild(context);
 2846  0
                     FaceletViewDeclarationLanguageBase.resetDynamicComponentNeedsRefreshFlag(context);
 2847  0
                     requiresDynamicRefresh = true;
 2848  
                 }
 2849  0
             }
 2850  0
             if (tempParent.getChildCount() > 1)
 2851  
             {
 2852  
                 // Multiple child. The tempParent will be returned. No need to
 2853  
                 // save MARK_CREATED.
 2854  0
                 createdComponent = tempParent;
 2855  0
                 tempParent.getAttributes().put("oam.vf.DYN_WRAPPER", baseKey);
 2856  0
                 tempParent.subscribeToEvent(PostRestoreStateEvent.class, new 
 2857  
                     RefreshDynamicComponentListener(taglibURI, tagName, attributes, baseKey));
 2858  0
                 if (requiresFaceletDynamicRefresh)
 2859  
                 {
 2860  0
                     FaceletViewDeclarationLanguageBase.dynamicComponentNeedsRefresh(context);
 2861  
                 }
 2862  
             }
 2863  0
             else if (tempParent.getChildCount() == 1)
 2864  
             {
 2865  0
                 createdComponent = tempParent.getChildren().get(0);
 2866  0
                 boolean requiresRefresh = false;
 2867  
                 // One child. In that case there are three choices:
 2868  0
                 if (UIComponent.isCompositeComponent(createdComponent))
 2869  
                 {
 2870  
                     // 1. Composite component. Needs special handling because
 2871  
                     // facets will be added programatically. The algorithm that
 2872  
                     // process the composite component content should occur
 2873  
                     // after the component is added to the view (PostAddToViewEvent).
 2874  
                     // Requires refresh. To do that, we need to save the MARK_CREATED
 2875  
                     // value and set it only when the full component is refreshed after 
 2876  
                     // restore it.
 2877  0
                     createdComponent.getAttributes().put("oam.vf.GEN_MARK_ID",
 2878  
                         createdComponent.getAttributes().get(ComponentSupport.MARK_CREATED));
 2879  0
                     createdComponent.getAttributes().put(ComponentSupport.MARK_CREATED, null);
 2880  0
                     createdComponent.subscribeToEvent(PostAddToViewEvent.class, new 
 2881  
                         CreateDynamicCompositeComponentListener(taglibURI, tagName, attributes, baseKey));
 2882  0
                     requiresRefresh = true;
 2883  0
                     if (requiresFaceletDynamicRefresh)
 2884  
                     {
 2885  0
                         FaceletViewDeclarationLanguageBase.dynamicComponentNeedsRefresh(context);
 2886  
                     }
 2887  
                 }
 2888  0
                 else if (createdComponent.getChildCount() > 0)
 2889  
                 {
 2890  
                     // 2. Single component with children inside.
 2891  
                     // Requires refresh. To do that, we need to save the MARK_CREATED
 2892  
                     // value and set it only when the full component is refreshed after 
 2893  
                     // restore it.
 2894  0
                     createdComponent.getAttributes().put("oam.vf.GEN_MARK_ID",
 2895  
                         createdComponent.getAttributes().get(ComponentSupport.MARK_CREATED));
 2896  0
                     createdComponent.getAttributes().put(ComponentSupport.MARK_CREATED, null);
 2897  0
                     requiresRefresh = true;
 2898  0
                     if (requiresFaceletDynamicRefresh)
 2899  
                     {
 2900  0
                         FaceletViewDeclarationLanguageBase.dynamicComponentNeedsRefresh(context);
 2901  
                     }
 2902  
                 }
 2903  0
                 else if (createdComponent.isTransient())
 2904  
                 {
 2905  
                     // Just transient markup inside. It is necessary to wrap
 2906  
                     // that content into a component. Requires refresh. No need to
 2907  
                     // save MARK_CREATED. No requires dynamic refresh.
 2908  0
                     createdComponent = tempParent;
 2909  0
                     tempParent.getAttributes().put("oam.vf.DYN_WRAPPER", baseKey);
 2910  0
                     requiresRefresh = true;
 2911  
                 }
 2912  
                 else
 2913  
                 {
 2914  
                     // 4. Single component without children: 
 2915  
                     // Remove MARK_CREATED because it does not requires
 2916  
                     // refresh on restore. When it is added to the component
 2917  
                     // tree, it will be saved and restored as if was a programatically
 2918  
                     // added component.
 2919  0
                     createdComponent.getAttributes().put(ComponentSupport.MARK_CREATED, null);
 2920  
                 }
 2921  0
                 if (requiresRefresh)
 2922  
                 {
 2923  0
                     createdComponent.subscribeToEvent(PostRestoreStateEvent.class, new 
 2924  
                         RefreshDynamicComponentListener(taglibURI, tagName, attributes, baseKey));
 2925  
                 }
 2926  0
                 if (requiresDynamicRefresh)
 2927  
                 {
 2928  0
                     createdComponent.subscribeToEvent(DynamicComponentRefreshTransientBuildEvent.class, new 
 2929  
                         RefreshDynamicComponentListener(taglibURI, tagName, attributes, baseKey));
 2930  0
                     createdComponent.getAttributes().put(
 2931  
                             DynamicComponentRefreshTransientBuildEvent.DYN_COMP_REFRESH_FLAG, Boolean.TRUE);
 2932  
                 }
 2933  0
                 if (requiresFaceletDynamicRefresh)
 2934  
                 {
 2935  0
                     createdComponent.subscribeToEvent(FaceletDynamicComponentRefreshTransientBuildEvent.class, new 
 2936  
                         RefreshDynamicComponentListener(taglibURI, tagName, attributes, baseKey));
 2937  
                 }
 2938  
             }
 2939  
         }
 2940  0
         catch (IOException e)
 2941  
         {
 2942  0
             throw new FacesException(e);
 2943  0
         }
 2944  0
         return createdComponent;
 2945  
     }
 2946  
     
 2947  
     protected RenderKitFactory getRenderKitFactory()
 2948  
     {
 2949  0
         if (_renderKitFactory == null)
 2950  
         {
 2951  0
             _renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 2952  
         }
 2953  0
         return _renderKitFactory;
 2954  
     }
 2955  
 }