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/11/11 03:42:45 UTC

svn commit: r1200705 - in /myfaces/core/trunk: impl/src/main/java/org/apache/myfaces/el/unified/resolver/CompositeComponentELResolver.java shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java

Author: lu4242
Date: Fri Nov 11 02:42:45 2011
New Revision: 1200705

URL: http://svn.apache.org/viewvc?rev=1200705&view=rev
Log:
MYFACES-2552 TagValueExpression.getType() returns null if the property in the managed bean is null and the expression points to a facelets composite component attribute

Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/CompositeComponentELResolver.java
    myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/CompositeComponentELResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/CompositeComponentELResolver.java?rev=1200705&r1=1200704&r2=1200705&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/CompositeComponentELResolver.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/CompositeComponentELResolver.java Fri Nov 11 02:42:45 2011
@@ -35,6 +35,9 @@ import javax.faces.component.UIComponent
 import javax.faces.context.FacesContext;
 import javax.faces.el.CompositeComponentExpressionHolder;
 
+import org.apache.myfaces.shared.config.MyfacesConfig;
+import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
+
 /**
  * Composite component attribute EL resolver.  See JSF spec, section 5.6.2.2.
  */
@@ -68,7 +71,89 @@ public final class CompositeComponentELR
     @Override
     public Class<?> getType(ELContext context, Object base, Object property)
     {
+        if (base != null && property != null &&
+             base instanceof CompositeComponentAttributesMapWrapper &&
+             property instanceof String)
+        {
+            FacesContext facesContext = facesContext(context);
+            if (facesContext == null)
+            {
+                facesContext = FacesContext.getCurrentInstance();
+            }
+            if (facesContext == null)
+            {
+                return null;
+            }
+            if (!MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isStrictJsf2CCELResolver())
+            {
+                // handle JSF 2.2 spec revisions:
+                // code resembles that found in Mojarra because it originates from
+                // the same contributor, whose ICLA is on file
+                Class<?> exprType = null;
+                Class<?> metaType = null;
+
+                CompositeComponentAttributesMapWrapper evalMap = (CompositeComponentAttributesMapWrapper) base;
+                ValueExpression ve = evalMap.getExpression((String) property);
+                if (ve != null)
+                {
+                    exprType = ve.getType(context);
+                }
+
+                if (!"".equals(property))
+                {
+                    if (evalMap._propertyDescriptors != null)
+                    {
+                        for (PropertyDescriptor pd : evalMap._propertyDescriptors)
+                        {
+                            if (property.equals(pd.getName()))
+                            {
+                                metaType = resolveType(context, pd);
+                                break;
+                            }
+                        }
+                    }
+                }
+                if (metaType != null)
+                {
+                    // override exprType only if metaType is narrower:
+                    if (exprType == null || exprType.isAssignableFrom(metaType))
+                    {
+                        context.setPropertyResolved(true);
+                        return metaType;
+                    }
+                }
+                return exprType;
+            }
+        }
+
         // Per the spec, return null.
+        return null;
+    }
+
+    // adapted from CompositeMetadataTargetImpl#getPropertyType():
+    private static Class<?> resolveType(ELContext context, PropertyDescriptor pd)
+    {
+        if (pd != null)
+        {
+            Object type = pd.getValue("type");
+            if (type != null)
+            {
+                type = ((ValueExpression)type).getValue(context);
+                if (type instanceof String)
+                {
+                    try
+                    {
+                        type = FaceletViewDeclarationLanguage._javaTypeToClass((String)type);
+                    }
+                    catch (ClassNotFoundException e)
+                    {
+                        type = null;
+                    }
+                }
+                return (Class<?>) type;
+            }
+            return pd.getPropertyType();
+        }
 
         return null;
     }

Modified: myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java?rev=1200705&r1=1200704&r2=1200705&view=diff
==============================================================================
--- myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java (original)
+++ myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java Fri Nov 11 02:42:45 2011
@@ -321,13 +321,25 @@ public class MyfacesConfig
      * 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. 
+     * using ui:include will be consistent. Note this behavior is a myfaces specific extension, so to ensure strict compatibility with the spec, 
+     * set this param to false (default false).
      */
     @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;
     
+    /**
+     * Change default getType() behavior for composite component EL resolver, from return null (see JSF 2_0 spec section 5_6_2_2) to
+     * use the metadata information added by composite:attribute, ensuring components working with chained EL expressions to find the
+     * right type when a getType() is called over the source EL expression.
+     * 
+     * To ensure strict compatibility with the spec set this param to true (by default is false, so the change is enabled by default). 
+     */
+    @JSFWebConfigParam(since="2.0.10", expectedValues="true, false", defaultValue="false", group="EL")
+    public final static String INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER = "org.apache.myfaces.STRICT_JSF_2_CC_EL_RESOLVER";
+    public final static boolean INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER_DEFAULT = false;
+    
     private boolean _prettyHtml;
     private boolean _detectJavascript;
     private boolean _allowJavascript;
@@ -352,6 +364,7 @@ public class MyfacesConfig
     private boolean _renderFormSubmitScriptInline;
     private boolean _debugPhaseListenerEnabled;
     private boolean _strictJsf2RefreshTargetAjax;
+    private boolean _strictJsf2CCELResolver;
 
     private static final boolean TOMAHAWK_AVAILABLE;
     private static final boolean MYFACES_IMPL_AVAILABLE;
@@ -445,6 +458,7 @@ public class MyfacesConfig
         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);
+        setStrictJsf2CCELResolver(INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER_DEFAULT);
     }
 
     private static MyfacesConfig createAndInitializeMyFacesConfig(ExternalContext extCtx)
@@ -530,6 +544,9 @@ public class MyfacesConfig
         
         myfacesConfig.setStrictJsf2RefreshTargetAjax(WebConfigParamUtils.getBooleanInitParameter(extCtx, 
                 INIT_PARAM_STRICT_JSF_2_REFRESH_TARGET_AJAX, INIT_PARAM_STRICT_JSF_2_REFRESH_TARGET_AJAX_DEFAULT));
+        
+        myfacesConfig.setStrictJsf2CCELResolver(WebConfigParamUtils.getBooleanInitParameter(extCtx, 
+                INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER, INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER_DEFAULT));
 
         if (TOMAHAWK_AVAILABLE)
         {
@@ -976,4 +993,14 @@ public class MyfacesConfig
     {
         this._strictJsf2RefreshTargetAjax = strictJsf2RefreshTargetAjax;
     }
+
+    public boolean isStrictJsf2CCELResolver()
+    {
+        return _strictJsf2CCELResolver;
+    }
+
+    public void setStrictJsf2CCELResolver(boolean strictJsf2CCELResolver)
+    {
+        this._strictJsf2CCELResolver = strictJsf2CCELResolver;
+    }
 }