You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ja...@apache.org on 2010/04/20 15:35:40 UTC

svn commit: r935912 - in /myfaces: core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/ shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/

Author: jakobk
Date: Tue Apr 20 13:35:40 2010
New Revision: 935912

URL: http://svn.apache.org/viewvc?rev=935912&view=rev
Log:
MYFACES-2663 NPE in UIParameter when value resolves to null (major refactoring of every use of UIParameter - introduced HtmlRendererUtils.getValidUIParameterChildren() to retrieve UIParameter children correctly)

Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormatRenderer.java
    myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java
    myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java
    myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java
    myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRenderer.java
    myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormatRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormatRenderer.java?rev=935912&r1=935911&r2=935912&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormatRenderer.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormatRenderer.java Tue Apr 20 13:35:40 2010
@@ -35,6 +35,7 @@ import org.apache.myfaces.buildtools.mav
 import org.apache.myfaces.shared_impl.renderkit.JSFAttr;
 import org.apache.myfaces.shared_impl.renderkit.RendererUtils;
 import org.apache.myfaces.shared_impl.renderkit.html.HtmlRenderer;
+import org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils;
 import org.apache.myfaces.shared_impl.renderkit.html.HtmlTextRendererBase;
 
 /**
@@ -90,18 +91,12 @@ public class HtmlFormatRenderer extends 
         else
         {
             List<Object> argsList = new ArrayList<Object>();
-            for (UIComponent child : htmlOutputFormat.getChildren())
+            
+            List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
+                    facesContext, htmlOutputFormat.getChildren(), false, false, false);
+            for (UIParameter param : validParams)
             {
-                if (child instanceof UIParameter)
-                {
-                    // check for the disable attribute (since 2.0)
-                    if (((UIParameter) child).isDisable())
-                    {
-                        // ignore this UIParameter and continue
-                        continue;
-                    }
-                    argsList.add(((UIParameter)child).getValue());
-                }
+                argsList.add(param.getValue());
             }
             
             args = argsList.toArray(new Object[argsList.size()]);

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java?rev=935912&r1=935911&r2=935912&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java Tue Apr 20 13:35:40 2010
@@ -34,7 +34,6 @@ import javax.faces.context.ExternalConte
 import javax.faces.context.FacesContext;
 import javax.faces.context.ResponseWriter;
 import javax.faces.event.ActionEvent;
-import javax.faces.application.ResourceHandler;
 
 import org.apache.myfaces.shared.config.MyfacesConfig;
 import org.apache.myfaces.shared.renderkit.ClientBehaviorEvents;
@@ -206,28 +205,19 @@ public class HtmlButtonRendererBase
         }
         
         // render the UIParameter children of the commandButton (since 2.0)
-        for (UIComponent child : uiComponent.getChildren())
-        {
-            if (child.getClass().equals(UIParameter.class))
-            {
-                UIParameter parameter = (UIParameter) child;
-                // check for the disable attribute
-                if (parameter.isDisable())
-                {
-                    continue;
-                }
-                HtmlInputHidden parameterComponent = new HtmlInputHidden();
-                parameterComponent.setId(parameter.getName());
-                parameterComponent.setValue(parameter.getValue());
-                parameterComponent.encodeAll(facesContext);
-            }
+        List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
+                facesContext, uiComponent.getChildren(), false, false);
+        for (UIParameter param : validParams)
+        {
+            HtmlInputHidden parameterComponent = new HtmlInputHidden();
+            parameterComponent.setId(param.getName());
+            parameterComponent.setValue(param.getValue());
+            parameterComponent.encodeAll(facesContext);
         }
     }
 
     protected String buildBehaviorizedOnClick(UIComponent uiComponent, Map<String, List<ClientBehavior>> behaviors, 
                                               FacesContext facesContext, ResponseWriter writer, FormInfo nestedFormInfo) {
-        //TODO fetch parameters from the button
-
         //we can omit autoscroll here for now maybe we should check if it is an ajax behavior and omit it only in this case
         StringBuilder userOnClick = new StringBuilder();
         //user onclick part 
@@ -253,8 +243,6 @@ public class HtmlButtonRendererBase
             }
         }
 
-        //TODO make parameter resolution here
-
         //according to the specification in jsf.util.chain jdocs and the spec document we have to use
         //jsf.util.chain to chain the functions and
         return HtmlRendererUtils.buildBehaviorChain(facesContext, uiComponent, behaviors,

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java?rev=935912&r1=935911&r2=935912&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java Tue Apr 20 13:35:40 2010
@@ -21,7 +21,6 @@ package org.apache.myfaces.shared.render
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -487,51 +486,40 @@ public abstract class HtmlLinkRendererBa
         return target;
     }
 
-    private StringBuffer addChildParameters(UIComponent component, UIComponent nestingForm) {
+    private StringBuffer addChildParameters(UIComponent component, UIComponent nestingForm) 
+    {
         //add child parameters
         StringBuffer params = new StringBuffer();
         params.append("[");
-        for (Iterator it = getChildren(component).iterator(); it.hasNext();) {
-
-            UIComponent child = (UIComponent) it.next();
-            if (child instanceof UIParameter) {
-                // check for the disable attribute (since 2.0)
-                if (((UIParameter) child).isDisable())
-                {
-                    // ignore this UIParameter and continue
-                    continue;
-                }
-                
-                String name = ((UIParameter) child).getName();
-
-                if (name == null) {
-                    throw new IllegalArgumentException("Unnamed parameter value not allowed within command link.");
-                }
-
-                //Not necessary, since we are using oamSetHiddenInput to create hidden fields
-                //addHiddenCommandParameter(FacesContext.getCurrentInstance(), nestingForm, name);
+        
+        List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
+                FacesContext.getCurrentInstance(), getChildren(component), false, false);
+        for (UIParameter param : validParams) 
+        {
+            String name = param.getName();
 
-                Object value = ((UIParameter) child).getValue();
+            //Not necessary, since we are using oamSetHiddenInput to create hidden fields
+            //addHiddenCommandParameter(FacesContext.getCurrentInstance(), nestingForm, name);
 
-                //UIParameter is no ValueHolder, so no conversion possible - calling .toString on value....
-                // MYFACES-1832 bad charset encoding for f:param
-                // if HTMLEncoder.encode is called, then
-                // when is called on writer.writeAttribute, encode method
-                // is called again so we have a duplicated encode
-                // call.
-                //String strParamValue = value != null ? org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(value.toString(), false, false) : "";
-                String strParamValue = value != null ? value.toString() : "";
+            Object value = param.getValue();
 
-                if (params.length() > 1) {
-                    params.append(",");
-                }
+            //UIParameter is no ValueHolder, so no conversion possible - calling .toString on value....
+            // MYFACES-1832 bad charset encoding for f:param
+            // if HTMLEncoder.encode is called, then
+            // when is called on writer.writeAttribute, encode method
+            // is called again so we have a duplicated encode call.
+            String strParamValue = value != null ? value.toString() : "";
 
-                params.append("['");
-                params.append(name);
-                params.append("','");
-                params.append(strParamValue);
-                params.append("']");
+            if (params.length() > 1) 
+            {
+                params.append(",");
             }
+
+            params.append("['");
+            params.append(name);
+            params.append("','");
+            params.append(strParamValue);
+            params.append("']");
         }
         params.append("]");
         return params;
@@ -613,22 +601,15 @@ public abstract class HtmlLinkRendererBa
     {
         boolean strictXhtmlLinks
                 = MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isStrictXhtmlLinks();
-        for (Iterator it = getChildren(linkComponent).iterator(); it.hasNext(); )
-        {
-            UIComponent child = (UIComponent)it.next();
-            if (child instanceof UIParameter)
-            {
-                // check for the disable attribute (since 2.0)
-                if (((UIParameter) child).isDisable())
-                {
-                    // ignore this UIParameter and continue
-                    continue;
-                }
-                String name = ((UIParameter)child).getName();
-                Object value = ((UIParameter)child).getValue();
-                addParameterToHref(name, value, hrefBuf, firstParameter, charEncoding, strictXhtmlLinks);
-                firstParameter = false;
-            }
+        
+        List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
+                facesContext, getChildren(linkComponent), false, false);
+        for (UIParameter param : validParams)
+        {
+            String name = param.getName();
+            Object value = param.getValue();
+            addParameterToHref(name, value, hrefBuf, firstParameter, charEncoding, strictXhtmlLinks);
+            firstParameter = false;
         }
     }
 

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java?rev=935912&r1=935911&r2=935912&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java Tue Apr 20 13:35:40 2010
@@ -19,20 +19,11 @@
 package org.apache.myfaces.shared.renderkit.html;
 
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import javax.faces.FacesException;
-import javax.faces.application.ConfigurableNavigationHandler;
-import javax.faces.application.NavigationCase;
-import javax.faces.application.NavigationHandler;
-import javax.faces.application.ViewHandler;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIOutcomeTarget;
-import javax.faces.component.UIParameter;
 import javax.faces.component.behavior.ClientBehavior;
 import javax.faces.component.behavior.ClientBehaviorHolder;
 import javax.faces.component.html.HtmlOutcomeTargetButton;
@@ -40,8 +31,6 @@ import javax.faces.context.ExternalConte
 import javax.faces.context.FacesContext;
 import javax.faces.context.ResponseWriter;
 
-import org.apache.myfaces.shared.config.MyfacesConfig;
-import org.apache.myfaces.shared.renderkit.ClientBehaviorEvents;
 import org.apache.myfaces.shared.renderkit.JSFAttr;
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 import org.apache.myfaces.shared.renderkit.html.util.JavascriptUtils;

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRenderer.java?rev=935912&r1=935911&r2=935912&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRenderer.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRenderer.java Tue Apr 20 13:35:40 2010
@@ -50,7 +50,7 @@ public abstract class HtmlRenderer
      * 
      * @return a list of UIComponent objects.
      */
