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

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

commit b5fe59623e91865b8cbab2f1da3606ef96d155fe
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Sat Feb 6 10:56:31 2021 +0100

    CAMEL-16102: Source code generate @InvokeOnHeader for reflection free
---
 .../java/org/apache/camel/spi/InvokeOnHeader.java  |  5 ++
 .../apache/camel/spi/InvokeOnHeaderStrategy.java   |  5 +-
 .../camel/support/HeaderSelectorProducer.java      |  8 +-
 .../packaging/GenerateInvokeOnHeaderMojo.java      | 91 +++++++++++++---------
 4 files changed, 67 insertions(+), 42 deletions(-)

diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/InvokeOnHeader.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/InvokeOnHeader.java
index 0dc11e9..55008ce 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/InvokeOnHeader.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/InvokeOnHeader.java
@@ -42,12 +42,17 @@ import org.apache.camel.Message;
  * <p/>
  * This can be used by Component implementations that uses 
org.apache.camel.support.HeaderSelectorProducer.
  *
+ * This requires to use Camel maven tooling (camel-package-maven-plugin) to 
generate java source code
+ * that selects and invokes the method at runtime.
+ *
  * @see Message#getHeader(String)
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.METHOD)
 public @interface InvokeOnHeader {
 
+    // TODO: Update javadoc as parameter binding has improved
+
     /**
      * Name of header.
      */
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/InvokeOnHeaderStrategy.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/InvokeOnHeaderStrategy.java
index 83f6b8d..487b2e6 100644
--- 
a/core/camel-api/src/main/java/org/apache/camel/spi/InvokeOnHeaderStrategy.java
+++ 
b/core/camel-api/src/main/java/org/apache/camel/spi/InvokeOnHeaderStrategy.java
@@ -23,17 +23,20 @@ import org.apache.camel.Exchange;
  * Pluggable strategy for invoking {@link InvokeOnHeader}.
  * <p>
  * Camel provides source code generated strategies via the camel maven tooling.
+ *
+ * @see InvokeOnHeader
  */
 public interface InvokeOnHeaderStrategy {
 
     /**
      * Invoke the method based on the header key
      *
-     * @param  target    the target such as HeaderSelectorProducer
+     * @param  target    the target such as a producer extending 
HeaderSelectorProducer
      * @param  key       the header key
      * @param  exchange  the exchange
      * @param  callback  the async callback
      * @return           option response from invoking the method, or 
<tt>null</tt> if the method is void
+     *                   if a value is returned, then this value is stored as 
result on the message body.
      * @throws Exception is thrown if error invoking the method.
      */
     Object invoke(Object target, String key, Exchange exchange, AsyncCallback 
callback) throws Exception;
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/HeaderSelectorProducer.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/HeaderSelectorProducer.java
index 6837c68..523923e 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/HeaderSelectorProducer.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/HeaderSelectorProducer.java
@@ -44,7 +44,7 @@ public abstract class HeaderSelectorProducer extends 
DefaultAsyncProducer implem
     private final Object target;
     private CamelContext camelContext;
     private InvokeOnHeaderStrategy strategy;
-    private InvokeOnHeaderStrategy strategy2;
+    private InvokeOnHeaderStrategy parentStrategy;
 
     public HeaderSelectorProducer(Endpoint endpoint, Supplier<String> 
headerSupplier) {
         this(endpoint, headerSupplier, () -> null, null);
@@ -154,7 +154,7 @@ public abstract class HeaderSelectorProducer extends 
DefaultAsyncProducer implem
             // some components may have a common base class they extend from 
(such as camel-infinispan)
             String key2 = this.getClass().getSuperclass().getName();
             String fqn2 = RESOURCE_PATH + key2;
-            strategy2 = 
camelContext.adapt(ExtendedCamelContext.class).getBootstrapFactoryFinder(RESOURCE_PATH)
+            parentStrategy = 
camelContext.adapt(ExtendedCamelContext.class).getBootstrapFactoryFinder(RESOURCE_PATH)
                     .newInstance(key2, InvokeOnHeaderStrategy.class)
                     .orElseThrow(() -> new IllegalArgumentException("Cannot 
find " + fqn2 + " in classpath."));
         }
@@ -175,8 +175,8 @@ public abstract class HeaderSelectorProducer extends 
DefaultAsyncProducer implem
 
             LOGGER.debug("Invoking @InvokeOnHeader method: {}", action);
             Object answer = strategy.invoke(target, action, exchange, 
callback);
-            if (answer == null && strategy2 != null) {
-                answer = strategy2.invoke(target, action, exchange, callback);
+            if (answer == null && parentStrategy != null) {
+                answer = parentStrategy.invoke(target, action, exchange, 
callback);
             }
             LOGGER.trace("Invoked @InvokeOnHeader method: {} -> {}", action, 
answer);
             if (answer != null) {
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/GenerateInvokeOnHeaderMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/GenerateInvokeOnHeaderMojo.java
index 3a4b27c..a78b90a 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/GenerateInvokeOnHeaderMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/GenerateInvokeOnHeaderMojo.java
@@ -23,11 +23,13 @@ import java.io.StringWriter;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.StringJoiner;
 import java.util.TreeSet;
 
 import org.apache.maven.plugin.MojoExecutionException;
@@ -40,6 +42,7 @@ import org.jboss.jandex.AnnotationInstance;
 import org.jboss.jandex.DotName;
 import org.jboss.jandex.Index;
 import org.jboss.jandex.IndexReader;
+import org.jboss.jandex.MethodInfo;
 import org.jboss.jandex.Type;
 
 /**
@@ -66,9 +69,8 @@ public class GenerateInvokeOnHeaderMojo extends 
AbstractGeneratorMojo {
     private static class InvokeOnHeaderModel {
         private String key;
         private String methodName;
-        private boolean isVoid;
-        private boolean callback;
-        private boolean exchange;
+        private String returnType;
+        private final List<String> args = new ArrayList<>();
 
         public String getKey() {
             return key;
@@ -86,28 +88,20 @@ public class GenerateInvokeOnHeaderMojo extends 
AbstractGeneratorMojo {
             this.methodName = methodName;
         }
 
-        public boolean isVoid() {
-            return isVoid;
+        public String getReturnType() {
+            return returnType;
         }
 
-        public void setVoid(boolean aVoid) {
-            isVoid = aVoid;
+        public void setReturnType(String returnType) {
+            this.returnType = returnType;
         }
 
-        public boolean isCallback() {
-            return callback;
+        public List<String> getArgs() {
+            return args;
         }
 
-        public void setCallback(boolean callback) {
-            this.callback = callback;
-        }
-
-        public boolean isExchange() {
-            return exchange;
-        }
-
-        public void setExchange(boolean exchange) {
-            this.exchange = exchange;
+        public void addArgs(String arg) {
+            args.add(arg);
         }
     }
 
@@ -142,18 +136,24 @@ public class GenerateInvokeOnHeaderMojo extends 
AbstractGeneratorMojo {
         annotations.forEach(a -> {
             String currentClass = 
a.target().asMethod().declaringClass().name().toString();
             String value = a.value().asString();
-            String methodName = a.target().asMethod().name();
-            boolean isVoid = Type.Kind.VOID == 
a.target().asMethod().returnType().kind();
-            boolean callback = a.target().asMethod().parameters().size() == 2;
-            boolean exchange = 
"org.apache.camel.Exchange".equals(a.target().asMethod().parameters().get(0).name().toString());
-            Set<InvokeOnHeaderModel> set = 
classes.computeIfAbsent(currentClass,
-                    k -> new 
TreeSet<>(Comparator.comparing(InvokeOnHeaderModel::getKey)));
+            MethodInfo mi = a.target().asMethod();
+
             InvokeOnHeaderModel model = new InvokeOnHeaderModel();
             model.setKey(value);
-            model.setMethodName(methodName);
-            model.setVoid(isVoid);
-            model.setCallback(callback);
-            model.setExchange(exchange);
+            model.setMethodName(mi.name());
+
+            boolean isVoid = Type.Kind.VOID == mi.returnType().kind();
+            if (isVoid) {
+                model.setReturnType("VOID");
+            } else {
+                model.setReturnType(mi.returnType().toString());
+            }
+            for (Type type : mi.parameters()) {
+                String arg = type.name().toString();
+                model.addArgs(arg);
+            }
+            Set<InvokeOnHeaderModel> set = 
classes.computeIfAbsent(currentClass,
+                    k -> new 
TreeSet<>(Comparator.comparing(InvokeOnHeaderModel::getKey)));
             set.add(model);
         });
 
@@ -221,18 +221,21 @@ public class GenerateInvokeOnHeaderMojo extends 
AbstractGeneratorMojo {
         if (!models.isEmpty()) {
             w.write("        switch (key) {\n");
             for (InvokeOnHeaderModel option : models) {
-                String invoke;
-                String arg1 = option.isExchange() ? "exchange" : 
"exchange.getMessage()";
-                String arg2 = option.isCallback() ? "callback" : null;
-                if (arg2 != null) {
-                    invoke = "target." + option.getMethodName() + "(" + arg1 + 
", " + arg2 + ")";
-                } else {
-                    invoke = "target." + option.getMethodName() + "(" + arg1 + 
")";
+                String invoke = "target." + option.getMethodName() + "(";
+                if (!option.getArgs().isEmpty()) {
+                    StringJoiner sj = new StringJoiner(", ");
+                    for (String arg : option.getArgs()) {
+                        String ba = bindArg(arg);
+                        sj.add(ba);
+                    }
+                    invoke += sj.toString();
                 }
+                invoke += ")";
+
                 if (!option.getKey().toLowerCase().equals(option.getKey())) {
                     w.write(String.format("        case \"%s\":\n", 
option.getKey().toLowerCase()));
                 }
-                if (option.isVoid()) {
+                if (option.getReturnType().equals("VOID")) {
                     w.write(String.format("        case \"%s\": %s; return 
null;\n", option.getKey(), invoke));
                 } else {
                     w.write(String.format("        case \"%s\": return %s;\n", 
option.getKey(), invoke));
@@ -248,4 +251,18 @@ public class GenerateInvokeOnHeaderMojo extends 
AbstractGeneratorMojo {
         w.write("\n");
     }
 
+    protected String bindArg(String type) {
+        if ("org.apache.camel.Exchange".equals(type)) {
+            return "exchange";
+        } else if ("org.apache.camel.Message".equals(type)) {
+            return "exchange.getMessage()";
+        } else if ("org.apache.camel.AsyncCallback".equals(type)) {
+            return "callback";
+        } else if ("org.apache.camel.CamelContext".equals(type)) {
+            return "exchange.getContext()";
+        } else {
+            return "exchange.getMessage().getBody(" + type + ".class)";
+        }
+    }
+
 }

Reply via email to