You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by de...@apache.org on 2017/09/17 12:29:32 UTC

[myfaces-trinidad] 02/10: TRINIDAD-1704 Committing Pavitra's patch to the private branch

This is an automated email from the ASF dual-hosted git repository.

deki pushed a commit to branch jsf2_ajax
in repository https://gitbox.apache.org/repos/asf/myfaces-trinidad.git

commit e0eb4794f70e66e13861da1228009c0fe2bc7d19
Author: Andrew Robinson <ar...@apache.org>
AuthorDate: Wed Feb 3 00:51:10 2010 +0000

    TRINIDAD-1704 Committing Pavitra's patch to the private branch
---
 .../src/main/webapp/WEB-INF/trinidad-config.xml    |   2 +-
 .../trinidad-demo/src/main/webapp/WEB-INF/web.xml  |   9 +-
 .../src/main/webapp/demos/ajaxPPRDemos.jspx        | 198 ++++++++++
 .../src/main/conf/META-INF/faces-config-base.xml   |   3 +
 .../context/PartialViewContextFactoryImpl.java     |  28 ++
 .../context/PartialViewContextImpl.java            | 437 +++++++++++++++++++++
 .../renderkit/core/CoreRenderKit.java              |  22 +-
 .../renderkit/core/ppr/PPRResponseWriter.java      | 121 ++++--
 .../renderkit/core/xhtml/CommandLinkRenderer.java  |   2 +-
 .../main/javascript/META-INF/adf/jsLibs/Core.js    |  12 +-
 .../main/javascript/META-INF/adf/jsLibs/Page.js    |  39 +-
 11 files changed, 834 insertions(+), 39 deletions(-)

diff --git a/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml b/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml
index af3f1a5..217b932 100644
--- a/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml
+++ b/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml
@@ -19,7 +19,7 @@
 	   
 -->
 <trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">
-  <debug-output>true</debug-output>
+  <!--debug-output>true</debug-output-->
   <!-- Uncomment to switch back to ALERT style client-side validation,
     or set to DISABLED to disable it altogether
   <client-validation>ALERT</client-validation>
diff --git a/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml b/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml
index ba33d24..a6797c0 100644
--- a/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml
+++ b/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml
@@ -67,10 +67,10 @@
 
   <!-- Trinidad by default uses an optimized client-side state saving
        mechanism. To disable that, uncomment the following -->
-  <!--context-param>
+  <context-param>
     <param-name>org.apache.myfaces.trinidad.CLIENT_STATE_METHOD</param-name>
-    <param-value>all</param-value>
-  </context-param-->
+    <param-value>token</param-value>
+  </context-param>
 <!-- When token client-side state saving is enabled, MyFaces Trinidad can apply an additional
      optimization by caching an entire UIViewRoot tree with each token. 
      (Note that this does not affect thread safety or session failover.) 
@@ -100,9 +100,8 @@
 
   <context-param>
     <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
-    <param-value>*.xhtml</param-value>
     <!-- to run facelets for jspx files comment the line above and uncomment line below-->
-    <!--param-value>*.xhtml;*.jspx</param-value-->
+    <param-value>*.xhtml;*.jspx</param-value>
   </context-param>
 
   <context-param>
