Coverage Report - org.apache.myfaces.context.servlet.PartialViewContextImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
PartialViewContextImpl
0%
0/266
0%
0/174
5
PartialViewContextImpl$PhaseAwareVisitCallback
0%
0/43
0%
0/20
5
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.context.servlet;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Collection;
 24  
 import java.util.Collections;
 25  
 import java.util.EnumSet;
 26  
 import java.util.List;
 27  
 import java.util.Set;
 28  
 import java.util.logging.Level;
 29  
 import java.util.logging.Logger;
 30  
 
 31  
 import javax.faces.FactoryFinder;
 32  
 import javax.faces.component.UIComponent;
 33  
 import javax.faces.component.UIViewParameter;
 34  
 import javax.faces.component.UIViewRoot;
 35  
 import javax.faces.component.html.HtmlBody;
 36  
 import javax.faces.component.html.HtmlHead;
 37  
 import javax.faces.component.visit.VisitCallback;
 38  
 import javax.faces.component.visit.VisitContext;
 39  
 import javax.faces.component.visit.VisitContextFactory;
 40  
 import javax.faces.component.visit.VisitHint;
 41  
 import javax.faces.component.visit.VisitResult;
 42  
 import javax.faces.context.ExternalContext;
 43  
 import javax.faces.context.FacesContext;
 44  
 import javax.faces.context.PartialResponseWriter;
 45  
 import javax.faces.context.PartialViewContext;
 46  
 import javax.faces.context.ResponseWriter;
 47  
 import javax.faces.event.PhaseId;
 48  
 import javax.faces.lifecycle.ClientWindow;
 49  
 import javax.faces.render.RenderKit;
 50  
 import javax.faces.render.RenderKitFactory;
 51  
 import javax.faces.view.ViewMetadata;
 52  
 
 53  
 import org.apache.myfaces.context.PartialResponseWriterImpl;
 54  
 import org.apache.myfaces.context.RequestViewContext;
 55  
 import org.apache.myfaces.renderkit.html.HtmlResponseStateManager;
 56  
 import org.apache.myfaces.shared.config.MyfacesConfig;
 57  
 import org.apache.myfaces.shared.util.ExternalContextUtils;
 58  
 import org.apache.myfaces.shared.util.StringUtils;
 59  
 
 60  
 public class PartialViewContextImpl extends PartialViewContext
 61  
 {
 62  
 
 63  
     private static final String FACES_REQUEST = "Faces-Request";
 64  
     private static final String PARTIAL_AJAX = "partial/ajax";
 65  
     private static final String PARTIAL_AJAX_REQ = "javax.faces.partial.ajax";
 66  
     private static final String PARTIAL_PROCESS = "partial/process";
 67  
     private static final String SOURCE_PARAM_NAME = "javax.faces.source";
 68  
     private static final String JAVAX_FACES_REQUEST = "javax.faces.request";
 69  
 
 70  
     /**
 71  
      * Internal extension for
 72  
      * https://issues.apache.org/jira/browse/MYFACES-2841
 73  
      * will be changed for 2.1 to the official marker
 74  
      */
 75  
     private static final String PARTIAL_IFRAME = "org.apache.myfaces.partial.iframe";
 76  
     
 77  0
     private static final  Set<VisitHint> PARTIAL_EXECUTE_HINTS = Collections.unmodifiableSet( 
 78  
             EnumSet.of(VisitHint.EXECUTE_LIFECYCLE, VisitHint.SKIP_UNRENDERED));
 79  
     
 80  
     // unrendered have to be skipped, transient definitely must be added to our list!
 81  0
     private static final  Set<VisitHint> PARTIAL_RENDER_HINTS = 
 82  
             Collections.unmodifiableSet(EnumSet.of(VisitHint.SKIP_UNRENDERED));
 83  
 
 84  0
     private FacesContext _facesContext = null;
 85  0
     private boolean _released = false;
 86  
     // Cached values, since their parent methods could be called
 87  
     // many times and the result does not change during the life time
 88  
     // of this object.
 89  0
     private Boolean _ajaxRequest = null;
 90  
 
 91  
     /**
 92  
      * Internal extension for
 93  
      * https://issues.apache.org/jira/browse/MYFACES-2841
 94  
      * will be changed for 2.1 to the official marker
 95  
      */
 96  0
     private Boolean _iframeRequest = null;
 97  
 
 98  0
     private Collection<String> _executeClientIds = null;
 99  0
     private Collection<String> _renderClientIds = null;
 100  
     // Values that need to be saved because exists a setXX method 
 101  0
     private Boolean _partialRequest = null;
 102  0
     private Boolean _renderAll = null;
 103  0
     private PartialResponseWriter _partialResponseWriter = null;
 104  0
     private VisitContextFactory _visitContextFactory = null;
 105  0
     private Boolean _resetValues = null;
 106  
 
 107  
     public PartialViewContextImpl(FacesContext context)
 108  0
     {
 109  0
         _facesContext = context;
 110  0
     }
 111  
     
 112  
     public PartialViewContextImpl(FacesContext context, 
 113  
             VisitContextFactory visitContextFactory)
 114  0
     {
 115  0
         _facesContext = context;
 116  0
         _visitContextFactory = visitContextFactory;
 117  0
     }
 118  
 
 119  
     @Override
 120  
     public boolean isAjaxRequest()
 121  
     {
 122  0
         assertNotReleased();
 123  0
         if (_ajaxRequest == null)
 124  
         {
 125  0
             String requestType = _facesContext.getExternalContext().
 126  
                    getRequestHeaderMap().get(FACES_REQUEST);
 127  0
             _ajaxRequest = (requestType != null && PARTIAL_AJAX.equals(requestType));
 128  0
             String reqParmamterPartialAjax = _facesContext.getExternalContext().
 129  
                     getRequestParameterMap().get(PARTIAL_AJAX_REQ);
 130  
             //jsdoc reference in an ajax request the javax.faces.partial.ajax must be set as ajax parameter
 131  
             //the other one is Faces-Request == partial/ajax which is basically the same
 132  0
             _ajaxRequest = _ajaxRequest || reqParmamterPartialAjax != null;
 133  
         }
 134  0
         return _ajaxRequest;
 135  
     }
 136  
 
 137  
     @Override
 138  
     public boolean isExecuteAll()
 139  
     {
 140  0
         assertNotReleased();
 141  
 
 142  0
         if (isAjaxRequest())
 143  
         {
 144  0
             String executeMode = _facesContext.getExternalContext().
 145  
                     getRequestParameterMap().get(
 146  
                     PartialViewContext.PARTIAL_EXECUTE_PARAM_NAME);
 147  0
             if (PartialViewContext.ALL_PARTIAL_PHASE_CLIENT_IDS.equals(executeMode))
 148  
             {
 149  0
                 return true;
 150  
             }
 151  
         }
 152  0
         return false;
 153  
     }
 154  
 
 155  
     @Override
 156  
     public boolean isPartialRequest()
 157  
     {
 158  0
         assertNotReleased();
 159  
 
 160  0
         if (_partialRequest == null)
 161  
         {
 162  0
             String requestType = _facesContext.getExternalContext().
 163  
                     getRequestHeaderMap().get(FACES_REQUEST);
 164  0
             _partialRequest = (requestType != null && PARTIAL_PROCESS.equals(requestType));
 165  
         }
 166  0
         return _partialRequest || isAjaxRequest();
 167  
     }
 168  
 
 169  
     @Override
 170  
     public boolean isRenderAll()
 171  
     {
 172  0
         assertNotReleased();
 173  
 
 174  0
         if (_renderAll == null)
 175  
         {
 176  0
             if (isAjaxRequest())
 177  
             {
 178  0
                 String executeMode = _facesContext.getExternalContext().
 179  
                         getRequestParameterMap().get(
 180  
                         PartialViewContext.PARTIAL_RENDER_PARAM_NAME);
 181  0
                 if (PartialViewContext.ALL_PARTIAL_PHASE_CLIENT_IDS.equals(executeMode))
 182  
                 {
 183  0
                     _renderAll = true;
 184  
                 }
 185  
             }
 186  0
             if (_renderAll == null)
 187  
             {
 188  0
                 _renderAll = false;
 189  
             }
 190  
         }
 191  0
         return _renderAll;
 192  
     }
 193  
 
 194  
     /**
 195  
      * Extension for
 196  
      * https://issues.apache.org/jira/browse/MYFACES-2841
 197  
      * internal extension which detects that the submit is an iframe request
 198  
      * will be changed for the official version which will come in 2.1
 199  
      *
 200  
      * @return true if the current request is an iframe based ajax request
 201  
      */
 202  
     public boolean isIFrameRequest()
 203  
     {
 204  0
         if (_iframeRequest == null)
 205  
         {
 206  0
             _iframeRequest = _facesContext.getExternalContext().getRequestParameterMap().containsKey(PARTIAL_IFRAME);
 207  
         }
 208  0
         return _iframeRequest;
 209  
     }
 210  
 
 211  
     @Override
 212  
     public void setPartialRequest(boolean isPartialRequest)
 213  
     {
 214  0
         assertNotReleased();
 215  
 
 216  0
         _partialRequest = isPartialRequest;
 217  
 
 218  0
     }
 219  
 
 220  
     @Override
 221  
     public void setRenderAll(boolean renderAll)
 222  
     {
 223  0
         assertNotReleased();
 224  
 
 225  0
         _renderAll = renderAll;
 226  0
     }
 227  
 
 228  
     @Override
 229  
     public Collection<String> getExecuteIds()
 230  
     {
 231  0
         assertNotReleased();
 232  
 
 233  0
         if (_executeClientIds == null)
 234  
         {
 235  0
             String executeMode = _facesContext.getExternalContext().
 236  
                     getRequestParameterMap().get(
 237  
                     PartialViewContext.PARTIAL_EXECUTE_PARAM_NAME);
 238  
 
 239  0
             if (executeMode != null && !"".equals(executeMode) &&
 240  
                     //!PartialViewContext.NO_PARTIAL_PHASE_CLIENT_IDS.equals(executeMode) &&
 241  
                     !PartialViewContext.ALL_PARTIAL_PHASE_CLIENT_IDS.equals(executeMode))
 242  
             {
 243  
 
 244  0
                 String[] clientIds
 245  
                         = StringUtils.splitShortString(_replaceTabOrEnterCharactersWithSpaces(executeMode), ' ');
 246  
 
 247  
                 //The collection must be mutable
 248  0
                 List<String> tempList = new ArrayList<String>();
 249  0
                 for (String clientId : clientIds)
 250  
                 {
 251  0
                     if (clientId.length() > 0)
 252  
                     {
 253  0
                         tempList.add(clientId);
 254  
                     }
 255  
                 }
 256  
                 // The "javax.faces.source" parameter needs to be added to the list of
 257  
                 // execute ids if missing (otherwise, we'd never execute an action associated
 258  
                 // with, e.g., a button).
 259  
 
 260  0
                 String source = _facesContext.getExternalContext().getRequestParameterMap().get
 261  
                         (PartialViewContextImpl.SOURCE_PARAM_NAME);
 262  
 
 263  0
                 if (source != null)
 264  
                 {
 265  0
                     source = source.trim();
 266  
 
 267  0
                     if (!tempList.contains(source))
 268  
                     {
 269  0
                         tempList.add(source);
 270  
                     }
 271  
                 }
 272  
 
 273  0
                 _executeClientIds = tempList;
 274  0
             }
 275  
             else
 276  
             {
 277  0
                 _executeClientIds = new ArrayList<String>();
 278  
             }
 279  
         }
 280  0
         return _executeClientIds;
 281  
     }
 282  
 
 283  
     private String _replaceTabOrEnterCharactersWithSpaces(String mode)
 284  
     {
 285  0
         StringBuilder builder = new StringBuilder(mode.length());
 286  0
         for (int i = 0; i < mode.length(); i++)
 287  
         {
 288  0
             if (mode.charAt(i) == '\t' ||
 289  
                     mode.charAt(i) == '\n')
 290  
             {
 291  0
                 builder.append(' ');
 292  
             }
 293  
             else
 294  
             {
 295  0
                 builder.append(mode.charAt(i));
 296  
             }
 297  
         }
 298  0
         return builder.toString();
 299  
     }
 300  
 
 301  
     @Override
 302  
     public Collection<String> getRenderIds()
 303  
     {
 304  0
         assertNotReleased();
 305  
 
 306  0
         if (_renderClientIds == null)
 307  
         {
 308  0
             String renderMode = _facesContext.getExternalContext().
 309  
                     getRequestParameterMap().get(
 310  
                     PartialViewContext.PARTIAL_RENDER_PARAM_NAME);
 311  
 
 312  0
             if (renderMode != null && !"".equals(renderMode) &&
 313  
                     //!PartialViewContext.NO_PARTIAL_PHASE_CLIENT_IDS.equals(renderMode) &&
 314  
                     !PartialViewContext.ALL_PARTIAL_PHASE_CLIENT_IDS.equals(renderMode))
 315  
             {
 316  0
                 String[] clientIds
 317  
                         = StringUtils.splitShortString(_replaceTabOrEnterCharactersWithSpaces(renderMode), ' ');
 318  
 
 319  
                 //The collection must be mutable
 320  0
                 List<String> tempList = new ArrayList<String>();
 321  0
                 for (String clientId : clientIds)
 322  
                 {
 323  0
                     if (clientId.length() > 0)
 324  
                     {
 325  0
                         tempList.add(clientId);
 326  
                     }
 327  
                 }
 328  0
                 _renderClientIds = tempList;
 329  0
             }
 330  
             else
 331  
             {
 332  0
                 _renderClientIds = new ArrayList<String>();
 333  
 
 334  0
                 if (PartialViewContext.ALL_PARTIAL_PHASE_CLIENT_IDS.equals(renderMode))
 335  
                 {
 336  0
                     _renderClientIds.add(PartialResponseWriter.RENDER_ALL_MARKER);
 337  
                 }
 338  
             }
 339  
         }
 340  0
         return _renderClientIds;
 341  
     }
 342  
 
 343  
     @Override
 344  
     public PartialResponseWriter getPartialResponseWriter()
 345  
     {
 346  0
         assertNotReleased();
 347  
 
 348  0
         if (_partialResponseWriter == null)
 349  
         {
 350  0
             ResponseWriter responseWriter = _facesContext.getResponseWriter();
 351  0
             if (responseWriter == null)
 352  
             {
 353  
                 // This case happens when getPartialResponseWriter() is called before
 354  
                 // render phase, like in ExternalContext.redirect(). We have to create a
 355  
                 // ResponseWriter from the RenderKit and then wrap if necessary. 
 356  
                 try
 357  
                 {
 358  0
                     RenderKit renderKit = _facesContext.getRenderKit();
 359  0
                     if (renderKit == null)
 360  
                     {
 361  
                         // If the viewRoot was set to null by some reason, or there is no 
 362  
                         // renderKitId on that view, this could be still an ajax redirect,
 363  
                         // so we have to try to calculate the renderKitId and return a 
 364  
                         // RenderKit instance, to send the response.
 365  0
                         String renderKitId
 366  
                                 = _facesContext.getApplication().getViewHandler().calculateRenderKitId(_facesContext);
 367  0
                         RenderKitFactory rkf
 368  
                                 = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 369  0
                         renderKit = rkf.getRenderKit(_facesContext, renderKitId);
 370  
                     }
 371  0
                     responseWriter = renderKit.createResponseWriter(
 372  
                             _facesContext.getExternalContext().getResponseOutputWriter(), "text/xml",
 373  
                             _facesContext.getExternalContext().getRequestCharacterEncoding());
 374  
                 }
 375  0
                 catch (IOException e)
 376  
                 {
 377  0
                     throw new IllegalStateException("Cannot create Partial Response Writer", e);
 378  0
                 }
 379  
             }
 380  
             // It is possible that the RenderKit return a PartialResponseWriter instance when 
 381  
             // createResponseWriter,  so we should cast here for it and prevent double wrapping.
 382  0
             if (responseWriter instanceof PartialResponseWriter)
 383  
             {
 384  0
                 _partialResponseWriter = (PartialResponseWriter) responseWriter;
 385  
             }
 386  
             else
 387  
             {
 388  0
                 _partialResponseWriter = new PartialResponseWriterImpl(responseWriter);
 389  
             }
 390  
         }
 391  0
         return _partialResponseWriter;
 392  
     }
 393  
 
 394  
     /**
 395  
      * process the partial response
 396  
      * allowed phase ids according to the spec
 397  
      *
 398  
      *
 399  
      */
 400  
     @Override
 401  
     public void processPartial(PhaseId phaseId)
 402  
     {
 403  0
         assertNotReleased();
 404  
 
 405  0
         UIViewRoot viewRoot = _facesContext.getViewRoot();
 406  
 
 407  0
         if (phaseId == PhaseId.APPLY_REQUEST_VALUES
 408  
                 || phaseId == PhaseId.PROCESS_VALIDATIONS
 409  
                 || phaseId == PhaseId.UPDATE_MODEL_VALUES)
 410  
         {
 411  0
             processPartialExecute(viewRoot, phaseId);
 412  
         }
 413  0
         else if (phaseId == PhaseId.RENDER_RESPONSE)
 414  
         {
 415  0
             processPartialRendering(viewRoot, phaseId);
 416  
         }
 417  0
     }
 418  
 
 419  
     private void processPartialExecute(UIViewRoot viewRoot, PhaseId phaseId)
 420  
     {
 421  0
         PartialViewContext pvc = _facesContext.getPartialViewContext();
 422  0
         Collection<String> executeIds = pvc.getExecuteIds();
 423  0
         if (executeIds == null || executeIds.isEmpty())
 424  
         {
 425  0
             return;
 426  
         }
 427  
         
 428  0
         VisitContext visitCtx = getVisitContextFactory().getVisitContext(_facesContext, executeIds, 
 429  
                 PARTIAL_EXECUTE_HINTS);
 430  0
         viewRoot.visitTree(visitCtx, new PhaseAwareVisitCallback(_facesContext, phaseId));
 431  0
     }
 432  
 
 433  
     private void processPartialRendering(UIViewRoot viewRoot, PhaseId phaseId)
 434  
     {
 435  
         //TODO process partial rendering
 436  
         //https://issues.apache.org/jira/browse/MYFACES-2118
 437  
         //Collection<String> renderIds = getRenderIds();
 438  
 
 439  
         // We need to always update the view state marker when processing partial
 440  
         // rendering, because there is no way to check when the state has been changed
 441  
         // or not. Anyway, if we return empty response, according to the spec a javascript
 442  
         // message displayed, so we need to return something.
 443  
         //if (renderIds == null || renderIds.isEmpty()) {
 444  
         //    return;
 445  
         //}
 446  
 
 447  
         // note that we cannot use this.getPartialResponseWriter(), because
 448  
         // this could cause problems if PartialResponseWriter is wrapped
 449  0
         PartialResponseWriter writer = _facesContext.getPartialViewContext().getPartialResponseWriter();
 450  0
         PartialViewContext pvc = _facesContext.getPartialViewContext();
 451  
 
 452  0
         ResponseWriter oldWriter = _facesContext.getResponseWriter();
 453  0
         boolean inDocument = false;
 454  
 
 455  
         //response type = text/xml
 456  
         //no caching and no timeout if possible!
 457  0
         ExternalContext externalContext = _facesContext.getExternalContext();
 458  0
         externalContext.setResponseContentType("text/xml");
 459  0
         externalContext.addResponseHeader("Pragma", "no-cache");
 460  0
         externalContext.addResponseHeader("Cache-control", "no-cache");
 461  
         //under normal circumstances pragma should be enough, IE needs
 462  
         //a special treatment!
 463  
         //http://support.microsoft.com/kb/234067
 464  0
         externalContext.addResponseHeader("Expires", "-1");
 465  
 
 466  
         try
 467  
         {
 468  0
             String currentEncoding = writer.getCharacterEncoding();
 469  0
             writer.writePreamble("<?xml version=\"1.0\" encoding=\""+
 470  
                 (currentEncoding == null ? "UTF-8" : currentEncoding) +"\"?>");
 471  0
             writer.startDocument();
 472  
             
 473  0
             writer.writeAttribute("id", viewRoot.getContainerClientId(_facesContext),"id");
 474  
             
 475  0
             inDocument = true;
 476  0
             _facesContext.setResponseWriter(writer);
 477  
             
 478  0
             if (isResetValues())
 479  
             {
 480  0
                 viewRoot.resetValues(_facesContext, getRenderIds());
 481  
             }
 482  
 
 483  0
             if (pvc.isRenderAll())
 484  
             {
 485  0
                 processRenderAll(viewRoot, writer);
 486  
             }
 487  
             else
 488  
             {
 489  0
                 Collection<String> renderIds = pvc.getRenderIds();
 490  
                 //Only apply partial visit if we have ids to traverse
 491  0
                 if (renderIds != null && !renderIds.isEmpty())
 492  
                 {
 493  
                     // render=@all, so output the body.
 494  0
                     if (renderIds.contains(PartialResponseWriter.RENDER_ALL_MARKER))
 495  
                     {
 496  0
                         processRenderAll(viewRoot, writer);
 497  
                     }
 498  
                     else
 499  
                     {
 500  0
                         List<UIComponent> updatedComponents = null;
 501  0
                         if (!ExternalContextUtils.isPortlet(_facesContext.getExternalContext()) &&
 502  
                                 MyfacesConfig.getCurrentInstance(externalContext).isStrictJsf2RefreshTargetAjax())
 503  
                         {
 504  0
                             RequestViewContext rvc = RequestViewContext.getCurrentInstance(_facesContext);
 505  0
                             if (rvc.isRenderTarget("head"))
 506  
                             {
 507  0
                                 UIComponent head = findHeadComponent(viewRoot);
 508  0
                                 if (head != null)
 509  
                                 {
 510  0
                                     writer.startUpdate("javax.faces.ViewHead");
 511  0
                                     head.encodeAll(_facesContext);
 512  0
                                     writer.endUpdate();
 513  0
                                     if (updatedComponents == null)
 514  
                                     {
 515  0
                                         updatedComponents = new ArrayList<UIComponent>();
 516  
                                     }
 517  0
                                     updatedComponents.add(head);
 518  
                                 }
 519  
                             }
 520  0
                             if (rvc.isRenderTarget("body") || rvc.isRenderTarget("form"))
 521  
                             {
 522  0
                                 UIComponent body = findBodyComponent(viewRoot);
 523  0
                                 if (body != null)
 524  
                                 {
 525  0
                                     writer.startUpdate("javax.faces.ViewBody");
 526  0
                                     body.encodeAll(_facesContext);
 527  0
                                     writer.endUpdate();
 528  0
                                     if (updatedComponents == null)
 529  
                                     {
 530  0
                                         updatedComponents = new ArrayList<UIComponent>();
 531  
                                     }
 532  0
                                     updatedComponents.add(body);
 533  
                                 }
 534  
                             }
 535  
                         }
 536  
 
 537  0
                         VisitContext visitCtx = getVisitContextFactory().getVisitContext(
 538  
                                 _facesContext, renderIds, PARTIAL_RENDER_HINTS);
 539  0
                         viewRoot.visitTree(visitCtx,
 540  
                                            new PhaseAwareVisitCallback(_facesContext, phaseId, updatedComponents));
 541  0
                     }
 542  
                 }
 543  0
                 else if (!ExternalContextUtils.isPortlet(_facesContext.getExternalContext()) &&
 544  
                         MyfacesConfig.getCurrentInstance(externalContext).isStrictJsf2RefreshTargetAjax())
 545  
                 {
 546  0
                     RequestViewContext rvc = RequestViewContext.getCurrentInstance(_facesContext);
 547  0
                     if (rvc.isRenderTarget("head"))
 548  
                     {
 549  0
                         UIComponent head = findHeadComponent(viewRoot);
 550  0
                         if (head != null)
 551  
                         {
 552  0
                             writer.startUpdate("javax.faces.ViewHead");
 553  0
                             head.encodeAll(_facesContext);
 554  0
                             writer.endUpdate();
 555  
                         }
 556  
                     }
 557  0
                     if (rvc.isRenderTarget("body") || rvc.isRenderTarget("form"))
 558  
                     {
 559  0
                         UIComponent body = findBodyComponent(viewRoot);
 560  0
                         if (body != null)
 561  
                         {
 562  0
                             writer.startUpdate("javax.faces.ViewBody");
 563  0
                             body.encodeAll(_facesContext);
 564  0
                             writer.endUpdate();
 565  
                         }
 566  
                     }
 567  
                 }
 568  
             }
 569  
 
 570  
             // invoke encodeAll() on every UIViewParameter in the view to 
 571  
             // enable every UIViewParameter to save its value in the state
 572  
             // just like UIViewRoot.encodeEnd() does on a normal request
 573  
             // (see MYFACES-2645 for details)
 574  0
             Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(viewRoot);
 575  0
             if (!viewParams.isEmpty())
 576  
             {
 577  0
                 for (UIViewParameter param : viewParams)
 578  
                 {
 579  0
                     param.encodeAll(_facesContext);
 580  0
                 }
 581  
             }
 582  
 
 583  
             //Retrieve the state and apply it if it is not null.
 584  0
             String viewState = _facesContext.getApplication().getStateManager().getViewState(_facesContext);
 585  0
             if (viewState != null)
 586  
             {
 587  0
                 writer.startUpdate(HtmlResponseStateManager.generateUpdateViewStateId(
 588  
                     _facesContext));
 589  0
                 writer.write(viewState);
 590  0
                 writer.endUpdate();
 591  
             }
 592  0
             else if (viewRoot.isTransient())
 593  
             {
 594  
                 //TODO: fix javascript side, so the field is not removed on ajax form update
 595  0
                 writer.startUpdate(HtmlResponseStateManager.generateUpdateViewStateId(
 596  
                     _facesContext));
 597  0
                 writer.write("stateless");
 598  0
                 writer.endUpdate();
 599  
                 //END TODO
 600  
             }
 601  
             
 602  
             
 603  0
             ClientWindow cw = _facesContext.getExternalContext().getClientWindow();
 604  0
             if (cw != null)
 605  
             {
 606  0
                 writer.startUpdate(HtmlResponseStateManager.generateUpdateClientWindowId(
 607  
                     _facesContext));
 608  0
                 writer.write(cw.getId());
 609  0
                 writer.endUpdate();
 610  
             }
 611  
         }
 612  0
         catch (IOException ex)
 613  
         {
 614  0
             Logger log = Logger.getLogger(PartialViewContextImpl.class.getName());
 615  0
             if (log.isLoggable(Level.SEVERE))
 616  
             {
 617  0
                 log.log(Level.SEVERE, "", ex);
 618  
             }
 619  
 
 620  
         }
 621  
         finally
 622  
         {
 623  0
             try
 624  
             {
 625  0
                 if (inDocument)
 626  
                 {
 627  0
                     writer.endDocument();
 628  
                 }
 629  0
                 writer.flush();
 630  
             }
 631  0
             catch (IOException ex)
 632  
             {
 633  0
                 Logger log = Logger.getLogger(PartialViewContextImpl.class.getName());
 634  0
                 if (log.isLoggable(Level.SEVERE))
 635  
                 {
 636  0
                     log.log(Level.SEVERE, "", ex);
 637  
                 }
 638  0
             }
 639  
 
 640  0
             _facesContext.setResponseWriter(oldWriter);
 641  0
         }
 642  
 
 643  0
     }
 644  
 
 645  
     private void processRenderAll(UIViewRoot viewRoot, PartialResponseWriter writer) throws IOException
 646  
     {
 647  
         //java.util.Iterator<UIComponent> iter = viewRoot.getFacetsAndChildren();
 648  0
         writer.startUpdate(PartialResponseWriter.RENDER_ALL_MARKER);
 649  
         //while (iter.hasNext()) 
 650  
         //{ 
 651  
         //UIComponent comp = iter.next();
 652  
 
 653  
         //TODO: Do not check for a specific instance,
 654  
         //just render all children.
 655  
         //if (comp instanceof javax.faces.component.html.HtmlBody)
 656  
         //{
 657  
         //comp.encodeAll (_facesContext);
 658  
         //}
 659  
         //}
 660  0
         for (int i = 0, childCount = viewRoot.getChildCount(); i < childCount; i++)
 661  
         {
 662  0
             UIComponent comp = viewRoot.getChildren().get(i);
 663  0
             comp.encodeAll(_facesContext);
 664  
         }
 665  0
         writer.endUpdate();
 666  0
     }
 667  
 
 668  
     /**
 669  
      * has to be thrown in many of the methods if the method is called after the instance has been released!
 670  
      */
 671  
     private void assertNotReleased()
 672  
     {
 673  0
         if (_released)
 674  
         {
 675  0
             throw new IllegalStateException("Error the FacesContext is already released!");
 676  
         }
 677  0
     }
 678  
 
 679  
     @Override
 680  
     public void release()
 681  
     {
 682  0
         assertNotReleased();
 683  0
         _visitContextFactory = null;
 684  0
         _executeClientIds = null;
 685  0
         _renderClientIds = null;
 686  0
         _ajaxRequest = null;
 687  0
         _partialRequest = null;
 688  0
         _renderAll = null;
 689  0
         _facesContext = null;
 690  0
         _released = true;
 691  0
     }
 692  
 
 693  
     private UIComponent findHeadComponent(UIViewRoot root)
 694  
     {
 695  0
         for (UIComponent child : root.getChildren())
 696  
         {
 697  0
             if (child instanceof HtmlHead)
 698  
             {
 699  0
                 return child;
 700  
             }
 701  
             else
 702  
             {
 703  0
                 for (UIComponent grandchild : child.getChildren())
 704  
                 {
 705  0
                     if (grandchild instanceof HtmlHead)
 706  
                     {
 707  0
                         return grandchild;
 708  
                     }
 709  0
                 }
 710  
             }
 711  0
         }
 712  0
         return null;
 713  
     }
 714  
 
 715  
     private UIComponent findBodyComponent(UIViewRoot root)
 716  
     {
 717  0
         for (UIComponent child : root.getChildren())
 718  
         {
 719  0
             if (child instanceof HtmlBody)
 720  
             {
 721  0
                 return child;
 722  
             }
 723  
             else
 724  
             {
 725  0
                 for (UIComponent grandchild : child.getChildren())
 726  
                 {
 727  0
                     if (grandchild instanceof HtmlBody)
 728  
                     {
 729  0
                         return grandchild;
 730  
                     }
 731  0
                 }
 732  
             }
 733  0
         }
 734  0
         return null;
 735  
     }
 736  
     
 737  
     private VisitContextFactory getVisitContextFactory()
 738  
     {
 739  0
         if (_visitContextFactory == null)
 740  
         {
 741  0
             _visitContextFactory = (VisitContextFactory)FactoryFinder.getFactory(FactoryFinder.VISIT_CONTEXT_FACTORY);
 742  
         }
 743  0
         return _visitContextFactory;
 744  
     }
 745  
 
 746  
     @Override
 747  
     public boolean isResetValues()
 748  
     {
 749  0
         if (_resetValues == null)
 750  
         {
 751  0
             String value = _facesContext.getExternalContext().getRequestParameterMap().
 752  
                 get(RESET_VALUES_PARAM_NAME);
 753  0
             _resetValues = "true".equals(value);
 754  
         }
 755  0
         return _resetValues;
 756  
     }
 757  
 
 758  
     private class PhaseAwareVisitCallback implements VisitCallback
 759  
     {
 760  
 
 761  
         private PhaseId _phaseId;
 762  
         private FacesContext _facesContext;
 763  
         private List<UIComponent> _alreadyUpdatedComponents;
 764  
 
 765  
         public PhaseAwareVisitCallback(FacesContext facesContext, PhaseId phaseId)
 766  0
         {
 767  0
             this._phaseId = phaseId;
 768  0
             this._facesContext = facesContext;
 769  0
             this._alreadyUpdatedComponents = null;
 770  0
         }
 771  
 
 772  
         public PhaseAwareVisitCallback(FacesContext facesContext, PhaseId phaseId,
 773  
                                        List<UIComponent> alreadyUpdatedComponents)
 774  0
         {
 775  0
             this._phaseId = phaseId;
 776  0
             this._facesContext = facesContext;
 777  0
             this._alreadyUpdatedComponents = alreadyUpdatedComponents;
 778  0
         }
 779  
 
 780  
         public VisitResult visit(VisitContext context, UIComponent target)
 781  
         {
 782  0
             if (_phaseId == PhaseId.APPLY_REQUEST_VALUES)
 783  
             {
 784  0
                 target.processDecodes(_facesContext);
 785  
             }
 786  0
             else if (_phaseId == PhaseId.PROCESS_VALIDATIONS)
 787  
             {
 788  0
                 target.processValidators(_facesContext);
 789  
             }
 790  0
             else if (_phaseId == PhaseId.UPDATE_MODEL_VALUES)
 791  
             {
 792  0
                 target.processUpdates(_facesContext);
 793  
             }
 794  0
             else if (_phaseId == PhaseId.RENDER_RESPONSE)
 795  
             {
 796  0
                 processRenderComponent(target);
 797  
             }
 798  
             else
 799  
             {
 800  0
                 throw new IllegalStateException("PPR Response, illegale phase called");
 801  
             }
 802  
 
 803  
             // Return VisitResult.REJECT as processDecodes/Validators/Updates already traverse sub tree
 804  0
             return VisitResult.REJECT;
 805  
         }
 806  
 
 807  
         /**
 808  
          * the rendering subpart of the tree walker
 809  
          * every component id which is passed down via render must be handled
 810  
          * here!
 811  
          *
 812  
          * @param target the target component to be handled!
 813  
          */
 814  
         private void processRenderComponent(UIComponent target)
 815  
         {
 816  0
             boolean inUpdate = false;
 817  0
             PartialResponseWriter writer = (PartialResponseWriter) _facesContext.getResponseWriter();
 818  0
             if (this._alreadyUpdatedComponents != null)
 819  
             {
 820  
                 //Check if the parent was already updated.
 821  0
                 UIComponent parent = target;
 822  0
                 while (parent != null)
 823  
                 {
 824  0
                     if (this._alreadyUpdatedComponents.contains(parent))
 825  
                     {
 826  0
                         return;
 827  
                     }
 828  0
                     parent = parent.getParent();
 829  
                 }
 830  
             }
 831  
             try
 832  
             {
 833  0
                 writer.startUpdate(target.getClientId(_facesContext));
 834  0
                 inUpdate = true;
 835  0
                 target.encodeAll(_facesContext);
 836  
             }
 837  0
             catch (IOException ex)
 838  
             {
 839  0
                 Logger log = Logger.getLogger(PartialViewContextImpl.class.getName());
 840  0
                 if (log.isLoggable(Level.SEVERE))
 841  
                 {
 842  0
                     log.log(Level.SEVERE, "IOException for rendering component", ex);
 843  
                 }
 844  
             }
 845  
             finally
 846  
             {
 847  0
                 if (inUpdate)
 848  
                 {
 849  
                     try
 850  
                     {
 851  0
                         writer.endUpdate();
 852  
                     }
 853  0
                     catch (IOException ex)
 854  
                     {
 855  0
                         Logger log = Logger.getLogger(PartialViewContextImpl.class.getName());
 856  0
                         if (log.isLoggable(Level.SEVERE))
 857  
                         {
 858  0
                             log.log(Level.SEVERE, "IOException for rendering component, stopping update rendering", ex);
 859  
                         }
 860  0
                     }
 861  
                 }
 862  
             }
 863  0
         }
 864  
     }
 865  
 }