You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/10/25 07:07:37 UTC

svn commit: r1188513 - in /myfaces/core/branches/2.0.x: impl/src/main/java/org/apache/myfaces/context/ impl/src/main/java/org/apache/myfaces/context/servlet/ impl/src/main/java/org/apache/myfaces/renderkit/html/ impl/src/main/java/org/apache/myfaces/vi...

Author: lu4242
Date: Tue Oct 25 05:07:37 2011
New Revision: 1188513

URL: http://svn.apache.org/viewvc?rev=1188513&view=rev
Log:
MYFACES-3367 Detect when to wpdate head or body target when content has been updated dynamically

Modified:
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlScriptRenderer.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlStylesheetRenderer.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java
    myfaces/core/branches/2.0.x/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java?rev=1188513&r1=1188512&r2=1188513&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java Tue Oct 25 05:07:37 2011
@@ -20,6 +20,7 @@ package org.apache.myfaces.context;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 import javax.faces.application.ResourceDependency;
 import javax.faces.component.UIViewRoot;
@@ -39,6 +40,8 @@ public class RequestViewContext
     private Map<ResourceDependency, Boolean> addedResources = new HashMap<ResourceDependency,Boolean>();
     
     private Map<Class<?>, Boolean> processedClasses = new HashMap<Class<?>,Boolean>();
+    
+    private Map<String, Boolean> renderTargetMap = null;
 
     static public RequestViewContext getCurrentInstance()
     {
@@ -95,4 +98,22 @@ public class RequestViewContext
     {
         processedClasses.put(inspectedClass, Boolean.TRUE);
     }
+    
+    public boolean isRenderTarget(String target)
+    {
+        if (renderTargetMap != null)
+        {
+            return Boolean.TRUE.equals(renderTargetMap.get(target));
+        }
+        return false;
+    }
+    
+    public void setRenderTarget(String target, boolean value)
+    {
+        if (renderTargetMap == null)
+        {
+            renderTargetMap = new HashMap<String, Boolean>(8);
+        }
+        renderTargetMap.put(target, value);
+    }
 }

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java?rev=1188513&r1=1188512&r2=1188513&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java Tue Oct 25 05:07:37 2011
@@ -31,6 +31,8 @@ import javax.faces.FactoryFinder;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewParameter;
 import javax.faces.component.UIViewRoot;
+import javax.faces.component.html.HtmlBody;
+import javax.faces.component.html.HtmlHead;
 import javax.faces.component.visit.VisitCallback;
 import javax.faces.component.visit.VisitContext;
 import javax.faces.component.visit.VisitHint;
@@ -46,6 +48,9 @@ import javax.faces.render.RenderKitFacto
 import javax.faces.view.ViewMetadata;
 
 import org.apache.myfaces.context.PartialResponseWriterImpl;