diff --git a/trinidad-examples/trinidad-demo/src/main/webapp/demos/ajaxPPRDemos.jspx b/trinidad-examples/trinidad-demo/src/main/webapp/demos/ajaxPPRDemos.jspx
new file mode 100644
index 0000000..9fb3ad4
--- /dev/null
+++ b/trinidad-examples/trinidad-demo/src/main/webapp/demos/ajaxPPRDemos.jspx
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+	   
+-->
+<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
+          xmlns:f="http://java.sun.com/jsf/core"
+          xmlns:h="http://java.sun.com/jsf/html"
+          xmlns:trh="http://myfaces.apache.org/trinidad/html"
+          xmlns:tr="http://myfaces.apache.org/trinidad">
+ <jsp:directive.page contentType="text/html;charset=utf-8"/>
+ <f:view>
+  <h:outputScript name="jsf.js" library="javax.faces" target="body" id="os"/>
+  <tr:document title="Partial Page Rendering Demos">
+    <tr:form>
+
+     <tr:panelPage>
+      <f:facet name="navigationGlobal">
+       <tr:navigationPane hint="buttons">
+        <tr:commandNavigationItem text="Return to Feature Demos page"
+                                immediate="true"
+                                action="demos"/>
+       </tr:navigationPane>
+      </f:facet>
+
+      <tr:panelHeader text="Welcome to the Apache Trinidad Partial Page Rendering Demos for JSF 2.0 Ajax">
+        <tr:outputFormatted styleUsage="instruction" id="of0"
+                            value="These demos test Trinidad PPR with JSF 2.0 Ajax using both 
+                            trinidad and JSF components."/>
+        <tr:panelGroupLayout layout="vertical">
+          <f:facet name="separator">
+            <tr:spacer width="30" height="10"/>
+          </f:facet>
+          <tr:panelHeader text="Command components using JSF 2.0 native Ajax support" id="phCmd">
+            <tr:outputFormatted styleUsage="instruction" id="of10"
+                                value="Tests commandButton components wired to use either Ajax JS API
+                                by itself or both JSF 2 Ajax and trinidad PPR. Clicking these buttons 
+                                should cause a partial or a full page submit (without errors) and 
+                                update the field on the right."/>
+            <tr:spacer height="10" id="sp10"/>
+            <tr:panelGroupLayout layout="horizontal" id="pgl10">
+              <tr:panelGroupLayout layout="vertical" id="pgl11">
+                <f:facet name="separator">
+                  <tr:spacer height="6" id="sp11"/>
+                </f:facet>
+                <tr:outputFormatted styleUsage="instruction" value="tr:commandButton using 
+                    jsf.ajax.request and partialSubmit=true." id="of11"/>
+                <tr:commandButton id="axBtn1"
+                                partialSubmit="true"
+                                text="Partial Submit"
+                                shortDesc="partialSubmit"
+                                actionListener="#{partialDemoUtil.action}"/>
+                  <!--f:ajax event="action" render=""/-->
+                <tr:outputFormatted styleUsage="instruction" value="tr:commandButton using jsf.ajax.request." 
+                 id="of12"/>
+                <tr:commandButton id="axBtn2"
+                                  text="Full Submit"
+                                  shortDesc="fullSubmit"
+                                  actionListener="#{partialDemoUtil.action}"/>
+                
+                <tr:outputFormatted styleUsage="instruction" value="h:commandButton using jsf.ajax.request." 
+                 id="of13"/>
+                
+                
+              </tr:panelGroupLayout>
+              
+              <tr:spacer width="30" height="10" id="sp12"/>
+             
+              <tr:panelGroupLayout id="pgl12">
+                <tr:panelLabelAndMessage label="Button Clicked: " id="plm10">
+                  <tr:outputFormatted id="btnTarget"
+                                     partialTriggers="axBtn1 axBtn2"
+                                     styleUsage="instruction"
+                                     value="#{partialDemoUtil.status.linkUpdate}">
+                    <f:convertDateTime pattern="HH:mm:ss"/>
+                  </tr:outputFormatted>
+                </tr:panelLabelAndMessage>
+             </tr:panelGroupLayout>
+           </tr:panelGroupLayout>
+         </tr:panelHeader>
+       
+         <tr:panelHeader text="InputText Component using JSF 2.0 Ajax" id="phInput">
+           <tr:outputFormatted styleUsage="instruction"
+                             value="Tests autoSubmitting text fields which is also wired to use JSF 
+                             2.0 Ajax."/>
+            <tr:panelGroupLayout layout="horizontal" id="pgl20">
+              <f:facet name="separator">
+                <tr:spacer height="10" id="sp20"/>
+              </f:facet>
+              <tr:panelGroupLayout layout="vertical" id="pgl21">
+                <f:facet name="separator">
+                  <tr:spacer height="6" id="sp21"/>
+                </f:facet>
+                <tr:outputFormatted styleUsage="instruction" value="tr:inputText with
+                    autoSubmit=true." id="of20"/>
+                <tr:inputText id="itxt1"
+                              autoSubmit="true"
+                              value="#{partialDemoUtil.status.textValue}"
+                              label="Enter text and tab out: "
+                              valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+                <tr:outputFormatted styleUsage="instruction" value="tr:inputText with
+                    autoSubmit=true inside a subform" id="of21"/>                
+                <tr:subform id="sf20">
+                  <tr:inputText autoSubmit="true" id="itxt2" label="Enter a different text and tab out: "
+                                 value="#{partialDemoUtil.status.textValue}"
+                                 valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+                </tr:subform>
+              </tr:panelGroupLayout>
+              
+              <tr:panelLabelAndMessage label="Input entered: ">
+               <tr:outputFormatted id="itTarget"
+                                   partialTriggers="itxt1 ::sf20:itxt2"
+                                   styleUsage="instruction"
+                                   value="#{partialDemoUtil.status.textStateText}"/>
+              </tr:panelLabelAndMessage>
+            </tr:panelGroupLayout>
+         </tr:panelHeader>
+         
+         <tr:panelHeader text="Radio Buttons">
+           <tr:outputFormatted styleUsage="instruction"
+                               value="This demo shows a two sets of radio buttons which use autoSubmit. 
+                               There is also an output component which is listening on updates to the 
+                               radio buttons and displaying status text accordingly."/>
+          <tr:panelGroupLayout layout="horizontal">
+           <tr:panelGroupLayout layout="vertical">
+            <tr:panelGroupLayout layout="horizontal">
+             <tr:outputFormatted styleUsage="instruction"
+                                 value="selectBooleanRadio buttons"/>
+             <tr:panelGroupLayout layout="vertical">
+              <tr:selectBooleanRadio id="sbr1"
+                                     group="theGroup"
+                                     selected="false"
+                                     text="item 1"
+                                     autoSubmit="true"
+                                     valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+              <tr:selectBooleanRadio id="sbr2"
+                                     group="theGroup"
+                                     text="item 2"
+                                     selected="false"
+                                     autoSubmit="true"
+                                     valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+              <tr:selectBooleanRadio id="sbr3"
+                                     group="theGroup"
+                                     text="item 3"
+                                     selected="false"
+                                     autoSubmit="true"
+                                     valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+             </tr:panelGroupLayout>
+            </tr:panelGroupLayout>
+            <tr:spacer width="30" height="10"/>
+            <tr:panelGroupLayout layout="vertical">
+             <tr:selectOneRadio id="sor1"
+                                label="selectOneRadio buttons"
+                                autoSubmit="true"
+                                valueChangeListener="#{partialDemoUtil.valueChanged}">
+              <tr:selectItem label="item 1" value="1" />
+              <tr:selectItem label="item 2" value="2" />
+              <tr:selectItem label="item 3" value="3" />
+             </tr:selectOneRadio>
+            </tr:panelGroupLayout>
+           </tr:panelGroupLayout>
+           <tr:spacer width="30" height="10"/>
+           <tr:panelLabelAndMessage label="Selected: ">
+            <tr:outputFormatted id="rbTarget"
+                                partialTriggers="sbr1 sbr2 sbr3 sor1"
+                                styleUsage="instruction"
+                                value="#{partialDemoUtil.status.radioStateText}">
+             <f:convertDateTime pattern="HH:mm:ss"/>
+            </tr:outputFormatted>
+           </tr:panelLabelAndMessage>
+          </tr:panelGroupLayout>
+         </tr:panelHeader>         
+
+
+      </tr:panelGroupLayout>
+     </tr:panelHeader>
+     </tr:panelPage>
+     
+    </tr:form>
+  
+  </tr:document>
+ </f:view>
+</jsp:root>
diff --git a/trinidad-impl/src/main/conf/META-INF/faces-config-base.xml b/trinidad-impl/src/main/conf/META-INF/faces-config-base.xml
index 382feaf..d47f07f 100644
--- a/trinidad-impl/src/main/conf/META-INF/faces-config-base.xml
+++ b/trinidad-impl/src/main/conf/META-INF/faces-config-base.xml
@@ -39,6 +39,9 @@
     <faces-context-factory>
       org.apache.myfaces.trinidadinternal.context.FacesContextFactoryImpl
     </faces-context-factory>
