diff --git a/docs/pom.xml b/docs/pom.xml index 22a6aebf..51ce7003 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -52,6 +52,11 @@ groovy-json compile + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/docs/src/main/groovy/org/springframework/cloud/internal/Main.groovy b/docs/src/main/groovy/org/springframework/cloud/internal/Main.groovy index ae07afbc..7b07ffb4 100644 --- a/docs/src/main/groovy/org/springframework/cloud/internal/Main.groovy +++ b/docs/src/main/groovy/org/springframework/cloud/internal/Main.groovy @@ -16,43 +16,48 @@ class Main { @CompileStatic static void main(String... args) { String outputFile = args[0] - String inclusionPattern = args.length > 0 ? args[1] : ".*" - new Main().generate(outputFile, inclusionPattern) - } - - void generate(String outputFile, String inclusionPattern) { - println "Parsing all configuration metadata" - Resource[] resources = new PathMatchingResourcePatternResolver() - .getResources("classpath*:/META-INF/spring-configuration-metadata.json") - println "Found [${resources.length}] configuration metadata jsons" - TreeSet names = new TreeSet() - def descriptions = [:] - int count = 0 - int matchingPropertyCount = 0 - int propertyCount = 0 - Pattern pattern = Pattern.compile(inclusionPattern) - resources.each { Resource resource -> - if (resource.url.toString().contains("cloud")) { - count++ - def slurper = new JsonSlurper() - slurper.parseText(resource.inputStream.text).properties.each { val -> - propertyCount++ - if (!pattern.matcher(val.name).matches()) { - return - } - matchingPropertyCount++ - names.add val.name - descriptions[val.name] = new ConfigValue(val.name, val.description, val.defaultValue) - } - } - } - println "Found [${count}] Cloud projects configuration metadata jsons. [${matchingPropertyCount}/${propertyCount}] were matching the pattern [${inclusionPattern}]" - println "Successfully built the description table" - if (names.empty) { - println("Will not update the table, since no configuration properties were found!") + String inclusionPattern = args.length > 1 ? args[1] : ".*" + File parent = new File(outputFile).parentFile + if (!parent.exists()) { + println "No parent directory [${parent.toString()}] found. Won't generate the configuration properties file" return } - new File(outputFile).text = """\ + new Generator().generate(outputFile, inclusionPattern) + } + + static class Generator { + void generate(String outputFile, String inclusionPattern) { + println "Parsing all configuration metadata" + Resource[] resources = getResources() + println "Found [${resources.length}] configuration metadata jsons" + TreeSet names = new TreeSet() + def descriptions = [:] + int count = 0 + int matchingPropertyCount = 0 + int propertyCount = 0 + Pattern pattern = Pattern.compile(inclusionPattern) + resources.each { Resource resource -> + if (resourceNameContainsPattern(resource)) { + count++ + def slurper = new JsonSlurper() + slurper.parseText(resource.inputStream.text).properties.each { val -> + propertyCount++ + if (!pattern.matcher(val.name).matches()) { + return + } + matchingPropertyCount++ + names.add val.name + descriptions[val.name] = new ConfigValue(val.name, val.description, val.defaultValue) + } + } + } + println "Found [${count}] Cloud projects configuration metadata jsons. [${matchingPropertyCount}/${propertyCount}] were matching the pattern [${inclusionPattern}]" + println "Successfully built the description table" + if (names.empty) { + println("Will not update the table, since no configuration properties were found!") + return + } + new File(outputFile).text = """\ |=== |Name | Default | Description @@ -60,9 +65,27 @@ ${names.collect { it -> return descriptions[it] }.join("\n")} |=== """ - println "Successfully stored the output file" + println "Successfully stored the output file" + } + + protected boolean resourceNameContainsPattern(Resource resource) { + try { + return resource.getURL().toString().contains("cloud") + } + catch (Exception e) { + println("Exception [${e}] for resource [${resource}] occurred while trying to retrieve its URL") + return false + } + } + + protected Resource[] getResources() { + return new PathMatchingResourcePatternResolver() + .getResources("classpath*:/META-INF/spring-configuration-metadata.json") + } + } + @CompileStatic static class ConfigValue { String name diff --git a/docs/src/test/java/org/springframework/cloud/internal/GeneratorTests.java b/docs/src/test/java/org/springframework/cloud/internal/GeneratorTests.java new file mode 100644 index 00000000..f84a79cb --- /dev/null +++ b/docs/src/test/java/org/springframework/cloud/internal/GeneratorTests.java @@ -0,0 +1,116 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.cloud.internal; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; + +import org.junit.jupiter.api.Test; + +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; + +import static org.assertj.core.api.BDDAssertions.then; + +class GeneratorTests { + + URL root = GeneratorTests.class.getResource("."); + + @Test + void should_not_create_a_file_when_no_properties_were_found() + throws URISyntaxException { + Main.Generator generator = new Main.Generator() { + @Override + protected Resource[] getResources() { + return new Resource[0]; + } + }; + File file = new File(root.toURI().toString(), "output.adoc"); + String inclusionPattern = ".*"; + + generator.generate(file.getAbsolutePath(), inclusionPattern); + + then(file).doesNotExist(); + } + + @Test + void should_create_a_file_when_cloud_file_was_found() { + Main.Generator generator = new Main.Generator() { + @Override + protected Resource[] getResources() { + return new Resource[] { resource("/not-matching-name.json"), + resource("/with-cloud-in-name.json") }; + } + + @Override + protected boolean resourceNameContainsPattern(Resource resource) { + try { + return resource.getURI().toString().contains("with-cloud"); + } + catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + }; + File file = new File(root.getFile().toString(), "output.adoc"); + String inclusionPattern = ".*"; + + generator.generate(file.getAbsolutePath(), inclusionPattern); + + then(file).exists(); + then(asString(file)).contains("spring.first-property") + .contains("unmatched.second-property") + .doesNotContain("example1.first-property"); + } + + @Test + void should_create_a_file_when_spring_property_was_found() { + Main.Generator generator = new Main.Generator() { + @Override + protected Resource[] getResources() { + return new Resource[] { resource("/not-matching-name.json"), + resource("/with-cloud-in-name.json") }; + } + }; + File file = new File(root.getFile().toString(), "output.adoc"); + String inclusionPattern = "spring.*"; + + generator.generate(file.getAbsolutePath(), inclusionPattern); + + then(file).exists(); + then(asString(file)).contains("spring.first-property") + .doesNotContain("example1.first-property") + .doesNotContain("unmatched.second-property"); + } + + static String asString(File file) { + try { + return new String(Files.readAllBytes(file.toPath())); + } + catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + + static Resource resource(String path) { + return new FileSystemResource(GeneratorTests.class.getResource(path).getFile()); + } + +} diff --git a/docs/src/test/java/org/springframework/cloud/internal/MainTests.java b/docs/src/test/java/org/springframework/cloud/internal/MainTests.java new file mode 100644 index 00000000..c94e83f6 --- /dev/null +++ b/docs/src/test/java/org/springframework/cloud/internal/MainTests.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.cloud.internal; + +import java.io.File; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.BDDAssertions.then; + +class MainTests { + + @Test + void should_do_nothing_when_parent_dir_is_not_found() { + File nonExistantFile = new File("/this/file/does/not/exist"); + + Main.main(nonExistantFile.getAbsolutePath()); + + then(nonExistantFile).doesNotExist(); + } +} diff --git a/docs/src/test/resources/not-matching-name.json b/docs/src/test/resources/not-matching-name.json new file mode 100644 index 00000000..9f002efa --- /dev/null +++ b/docs/src/test/resources/not-matching-name.json @@ -0,0 +1,16 @@ +{ + "properties": [ + { + "defaultValue": "false", + "name": "example1.first-property", + "description": "First Description", + "type": "java.lang.Boolean" + }, + { + "defaultValue": "true", + "name": "example2.second-property", + "description": "Second Description", + "type": "java.lang.Boolean" + } + ] +} diff --git a/docs/src/test/resources/with-cloud-in-name.json b/docs/src/test/resources/with-cloud-in-name.json new file mode 100644 index 00000000..1ad731f5 --- /dev/null +++ b/docs/src/test/resources/with-cloud-in-name.json @@ -0,0 +1,16 @@ +{ + "properties": [ + { + "defaultValue": "false", + "name": "spring.first-property", + "description": "First Description", + "type": "java.lang.Boolean" + }, + { + "defaultValue": "true", + "name": "unmatched.second-property", + "description": "Second Description", + "type": "java.lang.Boolean" + } + ] +}