Skip to content

Commit 0a3ca30

Browse files
committed
Switch WireMockToDslConverter to Jackson 3.
Signed-off-by: Olga Maciaszek-Sharma <[email protected]>
1 parent 3ba02f2 commit 0a3ca30

File tree

1 file changed

+89
-90
lines changed
  • spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/java/org/springframework/cloud/contract/verifier/wiremock

1 file changed

+89
-90
lines changed

spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/java/org/springframework/cloud/contract/verifier/wiremock/WireMockToDslConverter.java

Lines changed: 89 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,29 @@
1616

1717
package org.springframework.cloud.contract.verifier.wiremock;
1818

19-
import java.io.IOException;
2019
import java.util.ArrayList;
20+
import java.util.Collection;
2121
import java.util.Iterator;
2222
import java.util.List;
2323
import java.util.Map;
24-
import java.util.stream.StreamSupport;
25-
26-
import com.fasterxml.jackson.core.JsonParser;
27-
import com.fasterxml.jackson.core.JsonPointer;
28-
import com.fasterxml.jackson.core.util.DefaultIndenter;
29-
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
30-
import com.fasterxml.jackson.core.util.Separators;
31-
import com.fasterxml.jackson.databind.JsonNode;
32-
import com.fasterxml.jackson.databind.ObjectMapper;
33-
import com.fasterxml.jackson.databind.node.ArrayNode;
34-
import com.fasterxml.jackson.databind.node.IntNode;
35-
import com.fasterxml.jackson.databind.node.ObjectNode;
36-
import com.fasterxml.jackson.databind.node.TextNode;
24+
import java.util.Set;
25+
3726
import repackaged.nl.flotsam.xeger.Xeger;
27+
import tools.jackson.core.JsonPointer;
28+
import tools.jackson.core.util.DefaultIndenter;
29+
import tools.jackson.core.util.DefaultPrettyPrinter;
30+
import tools.jackson.databind.JsonNode;
31+
import tools.jackson.databind.json.JsonMapper;
32+
import tools.jackson.databind.node.ArrayNode;
33+
import tools.jackson.databind.node.IntNode;
34+
import tools.jackson.databind.node.ObjectNode;
35+
import tools.jackson.databind.node.StringNode;
3836

3937
import static org.apache.commons.text.StringEscapeUtils.escapeJava;
38+
import static tools.jackson.core.json.JsonReadFeature.ALLOW_JAVA_COMMENTS;
39+
import static tools.jackson.core.json.JsonReadFeature.ALLOW_SINGLE_QUOTES;
40+
import static tools.jackson.core.json.JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES;
41+
import static tools.jackson.core.json.JsonReadFeature.ALLOW_YAML_COMMENTS;
4042