-    public List getChildren(UIComponent component) 
+    public List<UIComponent> getChildren(UIComponent component) 
     {
         return component.getChildren();
     }

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java?rev=935912&r1=935911&r2=935912&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java Tue Apr 20 13:35:40 2010
@@ -1855,50 +1855,21 @@ public final class HtmlRendererUtils {
         
         // handle URL parameters
         Map<String, List<String>> parameters = new HashMap<String,List<String>>();
-        for (Iterator<UIComponent> it = component.getChildren().iterator(); it.hasNext(); )
-        {
-            UIComponent child = (UIComponent) it.next();
-            if (child instanceof UIParameter)
+        List<UIParameter> validParams = getValidUIParameterChildren(
+                facesContext, component.getChildren(), true, false);
+        for (UIParameter param : validParams)
+        {
+            String name = param.getName();
+            Object value = param.getValue();
+            if (parameters.containsKey(name))
             {
-                UIParameter param = (UIParameter) child;
-                
-                // check for the disable attribute (since 2.0)
-                if (param.isDisable())
-                {
-                    // ignore this UIParameter and continue
-                    continue;
-                }
-                String name = param.getName();
-                if (name == null || STR_EMPTY.equals(name))
-                {
-                    // warn for a null-name
-                    log.log(Level.WARNING, "The UIParameter " + RendererUtils.getPathToComponent(param) +
-                            " has a name of null or empty string and thus will not be added to the URL.");
-                    // and skip it
-                    continue;
-                }
-                Object value = param.getValue();
-                if (value == null)
-                {
-                    if (facesContext.isProjectStage(ProjectStage.Development))
-                    {
-                        // inform the user about the null value when in Development stage
-                        log.log(Level.INFO, "The UIParameter " + RendererUtils.getPathToComponent(param) +
-                                " has a value of null and thus will not be added to the URL.");
-                    }
-                    // skip a null-value
-                    continue;
-                }
-                if (parameters.containsKey(name))
-                {
-                    parameters.get(name).add(value.toString());
-                }
-                else
-                {
-                    List<String> list = new ArrayList<String>(1);
-                    list.add(value.toString());
-                    parameters.put(name, list);
-                }
+                parameters.get(name).add(value.toString());
+            }
+            else
+            {
+                List<String> list = new ArrayList<String>(1);
+                list.add(value.toString());
+                parameters.put(name, list);
             }
         }
         
@@ -2357,28 +2328,109 @@ public final class HtmlRendererUtils {
      * @param uiComponent
      * @return
      */
-    public static Map<String, String> mapAttachedParamsToStringValues(FacesContext facesContext, UIComponent uiComponent) {
+    public static Map<String, String> mapAttachedParamsToStringValues(FacesContext facesContext, UIComponent uiComponent) 
+    {
         Map<String, String> retVal = new HashMap<String, String>();
 
-        //we cannot use invokeContextCallback
+        List<UIParameter> validParams = getValidUIParameterChildren(
+                facesContext, uiComponent.getChildren(), true, true);
+        for (UIParameter param : validParams)
+        {
+            String name = param.getName();
+            Object value = param.getValue();
+            if (value instanceof String) 
+            {
+                value = "'" + ((String) value) + "'";
+            }
+            retVal.put(name, value.toString());
+        }
+        
+        return retVal;
+    }
+    
+    /**
+     * Calls getValidUIParameterChildren(facesContext, children, skipNullValue, skipUnrendered, true);
+     * 
+     * @param facesContext
+     * @param children
+     * @param skipNullValue
+     * @param skipUnrendered
+     * @return
+     */
+    public static List<UIParameter> getValidUIParameterChildren(FacesContext facesContext,
+            List<UIComponent> children, boolean skipNullValue, boolean skipUnrendered)
+    {
+        return getValidUIParameterChildren(facesContext, children, skipNullValue, skipUnrendered, true);
+    }
+    
+    /**
+     * Returns a List of all valid UIParameter children from the given children.
+     * Valid means that the UIParameter is not disabled, its name is not null 
+     * (if skipNullName is true), its value is not null (if skipNullValue is true) 
+     * and it is rendered (if skipUnrendered is true). This method also creates a 
+     * warning for every UIParameter with a null-name (again, if skipNullName is true)
+     * and, if ProjectStage is Development and skipNullValue is true, it informs the 
+     * user about every null-value.
+     * 
+     * @param facesContext
+     * @param children
+     * @param skipNullValue should UIParameters with a null value be skipped
+     * @param skipUnrendered should UIParameters with isRendered() returning false be skipped
+     * @param skipNullName should UIParameters with a null name be skipped 
+     *                     (normally true, but in the case of h:outputFormat false)
+     * @return
+     */
+    public static List<UIParameter> getValidUIParameterChildren(FacesContext facesContext,
+            List<UIComponent> children, boolean skipNullValue, boolean skipUnrendered, boolean skipNullName)
+    {
+        List<UIParameter> params = new ArrayList<UIParameter>();
         
-        for (Iterator<UIComponent> it = uiComponent.getFacetsAndChildren(); it.hasNext();) {
-            UIComponent target = it.next();
-            if (!(target instanceof UIParameter)) continue;
-            UIParameter param = (UIParameter) target;
-            if (param.isRendered() && param.getValue() != null
-                    && !param.isDisable()) 
+        for (UIComponent child : children)
+        {
+            if (child instanceof UIParameter)
             {
+                UIParameter param = (UIParameter) child;
+                
+                // check for the disable attribute (since 2.0)
+                // and the render attribute (only if skipUnrendered is true)
+                if (param.isDisable() ||
+                        (skipUnrendered && !param.isRendered()))
+                {
+                    // ignore this UIParameter and continue
+                    continue;
+                }
+                
+                // check the name
                 String name = param.getName();
-                Object value = param.getValue();
-                if (value instanceof String) {
-                    value = "'" + ((String) value) + "'";
+                if (skipNullName && (name == null || STR_EMPTY.equals(name)))
+                {
+                    // warn for a null-name
+                    log.log(Level.WARNING, "The UIParameter " + RendererUtils.getPathToComponent(param) +
+                            " has a name of null or empty string and thus will not be added to the URL.");
+                    // and skip it
+                    continue;
+                }
+                
+                // check the value
+                if (skipNullValue && param.getValue() == null)
+                {
+                    if (facesContext.isProjectStage(ProjectStage.Development))
+                    {
+                        // inform the user about the null value when in Development stage
+                        log.log(Level.INFO, "The UIParameter " + RendererUtils.getPathToComponent(param) +
+                                " has a value of null and thus will not be added to the URL.");
+                    }
+                    // skip a null-value
+                    continue;
                 }
-                retVal.put(name, value.toString());
+                
+                // add the param
+                params.add(param);
             }
         }
-        return retVal;
-   }
+        
+        return params;
+    }
     
     /**
      * @since 4.0.0