Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit 58bc6ea

Browse files
committed
#187 JSON payloads now allow comments
1 parent f62448b commit 58bc6ea

File tree

15 files changed

+196
-27
lines changed

15 files changed

+196
-27
lines changed

src/main/java/com/marklogic/appdeployer/command/clusters/ModifyLocalClusterCommand.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ public void execute(CommandContext context) {
2424
if (configDir != null && configDir.exists()) {
2525
for (File f : configDir.listFiles()) {
2626
if (f.isFile() && f.getName().startsWith("local-cluster")) {
27-
String payload = copyFileToString(f);
28-
payload = payloadTokenReplacer.replaceTokens(payload, context.getAppConfig(), false);
27+
String payload = copyFileToString(f, context);
2928
new ClusterManager(context.getManageClient()).modifyLocalCluster(payload, context.getAdminManager());
3029
}
3130
}

src/main/java/com/marklogic/appdeployer/export/impl/AbstractResourceExporter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.marklogic.mgmt.ManageClient;
1010
import com.marklogic.mgmt.PayloadParser;
1111
import com.marklogic.mgmt.resource.ResourceManager;
12+
import com.marklogic.mgmt.util.ObjectMapperFactory;
1213
import org.springframework.util.FileCopyUtils;
1314

1415
import java.io.File;
@@ -29,7 +30,7 @@ public abstract class AbstractResourceExporter extends LoggingObject implements
2930

3031
protected AbstractResourceExporter(ManageClient manageClient) {
3132
this.manageClient = manageClient;
32-
this.objectMapper = new ObjectMapper();
33+
this.objectMapper = ObjectMapperFactory.getObjectMapper();
3334
}
3435

3536
protected boolean isFormatXml() {
@@ -42,7 +43,7 @@ protected String removeJsonKeyFromPayload(String payload, String key) {
4243
if (node.has(key)) {
4344
node.remove(key);
4445
try {
45-
return payloadParser.getObjectMapper().writeValueAsString(node);
46+
return ObjectMapperFactory.getObjectMapper().writeValueAsString(node);
4647
} catch (JsonProcessingException e) {
4748
throw new RuntimeException("Unable to write forest JSON out as string: " + e.getMessage(), e);
4849
}

src/main/java/com/marklogic/appdeployer/scaffold/ScaffoldGenerator.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.marklogic.appdeployer.AppConfig;
1010
import com.marklogic.appdeployer.util.RestApiUtil;
1111
import com.marklogic.client.ext.helper.LoggingObject;
12+
import com.marklogic.mgmt.util.ObjectMapperFactory;
1213
import org.springframework.util.FileCopyUtils;
1314

1415
import java.io.File;
@@ -19,10 +20,13 @@
1920
*/
2021
public class ScaffoldGenerator extends LoggingObject {
2122

22-
protected ObjectMapper objectMapper = new ObjectMapper();
23+
protected ObjectMapper objectMapper;
2324
private PrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
2425

2526
public void generateScaffold(String path, AppConfig config) {
27+
if (objectMapper == null) {
28+
objectMapper = ObjectMapperFactory.getObjectMapper();
29+
}
2630
File rootDir = new File(path);
2731

2832
File configDir = getConfigDir(rootDir);
@@ -232,4 +236,11 @@ protected File getModulesDir(File rootDir) {
232236
return new File(rootDir, "src/main/ml-modules");
233237
}
234238

239+
public void setObjectMapper(ObjectMapper objectMapper) {
240+
this.objectMapper = objectMapper;
241+
}
242+
243+
public void setPrettyPrinter(PrettyPrinter prettyPrinter) {
244+
this.prettyPrinter = prettyPrinter;
245+
}
235246
}

src/main/java/com/marklogic/appdeployer/util/RestApiUtil.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
55
import com.fasterxml.jackson.databind.ObjectMapper;
66
import com.fasterxml.jackson.databind.node.ObjectNode;
7+
import com.marklogic.mgmt.util.ObjectMapperFactory;
78

89
public abstract class RestApiUtil {
910

1011
public static String buildDefaultRestApiJson() {
11-
ObjectMapper m = new ObjectMapper();
12+
ObjectMapper m = ObjectMapperFactory.getObjectMapper();
1213
ObjectNode node = m.createObjectNode();
1314
ObjectNode n = node.putObject("rest-api");
1415
n.put("name", "%%NAME%%");

src/main/java/com/marklogic/mgmt/DefaultManageConfigFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ public ManageConfig newManageConfig() {
6666
c.setConfigureSimpleSsl(Boolean.parseBoolean(prop));
6767
}
6868

69+
prop = getProperty("mlManageCleanJsonPayloads");
70+
if (prop != null) {
71+
logger.info("Cleaning Management API JSON payloads: " + prop);
72+
c.setCleanJsonPayloads(Boolean.parseBoolean(prop));
73+
}
74+
6975
prop = getProperty("mlAdminUsername");
7076
if (prop != null) {
7177
logger.info("Manage admin username: " + prop);

src/main/java/com/marklogic/mgmt/ManageClient.java

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.marklogic.mgmt;
22

3+
import com.fasterxml.jackson.databind.JsonNode;
34
import com.marklogic.client.ext.helper.LoggingObject;
5+
import com.marklogic.mgmt.util.ObjectMapperFactory;
46
import com.marklogic.rest.util.Fragment;
57
import com.marklogic.rest.util.RestTemplateUtil;
68
import org.jdom2.Namespace;
@@ -9,6 +11,8 @@
911
import org.springframework.util.MultiValueMap;
1012
import org.springframework.web.client.RestTemplate;
1113

14+
import java.io.IOException;
15+
import java.io.StringWriter;
1216
import java.net.URI;
1317
import java.util.ArrayList;
1418
import java.util.List;
@@ -22,6 +26,7 @@ public class ManageClient extends LoggingObject {
2226
private ManageConfig manageConfig;
2327
private RestTemplate restTemplate;
2428
private RestTemplate adminRestTemplate;
29+
private PayloadParser payloadParser;
2530

2631
/**
2732
* Can use this constructor when the default values in ManageConfig will work.
@@ -187,13 +192,44 @@ public void deleteAsAdmin(String path) {
187192
adminRestTemplate.delete(buildUri(path));
188193
}
189194

190-
public HttpEntity<String> buildJsonEntity(String json) {
195+
/**
196+
* Per #187 and version 3.1.0, when an HttpEntity is constructed with a JSON payload, this method will check to see
197+
* if it should "clean" the JSON via the Jackson library, which is primarily intended for removing comments from
198+
* JSON (comments that Jackson allows, but aren't allowed by the JSON spec). This behavior is disabled by default.
199+
*
200+
* @param json
201+
* @return
202+
*/
203+
public HttpEntity<String> buildJsonEntity(String json) {
191204
HttpHeaders headers = new HttpHeaders();
192205
headers.setContentType(MediaType.APPLICATION_JSON);
206+
if (manageConfig != null && manageConfig.isCleanJsonPayloads()) {
207+
json = cleanJsonPayload(json);
208+
}
193209
return new HttpEntity<String>(json, headers);
194210
}
195211

196-
public HttpEntity<String> buildXmlEntity(String xml) {
212+
/**
213+
* Per #187, and version 3.1.0, this will also use Jackson to remove any comments in the JSON payload, as Jackson
214+
* is now configured to ignore comments, but we still don't want to include them in the payload sent to MarkLogic.
215+
* @param payload
216+
* @return
217+
*/
218+
protected String cleanJsonPayload(String payload) {
219+
if (payloadParser == null) {
220+
payloadParser = new PayloadParser();
221+
}
222+
JsonNode node = payloadParser.parseJson(payload);
223+
StringWriter sw = new StringWriter();
224+
try {
225+
ObjectMapperFactory.getObjectMapper().writer().writeValue(sw, node);
226+
} catch (IOException ex) {
227+
throw new RuntimeException("Unable to write JSON payload as JsonNode back out to a string, cause: " + ex.getMessage());
228+
}
229+
return sw.toString();
230+
}
231+
232+
public HttpEntity<String> buildXmlEntity(String xml) {
197233
HttpHeaders headers = new HttpHeaders();
198234
headers.setContentType(MediaType.APPLICATION_XML);
199235
return new HttpEntity<String>(xml, headers);
@@ -213,7 +249,7 @@ protected void logAdminRequest(String path, String contentType, String method) {
213249
}
214250
}
215251

216-
public URI buildUri(String path) {
252+
public URI buildUri(String path) {
217253
return manageConfig.buildUri(path);
218254
}
219255

src/main/java/com/marklogic/mgmt/ManageConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class ManageConfig extends RestConfig {
2121
private boolean adminConfigureSimpleSsl;
2222
private String adminScheme = "http";
2323
private int adminPort = 8001;
24+
private boolean cleanJsonPayloads = false;
2425

2526
public ManageConfig() {
2627
this("localhost", DEFAULT_PASSWORD);
@@ -81,4 +82,12 @@ public String getAdminScheme() {
8182
public void setAdminScheme(String adminScheme) {
8283
this.adminScheme = adminScheme;
8384
}
85+
86+
public boolean isCleanJsonPayloads() {
87+
return cleanJsonPayloads;
88+
}
89+
90+
public void setCleanJsonPayloads(boolean cleanJsonPayloads) {
91+
this.cleanJsonPayloads = cleanJsonPayloads;
92+
}
8493
}

src/main/java/com/marklogic/mgmt/PayloadParser.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
package com.marklogic.mgmt;
22

3+
import com.fasterxml.jackson.core.JsonParser;
34
import com.fasterxml.jackson.databind.JsonNode;
45
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import com.marklogic.mgmt.util.ObjectMapperFactory;
57
import com.marklogic.rest.util.Fragment;
68

79
/**
810
* Utility class for parsing a JSON or XML payload and extracting values.
911
*/
1012
public class PayloadParser {
1113

12-
private ObjectMapper objectMapper = new ObjectMapper();
14+
private ObjectMapper objectMapper;
1315

1416
public JsonNode parseJson(String json) {
17+
if (objectMapper == null) {
18+
objectMapper = ObjectMapperFactory.getObjectMapper();
19+
}
1520
try {
1621
return objectMapper.readTree(json);
1722
} catch (Exception e) {
@@ -43,6 +48,9 @@ public String getPayloadFieldValue(String payload, String fieldName) {
4348
}
4449

4550
public boolean isJsonPayload(String payload) {
51+
if (payload == null) {
52+
return false;
53+
}
4654
String s = payload.trim();
4755
return s.startsWith("{") || s.startsWith("[");
4856
}

src/main/java/com/marklogic/mgmt/api/API.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.marklogic.mgmt.api;
22

33
import com.fasterxml.jackson.annotation.JsonInclude.Include;
4+
import com.fasterxml.jackson.core.JsonParser;
45
import com.fasterxml.jackson.databind.DeserializationFeature;
56
import com.fasterxml.jackson.databind.ObjectMapper;
67
import com.fasterxml.jackson.databind.SerializationFeature;
@@ -28,6 +29,7 @@
2829
import com.marklogic.mgmt.resource.groups.GroupManager;
2930
import com.marklogic.mgmt.resource.security.*;
3031
import com.marklogic.mgmt.resource.tasks.TaskManager;
32+
import com.marklogic.mgmt.util.ObjectMapperFactory;
3133
import com.marklogic.mgmt.util.SimplePropertySource;
3234
import com.marklogic.mgmt.util.SystemPropertySource;
3335

@@ -73,14 +75,7 @@ protected void initializeAdminManager() {
7375
}
7476

7577
protected ObjectMapper buildDefaultObjectMapper() {
76-
ObjectMapper m = new ObjectMapper();
77-
m.setPropertyNamingStrategy(new LowerCaseWithHyphensStrategy());
78-
m.setSerializationInclusion(Include.NON_NULL);
79-
m.enable(SerializationFeature.INDENT_OUTPUT);
80-
m.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
81-
// This is needed at least for localname on Element instances
82-
m.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
83-
return m;
78+
return ObjectMapperFactory.getObjectMapper();
8479
}
8580

8681
/**

src/main/java/com/marklogic/mgmt/resource/security/CertificateTemplateManager.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package com.marklogic.mgmt.resource.security;
22

3-
import com.fasterxml.jackson.databind.ObjectMapper;
43
import com.fasterxml.jackson.databind.node.ObjectNode;
5-
import com.marklogic.mgmt.resource.AbstractResourceManager;
64
import com.marklogic.mgmt.ManageClient;
5+
import com.marklogic.mgmt.resource.AbstractResourceManager;
6+
import com.marklogic.mgmt.util.ObjectMapperFactory;
77
import com.marklogic.rest.util.Fragment;
88
import org.springframework.http.ResponseEntity;
99

@@ -54,7 +54,7 @@ public ResponseEntity<String> generateTemporaryCertificate(String templateIdOrNa
5454

5555
public ResponseEntity<String> generateTemporaryCertificate(String templateIdOrName, String commonName,
5656
int validFor, String dnsName, String ipAddress, boolean ifNecessary) {
57-
ObjectNode node = new ObjectMapper().createObjectNode();
57+
ObjectNode node = ObjectMapperFactory.getObjectMapper().createObjectNode();
5858
node.put("operation", "generate-temporary-certificate");
5959
node.put("valid-for", validFor);
6060
node.put("common-name", commonName);
@@ -75,7 +75,7 @@ public ResponseEntity<String> generateTemporaryCertificate(String templateIdOrNa
7575
}
7676

7777
public Fragment getCertificatesForTemplate(String templateIdOrName) {
78-
ObjectNode node = new ObjectMapper().createObjectNode();
78+
ObjectNode node = ObjectMapperFactory.getObjectMapper().createObjectNode();
7979
node.put("operation", "get-certificates-for-template");
8080

8181
String json = node.toString();

0 commit comments

Comments
 (0)