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 <claus.ib...@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); - } - } -}