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:17 UTC
[camel] 02/02: CAMEL-15636: camel-bean - Optimize @Pattern
annotation discovery
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() {