+    <partial-view-context-factory>
+      org.apache.myfaces.trinidadinternal.context.PartialViewContextFactoryImpl
+    </partial-view-context-factory>
   </factory>
 
   <lifecycle>
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialViewContextFactoryImpl.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialViewContextFactoryImpl.java
new file mode 100644
index 0000000..c6a543c
--- /dev/null
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialViewContextFactoryImpl.java
@@ -0,0 +1,28 @@
+package org.apache.myfaces.trinidadinternal.context;
+
+import javax.faces.context.FacesContext;
+import javax.faces.context.FacesContextFactory;
+import javax.faces.context.PartialViewContext;
+import javax.faces.context.PartialViewContextFactory;
+
+public class PartialViewContextFactoryImpl
+  extends PartialViewContextFactory
+{
+  public PartialViewContextFactoryImpl(PartialViewContextFactory factory)
+  {
+    _factory = factory;
+  }
+
+  /**
+   * Creates a PartialViewContext instance that is optimized for Trinidad PPR.
+   * @param context 
+   * @return a PartialViewContext instance
+   */
+  public PartialViewContext getPartialViewContext(FacesContext context)
+  {
+    return new PartialViewContextImpl(context);
+  }
+  
+  private final PartialViewContextFactory _factory;
+  
+}
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialViewContextImpl.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialViewContextImpl.java
new file mode 100644
index 0000000..92a6abe
--- /dev/null
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PartialViewContextImpl.java
@@ -0,0 +1,437 @@
+package org.apache.myfaces.trinidadinternal.context;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+
+import java.util.Set;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.PartialResponseWriter;
+import javax.faces.context.PartialViewContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.event.PhaseId;
+
+import org.apache.myfaces.trinidad.component.UIXComponent;
+import org.apache.myfaces.trinidad.component.visit.VisitCallback;
+import org.apache.myfaces.trinidad.component.visit.VisitContext;
+import org.apache.myfaces.trinidad.component.visit.VisitHint;
+import org.apache.myfaces.trinidad.component.visit.VisitResult;
+import org.apache.myfaces.trinidad.context.PartialPageContext;
+import org.apache.myfaces.trinidad.context.RenderingContext;
+import org.apache.myfaces.trinidad.context.RequestContext;
+import org.apache.myfaces.trinidadinternal.renderkit.core.ppr.PPRResponseWriter;
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.PartialPageUtils;
+
+public class PartialViewContextImpl extends PartialViewContext
+{
+  public PartialViewContextImpl(FacesContext context) 
+  {
+    _context = context;
+  }
+
+  /**
+   * To force a full execute we always return an empty execute list.
+   * @return
+   */
+  public Collection<String> getExecuteIds()
+  {
+    /*
+    if (_executeIds == null) 
+    {
+      String executeStr = _facesContext.getExternalContext().getRequestParameterMap().get(
+        PartialViewContext.PARTIAL_EXECUTE_PARAM_NAME);
+    }
+    else
+    {
+      _executeIds = new ArrayList<String>();
+    }
+    */ 
+    _executeIds = new ArrayList<String>();
+    return _executeIds;
+  }
+
+  public Collection<String> getRenderIds()
+  {
+    return Collections.emptySet();
+  }
+
+  /**
+   * Return a PartialResponseWriter that consumes the Trinidad PprResponseWriter. 
+   * @return
+   */
+  public PartialResponseWriter getPartialResponseWriter()
+  {
+    if (_partialResponseWriter == null) 
+    {
+      _partialResponseWriter = new PPRPartialResponseWriter(_context.getResponseWriter());
+    }
+    return _partialResponseWriter;
+  }
+
+  public boolean isAjaxRequest()
+  {
+    _assertNotReleased();
+    if (_ajaxRequest == null) 
+    {
+        _ajaxRequest = _PARTIAL_AJAX.equals(_context.
+            getExternalContext().getRequestHeaderMap().get(_FACES_REQUEST));
+    }
+    return _ajaxRequest;
+  }
+
+  public boolean isPartialRequest()
+  {
+    _assertNotReleased();
+    if (_partialRequest == null) {
+        _partialRequest = isAjaxRequest() ||
+                _PARTIAL_PROCESS.equals(_context.
+                getExternalContext().getRequestHeaderMap().get(_FACES_REQUEST));
+    }
+    return _partialRequest;  
+  }
+
+  /**
+   * Trinidad PPR currently does a full decode/validate/update. So we return 'false' here, but in 
+   * processPartial, turn into a 'full tree visit'.
+   * @return true as the default executeList is set to be '@all'.
+   */
+  public boolean isExecuteAll()
+  {
+    _assertNotReleased();
+    String execute = _context.getExternalContext().getRequestParameterMap()
+      .get(PARTIAL_EXECUTE_PARAM_NAME);
+    
+    return execute.equals(this.ALL_PARTIAL_PHASE_CLIENT_IDS);
+  }
+
+  public boolean isRenderAll()
+  {
+    _assertNotReleased();
+    if (_renderAll == null) {
+        String render = _context.getExternalContext().getRequestParameterMap()
+                .get(PARTIAL_RENDER_PARAM_NAME);
+        _renderAll = (ALL_PARTIAL_PHASE_CLIENT_IDS.equals(render));
+    }
+
+    return _renderAll;  
+  }
+
+  public void setRenderAll(boolean renderAll)
+  {
+    _renderAll = renderAll;
+  }
+
+  public void setPartialRequest(boolean isPartialRequest)
+  {
+    _partialRequest = isPartialRequest;
+  }
+
+  public void release()
+  {
+    _ajaxRequest = null;
+    _executeIds = null;
+    _context = null;
+    _partialRequest = null;
+    _partialResponseWriter = null;
+    _released = true;
+    _renderAll = null;
+    _renderIds = null;
+  }
+
+  /**
+   * Handles the render phase alone as we perform a full 'execute' always.
+   * 
+   * @param phaseId
+   */
+  public void processPartial(PhaseId phaseId)
+  {
+    UIViewRoot viewRoot = _context.getViewRoot();
+    if (phaseId == PhaseId.APPLY_REQUEST_VALUES ||
+        phaseId == PhaseId.PROCESS_VALIDATIONS ||
+        phaseId == PhaseId.UPDATE_MODEL_VALUES)
+    {
+      // Assume the executeIds is set to @all to mimic a full tree visit. 
+      // Create a FullVisitContext
+      Collection <String> executeIds = getExecuteIds();
+
+      try 
+      {
+        _processExecute(viewRoot, phaseId, executeIds);
+      } 
+      catch (Exception e) 
+      {
+          // RELEASE_PENDING LOG EXCEPTION
+      }
+      
+    }
+    else if (phaseId == PhaseId.RENDER_RESPONSE)
+    {
+      _processRender(viewRoot, phaseId);
+    }
+
+  }
+
+  /**
+   * Performs a 'full' execute if executeIds is empty, in order to build the partialTrigger 
+   * listeners. Later, support for an 'optimized execute' will be added that 'visits' the executeId 
+   * components using the Trinidad visitTree implementation (that accounts for setup/teardown of 
+   * contexts.)
+   * @param component the UIViewRoot
+   * @param phaseId
+   * @param executeIds the Collection of ids to execute
+   */
+  private void _processExecute(
+    UIViewRoot component, 
+    PhaseId phaseId,
+    Collection<String> executeIds)
+  {
+    if (executeIds == null || executeIds.isEmpty())
+    {
+      // We use the tree visitor mechanism to locate the components to process. For now we ignore the 
+      // executeIds as we always want to perform a full decode. So a FullVisitContext is created and 
+      // the VisitCallback invoked for every component in the tree. 
+      VisitContext visitContext = 
+        RequestContext.getCurrentInstance().createVisitContext(_context, 
+                                                               executeIds, 
+                                                               _EXECUTE_VISIT_HINTS, 
+                                                               phaseId);
+      VisitCallback visitCallback = new ExecuteAllCallback(_context, phaseId);
+      UIXComponent.visitTree(visitContext, component, visitCallback);
+    }
+    else
+    {
+      // TODO: optimized decode??  
+    }
+  }
+
+  /**
+   * Performs a partial optimized rendering, if PPROptimization is enabled, otherwise defaults to a 
+   * full render. 
+   * 
+   * @param viewRoot
+   * @param phaseId
+   */
+  private void _processRender(UIComponent viewRoot, PhaseId phaseId)
+  {
+    boolean documentStarted = false;
+    
+    PartialResponseWriter partialResponseWriter = getPartialResponseWriter();
+    // Hold onto the original writer for later
+    ResponseWriter origResponseWriter = _context.getResponseWriter();
+    _context.setResponseWriter(partialResponseWriter);
+
+    ExternalContext extContext = _context.getExternalContext();
+    extContext.setResponseContentType(_RESPONSE_CONTENT_TYPE);
+    extContext.addResponseHeader("Pragma", "no-cache");
+    extContext.addResponseHeader("Cache-control", "no-cache");
+
+    try
+    {
+      partialResponseWriter.startDocument();
+      documentStarted = true;
+    
+      // determine whether we should try and optimize the PPR rendering
+      boolean encodeAllChildren = !PartialPageUtils.isOptimizedPPREnabled(_context, true);
+      
+      if (encodeAllChildren)
+      {
+        // We are guaranteed to be called on UIViewRoot. 
+        if (!viewRoot.isRendered()) 
+        {
+          return;
+        }
+      
+        // No PPR optimization, so encode all children
+        Iterator<UIComponent> children = viewRoot.getFacetsAndChildren();
+        while (children.hasNext()) 
+        {
+          children.next().encodeAll(_context);
+        }
+        
+        // TODO: Explcitly render out the view state as an update element.
+        _renderViewState(partialResponseWriter);
+      }
+      else
+      {
+        // TODO 
+        // HINT: PartialPageContext already creates a partial visit context. Reuse it??
+        
+        // Only visit tree if renderIds exist
+        Collection <String> renderIds = getRenderIds();
+        if (renderIds != null && !renderIds.isEmpty())
+        {
+          // perform an optimized partial visit of the children
+          RenderingContext rContext = RenderingContext.getCurrentInstance();
+          PartialPageContext pprContext = rContext.getPartialPageContext();
+         
+          VisitContext visitContext = pprContext.getVisitContext();
+          // component.visitTree(visitContext, new PhaseAwareVisitCallback(_context, phaseId));
+        }
+      }
+    }
+    catch (IOException e)
+    {
+      // launder the IOException as a FacesException, we'll unwrap this later
+      throw new FacesException(e);        
+    }
+    finally
+    {
+      try
+      {
+        if (documentStarted)
+        {
+          partialResponseWriter.endDocument();
+          documentStarted = false;
+        }
+      }
+      catch (IOException ioe2)
+      {
+        // TODO log exception
+      }
+      _context.setResponseWriter(origResponseWriter);
+    }
+  }
+  
+  private void _renderViewState(PartialResponseWriter writer)
+    throws IOException
+  {
+    // Get the view state and write it to the response..
+    writer.startUpdate(PartialResponseWriter.VIEW_STATE_MARKER);
+    String state = _context.getApplication().getStateManager().getViewState(_context);
+    writer.write(state);
+    writer.endUpdate();    
+  }
+  
+  @SuppressWarnings({"FinalPrivateMethod"})
+  private final void _assertNotReleased() 
+  {
+    if (_released) {
+        throw new IllegalStateException();
+    }
+  }
+
+
+
+
+  /**
+   * A simple PartialRepsonseWriter implementation that delegates most of its calls to the
+   * PPRResponseWriter as it already has the smarts to generate XML partial Ajax responses using the
+   * Trinidad partialTriggers mechanism.
+   */
+  private static final class PPRPartialResponseWriter extends PartialResponseWriter 
+  {
+    public PPRPartialResponseWriter(ResponseWriter writer)
+    {
+      super(null);
+      assert(writer instanceof PPRResponseWriter);
+      _pprWriter = (PPRResponseWriter) writer;
+    }
+
+    @Override
+    public void endDocument() throws IOException
+    {
+      getWrapped().endDocument();
+    }
+
+    @Override
+    public ResponseWriter getWrapped()
+    {
+      return _pprWriter;
+    }
+
+    @Override
+    public void startDocument() throws IOException
+    {
+      getWrapped().startDocument();
+    }
+
+
+    @Override
+    public void endUpdate()
+      throws IOException
+    {
+      _pprWriter.endUpdate();
+    }
+    
+    @Override
+    public void startUpdate(String string) throws IOException 
+    {
+      _pprWriter.startUpdate(string);
+    }
+
+    private PPRResponseWriter _pprWriter;
+  }
+  
+  /**
+   * Callback for encoding subtrees during optimized PPR tree visits
+   */
+  private static final class ExecuteAllCallback implements VisitCallback
+  {
+    public ExecuteAllCallback(
+      FacesContext context, 
+      PhaseId phaseId)
+    {
+      _context= context;
+      _phaseId = phaseId;
+    }
+    
+    public VisitResult visit(VisitContext context, UIComponent target)
+    {
+
+      // For UIViewRoot it's important to return VisitResult.ACCEPT to indicate that the tree 
+      // visit start processing its children. This is also required to not get into a recursive 
+      // hell as we got here to begin from UIViewRoot.processDecodes()
+      if (target instanceof UIViewRoot)
+        return VisitResult.ACCEPT;
+
+      // we have the subtree we want, execute it
+      if (_phaseId == PhaseId.APPLY_REQUEST_VALUES) 
+      {
+        target.processDecodes(_context);
+      } 
+      else if (_phaseId == PhaseId.PROCESS_VALIDATIONS) 
+      {
+        target.processValidators(_context);
+      } 
+      else if (_phaseId == PhaseId.UPDATE_MODEL_VALUES) 
+      {
+        target.processUpdates(_context);
+      }        
+
+      // we have finished processing desired target
+      return VisitResult.REJECT;
+    }
+    
+    private FacesContext _context;
+    private PhaseId      _phaseId;
+  }  
+  
+  private Boolean _ajaxRequest;
+  private List<String> _executeIds;
+  private FacesContext _context = null; 
+  private Boolean _partialRequest;
+  private PartialResponseWriter _partialResponseWriter;
+  private boolean _released;
+  private Boolean _renderAll;
+  private Collection<String> _renderIds;
+
+  private static final Set<VisitHint> _EXECUTE_VISIT_HINTS = EnumSet.of(VisitHint.SKIP_UNRENDERED,
+                                                                        VisitHint.EXECUTE_LIFECYCLE);  
+  
+  private static final String _RESPONSE_CONTENT_TYPE = "text/xml";
+  private static final String _FACES_REQUEST = "Faces-Request";
+  private static final String _PARTIAL_AJAX = "partial/ajax";
+  private static final String _PARTIAL_PROCESS = "partial/process";
+
+}
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/CoreRenderKit.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/CoreRenderKit.java
index 5e1283a..1057cda 100644
--- a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/CoreRenderKit.java
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/CoreRenderKit.java
@@ -143,11 +143,23 @@ public class CoreRenderKit extends RenderKitDecorator
     return "org.apache.myfaces.trinidad.core.desktop";
   }
 
