diff --git a/docs/src/main/asciidoc/verifier/contract.adoc b/docs/src/main/asciidoc/verifier/contract.adoc index ec1be7ff10..be8af502cc 100644 --- a/docs/src/main/asciidoc/verifier/contract.adoc +++ b/docs/src/main/asciidoc/verifier/contract.adoc @@ -602,10 +602,35 @@ and just register it in your `spring.factories` file [source] ---- -include::{tests_path}/spring-cloud-contract-stub-runner-moco/src/test/resources/META-INF/spring.factories[indent=0] +include::{tests_path}/spring-cloud-contract-stub-runner-moco/src/test/resources/META-INF/spring.factories[indent=0,lines=1,4] ---- that way you'll be able to run stubs using Moco. IMPORTANT: If you don't provide any implementation then the default one - WireMock based will be picked. If you provide more than one then the first one on the list will be picked. + +==== Custom Stub Downloader + +You can customize the way your stubs are downloaded. If you don't want to download the JARs +from Nexus / Artifactory in the way we do by default you can set your own implementation. +Below you can find an example of a Stub Downloader Provider that takes `json` files from the test resources +from classpath, copies them to a temp file and then passes that temporary folder + as a root for the stubs. + +[source,java] +---- +include::{tests_path}/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/ClasspathStubProvider.groovy[indent=0] +---- + +and just register it in your `spring.factories` file + +[source] +---- +include::{tests_path}/spring-cloud-contract-stub-runner-moco/src/test/resources/META-INF/spring.factories[indent=0,lines=5..-1] +---- + +that way you'll be able to pick a folder with the source of your stubs. + +IMPORTANT: If you don't provide any implementation then the default one - Aether based that will download stubs from a remote repo +will be picked. If you provide more than one then the first one on the list will be picked. diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/BatchStubRunnerFactory.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/BatchStubRunnerFactory.java index b0c5ead0bc..ad1e573fda 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/BatchStubRunnerFactory.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/BatchStubRunnerFactory.java @@ -32,7 +32,12 @@ public class BatchStubRunnerFactory { private final MessageVerifier contractVerifierMessaging; public BatchStubRunnerFactory(StubRunnerOptions stubRunnerOptions) { - this(stubRunnerOptions, new AetherStubDownloader(stubRunnerOptions), new NoOpStubMessages()); + this(stubRunnerOptions, aetherStubDownloader(stubRunnerOptions), new NoOpStubMessages()); + } + + private static StubDownloader aetherStubDownloader(StubRunnerOptions stubRunnerOptions) { + StubDownloaderBuilderProvider provider = new StubDownloaderBuilderProvider(); + return provider.hasBuilder() ? provider.get().build(stubRunnerOptions) : new AetherStubDownloader(stubRunnerOptions); } public BatchStubRunnerFactory(StubRunnerOptions stubRunnerOptions, StubDownloader stubDownloader) { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloader.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloader.java index 00ea82a126..26c46649a2 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloader.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloader.java @@ -19,6 +19,16 @@ package org.springframework.cloud.contract.stubrunner; import java.io.File; import java.util.Map; +/** + * Contract for providing a tuple containing configuration of a downloaded + * and unpacked stub, together with the file location of that extracted artifact. + * + * Note: Actually the artifact doesn't have to be a JAR. method name contains + * that suffix for historical reasons. + * + * @author Marcin Grzejszczak + * @since 1.0.0 + */ public interface StubDownloader { /** diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilder.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilder.java new file mode 100644 index 0000000000..545314162a --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilder.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.springframework.cloud.contract.stubrunner; + +/** + * Builder for a {@link StubDownloader}. Can't allow direct usage + * of {@link StubDownloader} cause in order to register instances + * of this interface in {@link org.springframework.core.io.support.SpringFactoriesLoader} + * one needs a default constructor whereas the {@link StubDownloader} + * instances need to be constructed from stub related options. + * + * @author Marcin Grzejszczak + * @since 1.1.0 + */ +public interface StubDownloaderBuilder { + + StubDownloader build(StubRunnerOptions stubRunnerOptions); +} \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilderProvider.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilderProvider.java new file mode 100644 index 0000000000..8660cc76ce --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilderProvider.java @@ -0,0 +1,30 @@ +package org.springframework.cloud.contract.stubrunner; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.core.io.support.SpringFactoriesLoader; + +/** + * Provider for {@link StubDownloaderBuilder} + * + * @author Marcin Grzejszczak + * @since 1.1.0 + */ +public class StubDownloaderBuilderProvider { + + private final List builders = new ArrayList<>(); + + public StubDownloaderBuilderProvider() { + this.builders.addAll( + SpringFactoriesLoader.loadFactories(StubDownloaderBuilder.class, null)); + } + + public StubDownloaderBuilder get() { + return this.builders.isEmpty() ? null : this.builders.get(0); + } + + public boolean hasBuilder() { + return get() != null; + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java index 957880d31f..f19a61d913 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java @@ -117,6 +117,30 @@ public class StubRunnerOptions { return this.stubIdsToPortMapping; } + public String getStubRepositoryRoot() { + return this.stubRepositoryRoot; + } + + public boolean isWorkOffline() { + return this.workOffline; + } + + public String getStubsClassifier() { + return this.stubsClassifier; + } + + public String getUsername() { + return this.username; + } + + public String getPassword() { + return this.password; + } + + public StubRunnerProxyOptions getStubRunnerProxyOptions() { + return this.stubRunnerProxyOptions; + } + public StubRunnerProxyOptions getProxyOptions() { return this.stubRunnerProxyOptions; } diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java index 0f240e4c21..4865a79305 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java @@ -28,7 +28,7 @@ import org.springframework.cloud.contract.stubrunner.BatchStubRunner; import org.springframework.cloud.contract.stubrunner.BatchStubRunnerFactory; import org.springframework.cloud.contract.stubrunner.RunningStubs; import org.springframework.cloud.contract.stubrunner.StubConfiguration; -import org.springframework.cloud.contract.stubrunner.StubDownloader; +import org.springframework.cloud.contract.stubrunner.StubDownloaderBuilderProvider; import org.springframework.cloud.contract.stubrunner.StubRunnerOptions; import org.springframework.cloud.contract.stubrunner.StubRunnerOptionsBuilder; import org.springframework.cloud.contract.verifier.messaging.MessageVerifier; @@ -53,8 +53,7 @@ public class StubRunnerConfiguration { @Autowired(required = false) private MessageVerifier contractVerifierMessaging; - @Autowired(required = false) - private StubDownloader stubDownloader; + private StubDownloaderBuilderProvider provider = new StubDownloaderBuilderProvider(); @Autowired private StubRunnerProperties props; @Autowired @@ -73,7 +72,7 @@ public class StubRunnerConfiguration { } StubRunnerOptions stubRunnerOptions = builder.build(); BatchStubRunner batchStubRunner = new BatchStubRunnerFactory(stubRunnerOptions, - this.stubDownloader != null ? this.stubDownloader + this.provider.hasBuilder() ? this.provider.get().build(stubRunnerOptions) : new AetherStubDownloader(stubRunnerOptions), this.contractVerifierMessaging != null ? this.contractVerifierMessaging : new NoOpStubMessages()).buildBatchStubRunner(); diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverter.groovy index dfbb64abbf..49d33b0d14 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverter.groovy @@ -39,20 +39,20 @@ import java.nio.file.Paths @CompileStatic class RecursiveFilesConverter { - private final StubGeneratorHolder holder + private final StubGeneratorProvider holder private final ContractVerifierConfigProperties properties private final File outMappingsDir - RecursiveFilesConverter(ContractVerifierConfigProperties properties, StubGeneratorHolder holder = null) { + RecursiveFilesConverter(ContractVerifierConfigProperties properties, StubGeneratorProvider holder = null) { this.properties = properties this.outMappingsDir = properties.stubsOutputDir - this.holder = holder ?: new StubGeneratorHolder() + this.holder = holder ?: new StubGeneratorProvider() } - RecursiveFilesConverter(ContractVerifierConfigProperties properties, File outMappingsDir, StubGeneratorHolder holder = null) { + RecursiveFilesConverter(ContractVerifierConfigProperties properties, File outMappingsDir, StubGeneratorProvider holder = null) { this.properties = properties this.outMappingsDir = outMappingsDir - this.holder = holder ?: new StubGeneratorHolder() + this.holder = holder ?: new StubGeneratorProvider() } void processFiles() { diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/StubGeneratorHolder.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/StubGeneratorProvider.groovy similarity index 84% rename from spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/StubGeneratorHolder.groovy rename to spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/StubGeneratorProvider.groovy index f996aa819f..9e187741ce 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/StubGeneratorHolder.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/StubGeneratorProvider.groovy @@ -10,15 +10,15 @@ import org.springframework.core.io.support.SpringFactoriesLoader * @since 1.1.0 */ @CompileStatic -class StubGeneratorHolder { +class StubGeneratorProvider { private final List converters = [] - StubGeneratorHolder() { + StubGeneratorProvider() { this.converters.addAll(SpringFactoriesLoader.loadFactories(StubGenerator, null)) } - StubGeneratorHolder(List converters) { + StubGeneratorProvider(List converters) { this.converters.addAll(converters) } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy index 47b83fac90..af860e0ff4 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy @@ -24,7 +24,7 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig import org.springframework.cloud.contract.verifier.converter.ConversionContractVerifierException import org.springframework.cloud.contract.verifier.converter.SingleFileConverter import org.springframework.cloud.contract.verifier.converter.StubGenerator -import org.springframework.cloud.contract.verifier.converter.StubGeneratorHolder +import org.springframework.cloud.contract.verifier.converter.StubGeneratorProvider import org.springframework.cloud.contract.verifier.file.ContractFileScanner import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.cloud.contract.verifier.util.NamesUtil @@ -45,34 +45,34 @@ import java.nio.file.Paths @Deprecated class RecursiveFilesConverter { - private final StubGeneratorHolder holder + private final StubGeneratorProvider holder private final ContractVerifierConfigProperties properties private final File outMappingsDir - RecursiveFilesConverter(ContractVerifierConfigProperties properties, StubGeneratorHolder holder = null) { + RecursiveFilesConverter(ContractVerifierConfigProperties properties, StubGeneratorProvider holder = null) { this.properties = properties this.outMappingsDir = properties.stubsOutputDir - this.holder = holder ?: new StubGeneratorHolder() + this.holder = holder ?: new StubGeneratorProvider() } - RecursiveFilesConverter(ContractVerifierConfigProperties properties, File outMappingsDir, StubGeneratorHolder holder = null) { + RecursiveFilesConverter(ContractVerifierConfigProperties properties, File outMappingsDir, StubGeneratorProvider holder = null) { this.properties = properties this.outMappingsDir = outMappingsDir - this.holder = holder ?: new StubGeneratorHolder() + this.holder = holder ?: new StubGeneratorProvider() } @Deprecated RecursiveFilesConverter(SingleFileConverter singleFileConverter, ContractVerifierConfigProperties properties) { this.properties = properties this.outMappingsDir = properties.stubsOutputDir - this.holder = new StubGeneratorHolder() + this.holder = new StubGeneratorProvider() } @Deprecated RecursiveFilesConverter(SingleFileConverter singleFileConverter, ContractVerifierConfigProperties properties, File outMappingsDir) { this.properties = properties this.outMappingsDir = outMappingsDir - this.holder = new StubGeneratorHolder() + this.holder = new StubGeneratorProvider() } void processFiles() { diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverterSpec.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverterSpec.groovy index 5d43e72ea0..20e7cdeff2 100755 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverterSpec.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverterSpec.groovy @@ -89,7 +89,7 @@ class RecursiveFilesConverterSpec extends Specification { ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.contractsDslDir = tmpFolder.root properties.stubsOutputDir = tmpFolder.root - RecursiveFilesConverter recursiveFilesConverter = new RecursiveFilesConverter(properties, new StubGeneratorHolder([stubGenerator])) + RecursiveFilesConverter recursiveFilesConverter = new RecursiveFilesConverter(properties, new StubGeneratorProvider([stubGenerator])) when: recursiveFilesConverter.processFiles() then: diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java index 26e0ed88da..815c7b7df2 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java @@ -10,6 +10,10 @@ import org.springframework.cloud.contract.maven.verifier.stubrunner.AetherStubDo import org.springframework.cloud.contract.stubrunner.AetherStubDownloader; import org.springframework.cloud.contract.stubrunner.ContractDownloader; import org.springframework.cloud.contract.stubrunner.StubConfiguration; +import org.springframework.cloud.contract.stubrunner.StubDownloader; +import org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder; +import org.springframework.cloud.contract.stubrunner.StubDownloaderBuilderProvider; +import org.springframework.cloud.contract.stubrunner.StubRunnerOptions; import org.springframework.cloud.contract.stubrunner.StubRunnerOptionsBuilder; import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; import org.springframework.util.StringUtils; @@ -33,6 +37,7 @@ class MavenContractsDownloader { private final Log log; private final AetherStubDownloaderFactory aetherStubDownloaderFactory; private final RepositorySystemSession repoSession; + private final StubDownloaderBuilderProvider stubDownloaderBuilderProvider; MavenContractsDownloader(MavenProject project, Dependency contractDependency, String contractsPath, String contractsRepositoryUrl, @@ -47,6 +52,7 @@ class MavenContractsDownloader { this.log = log; this.aetherStubDownloaderFactory = aetherStubDownloaderFactory; this.repoSession = repoSession; + this.stubDownloaderBuilderProvider = new StubDownloaderBuilderProvider(); } File downloadAndUnpackContractsIfRequired(ContractVerifierConfigProperties config, File defaultContractsDir) { @@ -77,20 +83,36 @@ class MavenContractsDownloader { this.contractsPath, this.project.getGroupId(), this.project.getArtifactId()); } - private AetherStubDownloader stubDownloader() { + private StubDownloader stubDownloader() { + StubDownloaderBuilder builder = this.stubDownloaderBuilderProvider.get(); if (StringUtils.hasText(this.contractsRepositoryUrl) || this.contractsWorkOffline) { this.log.info("Will download contracts from [" + this.contractsRepositoryUrl + "]. " + "Work offline switch equals to [" + this.contractsWorkOffline + "]"); - return new AetherStubDownloader( - new StubRunnerOptionsBuilder() - .withStubRepositoryRoot(this.contractsRepositoryUrl) - .withWorkOffline(this.contractsWorkOffline) - .build()); + if (builder != null) { + logStubDownloader(builder); + return builder.build(buildOptions()); + } + return new AetherStubDownloader(buildOptions()); } this.log.info("Will download contracts using current build's Maven repository setup"); + if (builder != null) { + logStubDownloader(builder); + return builder.build(buildOptions()); + } return this.aetherStubDownloaderFactory.build(this.repoSession); } + private void logStubDownloader(StubDownloaderBuilder builder) { + this.log.info("A custom stub downloader [" + builder + "] was provided"); + } + + StubRunnerOptions buildOptions() { + return new StubRunnerOptionsBuilder() + .withStubRepositoryRoot(this.contractsRepositoryUrl) + .withWorkOffline(this.contractsWorkOffline) + .build(); + } + private StubConfiguration stubConfiguration() { String groupId = this.contractDependency.getGroupId(); String artifactId = this.contractDependency.getArtifactId(); diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/stubrunner/AetherStubDownloaderFactory.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/stubrunner/AetherStubDownloaderFactory.java index 93b883b0c9..29c28f6d25 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/stubrunner/AetherStubDownloaderFactory.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/stubrunner/AetherStubDownloaderFactory.java @@ -23,6 +23,7 @@ import org.apache.maven.project.MavenProject; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; import org.springframework.cloud.contract.stubrunner.AetherStubDownloader; +import org.springframework.cloud.contract.stubrunner.StubDownloader; @Named @Singleton @@ -37,7 +38,7 @@ public class AetherStubDownloaderFactory { this.project = project; } - public AetherStubDownloader build(RepositorySystemSession repoSession) { + public StubDownloader build(RepositorySystemSession repoSession) { return new AetherStubDownloader(this.repoSystem, this.project.getRemoteProjectRepositories(), repoSession); } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/stubrunner/RemoteStubRunner.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/stubrunner/RemoteStubRunner.java index 7dcbb25747..4020385386 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/stubrunner/RemoteStubRunner.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/stubrunner/RemoteStubRunner.java @@ -22,10 +22,10 @@ import javax.inject.Named; import org.eclipse.aether.RepositorySystemSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.cloud.contract.stubrunner.AetherStubDownloader; import org.springframework.cloud.contract.stubrunner.BatchStubRunner; import org.springframework.cloud.contract.stubrunner.BatchStubRunnerFactory; import org.springframework.cloud.contract.stubrunner.RunningStubs; +import org.springframework.cloud.contract.stubrunner.StubDownloader; import org.springframework.cloud.contract.stubrunner.StubRunnerOptions; @Named @@ -39,7 +39,7 @@ public class RemoteStubRunner { } public BatchStubRunner run(StubRunnerOptions options, RepositorySystemSession repositorySystemSession) { - AetherStubDownloader stubDownloader = this.aetherStubDownloaderFactory.build(repositorySystemSession); + StubDownloader stubDownloader = this.aetherStubDownloaderFactory.build(repositorySystemSession); try { if (log.isDebugEnabled()) { log.debug("Launching StubRunner with args: " + options); diff --git a/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/ClasspathStubProvider.groovy b/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/ClasspathStubProvider.groovy new file mode 100644 index 0000000000..dfbd698b19 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/ClasspathStubProvider.groovy @@ -0,0 +1,96 @@ +/* + * 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. + */ + +package org.springframework.cloud.contract.stubrunner.provider.moco + +import org.springframework.cloud.contract.stubrunner.StubConfiguration +import org.springframework.cloud.contract.stubrunner.StubDownloader +import org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder +import org.springframework.cloud.contract.stubrunner.StubRunnerOptions +import org.springframework.core.io.DefaultResourceLoader +import org.springframework.core.io.Resource +import org.springframework.core.io.support.PathMatchingResourcePatternResolver + +import java.nio.file.Files + +/** + * Poor man's version of taking stubs from classpath. It needs much more + * love and attention to go to the main sources. + * + * @author Marcin Grzejszczak + */ +class ClasspathStubProvider implements StubDownloaderBuilder { + + private static final int TEMP_DIR_ATTEMPTS = 10000 + + @Override + public StubDownloader build(StubRunnerOptions stubRunnerOptions) { + final StubConfiguration configuration = stubRunnerOptions.getDependencies().first() + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver( + new DefaultResourceLoader()) + try { + String rootFolder = repoRoot(stubRunnerOptions) ?: "**/" + separatedArtifact(configuration) + "/**/*.json" + Resource[] resources = resolver.getResources(rootFolder) + final File tmp = createTempDir() + tmp.deleteOnExit() + // you'd have to write an impl to maintain the folder structure + // this is just for demo + resources.each { Resource resource -> + Files.copy(resource.getInputStream(), new File(tmp, resource.getFile().getName()).toPath()) + } + return new StubDownloader() { + @Override + public Map.Entry downloadAndUnpackStubJar( + StubConfiguration stubConfiguration) { + return new AbstractMap.SimpleEntry(configuration, tmp) + } + } + } catch (IOException e) { + throw new IllegalStateException(e) + } + } + + private String repoRoot(StubRunnerOptions stubRunnerOptions) { + switch (stubRunnerOptions.stubRepositoryRoot) { + case { !it }: + return "" + case { String root -> root.endsWith("**/*.json") }: + return stubRunnerOptions.stubRepositoryRoot + default: + return stubRunnerOptions.stubRepositoryRoot + "/**/*.json" + } + } + + private String separatedArtifact(StubConfiguration configuration) { + return configuration.getGroupId().replace(".", File.separator) + + File.separator + configuration.getArtifactId() + } + + // Taken from Guava + private File createTempDir() { + File baseDir = new File(System.getProperty("java.io.tmpdir")) + String baseName = System.currentTimeMillis() + "-" + for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) { + File tempDir = new File(baseDir, baseName + counter) + if (tempDir.mkdir()) { + return tempDir + } + } + throw new IllegalStateException( + "Failed to create directory within " + TEMP_DIR_ATTEMPTS + " attempts (tried " + baseName + "0 to " + baseName + ( + TEMP_DIR_ATTEMPTS - 1) + ")") + } +} \ No newline at end of file diff --git a/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStubSpec.groovy b/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStubSpec.groovy index 0e92c8f7e3..d413884df4 100644 --- a/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStubSpec.groovy +++ b/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStubSpec.groovy @@ -33,8 +33,8 @@ import spock.lang.Specification @ContextConfiguration(classes = Config, loader = SpringBootContextLoader) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @AutoConfigureStubRunner( ids = - ["org.springframework.cloud.contract.verifier.stubs:fraudDetectionServerMoco"], - repositoryRoot = "classpath:m2repo/repository/") + ["com.example:fraudDetectionServerMoco"], + repositoryRoot = "classpath:unpacked/") @DirtiesContext class MocoHttpServerStubSpec extends Specification { diff --git a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/META-INF/spring.factories b/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/META-INF/spring.factories index a48f1e4078..c0500db23e 100644 --- a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/META-INF/spring.factories +++ b/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/META-INF/spring.factories @@ -1,2 +1,8 @@ +# Example of a custom HTTP Server Stub org.springframework.cloud.contract.stubrunner.HttpServerStub=\ -org.springframework.cloud.contract.stubrunner.provider.moco.MocoHttpServerStub \ No newline at end of file +org.springframework.cloud.contract.stubrunner.provider.moco.MocoHttpServerStub + +# Example of a custom Stub Downloader Provider +org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder=\ +org.springframework.cloud.contract.stubrunner.provider.moco.ClasspathStubProvider + diff --git a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/0.0.1-SNAPSHOT/fraudDetectionServerMoco-0.0.1-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/0.0.1-SNAPSHOT/fraudDetectionServerMoco-0.0.1-SNAPSHOT-stubs.jar deleted file mode 100644 index f2153d4cc9..0000000000 Binary files a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/0.0.1-SNAPSHOT/fraudDetectionServerMoco-0.0.1-SNAPSHOT-stubs.jar and /dev/null differ diff --git a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/0.0.1-SNAPSHOT/fraudDetectionServerMoco-0.0.1-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/0.0.1-SNAPSHOT/fraudDetectionServerMoco-0.0.1-SNAPSHOT.pom deleted file mode 100644 index 4ac46b5839..0000000000 --- a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/0.0.1-SNAPSHOT/fraudDetectionServerMoco-0.0.1-SNAPSHOT.pom +++ /dev/null @@ -1,25 +0,0 @@ - - - - - 4.0.0 - org.springframework.cloud.contract.verifier.stubs - fraudDetectionServerMoco - 0.0.1-SNAPSHOT - pom - diff --git a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/maven-metadata.xml deleted file mode 100644 index 84801f46e2..0000000000 --- a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServerMoco/maven-metadata.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - org.springframework.cloud.contract.verifier.stubs - fraudDetectionServerMoco - 0.0.1-SNAPSHOT - - - 0.0.1-SNAPSHOT - - 20160409062112 - - diff --git a/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/unpacked/com/example/fraudDetectionServerMoco/someFolder/shouldSayHello.json b/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/unpacked/com/example/fraudDetectionServerMoco/someFolder/shouldSayHello.json new file mode 100644 index 0000000000..2c408a3ef7 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-moco/src/test/resources/unpacked/com/example/fraudDetectionServerMoco/someFolder/shouldSayHello.json @@ -0,0 +1,12 @@ +[ +{ + "request": { + "method" : "get", + "uri": "/name" + }, + "response": { + "text" : "fraudDetectionServerMoco", + "status": 200 + } +} +] \ No newline at end of file