+import org.apache.myfaces.context.RequestViewContext;
+import org.apache.myfaces.shared.config.MyfacesConfig;
+import org.apache.myfaces.shared.util.ExternalContextUtils;
 import org.apache.myfaces.shared.util.StringUtils;
 
 public class PartialViewContextImpl extends PartialViewContext {
@@ -434,8 +439,70 @@ public class PartialViewContextImpl exte
                     }
                     else
                     {
+                        List<UIComponent> updatedComponents = null;
+                        if (!ExternalContextUtils.isPortlet(_facesContext.getExternalContext()) &&
+                             MyfacesConfig.getCurrentInstance(externalContext).isStrictJsf2RefreshTargetAjax())
+                        {
+                            RequestViewContext rvc = RequestViewContext.getCurrentInstance(_facesContext);
+                            if (rvc.isRenderTarget("head"))
+                            {
+                                UIComponent head = findHeadComponent(viewRoot);
+                                if (head != null)
+                                {
+                                    writer.startUpdate("javax.faces.ViewHead");
+                                    head.encodeAll(_facesContext);
+                                    writer.endUpdate();
+                                    if (updatedComponents == null)
+                                    {
+                                        updatedComponents = new ArrayList<UIComponent>();
+                                    }
+                                    updatedComponents.add(head);
+                                }
+                            }
+                            if (rvc.isRenderTarget("body") || rvc.isRenderTarget("form"))
+                            {
+                                UIComponent body = findBodyComponent(viewRoot);
+                                if (body != null)
+                                {
+                                    writer.startUpdate("javax.faces.ViewBody");
+                                    body.encodeAll(_facesContext);
+                                    writer.endUpdate();
+                                    if (updatedComponents == null)
+                                    {
+                                        updatedComponents = new ArrayList<UIComponent>();
+                                    }
+                                    updatedComponents.add(body);
+                                }
+                            }
+                        }
+
                         VisitContext visitCtx = VisitContext.createVisitContext(_facesContext, renderIds, hints);
-                        viewRoot.visitTree(visitCtx, new PhaseAwareVisitCallback(_facesContext, phaseId));
+                        viewRoot.visitTree(visitCtx, new PhaseAwareVisitCallback(_facesContext, phaseId, updatedComponents));
+                    }
+                }
+                else if (!ExternalContextUtils.isPortlet(_facesContext.getExternalContext()) &&
+                        MyfacesConfig.getCurrentInstance(externalContext).isStrictJsf2RefreshTargetAjax())
+                {
+                    RequestViewContext rvc = RequestViewContext.getCurrentInstance(_facesContext);
+                    if (rvc.isRenderTarget("head"))
+                    {
+                        UIComponent head = findHeadComponent(viewRoot);
+                        if (head != null)
+                        {
+                            writer.startUpdate("javax.faces.ViewHead");
+                            head.encodeAll(_facesContext);
+                            writer.endUpdate();
+                        }
+                    }
+                    if (rvc.isRenderTarget("body") || rvc.isRenderTarget("form"))
+                    {
+                        UIComponent body = findBodyComponent(viewRoot);
+                        if (body != null)
+                        {
+                            writer.startUpdate("javax.faces.ViewBody");
+                            body.encodeAll(_facesContext);
+                            writer.endUpdate();
+                        }
                     }
                 }
             }
@@ -527,15 +594,67 @@ public class PartialViewContextImpl exte
         _facesContext = null;
         _released = true;
     }
