You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2022/12/07 13:51:43 UTC
[myfaces] branch 2.3-next updated: MYFACES-4523
This is an automated email from the ASF dual-hosted git repository.
tandraschko pushed a commit to branch 2.3-next
in repository https://gitbox.apache.org/repos/asf/myfaces.git
The following commit(s) were added to refs/heads/2.3-next by this push:
new f58a71758 MYFACES-4523
f58a71758 is described below
commit f58a71758cab0d1b879e57dde36ac35441cda123
Author: tandraschko <ta...@apache.org>
AuthorDate: Wed Dec 7 14:51:37 2022 +0100
MYFACES-4523
---
.../faces/component/_ComponentAttributesMap.java | 16 +-
.../api/shared/lang/PropertyDescriptorUtils.java | 693 +++++++++++----------
.../api/shared/lang/PropertyDescriptorWrapper.java | 166 +++--
.../myfaces/application/ApplicationImpl.java | 20 +-
.../myfaces/el/resolver/LambdaBeanELResolver.java | 347 ++++++-----
.../myfaces/view/facelets/component/UIRepeat.java | 59 +-
.../view/facelets/tag/BeanPropertyTagRule.java | 22 +-
.../facelets/tag/LambdaMetadataTargetImpl.java | 276 ++++----
8 files changed, 795 insertions(+), 804 deletions(-)
diff --git a/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java b/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java
index 50a35f375..49173e0d9 100755
--- a/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java
+++ b/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java
@@ -26,6 +26,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
import javax.el.ValueExpression;
import javax.faces.FacesException;
@@ -648,7 +650,11 @@ class _ComponentAttributesMap implements Map<String, Object>, Serializable
{
if (propertyDescriptor instanceof LambdaPropertyDescriptor)
{
- return ((LambdaPropertyDescriptor) propertyDescriptor).getReadFunction().apply(_component);
+ Function<Object, Object> readFunction = ((LambdaPropertyDescriptor) propertyDescriptor).getReadFunction();
+ if (readFunction != null)
+ {
+ return readFunction.apply(_component);
+ }
}
return readMethod.invoke(_component, EMPTY_ARGS);
@@ -681,9 +687,15 @@ class _ComponentAttributesMap implements Map<String, Object>, Serializable
try
{
+ BiConsumer<Object, Object> writeFunction = null;
if (propertyDescriptor instanceof LambdaPropertyDescriptor)
{
- ((LambdaPropertyDescriptor) propertyDescriptor).getWriteFunction().accept(_component, value);
+ writeFunction = ((LambdaPropertyDescriptor) propertyDescriptor).getWriteFunction();
+ }
+
+ if (writeFunction != null)
+ {
+ writeFunction.accept(_component, value);
}
else
{
diff --git a/api/src/main/java/org/apache/myfaces/core/api/shared/lang/PropertyDescriptorUtils.java b/api/src/main/java/org/apache/myfaces/core/api/shared/lang/PropertyDescriptorUtils.java
index 0b29ac34b..a38b0e566 100644
--- a/api/src/main/java/org/apache/myfaces/core/api/shared/lang/PropertyDescriptorUtils.java
+++ b/api/src/main/java/org/apache/myfaces/core/api/shared/lang/PropertyDescriptorUtils.java
@@ -1,343 +1,350 @@
-/*
- * 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.core.api.shared.lang;
-
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.invoke.CallSite;
-import java.lang.invoke.LambdaConversionException;
-import java.lang.invoke.LambdaMetafactory;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
-import java.util.function.ObjDoubleConsumer;
-import java.util.function.ObjIntConsumer;
-import java.util.function.ObjLongConsumer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.faces.FacesException;
-import javax.faces.context.ExternalContext;
-import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
-
-public class PropertyDescriptorUtils
-{
- private static final Logger LOG = Logger.getLogger(PropertyDescriptorUtils.class.getName());
-
- /**
- * Defines if Lambda expressions (via LambdaMetafactory) are used for getter/setter instead of Reflection.
- */
- @JSFWebConfigParam(since="2.3-next", defaultValue="true", expectedValues="true,false", tags="performance")
- public static final String USE_LAMBDA_METAFACTORY = "org.apache.myfaces.USE_LAMBDA_METAFACTORY";
-
- private static final String CACHE_KEY = PropertyDescriptorUtils.class.getName() + ".CACHE";
-
- private static Method privateLookupIn;
-
- static
- {
- try
- {
- privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class,
- MethodHandles.Lookup.class);
- }
- catch (Exception e)
- {
- }
- }
-
- private static Map<String, Map<String, ? extends PropertyDescriptorWrapper>> getCache(ExternalContext ec)
- {
- Map<String, Map<String, ? extends PropertyDescriptorWrapper>> cache =
- (Map<String, Map<String, ? extends PropertyDescriptorWrapper>>) ec.getApplicationMap().get(CACHE_KEY);
- if (cache == null)
- {
- cache = new ConcurrentHashMap<>(1000);
- ec.getApplicationMap().put(CACHE_KEY, cache);
- }
-
- return cache;
- }
-
- public static Map<String, ? extends PropertyDescriptorWrapper> getCachedPropertyDescriptors(ExternalContext ec,
- Class<?> target)
- {
- Map<String, ? extends PropertyDescriptorWrapper> cache = getCache(ec).get(target.getName());
- if (cache == null)
- {
- cache = getCache(ec).computeIfAbsent(target.getName(), k -> getPropertyDescriptors(ec, target));
- }
-
- return cache;
- }
-
- public static boolean isUseLambdaMetafactory(ExternalContext ec)
- {
- if (privateLookupIn == null)
- {
- return false;
- }
-
- // activated per default
- String useMethodHandles = ec.getInitParameter(USE_LAMBDA_METAFACTORY);
- return useMethodHandles == null || useMethodHandles.trim().isEmpty() || useMethodHandles.contains("true");
- }
-
- public static Map<String, ? extends PropertyDescriptorWrapper> getPropertyDescriptors(ExternalContext ec,
- Class<?> target)
- {
- if (isUseLambdaMetafactory(ec))
- {
- try
- {
- return getLambdaPropertyDescriptors(target);
- }
- catch (IllegalAccessException e)
- {
- LOG.log(Level.FINEST,
- "Could not generate LambdaPropertyDescriptor for "
- + target.getName() + ". Use PropertyDescriptor...");
- }
- catch (Throwable e)
- {
- LOG.log(Level.INFO,
- "Could not generate LambdaPropertyDescriptor for "
- + target.getName() + ". Use PropertyDescriptor...",
- e);
- }
- }
-
- try
- {
- PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(target).getPropertyDescriptors();
-
- Map<String, PropertyDescriptorWrapper> map = new ConcurrentHashMap<>(propertyDescriptors.length);
-
- for (int i = 0; i < propertyDescriptors.length; i++)
- {
- PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
- Method readMethod = propertyDescriptor.getReadMethod();
-
- map.put(propertyDescriptor.getName(),
- new PropertyDescriptorWrapper(target, propertyDescriptor, readMethod));
- }
-
- return map;
- }
- catch (IntrospectionException e)
- {
- throw new FacesException(e);
- }
- }
-
- public static LambdaPropertyDescriptor getLambdaPropertyDescriptor(Class<?> target, String name)
- {
- try
- {
- PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(target).getPropertyDescriptors();
- if (propertyDescriptors == null || propertyDescriptors.length == 0)
- {
- return null;
- }
-
- for (PropertyDescriptor pd : propertyDescriptors)
- {
- if (name.equals(pd.getName()))
- {
- MethodHandles.Lookup lookup = (MethodHandles.Lookup) privateLookupIn.invoke(null, target,
- MethodHandles.lookup());
- return createLambdaPropertyDescriptor(target, pd, lookup);
- }
- }
-
- throw new FacesException("Property \"" + name + "\" not found on \"" + target.getName() + "\"");
- }
- catch (Throwable e)
- {
- throw new FacesException(e);
- }
- }
-
-
- public static LambdaPropertyDescriptor createLambdaPropertyDescriptor(Class<?> target, PropertyDescriptor pd,
- MethodHandles.Lookup lookup) throws Throwable
- {
- LambdaPropertyDescriptor lpd = new LambdaPropertyDescriptor(target, pd);
-
- Method readMethod = pd.getReadMethod();
- if (readMethod != null)
- {
- MethodHandle handle = lookup.unreflect(readMethod);
- CallSite callSite = LambdaMetafactory.metafactory(lookup,
- "apply",
- MethodType.methodType(Function.class),
- MethodType.methodType(Object.class, Object.class),
- handle,
- handle.type());
- lpd.readFunction = (Function) callSite.getTarget().invokeExact();
- }
-
- Method writeMethod = pd.getWriteMethod();
- if (writeMethod != null)
- {
- MethodHandle handle = lookup.unreflect(writeMethod);
- lpd.writeFunction = createSetter(lookup, lpd, handle);
- }
-
- return lpd;
- }
-
- public static Map<String, LambdaPropertyDescriptor> getLambdaPropertyDescriptors(Class<?> target) throws Throwable
- {
- PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(target).getPropertyDescriptors();
- if (propertyDescriptors == null || propertyDescriptors.length == 0)
- {
- return Collections.emptyMap();
- }
-
- Map<String, LambdaPropertyDescriptor> properties = new ConcurrentHashMap<>(propertyDescriptors.length);
-
- MethodHandles.Lookup lookup = (MethodHandles.Lookup)
- privateLookupIn.invoke(null, target, MethodHandles.lookup());
- for (PropertyDescriptor pd : Introspector.getBeanInfo(target).getPropertyDescriptors())
- {
- LambdaPropertyDescriptor lpd = createLambdaPropertyDescriptor(target, pd, lookup);
- properties.put(pd.getName(), lpd);
- }
-
- return properties;
- }
-
- @SuppressWarnings("unchecked")
- protected static BiConsumer createSetter(MethodHandles.Lookup lookup, LambdaPropertyDescriptor propertyInfo,
- MethodHandle setterHandle)
- throws LambdaConversionException, Throwable
- {
- Class<?> propertyType = propertyInfo.getPropertyType();
- // special handling for primitives required, see https://dzone.com/articles/setters-method-handles-and-java-11
- if (propertyType.isPrimitive())
- {
- if (propertyType == double.class)
- {
- ObjDoubleConsumer consumer = (ObjDoubleConsumer) createSetterCallSite(
- lookup, setterHandle, ObjDoubleConsumer.class, double.class).getTarget().invokeExact();
- return (a, b) -> consumer.accept(a, (double) b);
- }
- else if (propertyType == int.class)
- {
- ObjIntConsumer consumer = (ObjIntConsumer) createSetterCallSite(
- lookup, setterHandle, ObjIntConsumer.class, int.class).getTarget().invokeExact();
- return (a, b) -> consumer.accept(a, (int) b);
- }
- else if (propertyType == long.class)
- {
- ObjLongConsumer consumer = (ObjLongConsumer) createSetterCallSite(
- lookup, setterHandle, ObjLongConsumer.class, long.class).getTarget().invokeExact();
- return (a, b) -> consumer.accept(a, (long) b);
- }
- else if (propertyType == float.class)
- {
- ObjFloatConsumer consumer = (ObjFloatConsumer) createSetterCallSite(
- lookup, setterHandle, ObjFloatConsumer.class, float.class).getTarget().invokeExact();
- return (a, b) -> consumer.accept(a, (float) b);
- }
- else if (propertyType == byte.class)
- {
- ObjByteConsumer consumer = (ObjByteConsumer) createSetterCallSite(
- lookup, setterHandle, ObjByteConsumer.class, byte.class).getTarget().invokeExact();
- return (a, b) -> consumer.accept(a, (byte) b);
- }
- else if (propertyType == char.class)
- {
- ObjCharConsumer consumer = (ObjCharConsumer) createSetterCallSite(
- lookup, setterHandle, ObjCharConsumer.class, char.class).getTarget().invokeExact();
- return (a, b) -> consumer.accept(a, (char) b);
- }
- else if (propertyType == short.class)
- {
- ObjShortConsumer consumer = (ObjShortConsumer) createSetterCallSite(
- lookup, setterHandle, ObjShortConsumer.class, short.class).getTarget().invokeExact();
- return (a, b) -> consumer.accept(a, (short) b);
- }
- else if (propertyType == boolean.class)
- {
- ObjBooleanConsumer consumer = (ObjBooleanConsumer) createSetterCallSite(
- lookup, setterHandle, ObjBooleanConsumer.class, boolean.class).getTarget().invokeExact();
- return (a, b) -> consumer.accept(a, (boolean) b);
- }
- else
- {
- throw new RuntimeException("Type is not supported yet: " + propertyType.getName());
- }
- }
- else
- {
- return (BiConsumer) createSetterCallSite(lookup, setterHandle, BiConsumer.class, Object.class).getTarget()
- .invokeExact();
- }
- }
-
- protected static CallSite createSetterCallSite(MethodHandles.Lookup lookup, MethodHandle setter,
- Class<?> interfaceType, Class<?> valueType)
- throws LambdaConversionException
- {
- return LambdaMetafactory.metafactory(lookup,
- "accept",
- MethodType.methodType(interfaceType),
- MethodType.methodType(void.class, Object.class, valueType),
- setter,
- setter.type());
- }
-
- @FunctionalInterface
- public interface ObjFloatConsumer<T extends Object>
- {
- public void accept(T t, float i);
- }
-
- @FunctionalInterface
- public interface ObjByteConsumer<T extends Object>
- {
- public void accept(T t, byte i);
- }
-
- @FunctionalInterface
- public interface ObjCharConsumer<T extends Object>
- {
- public void accept(T t, char i);
- }
-
- @FunctionalInterface
- public interface ObjShortConsumer<T extends Object>
- {
- public void accept(T t, short i);
- }
-
- @FunctionalInterface
- public interface ObjBooleanConsumer<T extends Object>
- {
- public void accept(T t, boolean i);
- }
-}
+/*
+ * 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.core.api.shared.lang;
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.function.ObjDoubleConsumer;
+import java.util.function.ObjIntConsumer;
+import java.util.function.ObjLongConsumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+
+public class PropertyDescriptorUtils
+{
+ private static final Logger LOG = Logger.getLogger(PropertyDescriptorUtils.class.getName());
+
+ /**
+ * Defines if Lambda expressions (via LambdaMetafactory) are used for getter/setter instead of Reflection.
+ */
+ @JSFWebConfigParam(since="2.3-next", defaultValue="true", expectedValues="true,false", tags="performance")
+ public static final String USE_LAMBDA_METAFACTORY = "org.apache.myfaces.USE_LAMBDA_METAFACTORY";
+
+ private static final String CACHE_KEY = PropertyDescriptorUtils.class.getName() + ".CACHE";
+
+ private static Method privateLookupIn;
+
+ static
+ {
+ try
+ {
+ privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class,
+ MethodHandles.Lookup.class);
+ }
+ catch (Exception e)
+ {
+ }
+ }
+
+ private static Map<String, Map<String, ? extends PropertyDescriptorWrapper>> getCache(ExternalContext ec)
+ {
+ Map<String, Map<String, ? extends PropertyDescriptorWrapper>> cache =
+ (Map<String, Map<String, ? extends PropertyDescriptorWrapper>>) ec.getApplicationMap().get(CACHE_KEY);
+ if (cache == null)
+ {
+ cache = new ConcurrentHashMap<>(1000);
+ ec.getApplicationMap().put(CACHE_KEY, cache);
+ }
+
+ return cache;
+ }
+
+ public static Map<String, ? extends PropertyDescriptorWrapper> getCachedPropertyDescriptors(ExternalContext ec,
+ Class<?> target)
+ {
+ Map<String, ? extends PropertyDescriptorWrapper> cache = getCache(ec).get(target.getName());
+ if (cache == null)
+ {
+ cache = getCache(ec).computeIfAbsent(target.getName(), k -> getPropertyDescriptors(ec, target));
+ }
+
+ return cache;
+ }
+
+ public static boolean isUseLambdaMetafactory(ExternalContext ec)
+ {
+ if (privateLookupIn == null)
+ {
+ return false;
+ }
+
+ // activated per default
+ String useMethodHandles = ec.getInitParameter(USE_LAMBDA_METAFACTORY);
+ return useMethodHandles == null || useMethodHandles.trim().isEmpty() || useMethodHandles.contains("true");
+ }
+
+ public static Map<String, ? extends PropertyDescriptorWrapper> getPropertyDescriptors(ExternalContext ec,
+ Class<?> target)
+ {
+ if (isUseLambdaMetafactory(ec))
+ {
+ try
+ {
+ return getLambdaPropertyDescriptors(target);
+ }
+ catch (IllegalAccessException e)
+ {
+ LOG.log(Level.FINEST,
+ "Could not generate LambdaPropertyDescriptor for "
+ + target.getName() + ". Use PropertyDescriptor...");
+ }
+ catch (Throwable e)
+ {
+ LOG.log(Level.INFO,
+ "Could not generate LambdaPropertyDescriptor for "
+ + target.getName() + ". Use PropertyDescriptor...",
+ e);
+ }
+ }
+
+ try
+ {
+ PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(target).getPropertyDescriptors();
+
+ Map<String, PropertyDescriptorWrapper> map = new ConcurrentHashMap<>(propertyDescriptors.length);
+
+ for (int i = 0; i < propertyDescriptors.length; i++)
+ {
+ PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
+ map.put(propertyDescriptor.getName(),
+ new PropertyDescriptorWrapper(target, propertyDescriptor));
+ }
+
+ return map;
+ }
+ catch (IntrospectionException e)
+ {
+ throw new FacesException(e);
+ }
+ }
+
+ public static LambdaPropertyDescriptor getLambdaPropertyDescriptor(Class<?> target, String name)
+ {
+ try
+ {
+ PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(target).getPropertyDescriptors();
+ if (propertyDescriptors == null || propertyDescriptors.length == 0)
+ {
+ return null;
+ }
+
+ for (PropertyDescriptor pd : propertyDescriptors)
+ {
+ if (name.equals(pd.getName()))
+ {
+ MethodHandles.Lookup lookup = (MethodHandles.Lookup) privateLookupIn.invoke(null, target,
+ MethodHandles.lookup());
+ return createLambdaPropertyDescriptor(target, pd, lookup);
+ }
+ }
+
+ throw new FacesException("Property \"" + name + "\" not found on \"" + target.getName() + "\"");
+ }
+ catch (Throwable e)
+ {
+ throw new FacesException(e);
+ }
+ }
+
+
+ public static LambdaPropertyDescriptor createLambdaPropertyDescriptor(Class<?> target, PropertyDescriptor pd,
+ MethodHandles.Lookup lookup) throws Throwable
+ {
+ if (pd.getPropertyType() == null)
+ {
+ return null;
+ }
+
+ LambdaPropertyDescriptor lpd = new LambdaPropertyDescriptor(target, pd);
+
+ Method readMethod = pd.getReadMethod();
+ if (readMethod != null)
+ {
+ MethodHandle handle = lookup.unreflect(readMethod);
+ CallSite callSite = LambdaMetafactory.metafactory(lookup,
+ "apply",
+ MethodType.methodType(Function.class),
+ MethodType.methodType(Object.class, Object.class),
+ handle,
+ handle.type());
+ lpd.readFunction = (Function) callSite.getTarget().invokeExact();
+ }
+
+ Method writeMethod = pd.getWriteMethod();
+ if (writeMethod != null)
+ {
+ MethodHandle handle = lookup.unreflect(writeMethod);
+ lpd.writeFunction = createSetter(lookup, lpd, handle);
+ }
+
+ return lpd;
+ }
+
+ public static Map<String, PropertyDescriptorWrapper> getLambdaPropertyDescriptors(Class<?> target) throws Throwable
+ {
+ PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(target).getPropertyDescriptors();
+ if (propertyDescriptors == null || propertyDescriptors.length == 0)
+ {
+ return Collections.emptyMap();
+ }
+
+ Map<String, PropertyDescriptorWrapper> properties = new ConcurrentHashMap<>(propertyDescriptors.length);
+
+ MethodHandles.Lookup lookup = (MethodHandles.Lookup)
+ privateLookupIn.invoke(null, target, MethodHandles.lookup());
+ for (PropertyDescriptor pd : Introspector.getBeanInfo(target).getPropertyDescriptors())
+ {
+ PropertyDescriptorWrapper wrapped = createLambdaPropertyDescriptor(target, pd, lookup);
+ if (wrapped == null)
+ {
+ wrapped = new PropertyDescriptorWrapper(target, pd);
+ }
+ properties.put(pd.getName(), wrapped);
+ }
+
+ return properties;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected static BiConsumer createSetter(MethodHandles.Lookup lookup, LambdaPropertyDescriptor propertyInfo,
+ MethodHandle setterHandle)
+ throws LambdaConversionException, Throwable
+ {
+ Class<?> propertyType = propertyInfo.getPropertyType();
+ // special handling for primitives required, see https://dzone.com/articles/setters-method-handles-and-java-11
+ if (propertyType.isPrimitive())
+ {
+ if (propertyType == double.class)
+ {
+ ObjDoubleConsumer consumer = (ObjDoubleConsumer) createSetterCallSite(
+ lookup, setterHandle, ObjDoubleConsumer.class, double.class).getTarget().invokeExact();
+ return (a, b) -> consumer.accept(a, (double) b);
+ }
+ else if (propertyType == int.class)
+ {
+ ObjIntConsumer consumer = (ObjIntConsumer) createSetterCallSite(
+ lookup, setterHandle, ObjIntConsumer.class, int.class).getTarget().invokeExact();
+ return (a, b) -> consumer.accept(a, (int) b);
+ }
+ else if (propertyType == long.class)
+ {
+ ObjLongConsumer consumer = (ObjLongConsumer) createSetterCallSite(
+ lookup, setterHandle, ObjLongConsumer.class, long.class).getTarget().invokeExact();
+ return (a, b) -> consumer.accept(a, (long) b);
+ }
+ else if (propertyType == float.class)
+ {
+ ObjFloatConsumer consumer = (ObjFloatConsumer) createSetterCallSite(
+ lookup, setterHandle, ObjFloatConsumer.class, float.class).getTarget().invokeExact();
+ return (a, b) -> consumer.accept(a, (float) b);
+ }
+ else if (propertyType == byte.class)
+ {
+ ObjByteConsumer consumer = (ObjByteConsumer) createSetterCallSite(
+ lookup, setterHandle, ObjByteConsumer.class, byte.class).getTarget().invokeExact();
+ return (a, b) -> consumer.accept(a, (byte) b);
+ }
+ else if (propertyType == char.class)
+ {
+ ObjCharConsumer consumer = (ObjCharConsumer) createSetterCallSite(
+ lookup, setterHandle, ObjCharConsumer.class, char.class).getTarget().invokeExact();
+ return (a, b) -> consumer.accept(a, (char) b);
+ }
+ else if (propertyType == short.class)
+ {
+ ObjShortConsumer consumer = (ObjShortConsumer) createSetterCallSite(
+ lookup, setterHandle, ObjShortConsumer.class, short.class).getTarget().invokeExact();
+ return (a, b) -> consumer.accept(a, (short) b);
+ }
+ else if (propertyType == boolean.class)
+ {
+ ObjBooleanConsumer consumer = (ObjBooleanConsumer) createSetterCallSite(
+ lookup, setterHandle, ObjBooleanConsumer.class, boolean.class).getTarget().invokeExact();
+ return (a, b) -> consumer.accept(a, (boolean) b);
+ }
+ else
+ {
+ throw new RuntimeException("Type is not supported yet: " + propertyType.getName());
+ }
+ }
+ else
+ {
+ return (BiConsumer) createSetterCallSite(lookup, setterHandle, BiConsumer.class, Object.class).getTarget()
+ .invokeExact();
+ }
+ }
+
+ protected static CallSite createSetterCallSite(MethodHandles.Lookup lookup, MethodHandle setter,
+ Class<?> interfaceType, Class<?> valueType)
+ throws LambdaConversionException
+ {
+ return LambdaMetafactory.metafactory(lookup,
+ "accept",
+ MethodType.methodType(interfaceType),
+ MethodType.methodType(void.class, Object.class, valueType),
+ setter,
+ setter.type());
+ }
+
+ @FunctionalInterface
+ public interface ObjFloatConsumer<T extends Object>
+ {
+ public void accept(T t, float i);
+ }
+
+ @FunctionalInterface
+ public interface ObjByteConsumer<T extends Object>
+ {
+ public void accept(T t, byte i);
+ }
+
+ @FunctionalInterface
+ public interface ObjCharConsumer<T extends Object>
+ {
+ public void accept(T t, char i);
+ }
+
+ @FunctionalInterface
+ public interface ObjShortConsumer<T extends Object>
+ {
+ public void accept(T t, short i);
+ }
+
+ @FunctionalInterface
+ public interface ObjBooleanConsumer<T extends Object>
+ {
+ public void accept(T t, boolean i);
+ }
+}
diff --git a/api/src/main/java/org/apache/myfaces/core/api/shared/lang/PropertyDescriptorWrapper.java b/api/src/main/java/org/apache/myfaces/core/api/shared/lang/PropertyDescriptorWrapper.java
index 27c927141..35fe312c3 100644
--- a/api/src/main/java/org/apache/myfaces/core/api/shared/lang/PropertyDescriptorWrapper.java
+++ b/api/src/main/java/org/apache/myfaces/core/api/shared/lang/PropertyDescriptorWrapper.java
@@ -1,86 +1,80 @@
-/*
- * 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.core.api.shared.lang;
-
-import java.beans.PropertyDescriptor;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.lang.reflect.Method;
-import javax.faces.FacesWrapper;
-
-public class PropertyDescriptorWrapper implements FacesWrapper<PropertyDescriptor>
-{
- private final PropertyDescriptor wrapped;
- private Reference<Method> readMethodRef;
- private Reference<Method> writeMethodRef;
-
- public PropertyDescriptorWrapper(Class<?> beanClass, PropertyDescriptor wrapped)
- {
- this.wrapped = wrapped;
- this.readMethodRef = new SoftReference<>(wrapped.getReadMethod());
- }
-
- public PropertyDescriptorWrapper(Class<?> beanClass, PropertyDescriptor wrapped, Method readMethod)
- {
- this.wrapped = wrapped;
- this.readMethodRef = new SoftReference<>(readMethod);
- }
-
- public Class<?> getPropertyType()
- {
- return wrapped.getPropertyType();
- }
-
- public String getName()
- {
- return wrapped.getName();
- }
-
- @Override
- public PropertyDescriptor getWrapped()
- {
- return wrapped;
- }
-
- public Method getReadMethod()
- {
- Method readMethod = readMethodRef.get();
- if (readMethod == null)
- {
- readMethod = wrapped.getReadMethod();
- readMethodRef = new SoftReference<>(readMethod);
- }
- return readMethod;
- }
-
- public Method getWriteMethod()
- {
- if (writeMethodRef == null || writeMethodRef.get() == null)
- {
- // In facelets, the Method instance used to write the variable is stored
- // in a variable (see org.apache.myfaces.view.facelets.tag.BeanPropertyTagRule),
- // so the impact of this synchronized call at the end is minimal compared with
- // getReadMethod. That's the reason why cache it here in a lazy way is enough
- // instead retrieve it as soon as this holder is created.
- Method writeMethod = wrapped.getWriteMethod();
- writeMethodRef = new SoftReference<>(writeMethod);
- }
- return writeMethodRef.get();
- }
-}
+/*
+ * 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.core.api.shared.lang;
+
+import java.beans.PropertyDescriptor;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Method;
+import javax.faces.FacesWrapper;
+
+public class PropertyDescriptorWrapper implements FacesWrapper<PropertyDescriptor>
+{
+ private final PropertyDescriptor wrapped;
+ private Reference<Method> readMethodRef;
+ private Reference<Method> writeMethodRef;
+
+ public PropertyDescriptorWrapper(Class<?> beanClass, PropertyDescriptor wrapped)
+ {
+ this.wrapped = wrapped;
+ this.readMethodRef = new SoftReference<>(wrapped.getReadMethod());
+ }
+
+ public Class<?> getPropertyType()
+ {
+ return wrapped.getPropertyType();
+ }
+
+ public String getName()
+ {
+ return wrapped.getName();
+ }
+
+ @Override
+ public PropertyDescriptor getWrapped()
+ {
+ return wrapped;
+ }
+
+ public Method getReadMethod()
+ {
+ Method readMethod = readMethodRef.get();
+ if (readMethod == null)
+ {
+ readMethod = wrapped.getReadMethod();
+ readMethodRef = new SoftReference<>(readMethod);
+ }
+ return readMethod;
+ }
+
+ public Method getWriteMethod()
+ {
+ if (writeMethodRef == null || writeMethodRef.get() == null)
+ {
+ // In facelets, the Method instance used to write the variable is stored
+ // in a variable (see org.apache.myfaces.view.facelets.tag.BeanPropertyTagRule),
+ // so the impact of this synchronized call at the end is minimal compared with
+ // getReadMethod. That's the reason why cache it here in a lazy way is enough
+ // instead retrieve it as soon as this holder is created.
+ Method writeMethod = wrapped.getWriteMethod();
+ writeMethodRef = new SoftReference<>(writeMethod);
+ }
+ return writeMethodRef.get();
+ }
+}
diff --git a/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java b/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
index f82301262..a3cbfbbda 100755
--- a/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
@@ -34,6 +34,8 @@ import java.util.MissingResourceException;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -1590,9 +1592,16 @@ public class ApplicationImpl extends Application
if (!pd.getPropertyType().isPrimitive())
{
Object defaultValue;
+
+ Function<Object, Object> readFunction = null;
if (pd instanceof LambdaPropertyDescriptor)
{
- defaultValue = ((LambdaPropertyDescriptor) pd).getReadFunction().apply(converter);
+ readFunction = ((LambdaPropertyDescriptor) pd).getReadFunction();
+ }
+
+ if (readFunction != null)
+ {
+ defaultValue = readFunction.apply(converter);
}
else
{
@@ -1606,9 +1615,16 @@ public class ApplicationImpl extends Application
}
Object convertedValue = ClassUtils.convertToType(property.getDefaultValue(), pd.getPropertyType());
+
+ BiConsumer<Object, Object> writeFunction = null;
if (pd instanceof LambdaPropertyDescriptor)
{
- ((LambdaPropertyDescriptor) pd).getWriteFunction().accept(converter, convertedValue);
+ writeFunction = ((LambdaPropertyDescriptor) pd).getWriteFunction();
+ }
+
+ if (writeFunction != null)
+ {
+ writeFunction.accept(converter, convertedValue);
}
else
{
diff --git a/impl/src/main/java/org/apache/myfaces/el/resolver/LambdaBeanELResolver.java b/impl/src/main/java/org/apache/myfaces/el/resolver/LambdaBeanELResolver.java
index cb8cb0d16..00518dda0 100644
--- a/impl/src/main/java/org/apache/myfaces/el/resolver/LambdaBeanELResolver.java
+++ b/impl/src/main/java/org/apache/myfaces/el/resolver/LambdaBeanELResolver.java
@@ -1,166 +1,181 @@
-/*
- * 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.el.resolver;
-
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.el.BeanELResolver;
-import javax.el.ELContext;
-import javax.el.ELException;
-import javax.el.PropertyNotFoundException;
-import javax.el.PropertyNotWritableException;
-import javax.faces.context.FacesContext;
-import org.apache.myfaces.core.api.shared.lang.LambdaPropertyDescriptor;
-import org.apache.myfaces.core.api.shared.lang.PropertyDescriptorUtils;
-import org.apache.myfaces.core.api.shared.lang.PropertyDescriptorWrapper;
-
-public class LambdaBeanELResolver extends BeanELResolver
-{
- private final ConcurrentHashMap<String, Map<String, ? extends PropertyDescriptorWrapper>> cache;
-
- public LambdaBeanELResolver()
- {
- this.cache = new ConcurrentHashMap<>(1000);
- }
-
- @Override
- public Class<?> getType(ELContext context, Object base, Object property)
- {
- Objects.requireNonNull(context);
- if (base == null || property == null)
- {
- return null;
- }
-
- context.setPropertyResolved(base, property);
-
- return getPropertyDescriptor(base, property).getPropertyType();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public Object getValue(ELContext context, Object base, Object property)
- {
- Objects.requireNonNull(context);
- if (base == null || property == null)
- {
- return null;
- }
-
- context.setPropertyResolved(base, property);
-
- try
- {
- PropertyDescriptorWrapper pd = getPropertyDescriptor(base, property);
- if (pd instanceof LambdaPropertyDescriptor)
- {
- return ((LambdaPropertyDescriptor) pd).getReadFunction().apply(base);
- }
-
- return pd.getWrapped().getReadMethod().invoke(base);
- }
- catch (Exception e)
- {
- throw new ELException(e);
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public void setValue(ELContext context, Object base, Object property, Object value)
- {
- Objects.requireNonNull(context);
- if (base == null || property == null)
- {
- return;
- }
-
- context.setPropertyResolved(base, property);
-
- PropertyDescriptorWrapper pd = getPropertyDescriptor(base, property);
- if (pd.getWrapped().getWriteMethod()== null)
- {
- throw new PropertyNotWritableException("Property \"" + (String) property
- + "\" in \"" + base.getClass().getName() + "\" is not writable!");
- }
-
- try
- {
- if (pd instanceof LambdaPropertyDescriptor)
- {
- ((LambdaPropertyDescriptor) pd).getWriteFunction().accept(base, value);
- }
- else
- {
- pd.getWrapped().getWriteMethod().invoke(base, value);
- }
- }
- catch (Exception e)
- {
- throw new ELException(e);
- }
- }
-
- @Override
- public boolean isReadOnly(ELContext context, Object base, Object property)
- {
- Objects.requireNonNull(context);
- if (base == null || property == null)
- {
- return false;
- }
-
- context.setPropertyResolved(base, property);
-
- return getPropertyDescriptor(base, property).getWrapped().getWriteMethod() == null;
- }
-
- @Override
- public Class<?> getCommonPropertyType(ELContext context, Object base)
- {
- if (base != null)
- {
- return Object.class;
- }
-
- return null;
- }
-
- protected PropertyDescriptorWrapper getPropertyDescriptor(Object base, Object property)
- {
- Map<String, ? extends PropertyDescriptorWrapper> beanCache = cache.get(base.getClass().getName());
- if (beanCache == null)
- {
- beanCache = PropertyDescriptorUtils.getCachedPropertyDescriptors(
- FacesContext.getCurrentInstance().getExternalContext(),
- base.getClass());
- cache.put(base.getClass().getName(), beanCache);
- }
-
- PropertyDescriptorWrapper pd = beanCache.get((String) property);
- if (pd == null)
- {
- throw new PropertyNotFoundException("Property [" + property
- + "] not found on type [" + base.getClass().getName() + "]");
- }
- return pd;
- }
-}
+/*
+ * 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.el.resolver;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+import javax.el.BeanELResolver;
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.PropertyNotFoundException;
+import javax.el.PropertyNotWritableException;
+import javax.faces.context.FacesContext;
+import org.apache.myfaces.core.api.shared.lang.LambdaPropertyDescriptor;
+import org.apache.myfaces.core.api.shared.lang.PropertyDescriptorUtils;
+import org.apache.myfaces.core.api.shared.lang.PropertyDescriptorWrapper;
+
+public class LambdaBeanELResolver extends BeanELResolver
+{
+ private final ConcurrentHashMap<String, Map<String, ? extends PropertyDescriptorWrapper>> cache;
+
+ public LambdaBeanELResolver()
+ {
+ this.cache = new ConcurrentHashMap<>(1000);
+ }
+
+ @Override
+ public Class<?> getType(ELContext context, Object base, Object property)
+ {
+ Objects.requireNonNull(context);
+ if (base == null || property == null)
+ {
+ return null;
+ }
+
+ context.setPropertyResolved(base, property);
+
+ return getPropertyDescriptor(base, property).getPropertyType();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object getValue(ELContext context, Object base, Object property)
+ {
+ Objects.requireNonNull(context);
+ if (base == null || property == null)
+ {
+ return null;
+ }
+
+ context.setPropertyResolved(base, property);
+
+ try
+ {
+ PropertyDescriptorWrapper pd = getPropertyDescriptor(base, property);
+
+ Function<Object, Object> readFunction = null;
+ if (pd instanceof LambdaPropertyDescriptor)
+ {
+ readFunction = ((LambdaPropertyDescriptor) pd).getReadFunction();
+ }
+
+ if (readFunction != null)
+ {
+ return readFunction.apply(base);
+ }
+
+ return pd.getWrapped().getReadMethod().invoke(base);
+ }
+ catch (Exception e)
+ {
+ throw new ELException(e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void setValue(ELContext context, Object base, Object property, Object value)
+ {
+ Objects.requireNonNull(context);
+ if (base == null || property == null)
+ {
+ return;
+ }
+
+ context.setPropertyResolved(base, property);
+
+ PropertyDescriptorWrapper pd = getPropertyDescriptor(base, property);
+ if (pd.getWrapped().getWriteMethod()== null)
+ {
+ throw new PropertyNotWritableException("Property \"" + (String) property
+ + "\" in \"" + base.getClass().getName() + "\" is not writable!");
+ }
+
+ try
+ {
+ BiConsumer<Object, Object> writeFunction = null;
+ if (pd instanceof LambdaPropertyDescriptor)
+ {
+ writeFunction = ((LambdaPropertyDescriptor) pd).getWriteFunction();
+ }
+
+ if (writeFunction != null)
+ {
+ writeFunction.accept(base, value);
+ }
+ else
+ {
+ pd.getWrapped().getWriteMethod().invoke(base, value);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new ELException(e);
+ }
+ }
+
+ @Override
+ public boolean isReadOnly(ELContext context, Object base, Object property)
+ {
+ Objects.requireNonNull(context);
+ if (base == null || property == null)
+ {
+ return false;
+ }
+
+ context.setPropertyResolved(base, property);
+
+ return getPropertyDescriptor(base, property).getWrapped().getWriteMethod() == null;
+ }
+
+ @Override
+ public Class<?> getCommonPropertyType(ELContext context, Object base)
+ {
+ if (base != null)
+ {
+ return Object.class;
+ }
+
+ return null;
+ }
+
+ protected PropertyDescriptorWrapper getPropertyDescriptor(Object base, Object property)
+ {
+ Map<String, ? extends PropertyDescriptorWrapper> beanCache = cache.get(base.getClass().getName());
+ if (beanCache == null)
+ {
+ beanCache = PropertyDescriptorUtils.getCachedPropertyDescriptors(
+ FacesContext.getCurrentInstance().getExternalContext(),
+ base.getClass());
+ cache.put(base.getClass().getName(), beanCache);
+ }
+
+ PropertyDescriptorWrapper pd = beanCache.get((String) property);
+ if (pd == null)
+ {
+ throw new PropertyNotFoundException("Property [" + property
+ + "] not found on type [" + base.getClass().getName() + "]");
+ }
+ return pd;
+ }
+}
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/component/UIRepeat.java b/impl/src/main/java/org/apache/myfaces/view/facelets/component/UIRepeat.java
index 66d3ae0c8..6978bc390 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/component/UIRepeat.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/component/UIRepeat.java
@@ -1678,59 +1678,12 @@ public class UIRepeat extends UIComponentBase implements NamingContainer
_rowStates.clear();
}
}
- if (initialStateMarked())
- {
- Object parentSaved = super.saveState(context);
- if (context.getCurrentPhaseId() != null &&
- !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
- {
- if (parentSaved == null /*&&_rowDeltaStates.isEmpty()*/ && _rowStates.isEmpty())
- {
- return null;
- }
- else
- {
- Object values[] = new Object[3];
- values[0] = super.saveState(context);
- values[1] = null;
- values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
- return values;
- }
- }
- else
- {
- if (parentSaved == null)
- {
- return null;
- }
- else
- {
- Object values[] = new Object[2];
- values[0] = super.saveState(context);
- values[1] = null;
- return values;
- }
- }
- }
- else
- {
- if (context.getCurrentPhaseId() != null &&
- !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
- {
- Object values[] = new Object[3];
- values[0] = super.saveState(context);
- values[1] = null;
- values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
- return values;
- }
- else
- {
- Object values[] = new Object[2];
- values[0] = super.saveState(context);
- values[1] = null;
- return values;
- }
- }
+
+ Object values[] = new Object[3];
+ values[0] = super.saveState(context);
+ values[1] = null;
+ values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
+ return values;
}
@Override
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/BeanPropertyTagRule.java b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/BeanPropertyTagRule.java
index 55615b541..455797379 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/BeanPropertyTagRule.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/BeanPropertyTagRule.java
@@ -41,21 +41,21 @@ public final class BeanPropertyTagRule extends MetaRule
@Override
public Metadata applyRule(String name, TagAttribute attribute, MetadataTarget meta)
{
+ BiConsumer<Object, Object> writeFunction = null;
if (meta instanceof LambdaMetadataTargetImpl)
{
- BiConsumer<Object, Object> f = ((LambdaMetadataTargetImpl) meta).getWriteFunction(name);
+ writeFunction = ((LambdaMetadataTargetImpl) meta).getWriteFunction(name);
+ }
- // if the property is writable
- if (f != null)
+ if (writeFunction != null)
+ {
+ if (attribute.isLiteral())
{
- if (attribute.isLiteral())
- {
- return new LiteralPropertyMetadata(meta.getPropertyType(name), f, attribute);
- }
- else
- {
- return new DynamicPropertyMetadata(meta.getPropertyType(name), f, attribute);
- }
+ return new LiteralPropertyMetadata(meta.getPropertyType(name), writeFunction, attribute);
+ }
+ else
+ {
+ return new DynamicPropertyMetadata(meta.getPropertyType(name), writeFunction, attribute);
}
}
else
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/LambdaMetadataTargetImpl.java b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/LambdaMetadataTargetImpl.java
index 5d5280543..76016b8e7 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/LambdaMetadataTargetImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/LambdaMetadataTargetImpl.java
@@ -1,141 +1,135 @@
-/*
- * 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.view.facelets.tag;
-
-import java.beans.IntrospectionException;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Method;
-import java.util.Map;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
-import javax.faces.context.FacesContext;
-import javax.faces.view.facelets.MetadataTarget;
-import org.apache.myfaces.core.api.shared.lang.LambdaPropertyDescriptor;
-import org.apache.myfaces.core.api.shared.lang.PropertyDescriptorUtils;
-import org.apache.myfaces.core.api.shared.lang.PropertyDescriptorWrapper;
-
-public class LambdaMetadataTargetImpl extends MetadataTarget
-{
- private final Map<String, ? extends PropertyDescriptorWrapper> propertyDescriptors;
- private final Class<?> type;
-
- public LambdaMetadataTargetImpl(Class<?> type) throws IntrospectionException
- {
- this.type = type;
- this.propertyDescriptors = PropertyDescriptorUtils.getCachedPropertyDescriptors(
- FacesContext.getCurrentInstance().getExternalContext(),
- type);
- }
-
- @Override
- public PropertyDescriptor getProperty(String name)
- {
- LambdaPropertyDescriptor lpd = getLambdaProperty(name);
- if (lpd == null)
- {
- return null;
- }
-
- return lpd.getWrapped();
- }
-
- @Override
- public Class<?> getPropertyType(String name)
- {
- LambdaPropertyDescriptor lpd = getLambdaProperty(name);
- if (lpd == null)
- {
- return null;
- }
-
- return lpd.getPropertyType();
- }
-
- @Override
- public Method getReadMethod(String name)
- {
- LambdaPropertyDescriptor lpd = getLambdaProperty(name);
- if (lpd == null)
- {
- return null;
- }
-
- return lpd.getReadMethod();
- }
-
- @Override
- public Class<?> getTargetClass()
- {
- return type;
- }
-
- @Override
- public Method getWriteMethod(String name)
- {
- LambdaPropertyDescriptor lpd = getLambdaProperty(name);
- if (lpd == null)
- {
- return null;
- }
-
- return lpd.getWriteMethod();
- }
-
- @Override
- public boolean isTargetInstanceOf(Class type)
- {
- return type.isAssignableFrom(type);
- }
-
- public LambdaPropertyDescriptor getLambdaProperty(String name)
- {
- PropertyDescriptorWrapper wrapper = propertyDescriptors.get(name);
-
- if (wrapper instanceof LambdaPropertyDescriptor)
- {
- return (LambdaPropertyDescriptor) wrapper;
- }
- else
- {
- return null;
- }
- }
-
- public Function<Object, Object> getReadFunction(String name)
- {
- LambdaPropertyDescriptor lpd = getLambdaProperty(name);
- if (lpd == null)
- {
- return null;
- }
-
- return lpd.getReadFunction();
- }
-
- public BiConsumer<Object, Object> getWriteFunction(String name)
- {
- LambdaPropertyDescriptor lpd = getLambdaProperty(name);
- if (lpd == null)
- {
- return null;
- }
-
- return lpd.getWriteFunction();
- }
-}
+/*
+ * 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.view.facelets.tag;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import javax.faces.context.FacesContext;
+import javax.faces.view.facelets.MetadataTarget;
+import org.apache.myfaces.core.api.shared.lang.LambdaPropertyDescriptor;
+import org.apache.myfaces.core.api.shared.lang.PropertyDescriptorUtils;
+import org.apache.myfaces.core.api.shared.lang.PropertyDescriptorWrapper;
+
+public class LambdaMetadataTargetImpl extends MetadataTarget
+{
+ private final Map<String, ? extends PropertyDescriptorWrapper> propertyDescriptors;
+ private final Class<?> type;
+
+ public LambdaMetadataTargetImpl(Class<?> type) throws IntrospectionException
+ {
+ this.type = type;
+ this.propertyDescriptors = PropertyDescriptorUtils.getCachedPropertyDescriptors(
+ FacesContext.getCurrentInstance().getExternalContext(),
+ type);
+ }
+
+ @Override
+ public PropertyDescriptor getProperty(String name)
+ {
+ LambdaPropertyDescriptor lpd = getLambdaProperty(name);
+ if (lpd == null)
+ {
+ return null;
+ }
+
+ return lpd.getWrapped();
+ }
+
+ @Override
+ public Class<?> getPropertyType(String name)
+ {
+ LambdaPropertyDescriptor lpd = getLambdaProperty(name);
+ if (lpd == null)
+ {
+ return null;
+ }
+
+ return lpd.getPropertyType();
+ }
+
+ @Override
+ public Method getReadMethod(String name)
+ {
+ LambdaPropertyDescriptor lpd = getLambdaProperty(name);
+ if (lpd == null)
+ {
+ return null;
+ }
+
+ return lpd.getReadMethod();
+ }
+
+ @Override
+ public Class<?> getTargetClass()
+ {
+ return type;
+ }
+
+ @Override
+ public Method getWriteMethod(String name)
+ {
+ LambdaPropertyDescriptor lpd = getLambdaProperty(name);
+ if (lpd == null)
+ {
+ return null;
+ }
+
+ return lpd.getWriteMethod();
+ }
+
+ @Override
+ public boolean isTargetInstanceOf(Class type)
+ {
+ return type.isAssignableFrom(type);
+ }
+
+ public LambdaPropertyDescriptor getLambdaProperty(String name)
+ {
+ PropertyDescriptorWrapper pdw = propertyDescriptors.get(name);
+ return pdw instanceof LambdaPropertyDescriptor
+ ? (LambdaPropertyDescriptor) pdw
+ : null;
+ }
+
+ public Function<Object, Object> getReadFunction(String name)
+ {
+ LambdaPropertyDescriptor lpd = getLambdaProperty(name);
+ if (lpd == null)
+ {
+ return null;
+ }
+
+ return lpd.getReadFunction();
+ }
+
+ public BiConsumer<Object, Object> getWriteFunction(String name)
+ {
+ LambdaPropertyDescriptor lpd = getLambdaProperty(name);
+ if (lpd == null)
+ {
+ return null;
+ }
+
+ return lpd.getWriteFunction();
+ }
+}