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"
+ }
+ ]
+}