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/14 07:53:06 UTC
[camel] 12/21: 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 master
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 59309b7c1d1116ad658f0b436abefd3e4b786f19
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 13 09:03:36 2019 +0200
CAMEL-13850: Optimize model classes to provide changeable properties that support property placeholders to avoid reflection. Work in progress.
---
.../apt/CoreEipAnnotationProcessorHelper.java | 180 +-----------------
.../tools/apt/PropertyPlaceholderGenerator.java | 206 +++++++++++++++++++++
2 files changed, 212 insertions(+), 174 deletions(-)
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 93f57a0..f003530 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
@@ -17,7 +17,6 @@
package org.apache.camel.tools.apt;
import java.io.PrintWriter;
-import java.io.Writer;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -35,8 +34,6 @@ import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
@@ -47,17 +44,16 @@ import javax.xml.bind.annotation.XmlValue;
import org.apache.camel.spi.AsPredicate;
import org.apache.camel.spi.Metadata;
-import org.apache.camel.tools.apt.helper.IOHelper;
import org.apache.camel.tools.apt.helper.JsonSchemaHelper;
import org.apache.camel.tools.apt.helper.Strings;
-import static org.apache.camel.tools.apt.AnnotationProcessorHelper.dumpExceptionToErrorFile;
import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findJavaDoc;
import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findTypeElement;
import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findTypeElementChildren;
import static org.apache.camel.tools.apt.AnnotationProcessorHelper.hasSuperClass;
import static org.apache.camel.tools.apt.AnnotationProcessorHelper.implementsInterface;
import static org.apache.camel.tools.apt.AnnotationProcessorHelper.processFile;
+import static org.apache.camel.tools.apt.PropertyPlaceholderGenerator.generatePropertyPlaceholderDefinitionsHelper;
import static org.apache.camel.tools.apt.helper.JsonSchemaHelper.sanitizeDescription;
import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
import static org.apache.camel.tools.apt.helper.Strings.isNullOrEmpty;
@@ -135,7 +131,7 @@ public class CoreEipAnnotationProcessorHelper {
// if last then generate source code for helper that contains all the generated property placeholder providers
// (this allows fast property placeholders at runtime without reflection overhead)
if (last) {
- writePropertyPlaceholderDefinitionsHelper(processingEnv, roundEnv, propertyPlaceholderDefinitions);
+ generatePropertyPlaceholderDefinitionsHelper(processingEnv, roundEnv, propertyPlaceholderDefinitions);
}
}
@@ -182,7 +178,7 @@ public class CoreEipAnnotationProcessorHelper {
String cn = def + "PropertyPlaceholderProvider";
String fqn = "org.apache.camel.model.placeholder." + cn;
- doWritePropertyPlaceholderProviderSource(processingEnv, parent, def, fqnDef, cn, fqn, options);
+ PropertyPlaceholderGenerator.generatePropertyPlaceholderProviderSource(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
@@ -196,175 +192,11 @@ public class CoreEipAnnotationProcessorHelper {
options.add(new EipOption("id", null, null, "java.lang.String", false, null, null, false, null, false, null, false, null, false));
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);
+ PropertyPlaceholderGenerator.generatePropertyPlaceholderProviderSource(processingEnv, parent, def, fqnDef, cn, fqn, options);
propertyPlaceholderDefinitions.add(fqnDef);
}
}
- private void doWritePropertyPlaceholderProviderSource(ProcessingEnvironment processingEnv, TypeElement parent,
- String def, String fqnDef, String cn, String fqn,
- Set<EipOption> options) {
-
- Writer w = null;
- try {
- JavaFileObject src = processingEnv.getFiler().createSourceFile(fqn, parent);
- 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.function.Consumer;\n");
- w.write("import java.util.function.Supplier;\n");
- w.write("\n");
- w.write("import org.apache.camel.CamelContext;\n");
- w.write("import " + fqnDef + ";\n");
- w.write("import org.apache.camel.spi.PropertyPlaceholderConfigurer;\n");
- w.write("\n");
- w.write("public class " + cn + " implements PropertyPlaceholderConfigurer {\n");
- w.write("\n");
- w.write(" private final Map<String, Supplier<String>> readPlaceholders = new HashMap<>();\n");
- w.write(" private final Map<String, Consumer<String>> writePlaceholders = new HashMap<>();\n");
- w.write("\n");
-
- // add constructor
- w.write(" public " + cn + "(Object obj) {\n");
- w.write(" " + def + " definition = (" + def + ") obj;\n");
- w.write("\n");
-
- // only include string types as they are the only ones we can use for property placeholders
- boolean found = false;
- for (EipOption option : options) {
- if ("java.lang.String".equals(option.getType())) {
- found = true;
- String getOrSet = sanitizePropertyPlaceholderOptionName(def, option);
- getOrSet = Character.toUpperCase(getOrSet.charAt(0)) + getOrSet.substring(1);
- w.write(" readPlaceholders.put(\"" + option.getName() + "\", definition::get" + getOrSet + ");\n");
- w.write(" writePlaceholders.put(\"" + option.getName() + "\", definition::set" + getOrSet + ");\n");
- }
- }
- if (!found) {
- w.write("\n");
- }
-
- w.write(" }\n");
- w.write("\n");
- w.write(" @Override\n");
- w.write(" public Map<String, Supplier<String>> getReadPropertyPlaceholderOptions(CamelContext camelContext) {\n");
- w.write(" return readPlaceholders;\n");
- w.write(" }\n");
- w.write("\n");
- w.write(" @Override\n");
- w.write(" public Map<String, Consumer<String>> getWritePropertyPlaceholderOptions(CamelContext camelContext) {\n");
- w.write(" return writePlaceholders;\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);
- }
- }
-
- /**
- * Some models have different setter/getter names vs the xml name (eg as defined in @XmlAttribute).
- * So we need to correct this using this method.
- */
- public String sanitizePropertyPlaceholderOptionName(String def, EipOption option) {
- if ("SimpleExpression".equals(def) || "JsonPathExpression".equals(def)) {
- if ("resultType".equals(option.getName())) {
- return "resultTypeName";
- }
- } else if ("EnrichDefinition".equals(def) || "PollEnrichDefinition".equals(def) || "ClaimCheckDefinition".equals(def)) {
- if ("strategyRef".equals(option.getName())) {
- return "aggregationStrategyRef";
- } else if ("strategyMethodName".equals(option.getName())) {
- return "aggregationStrategyMethodName";
- } else if ("strategyMethodAllowNull".equals(option.getName())) {
- return "aggregationStrategyMethodAllowNull";
- }
- } else if ("MethodCallExpression".equals(def)) {
- if ("beanType".equals(option.getName())) {
- return "beanTypeName";
- }
- } else if ("XPathExpression".equals(def)) {
- if ("documentType".equals(option.getName())) {
- return "documentTypeName";
- } else if ("resultType".equals(option.getName())) {
- return "resultTypeName";
- }
- } else if ("WireTapDefinition".equals(def)) {
- if ("processorRef".equals(option.getName())) {
- return "newExchangeProcessorRef";
- }
- } else if ("TidyMarkupDataFormat".equals(def)) {
- if ("dataObjectType".equals(option.getName())) {
- return "dataObjectTypeName";
- }
- } else if ("BindyDataFormat".equals(def)) {
- if ("classType".equals(option.getName())) {
- return "classTypeAsString";
- }
- }
-
- 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.spi.PropertyPlaceholderConfigurer;\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, PropertyPlaceholderConfigurer>> MAP;\n");
- w.write(" static {\n");
- w.write(" Map<Class, Function<Object, PropertyPlaceholderConfigurer>> map = new HashMap<>(" + propertyPlaceholderDefinitions.size() + ");\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<PropertyPlaceholderConfigurer> provider(Object definition) {\n");
- w.write(" Function<Object, PropertyPlaceholderConfigurer> 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
@@ -1277,7 +1109,7 @@ public class CoreEipAnnotationProcessorHelper {
return false;
}
- private static final class EipModel {
+ public static final class EipModel {
private String name;
private String title;
@@ -1379,7 +1211,7 @@ public class CoreEipAnnotationProcessorHelper {
}
}
- private static final class EipOption {
+ public static final class EipOption {
private String name;
private String displayName;
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/PropertyPlaceholderGenerator.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/PropertyPlaceholderGenerator.java
new file mode 100644
index 0000000..263f86e
--- /dev/null
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/PropertyPlaceholderGenerator.java
@@ -0,0 +1,206 @@
+/*
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.tools.apt;
+
+import java.io.Writer;
+import java.util.Set;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+
+import org.apache.camel.tools.apt.helper.IOHelper;
+
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.dumpExceptionToErrorFile;
+
+public class PropertyPlaceholderGenerator {
+
+ public static void generatePropertyPlaceholderProviderSource(ProcessingEnvironment processingEnv, TypeElement parent,
+ String def, String fqnDef, String cn, String fqn,
+ Set<CoreEipAnnotationProcessorHelper.EipOption> options) {
+
+ Writer w = null;
+ try {
+ JavaFileObject src = processingEnv.getFiler().createSourceFile(fqn, parent);
+ 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.function.Consumer;\n");
+ w.write("import java.util.function.Supplier;\n");
+ w.write("\n");
+ w.write("import org.apache.camel.CamelContext;\n");
+ w.write("import " + fqnDef + ";\n");
+ w.write("import org.apache.camel.spi.PropertyPlaceholderConfigurer;\n");
+ w.write("\n");
+ w.write("/**\n");
+ w.write(" * Source code generated by org.apache.camel:apt\n");
+ w.write(" */\n");
+ w.write("public class " + cn + " implements PropertyPlaceholderConfigurer {\n");
+ w.write("\n");
+ w.write(" private final Map<String, Supplier<String>> readPlaceholders = new HashMap<>();\n");
+ w.write(" private final Map<String, Consumer<String>> writePlaceholders = new HashMap<>();\n");
+ w.write("\n");
+
+ // add constructor
+ w.write(" public " + cn + "(Object obj) {\n");
+ w.write(" " + def + " definition = (" + def + ") obj;\n");
+ w.write("\n");
+
+ // only include string types as they are the only ones we can use for property placeholders
+ boolean found = false;
+ for (CoreEipAnnotationProcessorHelper.EipOption option : options) {
+ if ("java.lang.String".equals(option.getType())) {
+ found = true;
+ String getOrSet = sanitizePropertyPlaceholderOptionName(def, option);
+ getOrSet = Character.toUpperCase(getOrSet.charAt(0)) + getOrSet.substring(1);
+ w.write(" readPlaceholders.put(\"" + option.getName() + "\", definition::get" + getOrSet + ");\n");
+ w.write(" writePlaceholders.put(\"" + option.getName() + "\", definition::set" + getOrSet + ");\n");
+ }
+ }
+ if (!found) {
+ w.write("\n");
+ }
+
+ w.write(" }\n");
+ w.write("\n");
+ w.write(" @Override\n");
+ w.write(" public Map<String, Supplier<String>> getReadPropertyPlaceholderOptions(CamelContext camelContext) {\n");
+ w.write(" return readPlaceholders;\n");
+ w.write(" }\n");
+ w.write("\n");
+ w.write(" @Override\n");
+ w.write(" public Map<String, Consumer<String>> getWritePropertyPlaceholderOptions(CamelContext camelContext) {\n");
+ w.write(" return writePlaceholders;\n");
+ w.write(" }\n");
+ w.write("\n");
+ w.write("}\n");
+ w.write("\n");
+ } catch (Exception e) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Unable to generate source code file: " + fqn + ": " + e.getMessage());
+ dumpExceptionToErrorFile("camel-apt-error.log", "Unable to generate source code file: " + fqn, e);
+ } finally {
+ IOHelper.close(w);
+ }
+ }
+
+ public static void generatePropertyPlaceholderDefinitionsHelper(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv,
+ Set<String> propertyPlaceholderDefinitions) {
+
+ String fqn = "org.apache.camel.model.placeholder.DefinitionPropertiesPlaceholderProviderHelper";
+
+ Writer w = null;
+ try {
+ JavaFileObject src = processingEnv.getFiler().createSourceFile(fqn);
+ 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.spi.PropertyPlaceholderConfigurer;\n");
+ for (String def : propertyPlaceholderDefinitions) {
+ w.write("import " + def + ";\n");
+ }
+ w.write("\n");
+ w.write("/**\n");
+ w.write(" * Source code generated by org.apache.camel:apt\n");
+ w.write(" */\n");
+ w.write("public class DefinitionPropertiesPlaceholderProviderHelper {\n");
+ w.write("\n");
+ w.write(" private static final Map<Class, Function<Object, PropertyPlaceholderConfigurer>> MAP;\n");
+ w.write(" static {\n");
+ w.write(" Map<Class, Function<Object, PropertyPlaceholderConfigurer>> map = new HashMap<>(" + propertyPlaceholderDefinitions.size() + ");\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<PropertyPlaceholderConfigurer> provider(Object definition) {\n");
+ w.write(" Function<Object, PropertyPlaceholderConfigurer> 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 generate source code file: " + fqn + ": " + e.getMessage());
+ dumpExceptionToErrorFile("camel-apt-error.log", "Unable to generate source code file: " + fqn, e);
+ } finally {
+ IOHelper.close(w);
+ }
+ }
+
+ /**
+ * Some models have different setter/getter names vs the xml name (eg as defined in @XmlAttribute).
+ * So we need to correct this using this method.
+ */
+ private static String sanitizePropertyPlaceholderOptionName(String def, CoreEipAnnotationProcessorHelper.EipOption option) {
+ if ("SimpleExpression".equals(def) || "JsonPathExpression".equals(def)) {
+ if ("resultType".equals(option.getName())) {
+ return "resultTypeName";
+ }
+ } else if ("EnrichDefinition".equals(def) || "PollEnrichDefinition".equals(def) || "ClaimCheckDefinition".equals(def)) {
+ if ("strategyRef".equals(option.getName())) {
+ return "aggregationStrategyRef";
+ } else if ("strategyMethodName".equals(option.getName())) {
+ return "aggregationStrategyMethodName";
+ } else if ("strategyMethodAllowNull".equals(option.getName())) {
+ return "aggregationStrategyMethodAllowNull";
+ }
+ } else if ("MethodCallExpression".equals(def)) {
+ if ("beanType".equals(option.getName())) {
+ return "beanTypeName";
+ }
+ } else if ("XPathExpression".equals(def)) {
+ if ("documentType".equals(option.getName())) {
+ return "documentTypeName";
+ } else if ("resultType".equals(option.getName())) {
+ return "resultTypeName";
+ }
+ } else if ("WireTapDefinition".equals(def)) {
+ if ("processorRef".equals(option.getName())) {
+ return "newExchangeProcessorRef";
+ }
+ } else if ("TidyMarkupDataFormat".equals(def)) {
+ if ("dataObjectType".equals(option.getName())) {
+ return "dataObjectTypeName";
+ }
+ } else if ("BindyDataFormat".equals(def)) {
+ if ("classType".equals(option.getName())) {
+ return "classTypeAsString";
+ }
+ }
+
+ return option.getName();
+ }
+
+}