You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2020/10/05 18:39:15 UTC

[camel] branch master updated (f49a942 -> 60dc46c)

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

davsclaus pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from f49a942  Throttles strimzi startup to prevent resource reuse errors (#4365)
     new 4471a64  CAMEL-15634: camel-bean - Optimize to avoid NoSuchMethodException when discovering annotations
     new 60dc46c  CAMEL-15636: camel-bean - Optimize @Pattern annotation discovery

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/camel/component/bean/MethodInfo.java    | 205 ++++++++-------------
 1 file changed, 73 insertions(+), 132 deletions(-)


[camel] 01/02: CAMEL-15634: camel-bean - Optimize to avoid NoSuchMethodException when discovering annotations

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 4471a64a46aec040074872b2643f398cc220220a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Oct 5 16:14:10 2020 +0200

    CAMEL-15634: camel-bean - Optimize to avoid NoSuchMethodException when discovering annotations
---
 .../apache/camel/component/bean/MethodInfo.java    | 34 ++++++++++++----------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java b/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
index eb04847..44212be 100644
--- a/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
+++ b/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
@@ -118,7 +118,7 @@ public class MethodInfo {
         this.parametersExpression = createParametersExpression();
 
         Map<Class<?>, Annotation> collectedMethodAnnotation = collectMethodAnnotations(type, method);
-
+        // TODO: Optimize to make this find via above
         Pattern oneway = findOneWayAnnotation(method);
         if (oneway != null) {
             pattern = oneway.value();
@@ -170,21 +170,24 @@ public class MethodInfo {
         return annotations;
     }
 
-    private void collectMethodAnnotations(Class<?> c, Method method, Map<Class<?>, Annotation> annotations) {
-        for (Class<?> i : c.getInterfaces()) {
-            collectMethodAnnotations(i, method, annotations);
-        }
-        if (!c.isInterface() && c.getSuperclass() != null) {
-            collectMethodAnnotations(c.getSuperclass(), method, annotations);
-        }
-        // make sure the sub class can override the definition
-        try {
-            Annotation[] ma = c.getDeclaredMethod(method.getName(), method.getParameterTypes()).getAnnotations();
-            for (Annotation a : ma) {
-                annotations.put(a.annotationType(), a);
+    private void collectMethodAnnotations(Class<?> targetClazz, Method targetMethod, Map<Class<?>, Annotation> annotations) {
+        Class<?> searchType = targetClazz;
+        String name = targetMethod.getName();
+        Class<?>[] paramTypes = method.getParameterTypes();
+        while (searchType != null) {
+            Method[] methods = searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods();
+            for (Method method : methods) {
+                if (name.equals(method.getName()) && Arrays.equals(paramTypes, method.getParameterTypes())) {
+                    for (Annotation a : method.getAnnotations()) {
+                        // favour existing annotation so only add if not exists
+                        Class<?> at = a.annotationType();
+                        if (!annotations.containsKey(at)) {
+                            annotations.put(at, a);
+                        }
+                    }
+                }
             }
-        } catch (SecurityException | NoSuchMethodException e) {
-            // do nothing here
+            searchType = searchType.getSuperclass();
         }
     }
 
@@ -232,7 +235,6 @@ public class MethodInfo {
                     if (!ServiceHelper.isStarted(dynamicRouter)) {
                         ServiceHelper.startService(dynamicRouter);
                     }
-                    // TODO: Maybe use a new constant than EVALUATE_EXPRESSION_RESULT
                     // use a expression which invokes the method to be used by dynamic router
                     Expression expression = new DynamicRouterExpression(pojo);
                     exchange.setProperty(Exchange.EVALUATE_EXPRESSION_RESULT, expression);


[camel] 02/02: CAMEL-15636: camel-bean - Optimize @Pattern annotation discovery

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 60dc46cd0c161ee7289a94c755f2d9308c1736e6
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Oct 5 20:38:42 2020 +0200

    CAMEL-15636: camel-bean - Optimize @Pattern annotation discovery
---
 .../apache/camel/component/bean/MethodInfo.java    | 189 +++++++--------------
 1 file changed, 64 insertions(+), 125 deletions(-)

diff --git a/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java b/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
index 44212be..a506f18 100644
--- a/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
+++ b/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
@@ -18,16 +18,16 @@ package org.apache.camel.component.bean;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletionStage;
 
@@ -39,6 +39,8 @@ import org.apache.camel.ExchangePattern;
 import org.apache.camel.Expression;
 import org.apache.camel.ExpressionEvaluationException;
 import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.InOnly;
+import org.apache.camel.InOut;
 import org.apache.camel.Message;
 import org.apache.camel.NoTypeConversionAvailableException;
 import org.apache.camel.Pattern;
@@ -118,10 +120,11 @@ public class MethodInfo {
         this.parametersExpression = createParametersExpression();
 
         Map<Class<?>, Annotation> collectedMethodAnnotation = collectMethodAnnotations(type, method);
-        // TODO: Optimize to make this find via above
-        Pattern oneway = findOneWayAnnotation(method);
-        if (oneway != null) {
-            pattern = oneway.value();
+
+        // configure MEP if there was an annotation with @Pattern/@InOnly/@InOut
+        ExchangePattern aep = findExchangePatternAnnotation(collectedMethodAnnotation);
+        if (aep != null) {
+            pattern = aep;
         }
 
         org.apache.camel.RoutingSlip routingSlipAnnotation
@@ -164,30 +167,70 @@ public class MethodInfo {
         }
     }
 
+    /**
+     * Finds the oneway annotation in priority order; look for method level annotations first, then the class level
+     * annotations, then super class annotations then interface annotations
+     */
     private Map<Class<?>, Annotation> collectMethodAnnotations(Class<?> c, Method method) {
         Map<Class<?>, Annotation> annotations = new HashMap<>();
-        collectMethodAnnotations(c, method, annotations);
+
+        Set<Class<?>> search = new LinkedHashSet<>();
+        // first look for the top class itself and its super classes
+        addTypeAndSuperTypes(c, search);
+        // and interfaces for all the classes as last
+        Set<Class<?>> searchInterfaces = new LinkedHashSet<>();
+        for (Class<?> aClazz : search) {
+            Class<?>[] interfaces = aClazz.getInterfaces();
+            for (Class<?> anInterface : interfaces) {
+                addTypeAndSuperTypes(anInterface, searchInterfaces);
+            }
+        }
+        search.addAll(searchInterfaces);
+        collectMethodAnnotations(search.iterator(), method.getName(), annotations);
         return annotations;
     }
 
-    private void collectMethodAnnotations(Class<?> targetClazz, Method targetMethod, Map<Class<?>, Annotation> annotations) {
-        Class<?> searchType = targetClazz;
-        String name = targetMethod.getName();
+    /**
+     * Adds the current class and all of its base classes (apart from {@link Object} to the given list
+     */
+    private static void addTypeAndSuperTypes(Class<?> type, Set<Class<?>> result) {
+        for (Class<?> t = type; t != null && t != Object.class; t = t.getSuperclass()) {
+            result.add(t);
+        }
+    }
+
+    private void collectMethodAnnotations(
+            Iterator<?> it, String targetMethodName, Map<Class<?>, Annotation> annotations) {
         Class<?>[] paramTypes = method.getParameterTypes();
-        while (searchType != null) {
+        boolean aep = false;
+        while (it.hasNext()) {
+            Class<?> searchType = (Class<?>) it.next();
             Method[] methods = searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods();
             for (Method method : methods) {
-                if (name.equals(method.getName()) && Arrays.equals(paramTypes, method.getParameterTypes())) {
+                if (targetMethodName.equals(method.getName()) && Arrays.equals(paramTypes, method.getParameterTypes())) {
                     for (Annotation a : method.getAnnotations()) {
                         // favour existing annotation so only add if not exists
                         Class<?> at = a.annotationType();
                         if (!annotations.containsKey(at)) {
                             annotations.put(at, a);
                         }
+                        aep |= at == Pattern.class || at == InOnly.class || at == InOut.class;
+                    }
+                }
+            }
+            // special for @Pattern/@InOut/@InOnly
+            if (!aep) {
+                // look for this on class level
+                for (Annotation a : searchType.getAnnotations()) {
+                    // favour existing annotation so only add if not exists
+                    Class<?> at = a.annotationType();
+                    boolean valid = at == Pattern.class || at == InOnly.class || at == InOut.class;
+                    if (valid && !annotations.containsKey(at)) {
+                        aep = true;
+                        annotations.put(at, a);
                     }
                 }
             }
-            searchType = searchType.getSuperclass();
         }
     }
 
@@ -454,119 +497,15 @@ public class MethodInfo {
         return new ParameterExpression(createParameterExpressions());
     }
 
-    /**
-     * Finds the oneway annotation in priority order; look for method level annotations first, then the class level
-     * annotations, then super class annotations then interface annotations
-     *
-     * @param  method the method on which to search
-     * @return        the first matching annotation or none if it is not available
-     */
-    protected Pattern findOneWayAnnotation(Method method) {
-        Pattern answer = getPatternAnnotation(method);
-        if (answer == null) {
-            Class<?> type = method.getDeclaringClass();
-
-            // create the search order of types to scan
-            List<Class<?>> typesToSearch = new ArrayList<>();
-            addTypeAndSuperTypes(type, typesToSearch);
-            Class<?>[] interfaces = type.getInterfaces();
-            for (Class<?> anInterface : interfaces) {
-                addTypeAndSuperTypes(anInterface, typesToSearch);
-            }
-
-            // now let's scan for a type which the current declared class overloads
-            answer = findOneWayAnnotationOnMethod(typesToSearch, method);
-            if (answer == null) {
-                answer = findOneWayAnnotation(typesToSearch);
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Returns the pattern annotation on the given annotated element; either as a direct annotation or on an annotation
-     * which is also annotated
-     *
-     * @param  annotatedElement the element to look for the annotation
-     * @return                  the first matching annotation or null if none could be found
-     */
-    protected Pattern getPatternAnnotation(AnnotatedElement annotatedElement) {
-        return getPatternAnnotation(annotatedElement, 2);
-    }
-
-    /**
-     * Returns the pattern annotation on the given annotated element; either as a direct annotation or on an annotation
-     * which is also annotated
-     *
-     * @param  annotatedElement the element to look for the annotation
-     * @param  depth            the current depth
-     * @return                  the first matching annotation or null if none could be found
-     */
-    protected Pattern getPatternAnnotation(AnnotatedElement annotatedElement, int depth) {
-        Pattern answer = annotatedElement.getAnnotation(Pattern.class);
-        int nextDepth = depth - 1;
-
-        if (nextDepth > 0) {
-            // look at all the annotations to see if any of those are annotated
-            Annotation[] annotations = annotatedElement.getAnnotations();
-            for (Annotation annotation : annotations) {
-                Class<? extends Annotation> annotationType = annotation.annotationType();
-                if (annotation instanceof Pattern || annotationType.equals(annotatedElement)) {
-                    continue;
-                } else {
-                    Pattern another = getPatternAnnotation(annotationType, nextDepth);
-                    if (pattern != null) {
-                        if (answer == null) {
-                            answer = another;
-                        } else {
-                            LOG.warn("Duplicate pattern annotation: {} found on annotation: {} which will be ignored", another,
-                                    annotation);
-                        }
-                    }
-                }
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Adds the current class and all of its base classes (apart from {@link Object} to the given list
-     */
-    protected void addTypeAndSuperTypes(Class<?> type, List<Class<?>> result) {
-        for (Class<?> t = type; t != null && t != Object.class; t = t.getSuperclass()) {
-            result.add(t);
-        }
-    }
-
-    /**
-     * Finds the first annotation on the base methods defined in the list of classes
-     */
-    protected Pattern findOneWayAnnotationOnMethod(List<Class<?>> classes, Method method) {
-        for (Class<?> type : classes) {
-            try {
-                Method definedMethod = type.getMethod(method.getName(), method.getParameterTypes());
-                Pattern answer = getPatternAnnotation(definedMethod);
-                if (answer != null) {
-                    return answer;
-                }
-            } catch (NoSuchMethodException e) {
-                // ignore
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Finds the first annotation on the given list of classes
-     */
-    protected Pattern findOneWayAnnotation(List<Class<?>> classes) {
-        for (Class<?> type : classes) {
-            Pattern answer = getPatternAnnotation(type);
-            if (answer != null) {
-                return answer;
-            }
+    protected ExchangePattern findExchangePatternAnnotation(Map<Class<?>, Annotation> collectedMethodAnnotation) {
+        if (collectedMethodAnnotation.get(InOnly.class) != null) {
+            return ExchangePattern.InOnly;
+        } else if (collectedMethodAnnotation.get(InOut.class) != null) {
+            return ExchangePattern.InOut;
+        } else {
+            Pattern pattern = (Pattern) collectedMethodAnnotation.get(Pattern.class);
+            return pattern != null ? pattern.value() : null;
         }
-        return null;
     }
 
     protected boolean hasExceptionParameter() {