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 2019/08/13 06:25:06 UTC
[camel] 04/09: CAMEL-13850: Optimize model classes to provide
changeable properties that support property placeholders to avoid
reflection. Work in progress.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch CAMEL-13850
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 54a77dc1196b74f2b97e8d9b93e740baaf1a1473
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 12 22:08:43 2019 +0200
CAMEL-13850: Optimize model classes to provide changeable properties that support property placeholders to avoid reflection. Work in progress.
---
.../model/DefinitionPropertiesProviderHelper.java | 47 -------------
.../DefinitionPropertyPlaceholderConfigurable.java | 5 +-
.../apt/CoreEipAnnotationProcessorHelper.java | 77 +++++++++++++++++++---
.../camel/tools/apt/ModelAnnotationProcessor.java | 62 +++++++++++++----
.../tools/apt/SpringAnnotationProcessorHelper.java | 3 +-
5 files changed, 122 insertions(+), 72 deletions(-)
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertiesProviderHelper.java b/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertiesProviderHelper.java
deleted file mode 100644
index 86cb92e..0000000
--- a/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertiesProviderHelper.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.model;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Function;
-
-import org.apache.camel.model.placeholder.FromDefinitionPropertyPlaceholderProvider;
-import org.apache.camel.model.placeholder.LogDefinitionPropertyPlaceholderProvider;
-import org.apache.camel.model.placeholder.ToDefinitionPropertyPlaceholderProvider;
-
-public class DefinitionPropertiesProviderHelper {
-
- private static final Map<Class, Function<Object, DefinitionPropertyPlaceholderConfigurable>> MAP;
- static {
- Map<Class, Function<Object, DefinitionPropertyPlaceholderConfigurable>> map = new HashMap<>();
- map.put(FromDefinition.class, FromDefinitionPropertyPlaceholderProvider::new);
- map.put(LogDefinition.class, LogDefinitionPropertyPlaceholderProvider::new);
- map.put(ToDefinition.class, ToDefinitionPropertyPlaceholderProvider::new);
- MAP = map;
- }
-
- public static Optional<DefinitionPropertyPlaceholderConfigurable> provider(Object definition) {
- Function<Object, DefinitionPropertyPlaceholderConfigurable> func = MAP.get(definition.getClass());
- if (func != null) {
- return Optional.of(func.apply(definition));
- }
- return Optional.empty();
- }
-
-}
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertyPlaceholderConfigurable.java b/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertyPlaceholderConfigurable.java
index 9c82f6b..8d5758c 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertyPlaceholderConfigurable.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/DefinitionPropertyPlaceholderConfigurable.java
@@ -21,6 +21,7 @@ import java.util.function.Consumer;
import java.util.function.Supplier;
import org.apache.camel.CamelContext;
+import org.apache.camel.model.placeholder.DefinitionPropertiesPlaceholderProviderHelper;
/**
* To be used for configuring property placeholder options on the EIP models.
@@ -34,7 +35,7 @@ public interface DefinitionPropertyPlaceholderConfigurable {
* @return key/values of options
*/
default Map<String, Supplier<String>> getReadPropertyPlaceholderOptions(CamelContext camelContext) {
- DefinitionPropertyPlaceholderConfigurable aware = DefinitionPropertiesProviderHelper.provider(this).orElse(null);
+ DefinitionPropertyPlaceholderConfigurable aware = DefinitionPropertiesPlaceholderProviderHelper.provider(this).orElse(null);
return aware != null ? aware.getReadPropertyPlaceholderOptions(camelContext) : null;
}
@@ -43,7 +44,7 @@ public interface DefinitionPropertyPlaceholderConfigurable {
* This will be all the string based options.
*/
default Map<String, Consumer<String>> getWritePropertyPlaceholderOptions(CamelContext camelContext) {
- DefinitionPropertyPlaceholderConfigurable aware = DefinitionPropertiesProviderHelper.provider(this).orElse(null);
+ DefinitionPropertyPlaceholderConfigurable aware = DefinitionPropertiesPlaceholderProviderHelper.provider(this).orElse(null);
return aware != null ? aware.getWritePropertyPlaceholderOptions(camelContext) : null;
}
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessorHelper.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessorHelper.java
index edb48d7..fc00956 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessorHelper.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessorHelper.java
@@ -18,13 +18,13 @@ package org.apache.camel.tools.apt;
import java.io.PrintWriter;
import java.io.Writer;
+import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
-import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.annotation.processing.ProcessingEnvironment;
@@ -92,7 +92,8 @@ public class CoreEipAnnotationProcessorHelper {
private boolean skipUnwanted = true;
- protected void processModelClass(final ProcessingEnvironment processingEnv, final RoundEnvironment roundEnv, final TypeElement classElement) {
+ protected void processModelClass(final ProcessingEnvironment processingEnv, final RoundEnvironment roundEnv,
+ final TypeElement classElement, Set<String> propertyPlaceholderDefinitions, final boolean last) {
final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
String packageName = javaTypeName.substring(0, javaTypeName.lastIndexOf("."));
@@ -128,13 +129,20 @@ public class CoreEipAnnotationProcessorHelper {
fileName = name + ".json";
}
- // write json schema
- processFile(processingEnv, packageName, fileName, writer -> writeJSonSchemeDocumentation(processingEnv, writer, roundEnv, classElement, rootElement, javaTypeName, name));
- }
+ // write json schema and property placeholder provider
+ processFile(processingEnv, packageName, fileName, writer -> writeJSonSchemeDocumentation(processingEnv, writer,
+ roundEnv, classElement, rootElement, javaTypeName, name, propertyPlaceholderDefinitions));
+ // if last then generate
+ if (last) {
+ // lets sort themfirst
+ writePropertyPlaceholderDefinitionsHelper(processingEnv, roundEnv, propertyPlaceholderDefinitions);
+ }
+ }
+ // TODO: rename this
protected void writeJSonSchemeDocumentation(ProcessingEnvironment processingEnv, PrintWriter writer, RoundEnvironment roundEnv, TypeElement classElement,
- XmlRootElement rootElement, String javaTypeName, String modelName) {
+ XmlRootElement rootElement, String javaTypeName, String modelName, Set<String> propertyPlaceholderDefinitions) {
// gather eip information
EipModel eipModel = findEipModelProperties(processingEnv, roundEnv, classElement, javaTypeName, modelName);
@@ -152,11 +160,11 @@ public class CoreEipAnnotationProcessorHelper {
writer.println(json);
// write property placeholder source code
- writePropertyPlaceholderProviderSource(processingEnv, writer, roundEnv, classElement, eipModel, eipOptions);
+ writePropertyPlaceholderProviderSource(processingEnv, writer, roundEnv, classElement, eipModel, eipOptions, propertyPlaceholderDefinitions);
}
protected void writePropertyPlaceholderProviderSource(ProcessingEnvironment processingEnv, PrintWriter writer, RoundEnvironment roundEnv, TypeElement classElement,
- EipModel eipModel, Set<EipOption> options) {
+ EipModel eipModel, Set<EipOption> options, Set<String> propertyPlaceholderDefinitions) {
// the following are valid class elements which we want to generate
boolean rest = classElement.getQualifiedName().toString().startsWith("org.apache.camel.model.rest");
@@ -175,6 +183,7 @@ public class CoreEipAnnotationProcessorHelper {
String fqn = "org.apache.camel.model.placeholder." + cn;
doWritePropertyPlaceholderProviderSource(processingEnv, parent, def, fqnDef, cn, fqn, options);
+ propertyPlaceholderDefinitions.add(fqnDef);
// we also need to generate from when we generate route as from can also configure property placeholders
if ("RouteDefinition".equals(def)) {
@@ -188,6 +197,7 @@ public class CoreEipAnnotationProcessorHelper {
options.add(new EipOption("uri", null, null, "java.lang.String", false, null, null, false, null, false, null, false, null, false));
doWritePropertyPlaceholderProviderSource(processingEnv, parent, def, fqnDef, cn, fqn, options);
+ propertyPlaceholderDefinitions.add(fqnDef);
}
}
@@ -301,6 +311,57 @@ public class CoreEipAnnotationProcessorHelper {
return option.getName();
}
+ private void writePropertyPlaceholderDefinitionsHelper(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv,
+ Set<String> propertyPlaceholderDefinitions) {
+ Writer w = null;
+ try {
+ JavaFileObject src = processingEnv.getFiler().createSourceFile("org.apache.camel.model.placeholder.DefinitionPropertiesPlaceholderProviderHelper");
+ w = src.openWriter();
+
+ w.write("/* Generated by camel-apt */\n");
+ w.write("package org.apache.camel.model.placeholder;\n");
+ w.write("\n");
+ w.write("import java.util.HashMap;\n");
+ w.write("import java.util.Map;\n");
+ w.write("import java.util.Optional;\n");
+ w.write("import java.util.function.Function;\n");
+ w.write("import java.util.function.Supplier;\n");
+ w.write("\n");
+ w.write("import org.apache.camel.model.DefinitionPropertyPlaceholderConfigurable;\n");
+ for (String def : propertyPlaceholderDefinitions) {
+ w.write("import " + def + ";\n");
+ }
+ w.write("\n");
+ w.write("public class DefinitionPropertiesPlaceholderProviderHelper {\n");
+ w.write("\n");
+ w.write(" private static final Map<Class, Function<Object, DefinitionPropertyPlaceholderConfigurable>> MAP;\n");
+ w.write(" static {\n");
+ w.write(" Map<Class, Function<Object, DefinitionPropertyPlaceholderConfigurable>> map = new HashMap<>();\n");
+ for (String def : propertyPlaceholderDefinitions) {
+ String cn = def.substring(def.lastIndexOf('.') + 1);
+ w.write(" map.put(" + cn + ".class, " + cn + "PropertyPlaceholderProvider::new);\n");
+ }
+ w.write(" MAP = map;\n");
+ w.write(" }\n");
+ w.write("\n");
+ w.write(" public static Optional<DefinitionPropertyPlaceholderConfigurable> provider(Object definition) {\n");
+ w.write(" Function<Object, DefinitionPropertyPlaceholderConfigurable> func = MAP.get(definition.getClass());\n");
+ w.write(" if (func != null) {\n");
+ w.write(" return Optional.of(func.apply(definition));\n");
+ w.write(" }\n");
+ w.write(" return Optional.empty();\n");
+ w.write(" }\n");
+ w.write("\n");
+ w.write("}\n");
+ w.write("\n");
+ } catch (Exception e) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Unable to process annotated elements in " + getClass().getSimpleName() + ": " + e.getMessage());
+ dumpExceptionToErrorFile("camel-apt-error.log", "Error processing annotation in " + getClass().getSimpleName(), e);
+ } finally {
+ IOHelper.close(w);
+ }
+ }
+
public String createParameterJsonSchema(EipModel eipModel, Set<EipOption> options) {
StringBuilder buffer = new StringBuilder("{");
// eip model
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelAnnotationProcessor.java
index 211f42b..5d1e380 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelAnnotationProcessor.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelAnnotationProcessor.java
@@ -16,8 +16,13 @@
*/
package org.apache.camel.tools.apt;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import java.util.Set;
-
+import java.util.TreeSet;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
@@ -38,19 +43,48 @@ public class ModelAnnotationProcessor extends AbstractCamelAnnotationProcessor {
@Override
protected void doProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws Exception {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(XmlRootElement.class);
- for (Element element : elements) {
- if (element instanceof TypeElement) {
- TypeElement classElement = (TypeElement) element;
-
- final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
- boolean core = javaTypeName.startsWith("org.apache.camel.model");
- boolean spring = javaTypeName.startsWith("org.apache.camel.spring") || javaTypeName.startsWith("org.apache.camel.core.xml");
- if (core) {
- coreProcessor.processModelClass(processingEnv, roundEnv, classElement);
- } else if (spring) {
- springProcessor.processModelClass(processingEnv, roundEnv, classElement);
- }
- }
+
+ Set<? extends Element> coreElements = elements.stream()
+ .filter(new Predicate<Element>() {
+ @Override
+ public boolean test(Element element) {
+ if (element instanceof TypeElement) {
+ TypeElement classElement = (TypeElement) element;
+
+ final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
+ return javaTypeName.startsWith("org.apache.camel.model");
+ }
+ return false;
+ }
+ }).collect(Collectors.toSet());
+
+ Set<? extends Element> springElements = elements.stream()
+ .filter(new Predicate<Element>() {
+ @Override
+ public boolean test(Element element) {
+ if (element instanceof TypeElement) {
+ TypeElement classElement = (TypeElement) element;
+
+ final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
+ return javaTypeName.startsWith("org.apache.camel.spring") || javaTypeName.startsWith("org.apache.camel.core.xml");
+ }
+ return false;
+ }
+ }).collect(Collectors.toSet());
+
+ // we want them to be sorted
+ Set<String> propertyPlaceholderDefinitions = new TreeSet<>(String::compareToIgnoreCase);
+
+ Iterator it = coreElements.iterator();
+ while (it.hasNext()) {
+ TypeElement classElement = (TypeElement) it.next();
+ coreProcessor.processModelClass(processingEnv, roundEnv, classElement, propertyPlaceholderDefinitions, !it.hasNext());
+ }
+
+ it = springElements.iterator();
+ while (it.hasNext()) {
+ TypeElement classElement = (TypeElement) it.next();
+ springProcessor.processModelClass(processingEnv, roundEnv, classElement, !it.hasNext());
}
}
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessorHelper.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessorHelper.java
index 2300352..75f3110 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessorHelper.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessorHelper.java
@@ -56,7 +56,8 @@ import static org.apache.camel.tools.apt.helper.Strings.safeNull;
*/
public class SpringAnnotationProcessorHelper {
- protected void processModelClass(final ProcessingEnvironment processingEnv, final RoundEnvironment roundEnv, final TypeElement classElement) {
+ protected void processModelClass(final ProcessingEnvironment processingEnv, final RoundEnvironment roundEnv,
+ final TypeElement classElement, final boolean last) {
final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
String packageName = javaTypeName.substring(0, javaTypeName.lastIndexOf("."));