View Javadoc
1   /*
2    * Copyright 2013-2020 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.cloud.contract.maven.verifier;
18  
19  import java.io.File;
20  import java.util.Map;
21  
22  import org.apache.maven.model.Dependency;
23  import org.apache.maven.plugin.logging.Log;
24  import org.apache.maven.project.MavenProject;
25  
26  import org.springframework.cloud.contract.stubrunner.ContractDownloader;
27  import org.springframework.cloud.contract.stubrunner.StubConfiguration;
28  import org.springframework.cloud.contract.stubrunner.StubDownloader;
29  import org.springframework.cloud.contract.stubrunner.StubDownloaderBuilderProvider;
30  import org.springframework.cloud.contract.stubrunner.StubRunnerOptions;
31  import org.springframework.cloud.contract.stubrunner.StubRunnerOptionsBuilder;
32  import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
33  import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
34  import org.springframework.util.StringUtils;
35  
36  /**
37   * Downloads JAR with contracts.
38   *
39   * @author Marcin Grzejszczak
40   * @since 1.0.0
41   */
42  class MavenContractsDownloader {
43  
44  	private static final String LATEST_VERSION = "+";
45  
46  	private static final String CONTRACTS_DIRECTORY_PROP = "CONTRACTS_DIRECTORY";
47  
48  	private final MavenProject project;
49  
50  	private final Dependency contractDependency;
51  
52  	private final String contractsPath;
53  
54  	private final String contractsRepositoryUrl;
55  
56  	private final StubRunnerProperties.StubsMode stubsMode;
57  
58  	private final Log log;
59  
60  	private final StubDownloaderBuilderProvider stubDownloaderBuilderProvider;
61  
62  	private final String repositoryUsername;
63  
64  	private final String repositoryPassword;
65  
66  	private final String repositoryProxyHost;
67  
68  	private final Integer repositoryProxyPort;
69  
70  	private final boolean deleteStubsAfterTest;
71  
72  	private final Map<String, String> contractsProperties;
73  
74  	private final boolean failOnNoStubs;
75  
76  	MavenContractsDownloader(MavenProject project, Dependency contractDependency, String contractsPath,
77  			String contractsRepositoryUrl, StubRunnerProperties.StubsMode stubsMode, Log log, String repositoryUsername,
78  			String repositoryPassword, String repositoryProxyHost, Integer repositoryProxyPort,
79  			boolean deleteStubsAfterTest, Map<String, String> contractsProperties, boolean failOnNoContracts) {
80  		this.project = project;
81  		this.contractDependency = contractDependency;
82  		this.contractsPath = contractsPath;
83  		this.contractsRepositoryUrl = contractsRepositoryUrl;
84  		this.stubsMode = stubsMode;
85  		this.log = log;
86  		this.repositoryUsername = repositoryUsername;
87  		this.repositoryPassword = repositoryPassword;
88  		this.repositoryProxyHost = repositoryProxyHost;
89  		this.repositoryProxyPort = repositoryProxyPort;
90  		this.stubDownloaderBuilderProvider = new StubDownloaderBuilderProvider();
91  		this.deleteStubsAfterTest = deleteStubsAfterTest;
92  		this.contractsProperties = contractsProperties;
93  		this.failOnNoStubs = failOnNoContracts;
94  	}
95  
96  	File downloadAndUnpackContractsIfRequired(ContractVerifierConfigProperties config, File defaultContractsDir) {
97  		String contractsDirFromProp = this.project.getProperties().getProperty(directoryProperty());
98  		File downloadedContractsDir = StringUtils.hasText(contractsDirFromProp) ? new File(contractsDirFromProp) : null;
99  		// reuse downloaded contracts from another mojo
100 		if (downloadedContractsDir != null && downloadedContractsDir.exists()) {
101 			this.log.info("Another mojo has downloaded the contracts - will reuse them from [" + downloadedContractsDir
102 					+ "]");
103 			final ContractDownloader.InclusionProperties inclusionProperties = contractDownloader()
104 					.createNewInclusionProperties(downloadedContractsDir);
105 			config.setIncludedContracts(inclusionProperties.getIncludedContracts());
106 			config.setIncludedRootFolderAntPattern(inclusionProperties.getIncludedRootFolderAntPattern());
107 			return downloadedContractsDir;
108 		}
109 		else if (shouldDownloadContracts()) {
110 			this.log.info("Download dependency is provided - will retrieve contracts from a remote location");
111 			final ContractDownloader contractDownloader = contractDownloader();
112 			final File downloadedContracts = contractDownloader.unpackAndDownloadContracts();
113 			final ContractDownloader.InclusionProperties inclusionProperties = contractDownloader
114 					.createNewInclusionProperties(downloadedContracts);
115 			config.setIncludedContracts(inclusionProperties.getIncludedContracts());
116 			config.setIncludedRootFolderAntPattern(inclusionProperties.getIncludedRootFolderAntPattern());
117 			this.project.getProperties().setProperty(directoryProperty(), downloadedContracts.getAbsolutePath());
118 			return downloadedContracts;
119 		}
120 		this.log.info("Will use contracts provided in the folder [" + defaultContractsDir + "]");
121 		return defaultContractsDir;
122 	}
123 
124 	private String directoryProperty() {
125 		if (this.contractDependency == null) {
126 			return CONTRACTS_DIRECTORY_PROP;
127 		}
128 		return CONTRACTS_DIRECTORY_PROP + "_" + this.contractDependency.getGroupId() + ":"
129 				+ this.contractDependency.getArtifactId() + ":" + this.contractDependency.getVersion() + ":"
130 				+ this.contractDependency.getClassifier();
131 	}
132 
133 	private boolean shouldDownloadContracts() {
134 		return this.contractDependency != null && StringUtils.hasText(this.contractDependency.getArtifactId())
135 				|| StringUtils.hasText(this.contractsRepositoryUrl);
136 	}
137 
138 	ContractDownloader contractDownloader() {
139 		return new ContractDownloader(stubDownloader(), stubConfiguration(), this.contractsPath,
140 				this.project.getGroupId(), this.project.getArtifactId(), this.project.getVersion());
141 	}
142 
143 	private StubDownloader stubDownloader() {
144 		StubRunnerOptions stubRunnerOptions = buildOptions();
145 		return this.stubDownloaderBuilderProvider.get(stubRunnerOptions);
146 	}
147 
148 	StubRunnerOptions buildOptions() {
149 		StubRunnerOptionsBuilder builder = new StubRunnerOptionsBuilder()
150 				.withOptions(StubRunnerOptions.fromSystemProps()).withStubsMode(this.stubsMode)
151 				.withUsername(this.repositoryUsername).withPassword(this.repositoryPassword)
152 				.withDeleteStubsAfterTest(this.deleteStubsAfterTest).withProperties(this.contractsProperties)
153 				.withFailOnNoStubs(this.failOnNoStubs);
154 		if (StringUtils.hasText(this.contractsRepositoryUrl)) {
155 			builder.withStubRepositoryRoot(this.contractsRepositoryUrl);
156 		}
157 		if (this.repositoryProxyPort != null) {
158 			builder.withProxy(this.repositoryProxyHost, this.repositoryProxyPort);
159 		}
160 		return builder.build();
161 	}
162 
163 	private StubConfiguration stubConfiguration() {
164 		String groupId = this.contractDependency.getGroupId();
165 		String artifactId = this.contractDependency.getArtifactId();
166 		String version = StringUtils.hasText(this.contractDependency.getVersion())
167 				? this.contractDependency.getVersion() : LATEST_VERSION;
168 		String classifier = this.contractDependency.getClassifier();
169 		return new StubConfiguration(groupId, artifactId, version, classifier);
170 	}
171 
172 }