diff --git a/pom.xml b/pom.xml
index 8027811e6b..2556a94a19 100644
--- a/pom.xml
+++ b/pom.xml
@@ -136,6 +136,12 @@
pom
import
+
+
+ org.springframework
+ spring-core
+ 4.3.4.RELEASE
+
org.springframework.cloud
spring-cloud-netflix-dependencies
diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.java b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy
similarity index 80%
rename from spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.java
rename to spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy
index 964436c0bb..68c0d8fe45 100644
--- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.java
+++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy
@@ -1,10 +1,8 @@
-package org.springframework.cloud.contract.spec;
-
-import java.io.File;
+package org.springframework.cloud.contract.spec
/**
* Converter to be used to convert FROM {@link File} TO {@link Contract}
- * and from {@link Contract} to {@link T}
+ * and from {@link Contract} to {@code T}
*
* @param - type to which we want to convert the contract
*
@@ -20,7 +18,7 @@ public interface ContractConverter {
* @param file - file to be considered for conversion
* @return - {@code true} if the given implementation can convert the file
*/
- boolean isAccepted(File file);
+ boolean isAccepted(File file)
/**
* Converts the given {@link File} to its {@link Contract} representation
@@ -28,7 +26,7 @@ public interface ContractConverter {
* @param file - file to convert
* @return - {@link Contract} representation of the file
*/
- Contract convertFrom(File file);
+ Contract convertFrom(File file)
/**
* Converts the given {@link Contract} to a {@link T} representation
@@ -36,5 +34,5 @@ public interface ContractConverter {
* @param contract - the parsed contract
* @return - {@link T} the type to which we do the conversion
*/
- T convertTo(Contract contract);
+ T convertTo(Contract contract)
}
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/pom.xml b/spring-cloud-contract-tools/spring-cloud-contract-converters/pom.xml
index 2dc4823de6..dc77abad72 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-converters/pom.xml
+++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/pom.xml
@@ -38,11 +38,6 @@
com.github.tomakehurst
wiremock
-
- org.yaml
- snakeyaml
- optional
-
org.spockframework
spock-core
diff --git a/spring-cloud-contract-verifier/pom.xml b/spring-cloud-contract-verifier/pom.xml
index f18b506d13..a95c66a130 100644
--- a/spring-cloud-contract-verifier/pom.xml
+++ b/spring-cloud-contract-verifier/pom.xml
@@ -45,6 +45,11 @@
spring-rabbit
true
+
+ org.yaml
+ snakeyaml
+ optional
+
javax.inject
javax.inject
diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy
index 0109024833..70a61e458b 100644
--- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy
+++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy
@@ -123,7 +123,7 @@ class SingleTestGenerator {
if (log.isDebugEnabled()) {
log.debug("Stub content from file [${stubsFile.text}]")
}
- Contract stubContent = ContractVerifierDslConverter.convert(stubsFile)
+ Contract stubContent = it.convertedContract ?: ContractVerifierDslConverter.convert(stubsFile)
TestType testType = (stubContent.input || stubContent.outputMessage) ? TestType.MESSAGING : TestType.HTTP
return [(new ParsedDsl(it, stubContent, stubsFile)): testType]
}
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContract.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.java
similarity index 91%
rename from spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContract.java
rename to spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.java
index 4910d8d84b..72fb0bbfb4 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContract.java
+++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.java
@@ -1,4 +1,4 @@
-package org.springframework.cloud.contract.verifier.dsl;
+package org.springframework.cloud.contract.verifier.converter;
import java.util.HashMap;
import java.util.Map;
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContractConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy
similarity index 61%
rename from spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContractConverter.groovy
rename to spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy
index 4071cb5d51..c9b6aed109 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContractConverter.groovy
+++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy
@@ -1,4 +1,4 @@
-package org.springframework.cloud.contract.verifier.dsl
+package org.springframework.cloud.contract.verifier.converter
import groovy.transform.CompileStatic
import org.springframework.cloud.contract.spec.Contract
@@ -27,23 +27,23 @@ class YamlContractConverter implements ContractConverter {
YamlContract yamlContract = new Yaml().loadAs(new FileInputStream(file), YamlContract.class)
return Contract.make {
request {
- method(yamlContract.request.method)
- url(yamlContract.request.url)
+ method(yamlContract?.request?.method)
+ url(yamlContract?.request?.url)
headers {
- yamlContract.request.headers.each { String key, Object value ->
+ yamlContract?.request?.headers?.each { String key, Object value ->
header(key, value)
}
}
- body(yamlContract.request.body)
+ body(yamlContract?.request?.body)
}
response {
- status(yamlContract.response.status)
+ status(yamlContract?.response?.status)
headers {
- yamlContract.response.headers.each { String key, Object value ->
+ yamlContract?.response?.headers?.each { String key, Object value ->
header(key, value)
}
}
- body(yamlContract.response.body)
+ body(yamlContract?.response?.body)
}
}
}
@@ -57,15 +57,15 @@ class YamlContractConverter implements ContractConverter {
// TODO: Pick one of the sides - consumer / producer
YamlContract yamlContract = new YamlContract()
yamlContract.request.with {
- method = contract.request.method.clientValue
- url = contract.request.url.clientValue
- headers = (contract.request.headers as Headers).asStubSideMap()
- body = contract.request.body.clientValue as Map
+ method = contract?.request?.method?.clientValue
+ url = contract?.request?.url?.clientValue
+ headers = (contract?.request?.headers as Headers)?.asStubSideMap()
+ body = contract?.request?.body?.clientValue as Map
}
yamlContract.response.with {
- status = contract.response.status.clientValue as Integer
- headers = (contract.response.headers as Headers).asStubSideMap()
- body = contract.response.body.clientValue as Map
+ status = contract?.response?.status?.clientValue as Integer
+ headers = (contract?.response?.headers as Headers)?.asStubSideMap()
+ body = contract?.response?.body?.clientValue as Map
}
return yamlContract
}
diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy
index 45c33004bf..31c8d06434 100755
--- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy
+++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy
@@ -21,6 +21,9 @@ import com.google.common.collect.ListMultimap
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.apache.commons.lang3.SystemUtils
+import org.springframework.cloud.contract.spec.Contract
+import org.springframework.cloud.contract.spec.ContractConverter
+import org.springframework.core.io.support.SpringFactoriesLoader
import java.nio.file.FileSystem
import java.nio.file.FileSystems
@@ -74,7 +77,12 @@ class ContractFileScanner {
return result
}
+ /**
+ * We iterate over found contracts, filter out those that should be excluded
+ * and try to convert via pluggable Contract Converters any possible contracts
+ */
private void appendRecursively(File baseDir, ListMultimap result) {
+ List converters = SpringFactoriesLoader.loadFactories(ContractConverter, null)
File[] files = baseDir.listFiles()
if (!files) {
return;
@@ -85,12 +93,9 @@ class ContractFileScanner {
boolean contractFile = isContractFile(file)
boolean included = includeMatcher ? file.absolutePath.matches(includeMatcher) : true
if (contractFile && included) {
- Path path = file.toPath()
- Integer order = null
- if (hasScenarioFilenamePattern(path)) {
- order = index
- }
- result.put(file.parentFile.toPath(), new ContractMetadata(path, matchesPattern(file, ignoreMatchers), files.size(), order))
+ addContractToTestGeneration(result, files, file, index)
+ } else if (!contractFile && included) {
+ addContractToTestGeneration(converters, result, files, file, index)
} else {
appendRecursively(file, result)
if (log.isDebugEnabled()) {
@@ -105,6 +110,35 @@ class ContractFileScanner {
}
}
+ private void addContractToTestGeneration(List converters, ListMultimap result,
+ File[] files, File file, int index) {
+ boolean converted = false
+ for (ContractConverter converter : converters) {
+ if (converter.isAccepted(file)) {
+ addContractToTestGeneration(result, files, file, index, converter.convertFrom(file))
+ converted = true
+ break
+ }
+ }
+ if (!converted) {
+ appendRecursively(file, result)
+ if (log.isDebugEnabled()) {
+ log.debug("File [$file] wasn't ignored but no converter was applicable.")
+ }
+ }
+ }
+
+ private void addContractToTestGeneration(ListMultimap result, File[] files, File file,
+ int index, Contract convertedContract = null) {
+ Path path = file.toPath()
+ Integer order = null
+ if (hasScenarioFilenamePattern(path)) {
+ order = index
+ }
+ result.put(file.parentFile.toPath(), new ContractMetadata(path, matchesPattern(file, ignoreMatchers),
+ files.size(), order, convertedContract))
+ }
+
private boolean hasScenarioFilenamePattern(Path path) {
return SCENARIO_STEP_FILENAME_PATTERN.matcher(path.fileName.toString()).matches()
}
diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy
index 5bc5a668ec..05c17673b9 100644
--- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy
+++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy
@@ -17,9 +17,9 @@
package org.springframework.cloud.contract.verifier.file
import groovy.transform.CompileStatic
+import org.springframework.cloud.contract.spec.Contract
import java.nio.file.Path
-
/**
* Contains metadata for a particular file with a DSL
*
@@ -33,12 +33,14 @@ class ContractMetadata {
final boolean ignored
final int groupSize
final Integer order
+ final Contract convertedContract
- ContractMetadata(Path path, boolean ignored, int groupSize, Integer order) {
+ ContractMetadata(Path path, boolean ignored, int groupSize, Integer order, Contract convertedContract = null) {
this.groupSize = groupSize
this.path = path
this.ignored = ignored
this.order = order
+ this.convertedContract = convertedContract
}
@Override
@@ -48,6 +50,7 @@ class ContractMetadata {
", ignored=" + ignored +
", groupSize=" + groupSize +
", order=" + order +
+ ", convertedContract=" + convertedContract +
'}'
}
}
diff --git a/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories b/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
index 0e6be1c75d..505fcced9c 100644
--- a/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
@@ -5,4 +5,8 @@ org.springframework.cloud.contract.verifier.messaging.integration.ContractVerifi
org.springframework.cloud.contract.verifier.messaging.amqp.ContractVerifierAmqpAutoConfiguration,\
org.springframework.cloud.contract.verifier.messaging.amqp.RabbitMockConnectionFactoryAutoConfiguration,\
org.springframework.cloud.contract.verifier.messaging.camel.ContractVerifierCamelConfiguration,\
-org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierAutoConfiguration
\ No newline at end of file
+org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierAutoConfiguration
+
+# Converters
+org.springframework.cloud.contract.spec.ContractConverter=\
+org.springframework.cloud.contract.verifier.converter.YamlContractConverter
\ No newline at end of file
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContractConverterSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy
similarity index 96%
rename from spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContractConverterSpec.groovy
rename to spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy
index ba9e9dc955..419a01521b 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/YamlContractConverterSpec.groovy
+++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy
@@ -1,4 +1,4 @@
-package org.springframework.cloud.contract.verifier.dsl
+package org.springframework.cloud.contract.verifier.converter
import org.springframework.cloud.contract.spec.Contract
import spock.lang.Specification
@@ -59,4 +59,4 @@ class YamlContractConverterSpec extends Specification {
yamlContract.response.headers.find { it.key == "foo2" && it.value == "bar" }
yamlContract.response.body == [foo2: "bar"]
}
-}
\ No newline at end of file
+}
diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScannerSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScannerSpec.groovy
index 73e7fc85c0..e501184cbf 100644
--- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScannerSpec.groovy
+++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScannerSpec.groovy
@@ -73,4 +73,16 @@ class ContractFileScannerSpec extends Specification {
contracts.values().find { it.path.fileName.toString().startsWith('02') }.order == 1
contracts.values().find { it.path.fileName.toString().startsWith('03') }.order == 2
}
+
+ def "should find contract files with converters"() {
+ given:
+ File baseDir = new File(this.getClass().getResource("/directory/with/mixed").toURI())
+ ContractFileScanner scanner = new ContractFileScanner(baseDir, null, null)
+ when:
+ ListMultimap result = scanner.findContracts()
+ then:
+ result.keySet().size() == 1
+ result.entries().find { it.value.convertedContract && it.value.convertedContract.request.method.clientValue == "PUT" }
+ result.entries().find { !it.value.convertedContract && !it.value.ignored }
+ }
}
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/resources/contract.yml b/spring-cloud-contract-verifier/src/test/resources/contract.yml
similarity index 100%
rename from spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/resources/contract.yml
rename to spring-cloud-contract-verifier/src/test/resources/contract.yml
diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/mixed/contract.yml b/spring-cloud-contract-verifier/src/test/resources/directory/with/mixed/contract.yml
new file mode 100644
index 0000000000..783dafde0e
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/mixed/contract.yml
@@ -0,0 +1,13 @@
+request:
+ url: /foo
+ method: PUT
+ headers:
+ foo: bar
+ body:
+ foo: bar
+response:
+ status: 200
+ headers:
+ foo2: bar
+ body:
+ foo2: bar
\ No newline at end of file
diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/mixed/dsl.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/mixed/dsl.groovy
new file mode 100644
index 0000000000..958ccd0673
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/mixed/dsl.groovy
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2013-2016 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
+ *
+ * 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.
+ */
+