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/06/21 08:52:21 UTC
[camel] 06/08: CAMEL-13663: camel-main-maven-plugin to generte
spring-boot tooling metadata to fool Java editors to have code completions
for Camel Main application.properties files.
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 6f01e564794cef5a3dad6365a86c3c335b2cedc5
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Jun 21 09:51:40 2019 +0200
CAMEL-13663: camel-main-maven-plugin to generte spring-boot tooling metadata to fool Java editors to have code completions for Camel Main application.properties files.
---
.../java/org/apache/camel/maven/AutowireMojo.java | 282 ---------------------
.../apache/camel/maven/SpringBootToolingMojo.java | 152 -----------
2 files changed, 434 deletions(-)
diff --git a/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/AutowireMojo.java b/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/AutowireMojo.java
deleted file mode 100644
index a742f4a..0000000
--- a/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/AutowireMojo.java
+++ /dev/null
@@ -1,282 +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
- *
- * 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.maven;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.apache.camel.catalog.CamelCatalog;
-import org.apache.camel.catalog.JSonSchemaHelper;
-import org.apache.camel.maven.model.AutowireData;
-import org.apache.camel.support.PatternHelper;
-import org.apache.camel.util.IOHelper;
-import org.apache.camel.util.OrderedProperties;
-import org.apache.camel.util.StringHelper;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.plugins.annotations.ResolutionScope;
-import org.reflections.Reflections;
-
-/**
- * Pre scans your project and prepare autowiring by classpath scanning
- */
-@Mojo(name = "autowire", defaultPhase = LifecyclePhase.PROCESS_CLASSES, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE)
-@Deprecated
-public class AutowireMojo extends AbstractMainMojo {
-
- /**
- * When autowiring has detected multiple implementations (2 or more) of a given interface, which
- * cannot be mapped, should they be logged so you can see and add manual mapping if needed.
- */
- @Parameter(property = "camel.logUnmapped", defaultValue = "false")
- protected boolean logUnmapped;
-
- /**
- * The output directory for generated autowire file
- */
- @Parameter(readonly = true, defaultValue = "${project.build.directory}/classes/META-INF/services/org/apache/camel/")
- protected File outFolder;
-
- /**
- * To exclude autowiring specific properties with these key names.
- * You can also configure a single entry and separate the excludes with comma
- */
- @Parameter(property = "camel.exclude")
- protected String[] exclude;
-
- /**
- * To include autowiring specific properties or component with these key names.
- * You can also configure a single entry and separate the includes with comma
- */
- @Parameter(property = "camel.include")
- protected String[] include;
-
- /**
- * To setup special mappings between known types as key=value pairs.
- * You can also configure a single entry and separate the mappings with comma
- */
- @Parameter(property = "camel.mappings")
- protected String[] mappings;
-
- /**
- * Optional mappings file loaded from classpath, with mapping that override any default mappings
- */
- @Parameter(defaultValue = "${project.build.directory}/classes/camel-main-mappings.properties")
- protected File mappingsFile;
-
- @Override
- public void execute() throws MojoExecutionException, MojoFailureException {
- // load default mappings
- Properties mappingProperties = loadDefaultMappings();
- getLog().debug("Loaded default-mappings: " + mappingProperties);
- // add extra mappings
- if (this.mappings != null) {
- for (String m : this.mappings) {
- String key = StringHelper.before(m, "=");
- String value = StringHelper.after(m, "=");
- if (key != null && value != null) {
- mappingProperties.setProperty(key, value);
- getLog().debug("Added mapping from pom.xml: " + key + "=" + value);
- }
- }
- }
- Properties mappingFileProperties = loadMappingsFile();
- if (!mappingFileProperties.isEmpty()) {
- getLog().debug("Loaded mappings file: " + mappingsFile + " with mappings: " + mappingFileProperties);
- mappingProperties.putAll(mappingFileProperties);
- }
-
- final List<AutowireData> autowires = new ArrayList<>();
- ComponentCallback callback = (componentName, name, type, javaType, description, defaultValue) -> {
- if ("object".equals(type)) {
- if (!isValidPropertyName(componentName, name)) {
- getLog().debug("Skipping property name: " + name);
- return;
- }
- try {
- Class clazz = classLoader.loadClass(javaType);
- if (clazz.isInterface() && isComplexUserType(clazz)) {
- Set<Class<?>> classes = reflections.getSubTypesOf(clazz);
- // filter classes (must not be interfaces, must be public, must not be abstract, must be top level) and also a valid autowire class
- classes = classes.stream().filter(
- c -> !c.isInterface()
- && Modifier.isPublic(c.getModifiers())
- && !Modifier.isAbstract(c.getModifiers())
- && c.getEnclosingClass() == null
- && isValidAutowireClass(c))
- .collect(Collectors.toSet());
- Class best = chooseBestKnownType(componentName, name, clazz, classes, mappingProperties);
- if (best != null) {
- String key = "camel.component." + componentName + "." + name;
- String value = "#class:" + best.getName();
- getLog().debug(key + "=" + value);
- autowires.add(new AutowireData(key, value));
-
- // TODO: get options from best class (getter/setter pairs)
- // we dont have documentation
- // add as spring boot options
-
- }
- }
-
- } catch (Exception e) {
- // ignore
- getLog().debug("Cannot load class: " + name, e);
- }
- }
- };
-
- // perform the work with this callback
- doExecute(callback);
-
- if (!autowires.isEmpty()) {
- outFolder.mkdirs();
- File file = new File(outFolder, "autowire.properties");
- try {
- FileOutputStream fos = new FileOutputStream(file, false);
- fos.write("# Generated by camel build tools\n".getBytes());
- for (AutowireData data : autowires) {
- fos.write(data.getKey().getBytes());
- fos.write('=');
- fos.write(data.getValue().getBytes());
- fos.write('\n');
- }
- IOHelper.close(fos);
- getLog().info("Created file: " + file + " (autowire by classpath: " + autowires.size() + ")");
- } catch (Throwable e) {
- throw new MojoFailureException("Cannot write to file " + file + " due " + e.getMessage(), e);
- }
- }
- }
-
- protected Properties loadDefaultMappings() throws MojoFailureException {
- Properties mappings = new OrderedProperties();
- try {
- InputStream is = AutowireMojo.class.getResourceAsStream("/default-mappings.properties");
- if (is != null) {
- mappings.load(is);
- }
- } catch (IOException e) {
- throw new MojoFailureException("Cannot load default-mappings.properties from classpath");
- }
- return mappings;
- }
-
- protected Properties loadMappingsFile() throws MojoFailureException {
- Properties mappings = new OrderedProperties();
- if (mappingsFile.exists() && mappingsFile.isFile()) {
- try {
- InputStream is = new FileInputStream(mappingsFile);
- mappings.load(is);
- } catch (IOException e) {
- throw new MojoFailureException("Cannot load file: " + mappingsFile);
- }
- }
- return mappings;
- }
-
- protected Class chooseBestKnownType(String componentName, String optionName, Class type, Set<Class<?>> candidates, Properties knownTypes) {
- String known = knownTypes.getProperty(type.getName());
- if (known != null) {
- for (String k : known.split(";")) {
- // special as we should skip this option
- if ("#skip#".equals(k)) {
- return null;
- }
- Class found = candidates.stream().filter(c -> c.getName().equals(k)).findFirst().orElse(null);
- if (found != null) {
- return found;
- }
- }
- }
-
- if (candidates.size() == 1) {
- return candidates.iterator().next();
- } else if (candidates.size() > 1) {
- if (logUnmapped) {
- getLog().debug("Cannot chose best type: " + type.getName() + " among " + candidates.size() + " implementations: " + candidates);
- getLog().info("Cannot autowire option camel.component." + componentName + "." + optionName
- + " as the interface: " + type.getName() + " has " + candidates.size() + " implementations in the classpath:");
- for (Class c : candidates) {
- getLog().info("\t\t" + c.getName());
- }
- }
- }
- return null;
- }
-
- protected boolean isValidPropertyName(String componentName, String name) {
- // we want to regard names as the same if they are using dash or not, and also to be case insensitive.
- String prefix = "camel.component." + componentName + ".";
- name = StringHelper.dashToCamelCase(name);
-
- if (exclude != null && exclude.length > 0) {
- // works on components too
- for (String pattern : exclude) {
- pattern = pattern.trim();
- pattern = StringHelper.dashToCamelCase(pattern);
- if (PatternHelper.matchPattern(componentName, pattern)) {
- return false;
- }
- if (PatternHelper.matchPattern(name, pattern) || PatternHelper.matchPattern(prefix + name, pattern)) {
- return false;
- }
- }
- }
-
- if (include != null && include.length > 0) {
- for (String pattern : include) {
- pattern = pattern.trim();
- pattern = StringHelper.dashToCamelCase(pattern);
- if (PatternHelper.matchPattern(componentName, pattern)) {
- return true;
- }
- if (PatternHelper.matchPattern(name, pattern) || PatternHelper.matchPattern(prefix + name, pattern)) {
- return true;
- }
- }
- // we have include enabled and none matched so it should be false
- return false;
- }
-
- return true;
- }
-
- private static boolean isComplexUserType(Class type) {
- // lets consider all non java, as complex types
- return type != null && !type.isPrimitive() && !type.getName().startsWith("java.");
- }
-
- protected boolean isValidAutowireClass(Class clazz) {
- // skip all from Apache Camel and regular JDK as they would be default anyway
- return !clazz.getName().startsWith("org.apache.camel");
- }
-
-}
diff --git a/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/SpringBootToolingMojo.java b/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/SpringBootToolingMojo.java
deleted file mode 100644
index 9691afc..0000000
--- a/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/SpringBootToolingMojo.java
+++ /dev/null
@@ -1,152 +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
- *
- * 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.maven;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.camel.maven.model.SpringBootData;
-import org.apache.camel.util.IOHelper;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.plugins.annotations.ResolutionScope;
-
-import static org.apache.camel.util.StringHelper.camelCaseToDash;
-
-/**
- * Pre scans your project and builds spring boot tooling metafiles which fools tools to
- * offer code completion for editing properties files.
- */
-@Mojo(name = "spring-boot-tooling", defaultPhase = LifecyclePhase.PROCESS_CLASSES, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE)
-@Deprecated
-public class SpringBootToolingMojo extends AbstractMainMojo {
-
- /**
- * The output directory for generated spring boot tooling file
- */
- @Parameter(readonly = true, defaultValue = "${project.build.directory}/../src/main/resources/META-INF/")
- protected File outFolder;
-
- @Override
- public void execute() throws MojoExecutionException, MojoFailureException {
-
- final List<SpringBootData> componentData = new ArrayList<>();
- ComponentCallback callback = (componentName, name, type, javaType, description, defaultValue) -> {
- // we want to use dash in the name
- String dash = camelCaseToDash(name);
- String key = "camel.component." + componentName + "." + dash;
- componentData.add(new SpringBootData(key, springBootJavaType(javaType), description, defaultValue));
- };
-
- // perform the work with this callback
- doExecute(callback);
-
- if (!componentData.isEmpty()) {
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < componentData.size(); i++) {
- SpringBootData row = componentData.get(i);
- sb.append(" {\n");
- sb.append(" \"name\": \"" + row.getName() + "\",\n");
- sb.append(" \"type\": \"" + row.getJavaType() + "\",\n");
- sb.append(" \"description\": \"" + row.getDescription() + "\"");
- if (row.getDefaultValue() != null) {
- sb.append(",\n");
- if (springBootDefaultValueQuotes(row.getJavaType())) {
- sb.append(" \"defaultValue\": \"" + row.getDefaultValue() + "\"\n");
- } else {
- sb.append(" \"defaultValue\": " + row.getDefaultValue() + "\n");
- }
- } else {
- sb.append("\n");
- }
- if (i < componentData.size() - 1) {
- sb.append(" },\n");
- } else {
- sb.append(" }\n");
- }
- }
- sb.append(" ]\n");
- sb.append("}\n");
-
- // okay then add the components into the main json at the end so they get merged together
- // load camel-main metadata
- String mainJson = loadCamelMainConfigurationMetadata();
- if (mainJson == null) {
- getLog().warn("Cannot load camel-main-configuration-metadata.json from within the camel-main JAR from the classpath."
- + " Not possible to build spring boot configuration file for this project");
- return;
- }
- int pos = mainJson.lastIndexOf(" }");
- String newJson = mainJson.substring(0, pos);
- newJson = newJson + " },\n";
- newJson = newJson + sb.toString();
-
- outFolder.mkdirs();
- File file = new File(outFolder, "spring-configuration-metadata.json");
- try {
- FileOutputStream fos = new FileOutputStream(file, false);
- fos.write(newJson.getBytes());
- IOHelper.close(fos);
- getLog().info("Created file: " + file);
- } catch (Throwable e) {
- throw new MojoFailureException("Cannot write to file " + file + " due " + e.getMessage(), e);
- }
- }
- }
-
- private static String springBootJavaType(String javaType) {
- if ("boolean".equalsIgnoreCase(javaType)) {
- return "java.lang.Boolean";
- } else if ("int".equalsIgnoreCase(javaType)) {
- return "java.lang.Integer";
- } else if ("long".equalsIgnoreCase(javaType)) {
- return "java.lang.Long";
- } else if ("string".equalsIgnoreCase(javaType)) {
- return "java.lang.String";
- }
- return javaType;
- }
-
- private static boolean springBootDefaultValueQuotes(String javaType) {
- if ("java.lang.Boolean".equalsIgnoreCase(javaType)) {
- return false;
- } else if ("java.lang.Integer".equalsIgnoreCase(javaType)) {
- return false;
- } else if ("java.lang.Long".equalsIgnoreCase(javaType)) {
- return false;
- }
- return true;
- }
-
- protected String loadCamelMainConfigurationMetadata() throws MojoFailureException {
- try {
- InputStream is = classLoader.getResourceAsStream("META-INF/camel-main-configuration-metadata.json");
- String text = IOHelper.loadText(is);
- IOHelper.close(is);
- return text;
- } catch (Throwable e) {
- throw new MojoFailureException("Error during discovering camel-main from classpath due " + e.getMessage(), e);
- }
- }
-}