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

davsclaus pushed a commit to branch camel-3.20.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-3.20.x by this push:
     new deff49c127b CAMEL-18856: camel-main - Unable to declare java.util.List 
bean
deff49c127b is described below

commit deff49c127b763e383ef6cc0ef15f5eab4bfe0bc
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Wed Jan 4 09:04:09 2023 +0100

    CAMEL-18856: camel-main - Unable to declare java.util.List bean
---
 .../org/apache/camel/util/ObjectHelperTest.java    | 21 ++++++++++++++
 .../org/apache/camel/main/BaseMainSupport.java     | 11 ++++++--
 .../java/org/apache/camel/main/MainHelper.java     | 31 +++++++--------------
 .../java/org/apache/camel/main/MainBeansTest.java  | 30 ++++++++++++++++++++
 .../camel/support/PropertyBindingSupport.java      | 32 +++++++++-------------
 .../java/org/apache/camel/util/ObjectHelper.java   | 25 +++++++++++++++++
 .../java/org/apache/camel/util/StringHelper.java   |  9 ++++++
 7 files changed, 116 insertions(+), 43 deletions(-)

diff --git 
a/core/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java 
b/core/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java
index 6818c586a77..4b48a7f9a5d 100644
--- a/core/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java
@@ -48,6 +48,7 @@ import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.DefaultMessage;
 import org.apache.camel.support.ObjectHelper;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
@@ -1078,4 +1079,24 @@ public class ObjectHelperTest {
                 StreamSupport.stream(ObjectHelper.createIterable(content, 
";+", false, true).spliterator(), false)
                         .collect(Collectors.joining("-")));
     }
