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

Commit 5eb02cc

Browse files
committed
#94 Encoding "+" in a resource path; had to change some plumbing to construct a URI instance
1 parent a1aa204 commit 5eb02cc

File tree

10 files changed

+96
-473
lines changed

10 files changed

+96
-473
lines changed

src/main/java/com/marklogic/appdeployer/command/restapis/DeployRestApiServersCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,15 @@ protected String getDefaultRestApiPayload() {
147147
protected boolean deleteRestApi(String serverName, String groupName, ManageClient manageClient,
148148
boolean includeModules, boolean includeContent) {
149149
if (new ServerManager(manageClient, groupName).exists(serverName)) {
150-
String path = format("%s/v1/rest-apis/%s?", manageClient.getBaseUrl(), serverName);
150+
String path = format("/v1/rest-apis/%s?", serverName);
151151
if (includeModules) {
152152
path += "include=modules&";
153153
}
154154
if (includeContent) {
155155
path += "include=content";
156156
}
157157
logger.info("Deleting REST API, path: " + path);
158-
manageClient.getRestTemplate().exchange(path, HttpMethod.DELETE, null, String.class);
158+
manageClient.getRestTemplate().exchange(manageClient.buildUri(path), HttpMethod.DELETE, null, String.class);
159159
logger.info("Deleted REST API");
160160
return true;
161161
} else {

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public String getResourcesPath() {
2424
}
2525

2626
public String getResourcePath(String resourceNameOrId, String... resourceUrlParams) {
27+
resourceNameOrId = encodeResourceId(resourceNameOrId);
2728
return appendParamsAndValuesToPath(format("%s/%s", getResourcesPath(), resourceNameOrId), resourceUrlParams);
2829
}
2930

@@ -40,8 +41,8 @@ public boolean exists(String resourceNameOrId, String... resourceUrlParams) {
4041
}
4142

4243
public ResourcesFragment getAsXml() {
43-
Fragment f = useAdminUser() ? manageClient.getXmlAsAdmin(getResourcesPath()) : manageClient
44-
.getXml(getResourcesPath());
44+
Fragment f = useAdminUser() ? manageClient.getXmlAsAdmin(getResourcesPath())
45+
: manageClient.getXml(getResourcesPath());
4546
return new ResourcesFragment(f);
4647
}
4748

@@ -83,6 +84,19 @@ public SaveReceipt save(String payload) {
8384
return new SaveReceipt(resourceId, payload, path, response);
8485
}
8586

87+
/**
88+
* Mimetypes are likely to have a "+" in them, which the Management REST API won't support in a path - it needs to
89+
* be encoded. Other resources could have a "+" in their ID value as well. However, doing a full encoding doesn't
90+
* seem to be a great idea, as that will e.g. encode a forward slash in a mimetype as well, which will result in a
91+
* 404.
92+
*
93+
* @param idValue
94+
* @return
95+
*/
96+
protected String encodeResourceId(String idValue) {
97+
return idValue != null ? idValue.replace("+", "%2B") : idValue;
98+
}
99+
86100
/**
87101
* Most clients should just use the save method, but this is public for scenarios where a client knows an update
88102
* should be performed.
@@ -115,8 +129,8 @@ public DeleteReceipt deleteByIdField(String resourceIdFieldValue, String... reso
115129
public DeleteReceipt delete(String payload, String... resourceUrlParams) {
116130
String resourceId = getResourceId(payload);
117131
if (!exists(resourceId)) {
118-
logger.info(format("Could not find %s with name or ID of %s, so not deleting", getResourceName(),
119-
resourceId));
132+
logger.info(
133+
format("Could not find %s with name or ID of %s, so not deleting", getResourceName(), resourceId));
120134
return new DeleteReceipt(resourceId, null, false);
121135
} else {
122136
String path = getResourcePath(resourceId, resourceUrlParams);

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

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

3+
import java.net.URI;
34
import java.util.ArrayList;
45
import java.util.List;
56

@@ -26,7 +27,6 @@ public class ManageClient extends LoggingObject {
2627
private ManageConfig manageConfig;
2728
private RestTemplate restTemplate;
2829
private RestTemplate adminRestTemplate;
29-
private String baseUrl;
3030

3131
/**
3232
* Can use this constructor when the default values in ManageConfig will work.
@@ -55,51 +55,46 @@ public void initialize(ManageConfig config) {
5555
} else {
5656
this.adminRestTemplate = restTemplate;
5757
}
58-
59-
this.baseUrl = config.getBaseUrl();
60-
if (logger.isInfoEnabled()) {
61-
logger.info("Initialized ManageClient with base URL of: " + baseUrl);
62-
}
6358
}
6459

6560
public ResponseEntity<String> putJson(String path, String json) {
6661
logRequest(path, "JSON", "PUT");
67-
return restTemplate.exchange(baseUrl + path, HttpMethod.PUT, buildJsonEntity(json), String.class);
62+
return restTemplate.exchange(buildUri(path), HttpMethod.PUT, buildJsonEntity(json), String.class);
6863
}
6964

7065
public ResponseEntity<String> putJsonAsAdmin(String path, String json) {
7166
logAdminRequest(path, "JSON", "PUT");
72-
return adminRestTemplate.exchange(baseUrl + path, HttpMethod.PUT, buildJsonEntity(json), String.class);
67+
return adminRestTemplate.exchange(buildUri(path), HttpMethod.PUT, buildJsonEntity(json), String.class);
7368
}
7469

7570
public ResponseEntity<String> putXml(String path, String xml) {
7671
logRequest(path, "XML", "PUT");
77-
return restTemplate.exchange(baseUrl + path, HttpMethod.PUT, buildXmlEntity(xml), String.class);
72+
return restTemplate.exchange(buildUri(path), HttpMethod.PUT, buildXmlEntity(xml), String.class);
7873
}
7974

8075
public ResponseEntity<String> putXmlAsAdmin(String path, String xml) {
8176
logAdminRequest(path, "XML", "PUT");
82-
return adminRestTemplate.exchange(baseUrl + path, HttpMethod.PUT, buildXmlEntity(xml), String.class);
77+
return adminRestTemplate.exchange(buildUri(path), HttpMethod.PUT, buildXmlEntity(xml), String.class);
8378
}
8479

8580
public ResponseEntity<String> postJson(String path, String json) {
8681
logRequest(path, "JSON", "POST");
87-
return restTemplate.exchange(baseUrl + path, HttpMethod.POST, buildJsonEntity(json), String.class);
82+
return restTemplate.exchange(buildUri(path), HttpMethod.POST, buildJsonEntity(json), String.class);
8883
}
8984

9085
public ResponseEntity<String> postJsonAsAdmin(String path, String json) {
9186
logAdminRequest(path, "JSON", "POST");
92-
return adminRestTemplate.exchange(baseUrl + path, HttpMethod.POST, buildJsonEntity(json), String.class);
87+
return adminRestTemplate.exchange(buildUri(path), HttpMethod.POST, buildJsonEntity(json), String.class);
9388
}
9489

9590
public ResponseEntity<String> postXml(String path, String xml) {
9691
logRequest(path, "XML", "POST");
97-
return restTemplate.exchange(baseUrl + path, HttpMethod.POST, buildXmlEntity(xml), String.class);
92+
return restTemplate.exchange(buildUri(path), HttpMethod.POST, buildXmlEntity(xml), String.class);
9893
}
9994

10095
public ResponseEntity<String> postXmlAsAdmin(String path, String xml) {
10196
logAdminRequest(path, "XML", "POST");
102-
return adminRestTemplate.exchange(baseUrl + path, HttpMethod.POST, buildXmlEntity(xml), String.class);
97+
return adminRestTemplate.exchange(buildUri(path), HttpMethod.POST, buildXmlEntity(xml), String.class);
10398
}
10499

105100
public ResponseEntity<String> postForm(String path, String... params) {
@@ -111,12 +106,12 @@ public ResponseEntity<String> postForm(String path, String... params) {
111106
map.add(params[i], params[i + 1]);
112107
}
113108
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(map, headers);
114-
return restTemplate.exchange(baseUrl + path, HttpMethod.POST, entity, String.class);
109+
return restTemplate.exchange(buildUri(path), HttpMethod.POST, entity, String.class);
115110
}
116111

117112
public Fragment getXml(String path, String... namespacePrefixesAndUris) {
118113
logRequest(path, "XML", "GET");
119-
String xml = getRestTemplate().getForObject(getBaseUrl() + path, String.class);
114+
String xml = getRestTemplate().getForObject(buildUri(path), String.class);
120115
List<Namespace> list = new ArrayList<Namespace>();
121116
for (int i = 0; i < namespacePrefixesAndUris.length; i += 2) {
122117
list.add(Namespace.getNamespace(namespacePrefixesAndUris[i], namespacePrefixesAndUris[i + 1]));
@@ -126,7 +121,7 @@ public Fragment getXml(String path, String... namespacePrefixesAndUris) {
126121

127122
public Fragment getXmlAsAdmin(String path, String... namespacePrefixesAndUris) {
128123
logAdminRequest(path, "XML", "GET");
129-
String xml = getAdminRestTemplate().getForObject(getBaseUrl() + path, String.class);
124+
String xml = getAdminRestTemplate().getForObject(buildUri(path), String.class);
130125
List<Namespace> list = new ArrayList<Namespace>();
131126
for (int i = 0; i < namespacePrefixesAndUris.length; i += 2) {
132127
list.add(Namespace.getNamespace(namespacePrefixesAndUris[i], namespacePrefixesAndUris[i + 1]));
@@ -138,18 +133,25 @@ public String getJson(String path) {
138133
logRequest(path, "JSON", "GET");
139134
HttpHeaders headers = new HttpHeaders();
140135
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
141-
return getRestTemplate().exchange(getBaseUrl() + path, HttpMethod.GET, new HttpEntity<>(headers), String.class)
136+
return getRestTemplate().exchange(buildUri(path), HttpMethod.GET, new HttpEntity<>(headers), String.class)
142137
.getBody();
143138
}
144139

140+
public String getJson(URI uri) {
141+
logRequest(uri.toString(), "JSON", "GET");
142+
HttpHeaders headers = new HttpHeaders();
143+
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
144+
return getRestTemplate().exchange(uri, HttpMethod.GET, new HttpEntity<>(headers), String.class).getBody();
145+
}
146+
145147
public void delete(String path) {
146148
logRequest(path, "", "DELETE");
147-
restTemplate.delete(baseUrl + path);
149+
restTemplate.delete(buildUri(path));
148150
}
149151

150152
public void deleteAsAdmin(String path) {
151153
logAdminRequest(path, "", "DELETE");
152-
adminRestTemplate.delete(baseUrl + path);
154+
adminRestTemplate.delete(buildUri(path));
153155
}
154156

155157
public HttpEntity<String> buildJsonEntity(String json) {
@@ -178,12 +180,12 @@ protected void logAdminRequest(String path, String contentType, String method) {
178180
}
179181
}
180182

181-
public RestTemplate getRestTemplate() {
182-
return restTemplate;
183+
public URI buildUri(String path) {
184+
return manageConfig.buildUri(path);
183185
}
184186

185-
public String getBaseUrl() {
186-
return baseUrl;
187+
public RestTemplate getRestTemplate() {
188+
return restTemplate;
187189
}
188190

189191
public RestTemplate getAdminRestTemplate() {

src/main/java/com/marklogic/mgmt/admin/AdminManager.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.marklogic.mgmt.admin;
22

3+
import java.net.URI;
4+
35
import org.springframework.http.HttpEntity;
46
import org.springframework.http.HttpHeaders;
57
import org.springframework.http.HttpMethod;
@@ -39,7 +41,7 @@ public void init() {
3941
}
4042

4143
public void init(String licenseKey, String licensee) {
42-
final String url = adminConfig.getBaseUrl() + "/admin/v1/init";
44+
final URI uri = adminConfig.buildUri("/admin/v1/init");
4345

4446
String json = null;
4547
if (licenseKey != null && licensee != null) {
@@ -49,15 +51,15 @@ public void init(String licenseKey, String licensee) {
4951
}
5052
final String payload = json;
5153

52-
logger.info("Initializing MarkLogic at: " + url);
54+
logger.info("Initializing MarkLogic at: " + uri);
5355
invokeActionRequiringRestart(new ActionRequiringRestart() {
5456
@Override
5557
public boolean execute() {
5658
HttpHeaders headers = new HttpHeaders();
5759
headers.setContentType(MediaType.APPLICATION_JSON);
5860
HttpEntity<String> entity = new HttpEntity<String>(payload, headers);
5961
try {
60-
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
62+
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, entity, String.class);
6163
logger.info("Initialization response: " + response);
6264
// According to http://docs.marklogic.com/REST/POST/admin/v1/init, a 202 is sent back in the event a
6365
// restart is needed. A 400 or 401 will be thrown as an error by RestTemplate.
@@ -84,7 +86,7 @@ public void installAdmin() {
8486
}
8587

8688
public void installAdmin(String username, String password) {
87-
final String url = adminConfig.getBaseUrl() + "/admin/v1/instance-admin";
89+
final URI uri = adminConfig.buildUri("/admin/v1/instance-admin");
8890

8991
String json = null;
9092
if (username != null && password != null) {
@@ -95,15 +97,15 @@ public void installAdmin(String username, String password) {
9597
}
9698
final String payload = json;
9799

98-
logger.info("Installing admin user at: " + url);
100+
logger.info("Installing admin user at: " + uri);
99101
invokeActionRequiringRestart(new ActionRequiringRestart() {
100102
@Override
101103
public boolean execute() {
102104
HttpHeaders headers = new HttpHeaders();
103105
headers.setContentType(MediaType.APPLICATION_JSON);
104106
HttpEntity<String> entity = new HttpEntity<String>(payload, headers);
105107
try {
106-
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
108+
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, entity, String.class);
107109
logger.info("Admin installation response: " + response);
108110
// According to http://docs.marklogic.com/REST/POST/admin/v1/init, a 202 is sent back in the event a
109111
// restart is needed. A 400 or 401 will be thrown as an error by RestTemplate.
@@ -137,7 +139,7 @@ public void invokeActionRequiringRestart(ActionRequiringRestart action) {
137139
}
138140

139141
public String getLastRestartTimestamp() {
140-
return restTemplate.getForEntity(adminConfig.getBaseUrl() + "/admin/v1/timestamp", String.class).getBody();
142+
return restTemplate.getForEntity(adminConfig.buildUri("/admin/v1/timestamp"), String.class).getBody();
141143
}
142144

143145
public void waitForRestart() {
@@ -199,13 +201,13 @@ public boolean execute() {
199201
}
200202

201203
public Fragment getServerConfig() {
202-
return new Fragment(restTemplate.getForObject(adminConfig.getBaseUrl() + "/admin/v1/server-config", String.class));
204+
return new Fragment(restTemplate.getForObject(adminConfig.buildUri("/admin/v1/server-config"), String.class));
203205
}
204-
206+
205207
public String getServerVersion() {
206208
return getServerConfig().getElementValue("/m:host/m:version");
207209
}
208-
210+
209211
public void setWaitForRestartCheckInterval(int waitForRestartCheckInterval) {
210212
this.waitForRestartCheckInterval = waitForRestartCheckInterval;
211213
}

src/main/java/com/marklogic/mgmt/security/CertificateAuthorityManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ public ResponseEntity<String> create(String payload) {
2525
headers.setContentType(MediaType.TEXT_PLAIN);
2626

2727
HttpEntity<String> entity = new HttpEntity<String>(payload, headers);
28-
ResponseEntity<String> response = t.exchange(manageClient.getBaseUrl() + "/manage/v2/certificate-authorities",
28+
ResponseEntity<String> response = t.exchange(manageClient.buildUri("/manage/v2/certificate-authorities"),
2929
HttpMethod.POST, entity, String.class);
3030
return response;
3131
}
3232

3333
public ResourcesFragment getAsXml() {
3434
return new ResourcesFragment(manageClient.getXml("/manage/v2/certificate-authorities"));
3535
}
36-
36+
3737
public void delete(String resourceIdOrName) {
3838
manageClient.delete("/manage/v2/certificate-authorities/" + resourceIdOrName);
3939
}

src/main/java/com/marklogic/rest/util/RestConfig.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.marklogic.rest.util;
22

3+
import java.net.URI;
4+
import java.net.URISyntaxException;
5+
36
public class RestConfig {
47

58
private String host;
69
private int port;
710
private String username;
811
private String password;
12+
private String scheme = "http";
913

1014
public RestConfig() {
1115
}
@@ -19,11 +23,27 @@ public RestConfig(String host, int port, String username, String password) {
1923

2024
@Override
2125
public String toString() {
22-
return String.format("[host: %s, port: %d, username: %s]", host, port, username);
26+
return String.format("[scheme: %s, host: %s, port: %d, username: %s]", scheme, host, port, username);
27+
}
28+
29+
/**
30+
* Using the java.net.URI constructor that takes a string. Using any other constructor runs into encoding problems,
31+
* e.g. when a mimetype has a plus in it, that plus needs to be encoded, but doing as %2B will result in the % being
32+
* double encoded.
33+
*
34+
* @param path
35+
* @return
36+
*/
37+
public URI buildUri(String path) {
38+
try {
39+
return new URI(String.format("%s://%s:%d%s", getScheme(), getHost(), getPort(), path));
40+
} catch (URISyntaxException ex) {
41+
throw new RuntimeException("Unable to build URI for path: " + path + "; cause: " + ex.getMessage(), ex);
42+
}
2343
}
2444

2545
public String getBaseUrl() {
26-
return String.format("http://%s:%d", host, port);
46+
return String.format("%s://%s:%d", scheme, host, port);
2747
}
2848

2949
public String getHost() {
@@ -57,4 +77,12 @@ public String getPassword() {
5777
public void setPassword(String password) {
5878
this.password = password;
5979
}
80+
81+
public String getScheme() {
82+
return scheme;
83+
}
84+
85+
public void setScheme(String scheme) {
86+
this.scheme = scheme;
87+
}
6088
}

src/test/java/com/marklogic/appdeployer/command/mimetypes/ManageMimetypesTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ protected Command newCommand() {
1919

2020
@Override
2121
protected String[] getResourceNames() {
22-
return new String[] { "text/gradle" };
22+
return new String[] { "application/ditamap+xml" };
2323
}
2424

2525
}

0 commit comments

Comments
 (0)