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/07/26 05:43:22 UTC

svn commit: r1150980 - in /myfaces/shared/trunk_4.0.x/core/src: main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java test/java/org/apache/myfaces/shared/renderkit/RendererUtilsTest.java

Author: lu4242
Date: Tue Jul 26 03:43:21 2011
New Revision: 1150980

URL: http://svn.apache.org/viewvc?rev=1150980&view=rev
Log:
MYFACES-3126 RendererUtils.renderChild prevents rendered="" expression based on "#{component.parent}" (thanks to Martin Koci for provide this patch)

Modified:
    myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java
    myfaces/shared/trunk_4.0.x/core/src/test/java/org/apache/myfaces/shared/renderkit/RendererUtilsTest.java

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java?rev=1150980&r1=1150979&r2=1150980&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java Tue Jul 26 03:43:21 2011
@@ -527,7 +527,14 @@ public final class RendererUtils
     public static void renderChild(FacesContext facesContext, UIComponent child)
             throws IOException
     {
-
+        // The next isRendered() call is only shortcut:
+         // methods encodeBegin, encodeChildren and encodeEnd should proceed only if 
+        // "If our rendered property is true, render the (beginning, child, ending) of this component"
+        if (!isRendered(facesContext, child))
+        {
+            return;
+        }
+        
         child.encodeBegin(facesContext);
         if (child.getRendersChildren())
         {
@@ -540,6 +547,25 @@ public final class RendererUtils
         child.encodeEnd(facesContext);
     }
 
+    /**
+     * Call {@link #pushComponentToEL(javax.faces.context.FacesContext,javax.faces.component.UIComponent)}, 
+     * reads the isRendered property, call {@link
+     * UIComponent#popComponentFromEL} and returns the value of isRendered.
+     */
+    public static boolean isRendered(FacesContext facesContext, UIComponent uiComponent) {
+        // We must call pushComponentToEL here because ValueExpression may have 
+        // implicit object "component" used. 
+        try
+        {
+            uiComponent.pushComponentToEL(facesContext, uiComponent);
+            return uiComponent.isRendered();
+        }
+        finally
+        {       
+            uiComponent.popComponentFromEL(facesContext);
+        }
+    }
+
 
     public static List getSelectItemList(UISelectOne uiSelectOne)
     {

Modified: myfaces/shared/trunk_4.0.x/core/src/test/java/org/apache/myfaces/shared/renderkit/RendererUtilsTest.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/test/java/org/apache/myfaces/shared/renderkit/RendererUtilsTest.java?rev=1150980&r1=1150979&r2=1150980&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/test/java/org/apache/myfaces/shared/renderkit/RendererUtilsTest.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/test/java/org/apache/myfaces/shared/renderkit/RendererUtilsTest.java Tue Jul 26 03:43:21 2011
@@ -1,18 +1,45 @@
+/*
+ *  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.
+ */
 package org.apache.myfaces.shared.renderkit;
 
+import java.io.IOException;
 import java.io.StringWriter;
 
+import javax.el.ELContext;
 import javax.faces.application.Application;
 import javax.faces.application.ProjectStage;
 import javax.faces.application.Resource;
 import javax.faces.application.ResourceHandler;
+import javax.faces.component.UIComponent;
 import javax.faces.component.UIInput;
+import javax.faces.component.UIOutput;
+import javax.faces.component.UIPanel;
 import javax.faces.component.html.HtmlGraphicImage;
+import javax.faces.context.FacesContext;
+
+import junit.framework.Assert;
 
 import org.apache.myfaces.shared.renderkit.html.HTML;
 import org.apache.myfaces.test.base.AbstractJsfTestCase;
 import org.apache.myfaces.test.mock.MockResponseWriter;
 import org.easymock.classextension.EasyMock;
+import org.junit.Test;
 
 /**
  * 
@@ -46,6 +73,8 @@ public class RendererUtilsTest extends A
 	// a Component instance:
 	HtmlGraphicImage graphicImage = new HtmlGraphicImage();
 
+    private UIPanel parent;
+
 	public RendererUtilsTest(String name) {
 		super(name);
 	}
@@ -73,6 +102,8 @@ public class RendererUtilsTest extends A
 		graphicImage.getAttributes().put(JSFAttr.LIBRARY_ATTR, libraryName);
 		graphicImage.getAttributes().put(JSFAttr.NAME_ATTR, resourceName);
 		graphicImage.setId("graphicImageId");
+		
+		parent = new UIPanel();
 	}
 
 	protected void tearDown() throws Exception {
@@ -142,4 +173,102 @@ public class RendererUtilsTest extends A
         assertEquals("If submittedvalue is not String, toString() must be used", submittedValue.toString(), convertedUIOutputValue);
     }
 
+    /**
+     * test for MYFACES-3126
+     */
+    @Test
+    public void testRenderChild() throws IOException
+    {
+        
+       UIInput uiInput = _setUpComponentStack();
+       
+       RendererUtils.renderChild(facesContext, uiInput);
+       
+       assertEquals("Invocation must not change the current component", parent, UIComponent.getCurrentComponent(facesContext));
+    }
+
+    
+    /**
+     * Test that no method encode* are called if component is not rendered 
+     */
+    @Test
+    public void testRenderChild2() throws IOException {
+
+        MockComponent component = new MockComponent();
+        
+        RendererUtils.renderChild(facesContext, component);
+    }
+    
+    @Test
+    public void testIsRendered()
+    {
+        UIComponent uiComponent = new UIOutput();
+        boolean rendered = RendererUtils.isRendered(facesContext, uiComponent);
+        assertTrue(rendered);
+        
+        uiComponent.setRendered(false);
+        rendered = RendererUtils.isRendered(facesContext, uiComponent);
+        assertFalse(rendered);
+        
+        uiComponent = _setUpComponentStack();
+        rendered = RendererUtils.isRendered(facesContext, uiComponent);
+        assertFalse(rendered);
+        assertEquals("isRendered must not change current component", parent, UIComponent.getCurrentComponent(facesContext));
+    }
+    
+    /**
+     * Verifies the current component on stack
+     */
+    private class MockRenderedValueExpression extends org.apache.myfaces.test.el.MockValueExpression {
+
+        private final UIComponent toVerify;
+
+        public MockRenderedValueExpression(String expression, Class<?> expectedType, UIComponent toVerify) {
+            super(expression, expectedType);
+            this.toVerify = toVerify;
+        }
+        
+        @Override
+        public Object getValue(ELContext elContext) {
+          UIComponent currentComponent = UIComponent.getCurrentComponent(facesContext);
+          Assert.assertEquals("If this VE is called, component on stack must be actual" , currentComponent , toVerify);
+          return false;
+        }
+    }
+    
+    /** Verifies no call to encode* methods */
+    private class MockComponent extends UIOutput
+    {
+        @Override
+        public boolean isRendered() {
+            return false;
+        }
+        @Override
+        public void encodeBegin(FacesContext context) throws IOException {
+            fail();
+        }
+        @Override
+        public void encodeChildren(FacesContext context) throws IOException {
+            fail();
+        }
+        @Override
+        public void encodeEnd(FacesContext context) throws IOException {
+            fail();
+        }
+    }
+    
+    private UIInput _setUpComponentStack() {
+        UIInput uiInput = new UIInput();
+        parent.getChildren().add(uiInput);
+        uiInput.setId("testId");
+        
+        
+        MockRenderedValueExpression ve = new MockRenderedValueExpression("#{component.id eq 'testId'}", Boolean.class, uiInput);
+        uiInput.setValueExpression("rendered", ve);
+        
+       // simlulate that parent panel encodes children and is on the stack:
+       parent.pushComponentToEL(facesContext, null);
+        return uiInput;
+    }
+
 }