This is an automated email from the ASF dual-hosted git repository.

tandraschko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/openwebbeans.git


The following commit(s) were added to refs/heads/main by this push:
     new 6cac859c6 OWB-1436 
org.apache.webbeans.el22.WrappedValueExpressionNode'does not have the property 
'xxx'
6cac859c6 is described below

commit 6cac859c6194d9a8a7eba9d382b2c4cf75537f54
Author: Thomas Andraschko <[email protected]>
AuthorDate: Tue Jan 9 13:58:11 2024 +0100

    OWB-1436 org.apache.webbeans.el22.WrappedValueExpressionNode'does not have 
the property 'xxx'
---
 .../apache/webbeans/el22/WebBeansELResolver.java   |  63 +++++++----
 .../apache/webbeans/el/test/DotNamedBeansTest.java | 119 ++++++++++++++++++++-
 2 files changed, 154 insertions(+), 28 deletions(-)

diff --git 
a/webbeans-el22/src/main/java/org/apache/webbeans/el22/WebBeansELResolver.java 
b/webbeans-el22/src/main/java/org/apache/webbeans/el22/WebBeansELResolver.java
index c4dc5622f..6c6510bc1 100644
--- 
a/webbeans-el22/src/main/java/org/apache/webbeans/el22/WebBeansELResolver.java
+++ 
b/webbeans-el22/src/main/java/org/apache/webbeans/el22/WebBeansELResolver.java
@@ -18,21 +18,22 @@
  */
 package org.apache.webbeans.el22;
 
-import org.apache.webbeans.component.OwbBean;
-import org.apache.webbeans.config.WebBeansContext;
-import org.apache.webbeans.container.BeanManagerImpl;
-import org.apache.webbeans.el.ELContextStore;
-
 import jakarta.el.ELContext;
 import jakarta.el.ELException;
 import jakarta.el.ELResolver;
 import jakarta.enterprise.context.Dependent;
 import jakarta.enterprise.context.spi.CreationalContext;
 import jakarta.enterprise.inject.spi.Bean;
+import org.apache.webbeans.component.OwbBean;
+import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.container.BeanManagerImpl;
+import org.apache.webbeans.el.ELContextStore;
+
 import java.beans.FeatureDescriptor;
 import java.lang.reflect.Type;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.stream.Collectors;
 
 /**
@@ -55,17 +56,19 @@ import java.util.stream.Collectors;
 public class WebBeansELResolver extends ELResolver
 {
     private final WebBeansContext webBeansContext;
+    private Set<String> dotNamedBeansNegativeCache;
 
     public WebBeansELResolver()
     {
         webBeansContext = WebBeansContext.getInstance();
+        dotNamedBeansNegativeCache = new CopyOnWriteArraySet<>();
     }
     
     /**
      * {@inheritDoc}
      */
     @Override
-    public Class<?> getCommonPropertyType(ELContext arg0, Object arg1)
+    public Class<?> getCommonPropertyType(ELContext context, Object base)
     {
         return null;
     }
@@ -74,7 +77,7 @@ public class WebBeansELResolver extends ELResolver
      * {@inheritDoc}
      */
     @Override
-    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext arg0, 
Object arg1)
+    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext 
context, Object base)
     {
         return null;
     }
@@ -83,7 +86,7 @@ public class WebBeansELResolver extends ELResolver
      * {@inheritDoc}
      */    
     @Override
-    public Class<?> getType(ELContext arg0, Object arg1, Object arg2) throws 
ELException
+    public Class<?> getType(ELContext context, Object base, Object property) 
throws ELException
     {
         return null;
     }
@@ -95,9 +98,15 @@ public class WebBeansELResolver extends ELResolver
     @SuppressWarnings({"unchecked","deprecation"})
     public Object getValue(ELContext context, Object base, Object property) 
