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.io.IOException;
21  import java.util.Collections;
22  
23  import javax.inject.Inject;
24  
25  import org.apache.maven.execution.MavenSession;
26  import org.apache.maven.plugin.AbstractMojo;
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugin.MojoFailureException;
29  import org.apache.maven.plugins.annotations.Mojo;
30  import org.apache.maven.plugins.annotations.Parameter;
31  import org.apache.maven.plugins.annotations.ResolutionScope;
32  import org.eclipse.aether.RepositorySystemSession;
33  
34  import org.springframework.cloud.contract.maven.verifier.stubrunner.LocalStubRunner;
35  import org.springframework.cloud.contract.maven.verifier.stubrunner.RemoteStubRunner;
36  import org.springframework.cloud.contract.stubrunner.BatchStubRunner;
37  import org.springframework.cloud.contract.stubrunner.StubRunner;
38  import org.springframework.cloud.contract.stubrunner.StubRunnerOptions;
39  import org.springframework.cloud.contract.stubrunner.StubRunnerOptionsBuilder;
40  import org.springframework.util.StringUtils;
41  
42  /**
43   * Mojo for running stubs.
44   *
45   * @author Mariusz Smykula
46   * @author EddĂș MelĂ©ndez
47   */
48  @Mojo(name = "run", requiresProject = false, requiresDependencyResolution = ResolutionScope.RUNTIME)
49  public class RunMojo extends AbstractMojo {
50  
51  	private final LocalStubRunner localStubRunner;
52  
53  	private final RemoteStubRunner remoteStubRunner;
54  
55  	@Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
56  	private RepositorySystemSession repoSession;
57  
58  	@Parameter(defaultValue = ConvertMojo.DEFAULT_STUBS_DIR)
59  	private File stubsDirectory;
60  
61  	@Parameter(property = "stubsDirectory", defaultValue = "${basedir}")
62  	private File destination;
63  
64  	/**
65  	 * HTTP port for the WireMock server that serves stubs.
66  	 */
67  	@Parameter(property = "spring.cloud.contract.verifier.http.port", defaultValue = "8080")
68  	private int httpPort;
69  
70  	/**
71  	 * Set this to "true" to bypass verifier execution.
72  	 */
73  	@Parameter(property = "spring.cloud.contract.verifier.skip", defaultValue = "false")
74  	private boolean skip;
75  
76  	/**
77  	 * Set this to "true" to bypass verifier test generation.
78  	 */
79  	@Parameter(property = "spring.cloud.contract.verifier.skipTestOnly", defaultValue = "false")
80  	private boolean skipTestOnly;
81  
82  	/**
83  	 * List of stubs to be downloaded and ran in a colon separated Ivy notation.
84  	 */
85  	@Parameter(property = "spring.cloud.contract.verifier.stubs")
86  	private String stubs;
87  
88  	/**
89  	 * Minimal port at which the stub should start.
90  	 */
91  	@Parameter(property = "spring.cloud.contract.verifier.http.minPort", defaultValue = "10000")
92  	private int minPort;
93  
94  	/**
95  	 * Maximal port at which the stub should start.
96  	 */
97  	@Parameter(property = "spring.cloud.contract.verifier.http.maxPort", defaultValue = "15000")
98  	private int maxPort;
99  
100 	/**
101 	 * Should the plugin wait for the user to press the key after starting the stubs.
102 	 */
103 	@Parameter(property = "spring.cloud.contract.verifier.wait-for-key-pressed", defaultValue = "true")
104 	private boolean waitForKeyPressed;
105 
106 	/**
107 	 * Classifier used by stubs artifacts.
108 	 */
109 	@Parameter(defaultValue = "stubs")
110 	private String stubsClassifier = "stubs";
111 
112 	@Parameter(defaultValue = "${session}", readonly = true)
113 	private MavenSession mavenSession;
114 
115 	/**
116 	 *
117 	 */
118 	@Parameter(property = "spring.cloud.contract.verifier.server-id")
119 	private String serverId;
120 
121 	@Inject
122 	public RunMojo(LocalStubRunner localStubRunner, RemoteStubRunner remoteStubRunner) {
123 		this.localStubRunner = localStubRunner;
124 		this.remoteStubRunner = remoteStubRunner;
125 	}
126 
127 	@Override
128 	public void execute() throws MojoExecutionException, MojoFailureException {
129 		if (this.skip || this.skipTestOnly) {
130 			getLog().info("Skipping verifier execution: spring.cloud.contract.verifier.skip=" + this.skip);
131 			return;
132 		}
133 		BatchStubRunner batchStubRunner = null;
134 		StubRunnerOptionsBuilder optionsBuilder = new StubRunnerOptionsBuilder()
135 				.withStubsClassifier(this.stubsClassifier);
136 		if (!StringUtils.hasText(this.stubs)) {
137 			StubRunnerOptions options = optionsBuilder.withMinMaxPort(this.httpPort, this.httpPort).build();
138 			StubRunner stubRunner = this.localStubRunner.run(resolveStubsDirectory().getAbsolutePath(), options);
139 			batchStubRunner = new BatchStubRunner(Collections.singleton(stubRunner));
140 		}
141 		else {
142 			StubRunnerOptions options = optionsBuilder.withStubs(this.stubs).withMinMaxPort(this.minPort, this.maxPort)
143 					.withServerId(this.serverId).build();
144 			batchStubRunner = this.remoteStubRunner.run(options, this.repoSession);
145 		}
146 		pressAnyKeyToContinue();
147 		if (batchStubRunner != null) {
148 			try {
149 				batchStubRunner.close();
150 			}
151 			catch (IOException e) {
152 				throw new MojoExecutionException("Fail to close batch stub runner", e);
153 			}
154 		}
155 	}
156 
157 	private File resolveStubsDirectory() {
158 		if (isInsideProject()) {
159 			return this.stubsDirectory;
160 		}
161 		else {
162 			return this.destination;
163 		}
164 	}
165 
166 	private void pressAnyKeyToContinue() {
167 		if (!this.waitForKeyPressed) {
168 			return;
169 		}
170 		getLog().info("Press ENTER to continue...");
171 		try {
172 			System.in.read();
173 		}
174 		catch (Exception ignored) {
175 		}
176 	}
177 
178 	private boolean isInsideProject() {
179 		return this.mavenSession.getRequest().isProjectPresent();
180 	}
181 
182 }