4143
/**
4244
* Converts WireMock stubs into the DSL format.
@@ -69,14 +71,13 @@ public class WireMockToDslConverter {
6971

7072
private static final JsonPointer RESPONSE_HEADERS_POINTER = JsonPointer.compile("/response/headers");
7173

72-
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
73-
74-
static {
75-
OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
76-
OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_YAML_COMMENTS, true);
77-
OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
78-
OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
79-
}
74+
private static final JsonMapper OBJECT_MAPPER = JsonMapper
75+
.builder()
76+
.configure(ALLOW_JAVA_COMMENTS, true)
77+
.configure(ALLOW_YAML_COMMENTS, true)
78+
.configure(ALLOW_UNQUOTED_PROPERTY_NAMES, true)
79+
.configure(ALLOW_SINGLE_QUOTES, true)
80+
.build();
8081

8182
/**
8283
* Returns the string content of the contract.
@@ -100,7 +101,7 @@ private JsonNode parseStubDefinition(String wireMockStringStub) {
100101
try {
101102
return OBJECT_MAPPER.reader().readTree(wireMockStringStub);
102103
}
103-
catch (IOException e) {
104+
catch (Exception e) {
104105
throw new RuntimeException("WireMock string stub could not be read", e);
105106
}
106107
}
@@ -169,13 +170,19 @@ private String buildRequestHeaders(JsonNode wireMockStub) {
169170

170171
if (requestHeadersNode.isObject()) {
171172
requestHeadersBuilder.append("headers {\n");
172-
ObjectNode requestHeadersObjectNode = requestHeadersNode.deepCopy();
173-
Iterator<Map.Entry<String, JsonNode>> fields = requestHeadersObjectNode.fields();
174-
fields.forEachRemaining(c -> {
173+
JsonNode requestHeadersObjectNode = requestHeadersNode.deepCopy();
174+
Set<Map.Entry<String, JsonNode>> fields = requestHeadersObjectNode.properties();
175+
fields.forEach(c -> {
175176
requestHeadersBuilder.append("header('").append(c.getKey()).append("',");
176-
Map.Entry<String, JsonNode> headerValue = c.getValue().deepCopy().fields().next();
177-
String header = buildHeader(headerValue.getKey(), headerValue.getValue().asText());
178-
requestHeadersBuilder.append(header).append(")").append("\n");
177+
ObjectNode headersNode = (ObjectNode) c.getValue().deepCopy();
178+
Iterator<Map.Entry<String, JsonNode>> headersNodeIterator = headersNode.properties()
179+
.iterator();
180+
if (headersNodeIterator.hasNext()) {
181+
Map.Entry<String, JsonNode> headerValue = headersNodeIterator.next();
182+
String header = buildHeader(headerValue.getKey(), headerValue.getValue()
183+
.asString());
184+
requestHeadersBuilder.append(header).append(")").append("\n");
185+
}
179186
});
180187
requestHeadersBuilder.append("}");
181188
}
@@ -184,45 +191,48 @@ private String buildRequestHeaders(JsonNode wireMockStub) {
184191

185192
private String buildHeader(String method, String value) {
186193
switch (method) {
187-
case "equalTo":
188-
return "'" + value + "'";
189-
case "contains":
190-
String regex = "^.*" + value + ".*$";
191-
return "c(regex('" + escapeJava(regex) + "'))";
192-
default:
193-
return "c(regex('" + escapeJava(value) + "'))";
194+
case "equalTo":
195+
return "'" + value + "'";
196+
case "contains":
197+
String regex = "^.*" + value + ".*$";
198+
return "c(regex('" + escapeJava(regex) + "'))";
199+
default:
200+
return "c(regex('" + escapeJava(value) + "'))";
194201
}
195202
}
196203

197204
private String buildRequestBody(JsonNode wireMockStub) {
198205
final StringBuilder requestBody = new StringBuilder();
199206
JsonNode requestBodyNode = wireMockStub.at(REQUEST_BODY_POINTER);
200207
if (requestBodyNode.isArray()) {
201-
ArrayNode requestBodyArrayNode = requestBodyNode.deepCopy();
202-
Iterator<JsonNode> elements = requestBodyArrayNode.elements();
203-
Iterable<JsonNode> iterableFields = () -> elements;
208+
ArrayNode requestBodyArrayNode = (ArrayNode) requestBodyNode.deepCopy();
209+
Collection<JsonNode> elements = requestBodyArrayNode.elements();
204210
List<Map.Entry<String, JsonNode>> requestBodyObjectNodes = new ArrayList<>();
205-
StreamSupport.stream(iterableFields.spliterator(), false)
206-
.filter(f -> f instanceof ObjectNode)
207-
.map(f -> (ObjectNode) f)
208-
.map(ObjectNode::fields)
209-
.forEachOrdered(i -> i.forEachRemaining(requestBodyObjectNodes::add));
211+
212+
elements.stream()
213+
.filter(f -> f instanceof ObjectNode)
214+
.map(f -> (ObjectNode) f)
215+
.map(ObjectNode::properties)
216+
.forEachOrdered(requestBodyObjectNodes::addAll);
210217
requestBodyObjectNodes.stream()
211-
.filter(b -> b.getKey().equals("equalTo"))
212-
.findFirst()
213-
.ifPresent(b -> requestBody.append("body ('").append(b.getValue().asText()).append("')"));
218+
.filter(b -> b.getKey().equals("equalTo"))
219+
.findFirst()
220+
.ifPresent(b -> requestBody.append("body ('")
221+
.append(b.getValue().asString()).append("')"));
214222
requestBodyObjectNodes.stream()
215-
.filter(b -> b.getKey().equals("equalToJson"))
216-
.findFirst()
217-
.ifPresent(b -> requestBody.append("body ('").append(b.getValue().asText()).append("')"));
223+
.filter(b -> b.getKey().equals("equalToJson"))
224+
.findFirst()
225+
.ifPresent(b -> requestBody.append("body ('")
226+
.append(b.getValue().asString()).append("')"));
218227
requestBodyObjectNodes.stream()
219-
.filter(b -> b.getKey().equals("matches"))
220-
.findFirst()
221-
.ifPresent(b -> requestBody.append("body $(consumer(regex('")
222-
.append(escapeJava(b.getValue().asText()))
223-
.append("')), producer('")
224-
.append(new Xeger(escapeJava(b.getValue().asText())).generate())
225-
.append("'))"));
228+
.filter(b -> b.getKey().equals("matches"))
229+
.findFirst()
230+
.ifPresent(b -> requestBody.append("body $(consumer(regex('")
231+
.append(escapeJava(b.getValue().asString()))
232+
.append("')), producer('")
233+
.append(new Xeger(escapeJava(b.getValue()
234+
.asString())).generate())
235+
.append("'))"));
226236
}
227237
return requestBody.toString();
228238
}
@@ -243,8 +253,8 @@ private String buildResponseBody(JsonNode wireMockStub) {
243253
if (responseBodyNode.isInt()) {
244254
responseBody += "body( " + escapeJava(buildPrettyPrintResponseBody((IntNode) responseBodyNode)) + ")\n";
245255
}
246-
if (responseBodyNode.isTextual()) {
247-
responseBody += "body( \"" + escapeJava(buildPrettyPrintResponseBody((TextNode) responseBodyNode))
256+
if (responseBodyNode.isString()) {
257+
responseBody += "body( \"" + escapeJava(buildPrettyPrintResponseBody((StringNode) responseBodyNode))
248258
+ "\")\n";
249259
}
250260
return responseBody;
@@ -254,17 +264,22 @@ private String buildPrettyPrintResponseBody(IntNode node) {
254264
return node.asText();
255265
}
256266

257-
private String buildPrettyPrintResponseBody(TextNode node) {
267+
private String buildPrettyPrintResponseBody(StringNode node) {
258268
try {
259-
String textNode = node.asText();
260-
Object intermediateObjectForPrettyPrinting = OBJECT_MAPPER.reader().readValue(textNode, Object.class);
269+
String stringNode = node.asText();
270+
Object intermediateObjectForPrettyPrinting =
271+
OBJECT_MAPPER.readerFor(Object.class).readValue(stringNode);
272+
261273
DefaultIndenter customIndenter = new DefaultIndenter(" ", "\n");
262274
return OBJECT_MAPPER
263-
.writer(new PrivatePrettyPrinter().withArrayIndenter(customIndenter).withObjectIndenter(customIndenter))
264-
.writeValueAsString(intermediateObjectForPrettyPrinting);
275+
.writer()
276+
.with(new DefaultPrettyPrinter()
277+
.withArrayIndenter(customIndenter)
278+
.withObjectIndenter(customIndenter))
279+
.writeValueAsString(intermediateObjectForPrettyPrinting);
265280
}
266-
catch (IOException e) {
267-
throw new RuntimeException("WireMock response body could not be pretty printed");
281+
catch (Exception e) {
282+
throw new RuntimeException("WireMock response body could not be pretty printed", e);
268283
}
269284
}
270285

@@ -274,33 +289,17 @@ private String buildResponseHeaders(JsonNode wireMockStub) {
274289

275290
if (requestHeadersNode.isObject()) {
276291
responseHeadersBuilder.append("headers {\n");
277-
ObjectNode responseHeadersObjectNode = requestHeadersNode.deepCopy();
278-
Iterator<Map.Entry<String, JsonNode>> fields = responseHeadersObjectNode.fields();
279-
fields.forEachRemaining(c -> responseHeadersBuilder.append("header('")
280-
.append(c.getKey())
281-
.append("',")
282-
.append("'")
283-
.append(c.getValue().asText())
284-
.append("')\n"));
292+
JsonNode responseHeadersObjectNode = requestHeadersNode.deepCopy();
293+
Set<Map.Entry<String, JsonNode>> fields = responseHeadersObjectNode.properties();
294+
fields.forEach(c -> responseHeadersBuilder.append("header('")
295+
.append(c.getKey())
296+
.append("',")
297+
.append("'")
298+
.append(c.getValue().asString())
299+
.append("')\n"));
285300
responseHeadersBuilder.append("}");
286301
}
287302
return responseHeadersBuilder.toString();
288303
}
289304

290-
private static class PrivatePrettyPrinter extends DefaultPrettyPrinter {
291-
292-
@Override
293-
public DefaultPrettyPrinter createInstance() {
294-
return new PrivatePrettyPrinter();
295-
}
296-
297-
@Override
298-
public DefaultPrettyPrinter withSeparators(Separators separators) {
299-
_separators = separators;
300-
_objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSeparator() + " ";
301-
return this;
302-
}
303-
304-
}
305-
306305
}

0 commit comments

Comments
 (0)