throws ELException
     {
-        final BeanManagerImpl beanManager = 
webBeansContext.getBeanManagerImpl();
+        // we only check root beans
+        // or if its wrapped because of dot-names
+        if (base != null && !(base instanceof WrappedValueExpressionNode))
+        {
+            return null;
+        }
 
         // Check if the OWB actually got used in this application
+        final BeanManagerImpl beanManager = 
webBeansContext.getBeanManagerImpl();
         if (!beanManager.isInUse())
         {
             return null;
@@ -160,25 +169,33 @@ public class WebBeansELResolver extends ELResolver
     private Object findDottedName(final ELContext context, final Object base, 
final BeanManagerImpl beanManager,
                                   final ELContextStore elContextStore, final 
String beanName)
     {
-
         final String fqBeanName = base == null ? beanName : base + "." + 
beanName;
+        if (dotNamedBeansNegativeCache.contains(fqBeanName))
+        {
+            return null;
+        }
+
         final Set<Bean<?>> anyBeanName = beanManager.getBeans().stream()
-                                                    .filter(b -> b.getName() 
!= null)
-                                                    .filter(b -> 
b.getName().startsWith(fqBeanName))
-                                                    
.collect(Collectors.toSet());
+                .filter(b -> b.getName() != null)
+                .filter(b -> b.getName().equals(fqBeanName) || 
b.getName().startsWith(fqBeanName + "."))
+                .collect(Collectors.toSet());
 
-        // looks like a good candidate
-        if (anyBeanName.size() == 1 && 
fqBeanName.equals(anyBeanName.iterator().next().getName()))
+        // no exact and no startsWith match
+        if (anyBeanName.isEmpty())
         {
-            return getBeanWithScope(context, beanManager, beanName, 
elContextStore, anyBeanName);
+            dotNamedBeansNegativeCache.add(fqBeanName);
+            return null;
         }
-        // more than one bean with the same beginning or name not matching
-        else if (!anyBeanName.isEmpty())
+
+        // exact match
+        if (anyBeanName.size() == 1 && 
fqBeanName.equals(anyBeanName.iterator().next().getName()))
         {
-            context.setPropertyResolved(true);
-            return new WrappedValueExpressionNode(fqBeanName);
+            return getBeanWithScope(context, beanManager, fqBeanName, 
elContextStore, anyBeanName);
         }
-        return null;
+
+        // more than one bean with the same beginning
+        context.setPropertyResolved(true);
+        return new WrappedValueExpressionNode(fqBeanName);
     }
 
     protected Object getNormalScopedContextualInstance(BeanManagerImpl 
manager, ELContextStore store, ELContext context,
@@ -242,7 +259,7 @@ public class WebBeansELResolver extends ELResolver
      * {@inheritDoc}
      */    
     @Override
-    public boolean isReadOnly(ELContext arg0, Object arg1, Object arg2) throws 
ELException
+    public boolean isReadOnly(ELContext context, Object base, Object property) 
throws ELException
     {
         return false;
     }
@@ -251,7 +268,7 @@ public class WebBeansELResolver extends ELResolver
      * {@inheritDoc}
      */    
     @Override
-    public void setValue(ELContext arg0, Object arg1, Object arg2, Object 
arg3) throws ELException
+    public void setValue(ELContext context, Object base, Object property, 
Object value) throws ELException
     {
 
     }
diff --git 
a/webbeans-el22/src/test/java/org/apache/webbeans/el/test/DotNamedBeansTest.java
 
b/webbeans-el22/src/test/java/org/apache/webbeans/el/test/DotNamedBeansTest.java
index 638d7a5bb..276f71413 100644
--- 
a/webbeans-el22/src/test/java/org/apache/webbeans/el/test/DotNamedBeansTest.java
+++ 
b/webbeans-el22/src/test/java/org/apache/webbeans/el/test/DotNamedBeansTest.java
@@ -18,16 +18,25 @@
  */
 package org.apache.webbeans.el.test;
 
+import jakarta.el.ArrayELResolver;
+import jakarta.el.BeanELResolver;
+import jakarta.el.CompositeELResolver;
 import jakarta.el.ELContext;
 import jakarta.el.ELResolver;
 import jakarta.el.FunctionMapper;
+import jakarta.el.ListELResolver;
+import jakarta.el.MapELResolver;
 import jakarta.el.PropertyNotFoundException;
+import jakarta.el.StaticFieldELResolver;
 import jakarta.el.ValueExpression;
 import jakarta.el.VariableMapper;
 import jakarta.enterprise.context.Dependent;
+import jakarta.enterprise.context.RequestScoped;
 import jakarta.enterprise.inject.spi.BeanManager;
 import jakarta.inject.Named;
 import org.apache.el.ExpressionFactoryImpl;
+import org.apache.el.lang.FunctionMapperImpl;
+import org.apache.el.lang.VariableMapperImpl;
 import org.apache.webbeans.el22.WrappedExpressionFactory;
 import org.apache.webbeans.el22.WrappedValueExpressionNode;
 import org.apache.webbeans.exception.WebBeansConfigurationException;
@@ -99,6 +108,49 @@ public class DotNamedBeansTest extends AbstractUnitTest
         shutDownContainer();
     }
 
+    @Test
+    public void testNonDottedChildren() throws Exception
+    {
+        Collection<Class<?>> classes = new ArrayList<Class<?>>();
+
+        classes.add(Dogs.class);
+        classes.add(Dog.class);
+        classes.add(BlueGoldenFish.class);
+        classes.add(GoldenFish.class);
+
+        startContainer(classes);
+
+        Dog dog = evaluateValueExpression(getBeanManager(), "#{dog}", 
Dog.class);
+        dog.setParent(new Parent());
+        dog.getParent().setName("Hans");
+
+        String parentName = evaluateValueExpression(getBeanManager(), 
"#{dog.parent.name}", String.class);
+        Assert.assertEquals("Hans", parentName);
+
+        shutDownContainer();
+    }
+
+    @Test
+    public void testChildren() throws Exception
+    {
+        Collection<Class<?>> classes = new ArrayList<Class<?>>();
+
+        classes.add(Dog.class);
+        classes.add(BlueGoldenFish.class);
+        classes.add(GoldenFish.class);
+
+        startContainer(classes);
+
+        GoldenFish goldenFish = evaluateValueExpression(getBeanManager(), 
"#{magic.golden.fish}", GoldenFish.class);
+        goldenFish.setParent(new Parent());
+        goldenFish.getParent().setName("Hans");
+
+        String parentName = evaluateValueExpression(getBeanManager(), 
"#{magic.golden.fish.parent.name}", String.class);
+        Assert.assertEquals("Hans", parentName);
+
+        shutDownContainer();
+    }
+
     @Test(expected = WebBeansConfigurationException.class)
     public void testConflictingName() throws Exception
     {
@@ -146,19 +198,41 @@ public class DotNamedBeansTest extends AbstractUnitTest
         final WrappedExpressionFactory wrappedExpressionFactory = new 
WrappedExpressionFactory(new ExpressionFactoryImpl());
         final ELContext elContext = new ELContext() {
 
+            private CompositeELResolver elResolver;
+            private FunctionMapper functionMapper;
+            private VariableMapper variableMapper;
+
             @Override
             public ELResolver getELResolver() {
-                return beanManager.getELResolver();
+                if (elResolver == null)
+                {
+                    elResolver = new CompositeELResolver();
+                    elResolver.add(beanManager.getELResolver());
+                    elResolver.add(new StaticFieldELResolver());
+                    elResolver.add(new MapELResolver());
+                    elResolver.add(new ListELResolver());
+                    elResolver.add(new ArrayELResolver());
+                    elResolver.add(new BeanELResolver());
+                }
+                return elResolver;
             }
 
             @Override
             public FunctionMapper getFunctionMapper() {
-                return null;
+                if (functionMapper == null)
+                {
+                    functionMapper = new FunctionMapperImpl();
+                }
+                return functionMapper;
             }
 
             @Override
             public VariableMapper getVariableMapper() {
-                return null;
+                if (variableMapper == null)
+                {
+                    variableMapper = new VariableMapperImpl();
+                }
+                return variableMapper;
             }
         };
         final ValueExpression valueExpression = 
wrappedExpressionFactory.createValueExpression(elContext, expression, 
expectedType);
@@ -168,8 +242,17 @@ public class DotNamedBeansTest extends AbstractUnitTest
     }
 
     @Named("magic.golden.fish")
-    @Dependent
+    @RequestScoped
     public static class GoldenFish {
+        private Parent parent;
+
+        public Parent getParent() {
+            return parent;
+        }
+
+        public void setParent(Parent parent) {
+            this.parent = parent;
+        }
     }
 
     @Named("magic.golden")
@@ -182,9 +265,35 @@ public class DotNamedBeansTest extends AbstractUnitTest
     public static class BlueGoldenFish {
     }
 
+    @Named("dogs")
+    @RequestScoped
+    public static class Dogs {
+
+    }
+
     @Named("dog")
-    @Dependent
+    @RequestScoped
     public static class Dog {
+        private Parent parent;
+
+        public Parent getParent() {
+            return parent;
+        }
+
+        public void setParent(Parent parent) {
+            this.parent = parent;
+        }
     }
 
+    public static class Parent {
+        private String name;
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+    }
 }

Reply via email to