Skip to content

Commit 0a3bed1

Browse files
committed
Introduce JsonRpcMapper abstract
WIP References #378
1 parent 9711406 commit 0a3bed1

File tree

8 files changed

+263
-57
lines changed

8 files changed

+263
-57
lines changed

src/main/java/com/rabbitmq/tools/json/JSONUtil.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ public static Object fill(Object target, Map<String, Object> source, boolean use
6161
String name = prop.getName();
6262
Method setter = prop.getWriteMethod();
6363
if (setter != null && !Modifier.isStatic(setter.getModifiers())) {
64-
//System.out.println(target + " " + name + " <- " + source.get(name));
6564
setter.invoke(target, source.get(name));
6665
}
6766
}
@@ -74,7 +73,6 @@ public static Object fill(Object target, Map<String, Object> source, boolean use
7473
if (Modifier.isPublic(fieldMod) && !(Modifier.isFinal(fieldMod) ||
7574
Modifier.isStatic(fieldMod)))
7675
{
77-
//System.out.println(target + " " + field.getName() + " := " + source.get(field.getName()));
7876
try {
7977
field.set(target, source.get(field.getName()));
8078
} catch (IllegalArgumentException iae) {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.rabbitmq.tools.jsonrpc;
2+
3+
import com.rabbitmq.tools.json.JSONReader;
4+
import com.rabbitmq.tools.json.JSONWriter;
5+
6+
import java.lang.reflect.Method;
7+
import java.util.List;
8+
import java.util.Map;
9+
10+
/**
11+
*
12+
*/
13+
public class DefaultJsonRpcMapper implements JsonRpcMapper {
14+
15+
@Override
16+
public JsonRpcRequest parse(String requestBody, ServiceDescription description) {
17+
Map<String, Object> request = (Map<String,Object>) new JSONReader().read(requestBody);
18+
19+
return new JsonRpcRequest(
20+
request.get("id"), request.get("version").toString(), request.get("method").toString(),
21+
((List<?>) request.get("params")).toArray()
22+
);
23+
}
24+
25+
@Override
26+
public JsonRpcResponse parse(String responseBody) {
27+
Map<String, Object> map = (Map<String, Object>) (new JSONReader().read(responseBody));
28+
Map<String, Object> error;
29+
JsonRpcException exception = null;
30+
if (map.containsKey("error")) {
31+
error = (Map<String, Object>) map.get("error");
32+
exception = new JsonRpcException(
33+
new JSONWriter().write(error),
34+
(String) error.get("name"),
35+
error.get("code") == null ? 0 : (Integer) error.get("code"),
36+
(String) error.get("message"),
37+
error
38+
);
39+
}
40+
return new JsonRpcResponse(map, map.get("result"), map.get("error"), exception);
41+
}
42+
43+
@Override
44+
public Object[] parameters(JsonRpcRequest request, Method method) {
45+
Object[] parameters = request.getParameters();
46+
Object[] convertedParameters = new Object[parameters.length];
47+
Class<?>[] parameterTypes = method.getParameterTypes();
48+
for (int i = 0; i < parameters.length; i++) {
49+
convertedParameters[i] = convert(parameters[i], parameterTypes[i]);
50+
}
51+
return convertedParameters;
52+
}
53+
54+
@Override
55+
public String write(Object input) {
56+
return new JSONWriter().write(input);
57+
}
58+
59+
protected Object convert(Object input, Class<?> expectedClass) {
60+
return input;
61+
// if (input == null || input.getClass().equals(expectedClass)) {
62+
// return input;
63+
// }
64+
// System.err.println(input.getClass() + " " + expectedClass);
65+
// if (Long.class.equals(expectedClass) && input instanceof Integer) {
66+
// return Long.valueOf(((Integer) input).longValue());
67+
// } else if (long.class.equals(expectedClass) && input instanceof Integer) {
68+
// return
69+
// }
70+
// return input;
71+
}
72+
}

src/main/java/com/rabbitmq/tools/jsonrpc/JsonRpcClient.java

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public class JsonRpcClient extends RpcClient implements InvocationHandler {
6262
/** Holds the JSON-RPC service description for this client. */
6363
private ServiceDescription serviceDescription;
6464

65+
private final JsonRpcMapper mapper;
66+
6567
/**
6668
* Construct a new JsonRpcClient, passing the parameters through
6769
* to RpcClient's constructor. The service description record is
@@ -72,6 +74,7 @@ public JsonRpcClient(Channel channel, String exchange, String routingKey, int ti
7274
throws IOException, JsonRpcException, TimeoutException
7375
{
7476
super(channel, exchange, routingKey, timeout);
77+
this.mapper = new DefaultJsonRpcMapper();
7578
retrieveServiceDescription();
7679
}
7780

@@ -86,18 +89,14 @@ public JsonRpcClient(Channel channel, String exchange, String routingKey)
8689
* @return the result contained within the reply, if no exception is found
8790
* Throws JsonRpcException if the reply object contained an exception
8891
*/
89-
public static Object checkReply(Map<String, Object> reply)
92+
private Object checkReply(JsonRpcMapper.JsonRpcResponse reply)
9093
throws JsonRpcException
9194
{
92-
if (reply.containsKey("error")) {
93-
@SuppressWarnings("unchecked")
94-
Map<String, Object> map = (Map<String, Object>) reply.get("error");
95-
// actually a Map<String, Object>
96-
throw new JsonRpcException(map);
97-
}
95+
if (reply.getError() != null) {
96+
throw reply.getException();
97+
}
9898

99-
Object result = reply.get("result");
100-
return result;
99+
return reply.getResult();
101100
}
102101

103102
/**
@@ -114,16 +113,16 @@ public Object call(String method, Object[] params) throws IOException, JsonRpcEx
114113
request.put("method", method);
115114
request.put("version", ServiceDescription.JSON_RPC_VERSION);
116115
request.put("params", (params == null) ? new Object[0] : params);
117-
String requestStr = new JSONWriter().write(request);
116+
String requestStr = mapper.write(request);
118117
try {
119118
String replyStr = this.stringCall(requestStr);
120119
if (LOGGER.isDebugEnabled()) {
121120
LOGGER.debug("Reply string: {}", replyStr);
122121
}
123-
@SuppressWarnings("unchecked")
124-
Map<String, Object> map = (Map<String, Object>) (new JSONReader().read(replyStr));
125122

126-
return checkReply(map);
123+
JsonRpcMapper.JsonRpcResponse reply = mapper.parse(replyStr);
124+
125+
return checkReply(reply);
127126
} catch(ShutdownSignalException ex) {
128127
throw new IOException(ex.getMessage()); // wrap, re-throw
129128
}

src/main/java/com/rabbitmq/tools/jsonrpc/JsonRpcException.java

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,43 @@
1313
// If you have any questions regarding licensing, please contact us at
1414
// info@rabbitmq.com.
1515

16-
1716
package com.rabbitmq.tools.jsonrpc;
1817

19-
import java.util.Map;
20-
21-
import com.rabbitmq.tools.json.JSONWriter;
22-
2318
/**
2419
* Thrown when a JSON-RPC service indicates an error occurred during a call.
2520
*/
2621
public class JsonRpcException extends Exception {
22+
2723
/**
2824
* Default serialized version ID
2925
*/
3026
private static final long serialVersionUID = 1L;
31-
/** Usually the constant string, "JSONRPCError" */
27+
/**
28+
* Usually the constant string, "JSONRPCError"
29+
*/
3230
public String name;
33-
/** Error code */
31+
/**
32+
* Error code
33+
*/
3434
public int code;
35-
/** Error message */
35+
/**
36+
* Error message
37+
*/
3638
public String message;
37-
/** Error detail object - may not always be present or meaningful */
39+
/**
40+
* Error detail object - may not always be present or meaningful
41+
*/
3842
public Object error;
3943

4044
public JsonRpcException() {
4145
// no work needed in default no-arg constructor
4246
}
4347

44-
public JsonRpcException(Map<String, Object> errorMap) {
45-
super(new JSONWriter().write(errorMap));
46-
name = (String) errorMap.get("name");
47-
code = 0;
48-
if (errorMap.get("code") != null) { code = ((Integer) errorMap.get("code")); }
49-
message = (String) errorMap.get("message");
50-
error = errorMap.get("error");
48+
public JsonRpcException(String detailMessage, String name, int code, String message, Object error) {
49+
super(detailMessage);
50+
this.name = name;
51+
this.code = code;
52+
this.message = message;
53+
this.error = error;
5154
}
5255
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.rabbitmq.tools.jsonrpc;
2+
3+
import java.lang.reflect.Method;
4+
5+
/**
6+
*
7+
*/
8+
public interface JsonRpcMapper {
9+
10+
JsonRpcRequest parse(String requestBody, ServiceDescription description);
11+
12+
JsonRpcResponse parse(String responseBody);
13+
14+
Object[] parameters(JsonRpcRequest request, Method method);
15+
16+
String write(Object input);
17+
18+
class JsonRpcRequest {
19+
20+
private final Object id;
21+
private final String version;
22+
private final String method;
23+
private final Object[] parameters;
24+
25+
public JsonRpcRequest(Object id, String version, String method, Object[] parameters) {
26+
this.id = id;
27+
this.version = version;
28+
this.method = method;
29+
this.parameters = parameters;
30+
}
31+
32+
public Object getId() {
33+
return id;
34+
}
35+
36+
public String getVersion() {
37+
return version;
38+
}
39+
40+
public String getMethod() {
41+
return method;
42+
}
43+
44+
public Object[] getParameters() {
45+
return parameters;
46+
}
47+
48+
public boolean isSystem() {
49+
return method.startsWith("system.");
50+
}
51+
52+
public boolean isSystemDescribe() {
53+
return "system.describe".equals(method);
54+
}
55+
56+
}
57+
58+
class JsonRpcResponse {
59+
60+
private final Object reply;
61+
private final Object result;
62+
private final Object error;
63+
private final JsonRpcException exception;
64+
65+
public JsonRpcResponse(Object reply, Object result, Object error, JsonRpcException exception) {
66+
this.reply = reply;
67+
this.result = result;
68+
this.error = error;
69+
this.exception = exception;
70+
}
71+
72+
public Object getReply() {
73+
return reply;
74+
}
75+
76+
public Object getError() {
77+
return error;
78+
}
79+
80+
public Object getResult() {
81+
return result;
82+
}
83+
84+
public JsonRpcException getException() {
85+
return exception;
86+
}
87+
}
88+
89+
}

src/main/java/com/rabbitmq/tools/jsonrpc/JsonRpcServer.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public class JsonRpcServer extends StringRpcServer {
5555
/** The instance backing this server. */
5656
public Object interfaceInstance;
5757

58+
private final JsonRpcMapper mapper;
59+
5860
/**
5961
* Construct a server that talks to the outside world using the
6062
* given channel, and constructs a fresh temporary
@@ -70,6 +72,7 @@ public JsonRpcServer(Channel channel,
7072
throws IOException
7173
{
7274
super(channel);
75+
this.mapper = new DefaultJsonRpcMapper();
7376
init(interfaceClass, interfaceInstance);
7477
}
7578

@@ -98,6 +101,7 @@ public JsonRpcServer(Channel channel,
98101
throws IOException
99102
{
100103
super(channel, queueName);
104+
this.mapper = new DefaultJsonRpcMapper();
101105
init(interfaceClass, interfaceInstance);
102106
}
103107

@@ -126,25 +130,24 @@ public String doCall(String requestBody)
126130
LOGGER.debug("Request: {}", requestBody);
127131
}
128132
try {
129-
@SuppressWarnings("unchecked")
130-
Map<String, Object> request = (Map<String,Object>) new JSONReader().read(requestBody);
133+
JsonRpcMapper.JsonRpcRequest request = mapper.parse(requestBody, serviceDescription);
131134
if (request == null) {
132135
response = errorResponse(null, 400, "Bad Request", null);
133-
} else if (!ServiceDescription.JSON_RPC_VERSION.equals(request.get("version"))) {
136+
} else if (!ServiceDescription.JSON_RPC_VERSION.equals(request.getVersion())) {
134137
response = errorResponse(null, 505, "JSONRPC version not supported", null);
135138
} else {
136-
id = request.get("id");
137-
method = (String) request.get("method");
138-
List<?> parmList = (List<?>) request.get("params");
139-
params = parmList.toArray();
140-
if (method.equals("system.describe")) {
139+
id = request.getId();
140+
method = request.getMethod();
141+
params = request.getParameters();
142+
if (request.isSystemDescribe()) {
141143
response = resultResponse(id, serviceDescription);
142-
} else if (method.startsWith("system.")) {
144+
} else if (request.isSystem()) {
143145
response = errorResponse(id, 403, "System methods forbidden", null);
144146
} else {
145147
Object result;
146148
try {
147149
Method matchingMethod = matchingMethod(method, params);
150+
params = mapper.parameters(request, matchingMethod);
148151
if (LOGGER.isDebugEnabled()) {
149152
Collection<String> parametersValuesAndTypes = new ArrayList<String>();
150153
if (params != null) {
@@ -197,7 +200,7 @@ public Method matchingMethod(String methodName, Object[] params)
197200
* ID given, using the code, message, and possible
198201
* (JSON-encodable) argument passed in.
199202
*/
200-
public static String errorResponse(Object id, int code, String message, Object errorArg) {
203+
private String errorResponse(Object id, int code, String message, Object errorArg) {
201204
Map<String, Object> err = new HashMap<String, Object>();
202205
err.put("name", "JSONRPCError");
203206
err.put("code", code);
@@ -210,22 +213,21 @@ public static String errorResponse(Object id, int code, String message, Object e
210213
* Construct and encode a JSON-RPC success response for the
211214
* request ID given, using the result value passed in.
212215
*/
213-
public static String resultResponse(Object id, Object result) {
216+
private String resultResponse(Object id, Object result) {
214217
return response(id, "result", result);
215218
}
216219

217220
/**
218221
* Private API - used by errorResponse and resultResponse.
219222
*/
220-
public static String response(Object id, String label, Object value) {
223+
private String response(Object id, String label, Object value) {
221224
Map<String, Object> resp = new HashMap<String, Object>();
222225
resp.put("version", ServiceDescription.JSON_RPC_VERSION);
223226
if (id != null) {
224227
resp.put("id", id);
225228
}
226229
resp.put(label, value);
227-
String respStr = new JSONWriter().write(resp);
228-
//System.err.println(respStr);
230+
String respStr = mapper.write(resp);
229231
return respStr;
230232
}
231233

0 commit comments

Comments
 (0)