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();
+    }
+
+}