+
+    @Test
+    public void testAddListByIndex() {
+        List<Object> list = new ArrayList<>();
+        org.apache.camel.util.ObjectHelper.addListByIndex(list, 0, "aaa");
+        org.apache.camel.util.ObjectHelper.addListByIndex(list, 2, "ccc");
+        org.apache.camel.util.ObjectHelper.addListByIndex(list, 1, "bbb");
+
+        Assertions.assertEquals(3, list.size());
+        Assertions.assertEquals("aaa", list.get(0));
+        Assertions.assertEquals("bbb", list.get(1));
+        Assertions.assertEquals("ccc", list.get(2));
+
+        org.apache.camel.util.ObjectHelper.addListByIndex(list, 99, "zzz");
+        Assertions.assertEquals(100, list.size());
+        Assertions.assertNull(list.get(4));
+        Assertions.assertNull(list.get(50));
+        Assertions.assertNull(list.get(98));
+        Assertions.assertEquals("zzz", list.get(99));
+    }
 }
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 552cc495319..6eca2447c52 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -1405,8 +1405,13 @@ public abstract class BaseMainSupport extends 
BaseService {
         // create map beans if none already exists
         for (String name : beansMap) {
             if (camelContext.getRegistry().lookupByName(name) == null) {
-                // register bean as a map
-                Map<String, Object> bean = new LinkedHashMap<>();
+
+                // is the config list or map style
+                OrderedLocationProperties config = 
MainHelper.extractProperties(properties, name + "[", "]", false);
+                boolean list = 
config.keySet().stream().map(Object::toString).allMatch(StringHelper::isDigit);
+
+                // register bean as a list or map
+                Object bean = list ? new ArrayList<>() : new LinkedHashMap<>();
                 if (logSummary) {
                     LOG.info("Binding bean: {} (type: {}) to the registry", 
name, ObjectHelper.classCanonicalName(bean));
                 } else {
@@ -1428,7 +1433,7 @@ public abstract class BaseMainSupport extends BaseService 
{
             setPropertiesOnTarget(camelContext, bean, config, optionPrefix + 
name + ".", failIfNotSet, ignoreCase,
                     autoConfiguredProperties);
         }
-        // then set properties per bean (map style)
+        // then set properties per bean (map/list style)
         for (String name : beansMap) {
             Object bean = camelContext.getRegistry().lookupByName(name);
             if (bean == null) {
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainHelper.java 
b/core/camel-main/src/main/java/org/apache/camel/main/MainHelper.java
index d4eb6aa1bdc..df8dcf85cd2 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainHelper.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainHelper.java
@@ -493,29 +493,16 @@ public final class MainHelper {
     }
 
     public static OrderedLocationProperties 
extractProperties(OrderedLocationProperties properties, String optionPrefix) {
-        if (properties == null) {
-            return new OrderedLocationProperties();
-        }
-        OrderedLocationProperties rc = new OrderedLocationProperties();
-
-        Set<Object> toRemove = new HashSet<>();
-        for (var entry : properties.entrySet()) {
-            String key = entry.getKey().toString();
-            String loc = properties.getLocation(key);
-            if (key.startsWith(optionPrefix)) {
-                Object value = properties.get(key);
-                key = key.substring(optionPrefix.length());
-                rc.put(loc, key, value);
-                toRemove.add(entry.getKey());
-            }
-        }
-        toRemove.forEach(properties::remove);
-
-        return rc;
+        return extractProperties(properties, optionPrefix, null, true);
     }
 
     public static OrderedLocationProperties extractProperties(
             OrderedLocationProperties properties, String optionPrefix, String 
optionSuffix) {
+        return extractProperties(properties, optionPrefix, optionSuffix, true);
+    }
+
+    public static OrderedLocationProperties extractProperties(
+            OrderedLocationProperties properties, String optionPrefix, String 
optionSuffix, boolean remove) {
         if (properties == null) {
             return new OrderedLocationProperties();
         }
@@ -528,11 +515,13 @@ public final class MainHelper {
             if (key.startsWith(optionPrefix)) {
                 Object value = properties.get(key);
                 key = key.substring(optionPrefix.length());
-                if (key.endsWith(optionSuffix)) {
+                if (optionSuffix != null && key.endsWith(optionSuffix)) {
                     key = key.substring(0, key.length() - 
optionSuffix.length());
                 }
                 rc.put(loc, key, value);
-                toRemove.add(entry.getKey());
+                if (remove) {
+                    toRemove.add(entry.getKey());
+                }
             }
         }
         toRemove.forEach(properties::remove);
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainBeansTest.java 
b/core/camel-main/src/test/java/org/apache/camel/main/MainBeansTest.java
index dd704b2faae..6fa07348eb1 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/MainBeansTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainBeansTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.main;
 
+import java.util.List;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
@@ -23,6 +24,7 @@ import org.apache.camel.builder.RouteBuilder;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 
@@ -141,6 +143,34 @@ public class MainBeansTest {
         main.stop();
     }
 
+    @Test
+    public void testBindBeansListSquare() throws Exception {
+        Main main = new Main();
+        main.configure().addRoutesBuilder(new MyRouteBuilder());
+
+        // defining a list bean (un-ordered)
+        main.addProperty("camel.beans.myprojects[0]", "Camel");
+        main.addProperty("camel.beans.myprojects[2]", "Quarkus");
+        main.addProperty("camel.beans.myprojects[1]", "Kafka");
+
+        main.start();
+
+        CamelContext camelContext = main.getCamelContext();
+        assertNotNull(camelContext);
+
+        Object bean = camelContext.getRegistry().lookupByName("myprojects");
+        assertNotNull(bean);
+        assertInstanceOf(List.class, bean);
+
+        List<?> list = (List<?>) bean;
+        assertEquals(3, list.size());
+        assertEquals("Camel", list.get(0));
+        assertEquals("Kafka", list.get(1));
+        assertEquals("Quarkus", list.get(2));
+
+        main.stop();
+    }
+
     @Test
     public void testBindBeansMapSquareDotKey() throws Exception {
         Main main = new Main();
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
index 6ce1abb5b92..1288a6ea9b6 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
@@ -499,6 +499,18 @@ public final class PropertyBindingSupport {
                     ((Map) target).put(key, value);
                     bound = true;
                 }
+                // if the target value is a list type (and key is digit),
+                // then we can skip reflection and set the entry
+                if (!bound && List.class.isAssignableFrom(target.getClass()) 
&& StringHelper.isDigit(key)) {
+                    try {
+                        // key must be digit
+                        int idx = Integer.parseInt(key);
+                        
org.apache.camel.util.ObjectHelper.addListByIndex((List) target, idx, value);
+                        bound = true;
+                    } catch (NumberFormatException e) {
+                        // ignore
+                    }
+                }
                 if (!bound && reflection) {
                     // fallback to reflection based
                     bound = setSimplePropertyViaReflection(camelContext, 
target, key, value, fluentBuilder, allowPrivateSetter,
@@ -585,25 +597,7 @@ public final class PropertyBindingSupport {
             List list = (List) obj;
             if (isNotEmpty(lookupKey)) {
                 int idx = Integer.parseInt(lookupKey);
-                if (idx < list.size()) {
-                    list.set(idx, value);
-                } else if (idx == list.size()) {
-                    list.add(value);
-                } else {
-                    // If the list implementation is based on an array, we
-                    // can increase tha capacity to the required value to
-                    // avoid potential re-allocation weh invoking List::add.
-                    //
-                    // Note that ArrayList is the default List impl that
-                    // is automatically created if the property is null.
-                    if (list instanceof ArrayList) {
-                        ((ArrayList) list).ensureCapacity(idx + 1);
-                    }
-                    while (list.size() < idx) {
-                        list.add(null);
-                    }
-                    list.add(idx, value);
-                }
+                org.apache.camel.util.ObjectHelper.addListByIndex(list, idx, 
value);
             } else {
                 list.add(value);
             }
diff --git 
a/core/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java 
b/core/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java
index e1afbbaea1f..35d8efe3466 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java
@@ -1316,4 +1316,29 @@ public final class ObjectHelper {
         return objects != null ? Arrays.asList(objects) : 
Collections.emptyList();
     }
 
+    /**
+     * Adds the value to the list at the given index
+     */
+    public static void addListByIndex(List<Object> list, int idx, Object 
value) {
+        if (idx < list.size()) {
+            list.set(idx, value);
+        } else if (idx == list.size()) {
+            list.add(value);
+        } else {
+            // If the list implementation is based on an array, we
+            // can increase tha capacity to the required value to
+            // avoid potential re-allocation when invoking List::add.
+            //
+            // Note that ArrayList is the default List impl that
+            // is automatically created if the property is null.
+            if (list instanceof ArrayList) {
+                ((ArrayList<?>) list).ensureCapacity(idx + 1);
+            }
+            while (list.size() < idx) {
+                list.add(null);
+            }
+            list.add(idx, value);
+        }
+    }
+
 }
diff --git 
a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java 
b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
index aff3b0bf298..26fb5d61bb0 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
@@ -1156,4 +1156,13 @@ public final class StringHelper {
         }
     }
 
+    public static boolean isDigit(String s) {
+        for (char ch : s.toCharArray()) {
+            if (!Character.isDigit(ch)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 }

Reply via email to