+  /**
+   * Return <code>true</code> if the request header <code>Faces-Request</code> is present with the 
+   * value <code>partial/ajax</code>. Otherwise, return <code>false</code>.
+   * 
+   * @param ec the ExternalContext instance.
+   * @return
+   */
   static public boolean isAjaxRequest(ExternalContext ec)
   {
-    return "true".equals(ec.getRequestHeaderMap().get(_PPR_REQUEST_HEADER));
+    return _PARTIAL_AJAX.equals(ec.getRequestHeaderMap().get(_FACES_REQUEST_HEADER));
   }
 
+  /**
+   * TODO: Use JSF2.0 <code>Faces-Request</code> parameter.
+   * @param parameters
+   * @return
+   */
   static public boolean isPartialRequest(Map<String, String[]> parameters)
   {
     String[] array = parameters.get(_PPR_REQUEST_HEADER);
@@ -156,6 +168,11 @@ public class CoreRenderKit extends RenderKitDecorator
     return "true".equals(array[0]);
   }
 
+  /**
+   * TODO: Use JSF2.0 <code>Faces-Request</code> parameter.
+   * @param ec
+   * @return
+   */
   static public boolean isPartialRequest(ExternalContext ec)
   {
     // A partial request could be an AJAX request, or it could
@@ -803,6 +820,9 @@ public class CoreRenderKit extends RenderKitDecorator
   static private final String _SCRIPT_LIST_KEY =
     "org.apache.myfaces.trinidadinternal.renderkit.ScriptList";
   static private final String _PPR_REQUEST_HEADER = "Tr-XHR-Message";
+  private static final String _FACES_REQUEST_HEADER = "Faces-Request";
+  private static final String _PARTIAL_AJAX = "partial/ajax";
+
 
   static private final String _USE_DIALOG_POPUP_INIT_PARAM =
     "org.apache.myfaces.trinidad.ENABLE_LIGHTWEIGHT_DIALOGS";
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java
index 439affd..56c4a71 100644
--- a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java
@@ -23,11 +23,13 @@ import java.io.IOException;
 import java.io.Writer;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import javax.faces.component.UIComponent;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
+import javax.faces.context.PartialResponseWriter;
 import javax.faces.context.ResponseWriter;
 
 import org.apache.myfaces.trinidad.context.PartialPageContext;
@@ -36,6 +38,7 @@ import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
 import org.apache.myfaces.trinidad.util.Service;
 
+import org.apache.myfaces.trinidadinternal.io.ResponseWriterDecorator;
 import org.apache.myfaces.trinidadinternal.renderkit.core.pages.GenericEntry;
 
 /**
@@ -48,7 +51,7 @@ import org.apache.myfaces.trinidadinternal.renderkit.core.pages.GenericEntry;
  * TODO: write out fragments only once we've detected the
  * ID, to avoid sending unnecessary fragments
  */
-public class PPRResponseWriter extends ScriptBufferingResponseWriter
+public class PPRResponseWriter extends ResponseWriterDecorator // ScriptBufferingResponseWriter
 {
   public PPRResponseWriter(ResponseWriter     out,
                            RenderingContext   rc)
@@ -68,7 +71,7 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
   PPRResponseWriter(ResponseWriter out,
                     PPRResponseWriter base)
   {
-    super(out, base);
+    super(out);
     // New XmlResponseWriter
     _xml        = new XmlResponseWriter(out, out.getCharacterEncoding());
     // But the rest of the state is shared
@@ -116,9 +119,10 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     // Stick another PI indicating that this is a rich reponse
     // Used for an Iframe based communication channel, since it cannot 
     // read response headers
-    _xml.write("<?Tr-XHR-Response-Type ?>\n");
+    // TODO: Do we need this?
+    // _xml.write("<?Tr-XHR-Response-Type ?>\n");
 
-    _xml.startElement("content", null);
+    _xml.startElement(_ELEMENT_PARTIAL_RESPONSE, null);
     String viewId = _facesContext.getViewRoot().getViewId();
     // HACK: don't write out an "action" for PPR on a GenericEntry page
     // (basically entirely for the InlineDatePicker case)
@@ -132,8 +136,9 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     }
 
     // TODO: Portlet support for PPR?
-
-    _xml.writeText(" ", null);
+    // TODO: PS - Not sure why this extra space is being written out, but this causes an 'malformed 
+    // XML error to be thrown by JSF 2 Ajax. Commented out the line.
+    // _xml.writeText(" ", null);
 
     _state.documentStarting = false;
   }
@@ -141,12 +146,13 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
   public void endDocument() throws IOException
   {
     // Write out any buffered <script src=""> or inline scripts
-    writeBufferedScripts();
+    // TODO: No need to write buffered scripts as we directly let script pass through
+    // writeBufferedScripts();
     
     // Write out all of the framework-level scripts
     writeFrameworkScripts();
-    
-    _xml.endElement("content");
+    _endChanges();
+    _xml.endElement(_ELEMENT_PARTIAL_RESPONSE);
     _xml.endDocument();
 
     // Force "inside target mode" - this is for Facelets,
@@ -311,9 +317,49 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     return _xml;
   }
   
+  
+  public void endUpdate() throws IOException
+  {
+    super.flush();
+
+    if (_state._allowedUpdateStarted)
+    {
+      _xml.write("]]>");
+      _xml.endElement(_ELEMENT_CHANGES_UPDATE);
+      _xml.flush();
+      _state._allowedUpdateStarted = false;
+    }
+  }
+  
+ 
+  /**
+   * Starts an update element for non-PPR based content. For e.g., for rendering out the 
+   * "javax.faces.ViewState" id.
+   * @param id the id to use for the update element
+   */
+  public void startUpdate(String id) throws IOException 
+  {
+    if (id != null && _allowedIds.contains(id))
+    {
+      _startChanges();
+      
+      if (!_state._allowedUpdateStarted)
+      {
+        _state._allowedUpdateStarted = true;
+        _xml.startElement(_ELEMENT_CHANGES_UPDATE, null);
+        _xml.writeAttribute(_ATTRIBUTE_ID, id, null);
+        _xml.write("<![CDATA[");
+        _xml.flush();
+      }
+    }
+  }  
+
+  
   /*
    * Writes out buffered inline scripts and script libraries
    */
+  
+/*  
   protected void writeBufferedScripts() throws IOException
   {
     List<String> libraries = getBufferedLibraries();
@@ -332,17 +378,18 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     {
       for (String script : scripts)
       {
-        _xml.startElement("script", null);
+        _xml.startElement(_ELEMENT_EVAL, null);
         _xml.write("<![CDATA[");
         _xml.write(script);
         _xml.write("]]>");
-        _xml.endElement("script");
+        _xml.endElement(_ELEMENT_EVAL);
       }
     }
 
     // Clear out any buffered scripts/libraries
     clearBufferedContents();
   }
+*/ 
   
   /*
    * Writes out framework-level scripts
@@ -391,7 +438,7 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     if (tag != null)
     {
       super.flush();
-      tag.start(_state.pprContext, elementName);
+      tag.startUpdate(_state.pprContext, elementName);
     }
 
     _state.componentStack.add(tag);
@@ -405,7 +452,7 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     componentStack.remove(pos);
 
     if (tag != null)
-      tag.finish(_state.pprContext, elementName);
+      tag.finishUpdate(_state.pprContext, elementName);
   }
 
   private boolean _isInsideTarget()
@@ -414,7 +461,8 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     // a partial target subtree.  Otherwise, we discard all
     // output.
     return _state.forceInsideTarget ||
-           _state.pprContext.isInsidePartialTarget();
+           _state.pprContext.isInsidePartialTarget() ||
+           _state._allowedUpdateStarted;
            
   }
 
@@ -468,7 +516,24 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     }
   }
 
+  private void _startChanges() throws IOException
+  {
+    if (!_state.changesStarted)
+    {
+      _xml.startElement(_ELEMENT_CHANGES, null);
+      _state.changesStarted = true;
+    }
+  }
 
+  private void _endChanges()
+    throws IOException
+  {
+    if (_state.changesStarted)
+    {
+      _xml.endElement("changes");
+      _state.changesStarted = false;
+    }
+  }
   //
   // Class representing PPR behavior associated with a tag.  The
   // base class simply tells PPR when it's working with a partial target
@@ -480,14 +545,16 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
       _id = id;
     }
 
-    public void start(
+    public void startUpdate(
       PartialPageContextImpl pprContext,
       String             elementName) throws IOException
     {
       if (_id != null)
       {
+        _startChanges();
         pprContext.pushRenderedPartialTarget(_id);
-        _xml.startElement("fragment",null);
+        _xml.startElement(_ELEMENT_CHANGES_UPDATE, null);
+        _xml.writeAttribute(_ATTRIBUTE_ID, _id, null);
         _xml.write("<![CDATA[");
         _xml.flush(); // NEW
 
@@ -501,7 +568,7 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
       }
     }
 
-    public void finish(
+    public void finishUpdate(
       PartialPageContextImpl pprContext,
       String             elementName) throws IOException
     {
@@ -520,7 +587,7 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
         PPRResponseWriter.super.flush();
       
         _xml.write("]]>");
-        _xml.endElement("fragment");
+        _xml.endElement(_ELEMENT_CHANGES_UPDATE);
         _xml.flush();
         
         pprContext.popRenderedPartialTarget();
@@ -567,11 +634,6 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     private String _id;
   }
 
-  
-  private State _state;
-  private ResponseWriter _xml;
-  private final FacesContext _facesContext =
-   FacesContext.getCurrentInstance();
 
   static private class State
   {
@@ -585,9 +647,22 @@ public class PPRResponseWriter extends ScriptBufferingResponseWriter
     public int           elementDepth;
     public boolean       documentStarted;
     public boolean       documentStarting;
+    public boolean       changesStarted;
+    private boolean      _allowedUpdateStarted;
     public final List<PPRTag> componentStack = new ArrayList<PPRTag>(50);
     public final PartialPageContextImpl pprContext;
   }
 
+  private State _state;
+  private ResponseWriter _xml;
+  private final FacesContext _facesContext = FacesContext.getCurrentInstance();
+  
   static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(PPRResponseWriter.class);
+  private static final String _ELEMENT_PARTIAL_RESPONSE = "partial-response";
+  private static final String _ELEMENT_CHANGES = "changes";
+  private static final String _ELEMENT_CHANGES_UPDATE = "update";
+  private static final String _ELEMENT_EVAL = "eval";
+  private static final String _ATTRIBUTE_ID = "id";
+  private static final List<String> _allowedIds = Arrays.asList(PartialResponseWriter.VIEW_STATE_MARKER);
+
 }
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/CommandLinkRenderer.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/CommandLinkRenderer.java
index 58bc5c0..c178c4a 100644
--- a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/CommandLinkRenderer.java
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/CommandLinkRenderer.java
@@ -75,7 +75,7 @@ public class CommandLinkRenderer extends GoLinkRenderer
       Map<String, String> parameterMap =
         context.getExternalContext().getRequestParameterMap();
 
-      Object source = parameterMap.get("source");
+      Object source = parameterMap.get("javax.faces.source");
       String clientId = component.getClientId(context);
 
       if ((source != null) && source.equals(clientId))
diff --git a/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Core.js b/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Core.js
index 2a4537e..8c346a5 100644
--- a/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Core.js
+++ b/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Core.js
@@ -1701,7 +1701,8 @@ function submitForm(
   form,
   doValidate,
   parameters,
-  isPartial
+  isPartial, 
+  event
   )
 {
   // If we've delayed any sort of event submission, we won't want to do it at
@@ -1862,7 +1863,7 @@ function submitForm(
       }
       else
       {
-        TrPage.getInstance().sendPartialFormPost(form, parameters);
+        TrPage.getInstance().sendPartialFormPost(form, parameters, null, event);
       }
     }
     else
@@ -3868,7 +3869,8 @@ function _firePartialChange(url)
 function _submitPartialChange(
   form,
   doValidate,
-  parameters)
+  parameters,
+  event)
 {
   // If there's no PPR iframe, then just perform a normal,
   // full-page submission.
@@ -3886,10 +3888,10 @@ function _submitPartialChange(
   parameters = _addFormParameter(parameters, "partial", "true");
 
   // block all mouse clicks until the submit is done
-    _pprStartBlocking(window);
+  _pprStartBlocking(window);
 
   // Submit the form
-  var submitted = submitForm(form, doValidate, parameters, true);
+  var submitted = submitForm(form, doValidate, parameters, true, event);
 
   // If the form wasn't actually submitted, update the ref count
   if (!submitted)
diff --git a/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js b/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
index 0b902f7..9028b87 100644
--- a/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
+++ b/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
@@ -53,11 +53,22 @@ TrPage.prototype.getRequestQueue = function()
 TrPage.prototype.sendPartialFormPost = function(
   actionForm,
   params,
-  headerParams)
+  headerParams,
+  event)
 {
+  var source = "";
+  if (params != null)
+    source = params.source;
+
+  TrPage._delegateToJSFAjax(actionForm, source, event, params);
+
+
+  /** Delegating to jsf.ajax.request(). Do not call the Trinidad PPR request mechanism
+   
   this.getRequestQueue().sendFormPost(
     this, this._requestStatusChanged,
     actionForm, params, headerParams);
+  */
 }
 
 TrPage.prototype._requestStatusChanged = function(requestEvent)
