This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
commit 28486bea0558ae4aaefcac4279d4f15ae2891a80 Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Mon Jan 20 10:23:12 2020 +0100 [CAMEL-14410] Switch to camel 3.1.0-SNAPSHOT --- camel-spring-boot/pom.xml | 13 + pom.xml | 2 +- .../pom.xml | 5 + .../maven/AbstractSpringBootGenerator.java | 11 +- .../maven/PrepareCatalogSpringBootMojo.java | 2 - .../maven/SpringBootAutoConfigurationMojo.java | 245 ++++++------- ...pdateSpringBootAutoConfigurationReadmeMojo.java | 402 +++++++++++++++++++++ 7 files changed, 542 insertions(+), 138 deletions(-) diff --git a/camel-spring-boot/pom.xml b/camel-spring-boot/pom.xml index 3087d69..e7401cd 100644 --- a/camel-spring-boot/pom.xml +++ b/camel-spring-boot/pom.xml @@ -172,6 +172,19 @@ </goals> <phase>process-classes</phase> </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.camel.springboot</groupId> + <artifactId>camel-spring-boot-generator-maven-plugin</artifactId> + <version>${project.version}</version> + <configuration> + <!-- set to true to make build fail fast if missing documentation in docs files --> + <failFast>true</failFast> + <!-- set to true to make build fail if an option has no description --> + <failOnMissingDescription>true</failOnMissingDescription> + </configuration> + <executions> <execution> <id>readme</id> <goals> diff --git a/pom.xml b/pom.xml index c660115..d128e1e 100644 --- a/pom.xml +++ b/pom.xml @@ -115,7 +115,7 @@ <spring-boot-version>2.2.3.RELEASE</spring-boot-version> <!-- Camel target version --> - <camel-version>3.0.0</camel-version> + <camel-version>3.1.0-SNAPSHOT</camel-version> <!-- versions --> <aether-version>1.0.2.v20150114</aether-version> diff --git a/tooling/camel-spring-boot-generator-maven-plugin/pom.xml b/tooling/camel-spring-boot-generator-maven-plugin/pom.xml index 515ac25..f8e4c5a 100644 --- a/tooling/camel-spring-boot-generator-maven-plugin/pom.xml +++ b/tooling/camel-spring-boot-generator-maven-plugin/pom.xml @@ -54,6 +54,11 @@ </dependency> <dependency> <groupId>org.apache.camel</groupId> + <artifactId>camel-tooling-util</artifactId> + <version>${camel-version}</version> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> <artifactId>bom-generator-maven-plugin</artifactId> <version>${camel-version}</version> </dependency> diff --git a/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/AbstractSpringBootGenerator.java b/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/AbstractSpringBootGenerator.java index b9a2bc1..8b5524c 100644 --- a/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/AbstractSpringBootGenerator.java +++ b/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/AbstractSpringBootGenerator.java @@ -17,35 +17,28 @@ package org.apache.camel.springboot.maven; import java.io.File; -import java.io.FileFilter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOError; import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.function.Supplier; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; import java.util.zip.ZipEntry; +import org.apache.camel.tooling.util.PackageHelper; import org.apache.commons.io.IOUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; 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.apache.maven.project.MavenProject; -import static org.apache.camel.maven.packaging.PackageHelper.loadText; - public abstract class AbstractSpringBootGenerator extends AbstractMojo { /** @@ -144,7 +137,7 @@ public abstract class AbstractSpringBootGenerator extends AbstractMojo { protected static String loadJson(JarFile jar, JarEntry je) { try (InputStream is = jar.getInputStream(je)) { - return loadText(is); + return PackageHelper.loadText(is); } catch (IOException e) { throw new IOError(e); } diff --git a/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/PrepareCatalogSpringBootMojo.java b/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/PrepareCatalogSpringBootMojo.java index d8b9fb4..0889287 100644 --- a/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/PrepareCatalogSpringBootMojo.java +++ b/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/PrepareCatalogSpringBootMojo.java @@ -37,8 +37,6 @@ 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.maven.packaging.PackageHelper.loadText; - /** * Prepares the Spring Boot provider camel catalog to include component it supports */ diff --git a/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/SpringBootAutoConfigurationMojo.java b/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/SpringBootAutoConfigurationMojo.java index fb4f3bd..4436bde 100644 --- a/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/SpringBootAutoConfigurationMojo.java +++ b/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/SpringBootAutoConfigurationMojo.java @@ -45,7 +45,7 @@ import java.util.zip.ZipEntry; import javax.annotation.Generated; import javax.xml.bind.annotation.XmlTransient; -import org.apache.camel.maven.packaging.JSonSchemaHelper; +import org.apache.camel.maven.packaging.AbstractGeneratorMojo; import org.apache.camel.maven.packaging.model.ComponentModel; import org.apache.camel.maven.packaging.model.ComponentOptionModel; import org.apache.camel.maven.packaging.model.DataFormatModel; @@ -55,14 +55,16 @@ import org.apache.camel.maven.packaging.model.LanguageModel; import org.apache.camel.maven.packaging.model.LanguageOptionModel; import org.apache.camel.maven.packaging.model.OtherModel; import org.apache.camel.maven.packaging.model.OtherOptionModel; -import org.apache.camel.maven.packaging.srcgen.Annotation; -import org.apache.camel.maven.packaging.srcgen.GenericType; -import org.apache.camel.maven.packaging.srcgen.JavaClass; -import org.apache.camel.maven.packaging.srcgen.Method; -import org.apache.camel.maven.packaging.srcgen.Property; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; +import org.apache.camel.tooling.util.JSonSchemaHelper; +import org.apache.camel.tooling.util.PackageHelper; +import org.apache.camel.tooling.util.srcgen.Annotation; +import org.apache.camel.tooling.util.srcgen.GenericType; +import org.apache.camel.tooling.util.srcgen.JavaClass; +import org.apache.camel.tooling.util.srcgen.Method; +import org.apache.camel.tooling.util.srcgen.Property; import org.apache.commons.io.FileUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; @@ -89,15 +91,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; -import static org.apache.camel.maven.packaging.AbstractGeneratorMojo.updateResource; -import static org.apache.camel.maven.packaging.JSonSchemaHelper.getPropertyDefaultValue; -import static org.apache.camel.maven.packaging.JSonSchemaHelper.getPropertyDescriptionValue; -import static org.apache.camel.maven.packaging.JSonSchemaHelper.getPropertyJavaType; -import static org.apache.camel.maven.packaging.JSonSchemaHelper.getPropertyType; -import static org.apache.camel.maven.packaging.JSonSchemaHelper.getSafeValue; -import static org.apache.camel.maven.packaging.JSonSchemaHelper.parseJsonSchema; -import static org.apache.camel.maven.packaging.PackageHelper.loadText; - /** * Generate Spring Boot auto configuration files for Camel components and data * formats. @@ -918,11 +911,11 @@ public class SpringBootAutoConfigurationMojo extends AbstractSpringBootGenerator } if (optionName != null) { - javaType = getPropertyJavaType(rows, optionName); - type = getPropertyType(rows, optionName); - defaultValue = getPropertyDefaultValue(rows, optionName); + javaType = JSonSchemaHelper.getPropertyJavaType(rows, optionName); + type = JSonSchemaHelper.getPropertyType(rows, optionName); + defaultValue = JSonSchemaHelper.getPropertyDefaultValue(rows, optionName); // favour description from the model - description = getPropertyDescriptionValue(rows, optionName); + description = JSonSchemaHelper.getPropertyDescriptionValue(rows, optionName); if (description != null) { prop.getField().getJavaDoc().setFullText(description); } @@ -1883,56 +1876,56 @@ public class SpringBootAutoConfigurationMojo extends AbstractSpringBootGenerator List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false); ComponentModel component = new ComponentModel(); - component.setScheme(getSafeValue("scheme", rows)); - component.setSyntax(getSafeValue("syntax", rows)); - component.setAlternativeSyntax(getSafeValue("alternativeSyntax", rows)); - component.setTitle(getSafeValue("title", rows)); - component.setDescription(getSafeValue("description", rows)); + component.setScheme(JSonSchemaHelper.getSafeValue("scheme", rows)); + component.setSyntax(JSonSchemaHelper.getSafeValue("syntax", rows)); + component.setAlternativeSyntax(JSonSchemaHelper.getSafeValue("alternativeSyntax", rows)); + component.setTitle(JSonSchemaHelper.getSafeValue("title", rows)); + component.setDescription(JSonSchemaHelper.getSafeValue("description", rows)); component.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows)); - component.setLabel(getSafeValue("label", rows)); - component.setDeprecated(getSafeValue("deprecated", rows)); - component.setDeprecationNote(getSafeValue("deprecationNote", rows)); - component.setConsumerOnly(getSafeValue("consumerOnly", rows)); - component.setProducerOnly(getSafeValue("producerOnly", rows)); - component.setJavaType(getSafeValue("javaType", rows)); - component.setGroupId(getSafeValue("groupId", rows)); - component.setArtifactId(getSafeValue("artifactId", rows)); - component.setVersion(getSafeValue("version", rows)); + component.setLabel(JSonSchemaHelper.getSafeValue("label", rows)); + component.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows)); + component.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", rows)); + component.setConsumerOnly(JSonSchemaHelper.getSafeValue("consumerOnly", rows)); + component.setProducerOnly(JSonSchemaHelper.getSafeValue("producerOnly", rows)); + component.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows)); + component.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows)); + component.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows)); + component.setVersion(JSonSchemaHelper.getSafeValue("version", rows)); rows = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true); for (Map<String, String> row : rows) { ComponentOptionModel option = new ComponentOptionModel(); - option.setName(getSafeValue("name", row)); - option.setDisplayName(getSafeValue("displayName", row)); - option.setKind(getSafeValue("kind", row)); - option.setType(getSafeValue("type", row)); - option.setJavaType(getSafeValue("javaType", row)); - option.setDeprecated(getSafeValue("deprecated", row)); - option.setDeprecationNote(getSafeValue("deprecationNote", row)); - option.setDescription(getSafeValue("description", row)); - option.setDefaultValue(getSafeValue("defaultValue", row)); - option.setEnums(getSafeValue("enum", row)); + option.setName(JSonSchemaHelper.getSafeValue("name", row)); + option.setDisplayName(JSonSchemaHelper.getSafeValue("displayName", row)); + option.setKind(JSonSchemaHelper.getSafeValue("kind", row)); + option.setType(JSonSchemaHelper.getSafeValue("type", row)); + option.setJavaType(JSonSchemaHelper.getSafeValue("javaType", row)); + option.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", row)); + option.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", row)); + option.setDescription(JSonSchemaHelper.getSafeValue("description", row)); + option.setDefaultValue(JSonSchemaHelper.getSafeValue("defaultValue", row)); + option.setEnums(JSonSchemaHelper.getSafeValue("enum", row)); component.addComponentOption(option); } rows = JSonSchemaHelper.parseJsonSchema("properties", json, true); for (Map<String, String> row : rows) { EndpointOptionModel option = new EndpointOptionModel(); - option.setName(getSafeValue("name", row)); - option.setDisplayName(getSafeValue("displayName", row)); - option.setKind(getSafeValue("kind", row)); - option.setGroup(getSafeValue("group", row)); - option.setRequired(getSafeValue("required", row)); - option.setType(getSafeValue("type", row)); - option.setJavaType(getSafeValue("javaType", row)); - option.setEnums(getSafeValue("enum", row)); - option.setPrefix(getSafeValue("prefix", row)); - option.setMultiValue(getSafeValue("multiValue", row)); - option.setDeprecated(getSafeValue("deprecated", row)); - option.setDeprecationNote(getSafeValue("deprecationNote", row)); - option.setDefaultValue(getSafeValue("defaultValue", row)); - option.setDescription(getSafeValue("description", row)); - option.setEnumValues(getSafeValue("enum", row)); + option.setName(JSonSchemaHelper.getSafeValue("name", row)); + option.setDisplayName(JSonSchemaHelper.getSafeValue("displayName", row)); + option.setKind(JSonSchemaHelper.getSafeValue("kind", row)); + option.setGroup(JSonSchemaHelper.getSafeValue("group", row)); + option.setRequired(JSonSchemaHelper.getSafeValue("required", row)); + option.setType(JSonSchemaHelper.getSafeValue("type", row)); + option.setJavaType(JSonSchemaHelper.getSafeValue("javaType", row)); + option.setEnums(JSonSchemaHelper.getSafeValue("enum", row)); + option.setPrefix(JSonSchemaHelper.getSafeValue("prefix", row)); + option.setMultiValue(JSonSchemaHelper.getSafeValue("multiValue", row)); + option.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", row)); + option.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", row)); + option.setDefaultValue(JSonSchemaHelper.getSafeValue("defaultValue", row)); + option.setDescription(JSonSchemaHelper.getSafeValue("description", row)); + option.setEnumValues(JSonSchemaHelper.getSafeValue("enum", row)); component.addEndpointOption(option); } @@ -1943,32 +1936,32 @@ public class SpringBootAutoConfigurationMojo extends AbstractSpringBootGenerator List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("dataformat", json, false); DataFormatModel dataFormat = new DataFormatModel(); - dataFormat.setTitle(getSafeValue("title", rows)); - dataFormat.setName(getSafeValue("name", rows)); - dataFormat.setModelName(getSafeValue("modelName", rows)); - dataFormat.setDescription(getSafeValue("description", rows)); + dataFormat.setTitle(JSonSchemaHelper.getSafeValue("title", rows)); + dataFormat.setName(JSonSchemaHelper.getSafeValue("name", rows)); + dataFormat.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows)); + dataFormat.setDescription(JSonSchemaHelper.getSafeValue("description", rows)); dataFormat.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows)); - dataFormat.setLabel(getSafeValue("label", rows)); - dataFormat.setDeprecated(getSafeValue("deprecated", rows)); - dataFormat.setDeprecationNote(getSafeValue("deprecationNote", rows)); - dataFormat.setJavaType(getSafeValue("javaType", rows)); - dataFormat.setGroupId(getSafeValue("groupId", rows)); - dataFormat.setArtifactId(getSafeValue("artifactId", rows)); - dataFormat.setVersion(getSafeValue("version", rows)); + dataFormat.setLabel(JSonSchemaHelper.getSafeValue("label", rows)); + dataFormat.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows)); + dataFormat.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", rows)); + dataFormat.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows)); + dataFormat.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows)); + dataFormat.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows)); + dataFormat.setVersion(JSonSchemaHelper.getSafeValue("version", rows)); rows = JSonSchemaHelper.parseJsonSchema("properties", json, true); for (Map<String, String> row : rows) { DataFormatOptionModel option = new DataFormatOptionModel(); - option.setName(getSafeValue("name", row)); - option.setDisplayName(getSafeValue("displayName", row)); - option.setKind(getSafeValue("kind", row)); - option.setType(getSafeValue("type", row)); - option.setJavaType(getSafeValue("javaType", row)); - option.setDeprecated(getSafeValue("deprecated", row)); - option.setDeprecationNote(getSafeValue("deprecationNote", row)); - option.setDescription(getSafeValue("description", row)); - option.setDefaultValue(getSafeValue("defaultValue", row)); - option.setEnumValues(getSafeValue("enum", row)); + option.setName(JSonSchemaHelper.getSafeValue("name", row)); + option.setDisplayName(JSonSchemaHelper.getSafeValue("displayName", row)); + option.setKind(JSonSchemaHelper.getSafeValue("kind", row)); + option.setType(JSonSchemaHelper.getSafeValue("type", row)); + option.setJavaType(JSonSchemaHelper.getSafeValue("javaType", row)); + option.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", row)); + option.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", row)); + option.setDescription(JSonSchemaHelper.getSafeValue("description", row)); + option.setDefaultValue(JSonSchemaHelper.getSafeValue("defaultValue", row)); + option.setEnumValues(JSonSchemaHelper.getSafeValue("enum", row)); dataFormat.addDataFormatOption(option); } @@ -1979,32 +1972,32 @@ public class SpringBootAutoConfigurationMojo extends AbstractSpringBootGenerator List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false); LanguageModel language = new LanguageModel(); - language.setTitle(getSafeValue("title", rows)); - language.setName(getSafeValue("name", rows)); - language.setModelName(getSafeValue("modelName", rows)); - language.setDescription(getSafeValue("description", rows)); + language.setTitle(JSonSchemaHelper.getSafeValue("title", rows)); + language.setName(JSonSchemaHelper.getSafeValue("name", rows)); + language.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows)); + language.setDescription(JSonSchemaHelper.getSafeValue("description", rows)); language.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows)); - language.setLabel(getSafeValue("label", rows)); - language.setDeprecated(getSafeValue("deprecated", rows)); - language.setDeprecationNote(getSafeValue("deprecationNote", rows)); - language.setJavaType(getSafeValue("javaType", rows)); - language.setGroupId(getSafeValue("groupId", rows)); - language.setArtifactId(getSafeValue("artifactId", rows)); - language.setVersion(getSafeValue("version", rows)); + language.setLabel(JSonSchemaHelper.getSafeValue("label", rows)); + language.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows)); + language.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", rows)); + language.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows)); + language.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows)); + language.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows)); + language.setVersion(JSonSchemaHelper.getSafeValue("version", rows)); rows = JSonSchemaHelper.parseJsonSchema("properties", json, true); for (Map<String, String> row : rows) { LanguageOptionModel option = new LanguageOptionModel(); - option.setName(getSafeValue("name", row)); - option.setDisplayName(getSafeValue("displayName", row)); - option.setKind(getSafeValue("kind", row)); - option.setType(getSafeValue("type", row)); - option.setJavaType(getSafeValue("javaType", row)); - option.setDeprecated(getSafeValue("deprecated", row)); - option.setDeprecationNote(getSafeValue("deprecationNote", row)); - option.setDescription(getSafeValue("description", row)); - option.setDefaultValue(getSafeValue("defaultValue", row)); - option.setEnumValues(getSafeValue("enum", row)); + option.setName(JSonSchemaHelper.getSafeValue("name", row)); + option.setDisplayName(JSonSchemaHelper.getSafeValue("displayName", row)); + option.setKind(JSonSchemaHelper.getSafeValue("kind", row)); + option.setType(JSonSchemaHelper.getSafeValue("type", row)); + option.setJavaType(JSonSchemaHelper.getSafeValue("javaType", row)); + option.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", row)); + option.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", row)); + option.setDescription(JSonSchemaHelper.getSafeValue("description", row)); + option.setDefaultValue(JSonSchemaHelper.getSafeValue("defaultValue", row)); + option.setEnumValues(JSonSchemaHelper.getSafeValue("enum", row)); language.addLanguageOption(option); } @@ -2012,33 +2005,33 @@ public class SpringBootAutoConfigurationMojo extends AbstractSpringBootGenerator } private OtherModel generateOtherModel(String json) { - List<Map<String, String>> rows = parseJsonSchema("model", json, false); + List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("model", json, false); OtherModel model = new OtherModel(); - model.setName(getSafeValue("name", rows)); - model.setTitle(getSafeValue("title", rows)); - model.setDescription(getSafeValue("description", rows)); - model.setJavaType(getSafeValue("javaType", rows)); - model.setLabel(getSafeValue("label", rows)); - model.setDeprecated(getSafeValue("deprecated", rows)); - model.setDeprecationNote(getSafeValue("deprecationNote", rows)); - - rows = parseJsonSchema("properties", json, true); + model.setName(JSonSchemaHelper.getSafeValue("name", rows)); + model.setTitle(JSonSchemaHelper.getSafeValue("title", rows)); + model.setDescription(JSonSchemaHelper.getSafeValue("description", rows)); + model.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows)); + model.setLabel(JSonSchemaHelper.getSafeValue("label", rows)); + model.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows)); + model.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", rows)); + + rows = JSonSchemaHelper.parseJsonSchema("properties", json, true); for (Map<String, String> row : rows) { OtherOptionModel option = new OtherOptionModel(); - option.setName(getSafeValue("name", row)); - option.setDisplayName(getSafeValue("displayName", row)); - option.setKind(getSafeValue("kind", row)); - option.setGroup(getSafeValue("group", row)); - option.setRequired(getSafeValue("required", row)); - option.setType(getSafeValue("type", row)); - option.setJavaType(getSafeValue("javaType", row)); - option.setEnums(getSafeValue("enum", row)); - option.setDeprecated(getSafeValue("deprecated", row)); - option.setDeprecationNote(getSafeValue("deprecationNote", row)); - option.setDefaultValue(getSafeValue("defaultValue", row)); - option.setDescription(getSafeValue("description", row)); - option.setEnums(getSafeValue("enums", row)); + option.setName(JSonSchemaHelper.getSafeValue("name", row)); + option.setDisplayName(JSonSchemaHelper.getSafeValue("displayName", row)); + option.setKind(JSonSchemaHelper.getSafeValue("kind", row)); + option.setGroup(JSonSchemaHelper.getSafeValue("group", row)); + option.setRequired(JSonSchemaHelper.getSafeValue("required", row)); + option.setType(JSonSchemaHelper.getSafeValue("type", row)); + option.setJavaType(JSonSchemaHelper.getSafeValue("javaType", row)); + option.setEnums(JSonSchemaHelper.getSafeValue("enum", row)); + option.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", row)); + option.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", row)); + option.setDefaultValue(JSonSchemaHelper.getSafeValue("defaultValue", row)); + option.setDescription(JSonSchemaHelper.getSafeValue("description", row)); + option.setEnums(JSonSchemaHelper.getSafeValue("enums", row)); model.addOptionModel(option); } @@ -2089,12 +2082,12 @@ public class SpringBootAutoConfigurationMojo extends AbstractSpringBootGenerator try { String header; try (InputStream is = getClass().getClassLoader().getResourceAsStream("license-header-java.txt")) { - header = loadText(is); + header = PackageHelper.loadText(is); } String code = header + source; getLog().debug("Source code generated:\n" + code); - updateResource(null, target.toPath(), code); + AbstractGeneratorMojo.updateResource(null, target.toPath(), code); } catch (Exception e) { throw new MojoFailureException("IOError with file " + target, e); } @@ -2158,7 +2151,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractSpringBootGenerator // create new file try { InputStream is = getClass().getClassLoader().getResourceAsStream("license-header.txt"); - String header = loadText(is); + String header = PackageHelper.loadText(is); String code = sb.toString(); // add empty new line after header code = header + "\n" + code; diff --git a/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/UpdateSpringBootAutoConfigurationReadmeMojo.java b/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/UpdateSpringBootAutoConfigurationReadmeMojo.java new file mode 100644 index 0000000..19c545c --- /dev/null +++ b/tooling/camel-spring-boot-generator-maven-plugin/src/main/java/org/apache/camel/springboot/maven/UpdateSpringBootAutoConfigurationReadmeMojo.java @@ -0,0 +1,402 @@ +/* + * 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.springboot.maven; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +import org.apache.camel.maven.packaging.MvelHelper; +import org.apache.camel.maven.packaging.model.SpringBootAutoConfigureOptionModel; +import org.apache.camel.maven.packaging.model.SpringBootModel; +import org.apache.camel.tooling.util.Strings; +import org.apache.camel.util.json.DeserializationException; +import org.apache.camel.util.json.JsonArray; +import org.apache.camel.util.json.JsonObject; +import org.apache.camel.util.json.Jsoner; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.mvel2.templates.TemplateRuntime; +import org.sonatype.plexus.build.incremental.BuildContext; + +import static org.apache.camel.tooling.util.PackageHelper.loadText; +import static org.apache.camel.tooling.util.PackageHelper.writeText; + +/** + * For all the Camel components that has Spring Boot starter JAR, their documentation + * .adoc files in their component directory is updated to include spring boot auto configuration options. + */ +@Mojo(name = "update-spring-boot-auto-configuration-readme", threadSafe = true) +public class UpdateSpringBootAutoConfigurationReadmeMojo extends AbstractMojo { + + /** + * The maven project. + */ + @Parameter(property = "project", required = true, readonly = true) + protected MavenProject project; + + /** + * The project build directory + * + */ + @Parameter(defaultValue = "${project.build.directory}") + protected File buildDir; + + /** + * The documentation directory + * + */ + @Parameter(defaultValue = "${basedir}/../../../../components/") + protected File componentsDir; + + /** + * Whether to fail the build fast if any Warnings was detected. + */ + @Parameter + protected Boolean failFast; + + /** + * Whether to fail if an option has no documentation. + */ + @Parameter + protected Boolean failOnMissingDescription; + + /** + * build context to check changed files and mark them for refresh (used for + * m2e compatibility) + */ + @Component + private BuildContext buildContext; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + try { + executeStarter(project.getBasedir()); + } catch (Exception e) { + throw new MojoFailureException("Error processing spring-configuration-metadata.json", e); + } + } + + private void executeStarter(File starter) throws Exception { + File jsonFile = new File(buildDir, "classes/META-INF/spring-configuration-metadata.json"); + + // only if there is components we should update the documentation files + if (jsonFile.exists()) { + getLog().debug("Processing Spring Boot auto-configuration file: " + jsonFile); + Object js = Jsoner.deserialize(new FileReader(jsonFile)); + if (js != null) { + String name = starter.getName(); + + if (!isValidStarter(name)) { + return; + } + + File compDir = getComponentsDir(name); + + File[] docFiles; + File docFolder; + String componentName; + if ("camel-spring-boot".equals(name)) { + // special for camel-spring-boot where we also want to auto-generate the options in the adoc file + componentName = "spring-boot"; + docFolder = new File(compDir, "/src/main/docs/"); + docFiles = docFolder.listFiles(new ComponentDocFilter(componentName)); + } else if ("camel-univocity-parsers-starter".equals(name)) { + // special for univocity-parsers + componentName = "univocity"; + docFolder = new File(compDir, "camel-univocity-parsers/src/main/docs/"); + docFiles = docFolder.listFiles(new ComponentDocFilter(componentName)); + } else { + // skip camel- and -starter in the end + componentName = name.substring(6, name.length() - 8); + getLog().debug("Camel component: " + componentName); + docFolder = new File(compDir, "camel-" + componentName + "/src/main/docs/"); + docFiles = docFolder.listFiles(new ComponentDocFilter(componentName)); + + // maybe its one of those component that has subfolders with -api and -component + if (docFiles == null || docFiles.length == 0) { + docFolder = new File(compDir, "camel-" + componentName + "/camel-" + componentName + "-component/src/main/docs/"); + docFiles = docFolder.listFiles(new ComponentDocFilter(componentName)); + } + } + + if (docFiles != null && docFiles.length > 0) { + List<File> files = Arrays.asList(docFiles); + + // find out if the JAR has a Camel component, dataformat, or language + boolean hasComponentDataFormatOrLanguage = files.stream().anyMatch( + f -> f.getName().endsWith("-component.adoc") || f.getName().endsWith("-dataformat.adoc") || f.getName().endsWith("-language.adoc")); + + // if so then skip the root adoc file as its just a introduction to the others + if (hasComponentDataFormatOrLanguage) { + files = Arrays.stream(docFiles).filter(f -> !f.getName().equals(componentName + ".adoc")).collect(Collectors.toList()); + } + + if (files.size() == 1) { + List<SpringBootAutoConfigureOptionModel> models = parseSpringBootAutoConfigureModels(jsonFile, null); + + // special for other kind of JARs that is not a regular Camel component,dataformat,language + boolean onlyOther = files.size() == 1 && !hasComponentDataFormatOrLanguage; + if (models.isEmpty() && onlyOther) { + // there are no spring-boot auto configuration for this other kind of JAR so lets just ignore this + return; + } + File docFile = files.get(0); + + // check for missing description on options + boolean noDescription = false; + for (SpringBootAutoConfigureOptionModel o : models) { + if (Strings.isEmpty(o.getDescription())) { + noDescription = true; + getLog().warn("Option " + o.getName() + " has no description"); + } + } + if (noDescription && isFailOnNoDescription()) { + throw new MojoExecutionException("Failed build due failOnMissingDescription=true"); + } + + String changed = templateAutoConfigurationOptions(models, componentName); + boolean updated = updateAutoConfigureOptions(docFile, changed); + if (updated) { + getLog().info("Updated doc file: " + docFile); + } else { + getLog().debug("No changes to doc file: " + docFile); + } + } else if (files.size() > 1) { + // when we have 2 or more files we need to filter the model options accordingly + for (File docFile : files) { + String docName = docFile.getName(); + int pos = docName.lastIndexOf("-"); + // spring-boot use lower cased keys + String prefix = pos > 0 ? docName.substring(0, pos).toLowerCase(Locale.US) : null; + + List<SpringBootAutoConfigureOptionModel> models = parseSpringBootAutoConfigureModels(jsonFile, prefix); + + // check for missing description on options + boolean noDescription = false; + for (SpringBootAutoConfigureOptionModel o : models) { + if (Strings.isEmpty(o.getDescription())) { + noDescription = true; + getLog().warn("Option " + o.getName() + " has no description"); + } + } + if (noDescription && isFailOnNoDescription()) { + throw new MojoExecutionException("Failed build due failOnMissingDescription=true"); + } + + String changed = templateAutoConfigurationOptions(models, componentName); + boolean updated = updateAutoConfigureOptions(docFile, changed); + if (updated) { + getLog().info("Updated doc file: " + docFile); + } else { + getLog().debug("No changes to doc file: " + docFile); + } + } + } + } else { + getLog().warn("No component docs found in folder: " + docFolder); + if (isFailFast()) { + throw new MojoExecutionException("Failed build due failFast=true"); + } + } + } + } + } + + private File getComponentsDir(String name) { + if ("camel-spring-boot".equals(name)) { + // special for camel-spring-boot + return project.getBasedir(); + } else { + return componentsDir; + } + } + + private static final class ComponentDocFilter implements FileFilter { + + private final String componentName; + + public ComponentDocFilter(String componentName) { + this.componentName = asComponentName(componentName); + } + + @Override + public boolean accept(File pathname) { + String name = pathname.getName(); + return name.startsWith(componentName) && name.endsWith(".adoc"); + } + } + + private static String asComponentName(String componentName) { + if ("fastjson".equals(componentName)) { + return "json-fastjson"; + } else if ("gson".equals(componentName)) { + return "json-gson"; + } else if ("jackson".equals(componentName)) { + return "json-jackson"; + } else if ("johnzon".equals(componentName)) { + return "json-johnzon"; + } else if ("snakeyaml".equals(componentName)) { + return "yaml-snakeyaml"; + } else if ("cassandraql".equals(componentName)) { + return "cql"; + } else if ("josql".equals(componentName)) { + return "sql"; + } else if ("juel".equals(componentName)) { + return "el"; + } else if ("jsch".equals(componentName)) { + return "scp"; + } else if ("printer".equals(componentName)) { + return "lpr"; + } else if ("saxon".equals(componentName)) { + return "xquery"; + } else if ("stringtemplate".equals(componentName)) { + return "string-template"; + } else if ("tagsoup".equals(componentName)) { + return "tidyMarkup"; + } + return componentName; + } + + private static boolean isValidStarter(String name) { + // skip these + if ("camel-core-starter".equals(name)) { + return false; + } + return true; + } + + private List<SpringBootAutoConfigureOptionModel> parseSpringBootAutoConfigureModels(File file, String include) throws IOException, DeserializationException { + getLog().debug("Parsing Spring Boot AutoConfigureModel using include: " + include); + List<SpringBootAutoConfigureOptionModel> answer = new ArrayList<>(); + + JsonObject obj = (JsonObject) Jsoner.deserialize(new FileReader(file)); + + JsonArray arr = obj.getCollection("properties"); + if (arr != null && !arr.isEmpty()) { + arr.forEach(e -> { + JsonObject row = (JsonObject) e; + String name = row.getString("name"); + String javaType = row.getString("type"); + String desc = row.getStringOrDefault("description", ""); + String defaultValue = row.getStringOrDefault("defaultValue", ""); + + // is the option deprecated then include that as well in the description + String deprecated = row.getStringOrDefault("deprecated", ""); + String deprecationNote = row.getStringOrDefault("deprecationNote", ""); + if ("true".equals(deprecated)) { + desc = "*Deprecated* " + desc; + if (!Strings.isEmpty(deprecationNote)) { + if (!desc.endsWith(".")) { + desc = desc + ". Deprecation note: " + deprecationNote; + } else { + desc = desc + " Deprecation note: " + deprecationNote; + } + } + } + + // skip this special option and also if not matching the filter + boolean skip = name.endsWith("customizer.enabled") || include != null && !name.contains("." + include + "."); + if (!skip) { + SpringBootAutoConfigureOptionModel model = new SpringBootAutoConfigureOptionModel(); + model.setName(name); + model.setJavaType(javaType); + model.setDefaultValue(defaultValue); + model.setDescription(desc); + answer.add(model); + } + }); + } + + return answer; + } + + private boolean updateAutoConfigureOptions(File file, String changed) throws MojoExecutionException { + if (!file.exists()) { + return false; + } + + try { + String text = loadText(new FileInputStream(file)); + + String existing = Strings.between(text, "// spring-boot-auto-configure options: START", "// spring-boot-auto-configure options: END"); + if (existing != null) { + // remove leading line breaks etc + existing = existing.trim(); + changed = changed.trim(); + if (existing.equals(changed)) { + return false; + } else { + String before = Strings.before(text, "// spring-boot-auto-configure options: START"); + String after = Strings.after(text, "// spring-boot-auto-configure options: END"); + text = before + "// spring-boot-auto-configure options: START\n" + changed + "\n// spring-boot-auto-configure options: END" + after; + writeText(file, text); + return true; + } + } else { + getLog().warn("Cannot find markers in file " + file); + getLog().warn("Add the following markers"); + getLog().warn("\t// spring-boot-auto-configure options: START"); + getLog().warn("\t// spring-boot-auto-configure options: END"); + if (isFailFast()) { + throw new MojoExecutionException("Failed build due failFast=true"); + } + return false; + } + } catch (Exception e) { + throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e); + } + } + + private String templateAutoConfigurationOptions(List<SpringBootAutoConfigureOptionModel> options, String componentName) throws MojoExecutionException { + SpringBootModel model = new SpringBootModel(); + model.setGroupId(project.getGroupId()); + model.setArtifactId("camel-" + componentName + "-starter"); + model.setVersion(project.getVersion()); + model.setOptions(options); + + try { + String template = loadText(UpdateSpringBootAutoConfigurationReadmeMojo.class.getClassLoader().getResourceAsStream("spring-boot-auto-configure-options.mvel")); + String out = (String) TemplateRuntime.eval(template, model, Collections.singletonMap("util", MvelHelper.INSTANCE)); + return out; + } catch (Exception e) { + throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e); + } + } + + private boolean isFailFast() { + return failFast != null && failFast; + } + + private boolean isFailOnNoDescription() { + return failOnMissingDescription != null && failOnMissingDescription; + } + +} \ No newline at end of file