+    
+    private UIComponent findHeadComponent(UIViewRoot root)
+    {
+        for (UIComponent child : root.getChildren())
+        {
+            if (child instanceof HtmlHead)
+            {
+                return child;
+            }
+            else
+            {
+                for (UIComponent grandchild : child.getChildren())
+                {
+                    if (child instanceof HtmlHead)
+                    {
+                        return child;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+    
+    private UIComponent findBodyComponent(UIViewRoot root)
+    {
+        for (UIComponent child : root.getChildren())
+        {
+            if (child instanceof HtmlBody)
+            {
+                return child;
+            }
+            else
+            {
+                for (UIComponent grandchild : child.getChildren())
+                {
+                    if (child instanceof HtmlBody)
+                    {
+                        return child;
+                    }
+                }
+            }
+        }
+        return null;
+    }
 
     private class PhaseAwareVisitCallback implements VisitCallback {
 
         private PhaseId _phaseId;
         private FacesContext _facesContext;
+        private List<UIComponent> _alreadyUpdatedComponents;
 
         public PhaseAwareVisitCallback(FacesContext facesContext, PhaseId phaseId) {
             this._phaseId = phaseId;
             this._facesContext = facesContext;
+            this._alreadyUpdatedComponents = null;
+        }
+        
+        public PhaseAwareVisitCallback(FacesContext facesContext, PhaseId phaseId, List<UIComponent> alreadyUpdatedComponents) {
+            this._phaseId = phaseId;
+            this._facesContext = facesContext;
+            this._alreadyUpdatedComponents = alreadyUpdatedComponents;
         }
 
         public VisitResult visit(VisitContext context, UIComponent target) {
@@ -565,6 +684,19 @@ public class PartialViewContextImpl exte
         private void processRenderComponent(UIComponent target) {
             boolean inUpdate = false;
             PartialResponseWriter writer = (PartialResponseWriter) _facesContext.getResponseWriter();
+            if (this._alreadyUpdatedComponents != null)
+            {
+                //Check if the parent was already updated.
+                UIComponent parent = target;
+                while (parent != null)
+                {
+                    if (this._alreadyUpdatedComponents.contains(parent))
+                    {
+                        return;
+                    }
+                    parent = parent.getParent();
+                }
+            }
             try {
                 writer.startUpdate(target.getClientId(_facesContext));
                 inUpdate = true;

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlScriptRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlScriptRenderer.java?rev=1188513&r1=1188512&r2=1188513&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlScriptRenderer.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlScriptRenderer.java Tue Oct 25 05:07:37 2011
@@ -32,18 +32,19 @@ import javax.faces.context.ResponseWrite
 import javax.faces.event.ComponentSystemEvent;
 import javax.faces.event.ComponentSystemEventListener;
 import javax.faces.event.ListenerFor;
-import javax.faces.event.ListenersFor;
 import javax.faces.event.PostAddToViewEvent;
 import javax.faces.event.PreRenderViewEvent;
 import javax.faces.render.Renderer;
 import javax.faces.view.Location;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderer;
+import org.apache.myfaces.context.RequestViewContext;
+import org.apache.myfaces.shared.config.MyfacesConfig;
 import org.apache.myfaces.shared.renderkit.JSFAttr;
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 import org.apache.myfaces.shared.renderkit.html.HTML;
 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
-import org.apache.myfaces.view.facelets.PostBuildComponentTreeOnRestoreViewEvent;
+import org.apache.myfaces.shared.util.ExternalContextUtils;
 import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 
@@ -55,14 +56,13 @@ import org.apache.myfaces.view.facelets.
  * @since 2.0
  */
 @JSFRenderer(renderKitId = "HTML_BASIC", family = "javax.faces.Output", type = "javax.faces.resource.Script")
-@ListenersFor({
-@ListenerFor(systemEventClass = PostAddToViewEvent.class),
-@ListenerFor(systemEventClass = PostBuildComponentTreeOnRestoreViewEvent.class)
-})
+@ListenerFor(systemEventClass = PostAddToViewEvent.class)
 public class HtmlScriptRenderer extends Renderer implements ComponentSystemEventListener {
     //private static final Log log = LogFactory.getLog(HtmlScriptRenderer.class);
     private static final Logger log = Logger.getLogger(HtmlScriptRenderer.class.getName());
 
+    private static final String IS_BUILDING_INITIAL_STATE = "javax.faces.IS_BUILDING_INITIAL_STATE";
+
     public void processEvent(ComponentSystemEvent event) {
         if (event instanceof PostAddToViewEvent) {
             UIComponent component = event.getComponent();
@@ -70,19 +70,6 @@ public class HtmlScriptRenderer extends 
             if (target != null) {
                 FacesContext facesContext = FacesContext.getCurrentInstance();
 
-                //if (component.getId() != null)
-                //{
-                //    UniqueIdVendor uiv = findParentUniqueIdVendor(component);
-                //
-                //    if ( (!(uiv instanceof UIViewRoot)) && component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
-                //    {
-                //        // The id was set using the closest UniqueIdVendor, but since this one
-                //        // will be relocated, we need to assign an id from the current root.
-                //        // otherwise a duplicate id exception could happen.
-                //        component.setId(facesContext.getViewRoot().createUniqueId(facesContext, null));
-                //    }
-                //}
-
                 Location location = (Location) component.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
                 if (location != null)
                 {
@@ -94,7 +81,20 @@ public class HtmlScriptRenderer extends 
                                 ComponentSupport.getFindComponentExpression(facesContext, ccParent));
                     }
                 }
-                
+
+                // If this is an ajax request and the view is being refreshed and a PostAddToViewEvent
+                // was propagated to relocate this resource, means the header must be refreshed.
+                // Note ajax request does not occur 
+                if (!ExternalContextUtils.isPortlet(facesContext.getExternalContext()) &&
+                    facesContext.getPartialViewContext().isAjaxRequest() && 
+                    !facesContext.getAttributes().containsKey(IS_BUILDING_INITIAL_STATE) &&
+                    MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isStrictJsf2RefreshTargetAjax())
+                {
+                    //!(component.getParent() instanceof ComponentResourceContainer)
+                    RequestViewContext requestViewContext = RequestViewContext.getCurrentInstance(facesContext);
+                    requestViewContext.setRenderTarget("head", true);
+                }
+
                 facesContext.getViewRoot().addComponentResource(facesContext,
                         component, target);
             }
@@ -116,21 +116,6 @@ public class HtmlScriptRenderer extends 
         }
     }
 
-//private static UniqueIdVendor findParentUniqueIdVendor(UIComponent component)
-//{
-//    UIComponent parent = component.getParent();
-//
-//    while (parent != null)
-//    {
-//        if (parent instanceof UniqueIdVendor)
-//        {
-//            return (UniqueIdVendor) parent;
-//        }
-//        parent = parent.getParent();
-//    }
-//    return null;
-//}
-
     @Override
     public boolean getRendersChildren() {
         return true;
@@ -250,33 +235,4 @@ public class HtmlScriptRenderer extends 
         }
     }
 
-    /*
-    private boolean _initialStateMarked;
-
-    public void clearInitialState() {
-        _initialStateMarked = false;
-    }
-
-    public boolean initialStateMarked() {
-        return _initialStateMarked;
-    }
-
-    public void markInitialState() {
-        _initialStateMarked = true;
-    }
-
-    public boolean isTransient() {
-        return false;
-    }
-
-    public void restoreState(FacesContext context, Object state) {
-    }
-
-    public Object saveState(FacesContext context) {
-        return null;
-    }
-
-    public void setTransient(boolean newTransientValue) {
-    }
-    */
 }

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlStylesheetRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlStylesheetRenderer.java?rev=1188513&r1=1188512&r2=1188513&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlStylesheetRenderer.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlStylesheetRenderer.java Tue Oct 25 05:07:37 2011
@@ -31,85 +31,77 @@ import javax.faces.context.ResponseWrite
 import javax.faces.event.ComponentSystemEvent;
 import javax.faces.event.ComponentSystemEventListener;
 import javax.faces.event.ListenerFor;
-import javax.faces.event.ListenersFor;
 import javax.faces.event.PostAddToViewEvent;
 import javax.faces.render.Renderer;
 import javax.faces.view.Location;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderer;
+import org.apache.myfaces.context.RequestViewContext;
+import org.apache.myfaces.shared.config.MyfacesConfig;
 import org.apache.myfaces.shared.renderkit.JSFAttr;
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 import org.apache.myfaces.shared.renderkit.html.HTML;
 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
-import org.apache.myfaces.view.facelets.PostBuildComponentTreeOnRestoreViewEvent;
+import org.apache.myfaces.shared.util.ExternalContextUtils;
 import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 
 /**
- * Renderer used by h:outputStylesheet component
+ * Renderer used by h:outputStylesheet component 
+ * 
+ * Note: originally this component required PostBuildComponentTreeOnRestoreViewEvent,
+ * but that is no longer true because a tag handler implementing RelocatableResourceHandler
+ * interface was associated, so the component is really marked and refreshed.
  * 
  * @since 2.0
  * @author Leonardo Uribe (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
 @JSFRenderer(renderKitId = "HTML_BASIC", family = "javax.faces.Output", type = "javax.faces.resource.Stylesheet")
-@ListenersFor({
-@ListenerFor(systemEventClass = PostAddToViewEvent.class),
-@ListenerFor(systemEventClass = PostBuildComponentTreeOnRestoreViewEvent.class)
-})
+@ListenerFor(systemEventClass = PostAddToViewEvent.class)
 public class HtmlStylesheetRenderer extends Renderer implements
     ComponentSystemEventListener
 {
     //private static final Log log = LogFactory.getLog(HtmlStylesheetRenderer.class);
     private static final Logger log = Logger.getLogger(HtmlStylesheetRenderer.class.getName());
     
+    private static final String IS_BUILDING_INITIAL_STATE = "javax.faces.IS_BUILDING_INITIAL_STATE";
+    
     public void processEvent(ComponentSystemEvent event)
     {
-        UIComponent component = event.getComponent();
-        FacesContext facesContext = FacesContext.getCurrentInstance();
-        
-        //if (component.getId() != null)
-        //{
-        //    UniqueIdVendor uiv = findParentUniqueIdVendor(component);
-        //
-        //    if ( (!(uiv instanceof UIViewRoot)) && component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
-        //    {
-        //        // The id was set using the closest UniqueIdVendor, but since this one
-        //        // will be relocated, we need to assign an id from the current root.
-        //        // otherwise a duplicate id exception could happen.
-        //        component.setId(facesContext.getViewRoot().createUniqueId(facesContext, null));
-        //    }
-        //}
-        Location location = (Location) component.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
-        if (location != null)
-        {
-            UIComponent ccParent = CompositeComponentELUtils.getCompositeComponentBasedOnLocation(facesContext, location); 
-            if (ccParent != null)
-            {
-                component.getAttributes().put(
-                        CompositeComponentELUtils.CC_FIND_COMPONENT_EXPRESSION,
-                        ComponentSupport.getFindComponentExpression(facesContext, ccParent));
+        if (event instanceof PostAddToViewEvent)
+        {
+            UIComponent component = event.getComponent();
+            FacesContext facesContext = FacesContext.getCurrentInstance();
+            
+            Location location = (Location) component.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
+            if (location != null)
+            {
+                UIComponent ccParent = CompositeComponentELUtils.getCompositeComponentBasedOnLocation(facesContext, location); 
+                if (ccParent != null)
+                {
+                    component.getAttributes().put(
+                            CompositeComponentELUtils.CC_FIND_COMPONENT_EXPRESSION,
+                            ComponentSupport.getFindComponentExpression(facesContext, ccParent));
+                }
+            }
+            // If this is an ajax request and the view is being refreshed and a PostAddToViewEvent
+            // was propagated to relocate this resource, means the header must be refreshed.
+            // Note ajax request does not occur 
+            if (!ExternalContextUtils.isPortlet(facesContext.getExternalContext()) &&
+                facesContext.getPartialViewContext().isAjaxRequest() && 
+                !facesContext.getAttributes().containsKey(IS_BUILDING_INITIAL_STATE) &&
+                MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isStrictJsf2RefreshTargetAjax())
+            {
+                //!(component.getParent() instanceof ComponentResourceContainer)
+                RequestViewContext requestViewContext = RequestViewContext.getCurrentInstance(facesContext);
+                requestViewContext.setRenderTarget("head", true);
             }
+            facesContext.getViewRoot().addComponentResource(facesContext,
+                        component, "head");
         }
-        facesContext.getViewRoot().addComponentResource(facesContext,
-                    component, "head");
     }
     
-    //private static UniqueIdVendor findParentUniqueIdVendor(UIComponent component)
-    //{
-    //    UIComponent parent = component.getParent();
-    //
-    //    while (parent != null)
-    //    {
-    //        if (parent instanceof UniqueIdVendor)
-    //        {
-    //            return (UniqueIdVendor) parent;
-    //        }
-    //        parent = parent.getParent();
-    //    }
-    //    return null;
-    //}
-
     @Override
     public boolean getRendersChildren()
     {
@@ -234,40 +226,4 @@ public class HtmlStylesheetRenderer exte
             writer.endElement(HTML.LINK_ELEM);
         }
     }
-
-    /*
-    private boolean _initialStateMarked;
-    
-    public void clearInitialState()
-    {
-        _initialStateMarked = false;
-    }
-
-    public boolean initialStateMarked()
-    {
-        return _initialStateMarked;
-    }
-
-    public void markInitialState()
-    {
-        _initialStateMarked = true;
-    }
-
-    public boolean isTransient()
-    {
-        return false;
-    }
-
-    public void restoreState(FacesContext context, Object state)
-    {
-    }
-
-    public Object saveState(FacesContext context)
-    {
-        return null;
-    }
-
-    public void setTransient(boolean newTransientValue)
-    {
-    }*/
 }

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java?rev=1188513&r1=1188512&r2=1188513&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java Tue Oct 25 05:07:37 2011
@@ -195,6 +195,10 @@ public class ComponentTagHandlerDelegate
         // grab our component
         UIComponent c = null;
         //boolean componentFoundInserted = false;
+
+        //Used to preserve the original parent. Note when the view is being refreshed, the real parent could be
+        //another component.
+        UIComponent oldParent = parent;
         
         if (mctx.isRefreshingTransientBuild())
         {
@@ -335,7 +339,13 @@ public class ComponentTagHandlerDelegate
             //{
                 if (mctx.isRefreshingTransientBuild())
                 {
-                    facesContext.setProcessingEvents(false); 
+                    facesContext.setProcessingEvents(false);
+                    if (_relocatableResourceHandler != null &&
+                        parent != null && !parent.equals(c.getParent()))
+                    {
+                        // Replace parent with the relocated parent.
+                        parent = c.getParent();
+                    }
                 }
                 if (facetName == null)
                 {
@@ -414,7 +424,7 @@ public class ComponentTagHandlerDelegate
             }
         }
         
-        _delegate.onComponentPopulated(ctx, c, parent);
+        _delegate.onComponentPopulated(ctx, c, oldParent);
 
         //if (!componentFoundInserted)
         //{

Modified: myfaces/core/branches/2.0.x/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java?rev=1188513&r1=1188512&r2=1188513&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java (original)
+++ myfaces/core/branches/2.0.x/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java Tue Oct 25 05:07:37 2011
@@ -26,6 +26,7 @@ import javax.servlet.ServletContext;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 import org.apache.myfaces.shared.util.ClassUtils;
+import org.apache.myfaces.shared.util.WebConfigParamUtils;
 
 /**
  * Holds all configuration init parameters (from web.xml) that are independent
@@ -297,6 +298,15 @@ public class MyfacesConfig
     public final static String INIT_PARAM_DEBUG_PHASE_LISTENER = "org.apache.myfaces.DEBUG_PHASE_LISTENER";
     public final static boolean INIT_PARAM_DEBUG_PHASE_LISTENER_DEFAULT = false;
     
+    /**
+     * Detect if a target (usually head) should be update for the current view in an ajax render operation. This is activated if a css or js resource
+     * is added dynamically by effect of a refresh (c:if, ui:include src="#{...}" or a manipulation of the tree). This ensures ajax updates of content 
+     * using ui:include will be consistent. 
+     */
+    @JSFWebConfigParam(since="2.0.10", expectedValues="true, false", defaultValue="false")
+    public final static String INIT_PARAM_STRICT_JSF_2_REFRESH_TARGET_AJAX = "org.apache.myfaces.STRICT_JSF_2_REFRESH_TARGET_AJAX";
+    public final static boolean INIT_PARAM_STRICT_JSF_2_REFRESH_TARGET_AJAX_DEFAULT = false;
+    
     private boolean _prettyHtml;
     private boolean _detectJavascript;
     private boolean _allowJavascript;
@@ -320,6 +330,7 @@ public class MyfacesConfig
     private boolean _wrapScriptContentWithXmlCommentTag;
     private boolean _renderFormSubmitScriptInline;
     private boolean _debugPhaseListenerEnabled;
+    private boolean _strictJsf2RefreshTargetAjax;
 
     private static final boolean TOMAHAWK_AVAILABLE;
     private static final boolean MYFACES_IMPL_AVAILABLE;
@@ -412,6 +423,7 @@ public class MyfacesConfig
         setCheckExtensionsFilter(false);
         setRenderFormSubmitScriptInline(INIT_PARAM_RENDER_FORM_SUBMIT_SCRIPT_INLINE_DEFAULT);
         setDebugPhaseListenerEnabled(INIT_PARAM_DEBUG_PHASE_LISTENER_DEFAULT);
+        setStrictJsf2RefreshTargetAjax(INIT_PARAM_STRICT_JSF_2_REFRESH_TARGET_AJAX_DEFAULT);
     }
 
     private static MyfacesConfig createAndInitializeMyFacesConfig(ExternalContext extCtx) {
@@ -486,6 +498,9 @@ public class MyfacesConfig
         
         myfacesConfig.setDebugPhaseListenerEnabled(getBooleanInitParameter(extCtx, INIT_PARAM_DEBUG_PHASE_LISTENER,
                 INIT_PARAM_DEBUG_PHASE_LISTENER_DEFAULT));
+        
+        myfacesConfig.setStrictJsf2RefreshTargetAjax(WebConfigParamUtils.getBooleanInitParameter(extCtx, 
+                INIT_PARAM_STRICT_JSF_2_REFRESH_TARGET_AJAX, INIT_PARAM_STRICT_JSF_2_REFRESH_TARGET_AJAX_DEFAULT));
 
         if (TOMAHAWK_AVAILABLE)
         {
@@ -903,4 +918,14 @@ public class MyfacesConfig
     {
         this._debugPhaseListenerEnabled = debugPhaseListener;
     }
+
+    public boolean isStrictJsf2RefreshTargetAjax()
+    {
+        return _strictJsf2RefreshTargetAjax;
+    }
+
+    public void setStrictJsf2RefreshTargetAjax(boolean strictJsf2RefreshTargetAjax)
+    {
+        this._strictJsf2RefreshTargetAjax = strictJsf2RefreshTargetAjax;
+    }
 }