@@ -746,9 +757,10 @@ TrPage._autoSubmit = function(formId, inputId, event, validateForm, params)
     if (event["type"] == "hidden")
       event = window.event;
   }
-
+  
   // If onchange is used for validation, then first validate 
   // just the current input
+
   var isValid = true;
   if (_TrEventBasedValidation)
     isValid = _validateInput(event, true);
@@ -761,6 +773,27 @@ TrPage._autoSubmit = function(formId, inputId, event, validateForm, params)
     params.event = "autosub";
     params.source = inputId;
   
-    _submitPartialChange(formId, validateForm, params);
+    _submitPartialChange(formId, validateForm, params, event);
   }
 }
+
+/**
+ * Causes a partial submit to occur on a given component using the jsf.ajax.request call. The 
+ * specified component will not be validated (yet).
+ * @param formId(String) Id of the form to partial submit.
+ * @param inputId(String) Id of the element causing the partial submit.  
+ * @param event(Event) The javascript event object.
+ * @param params(Object} additional parameters to send
+ */
+TrPage._delegateToJSFAjax = function(formId, inputId, event, params)
+{
+  var doc = window.document;
+  var source = _getElementById(doc, inputId);
+
+  if (!params)
+    params = {};
+
+  // TODO: add execute and render targets??
+  
+  jsf.ajax.request(source, event, params);
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@myfaces.apache.org" <co...@myfaces.apache.org>.