From c9efcb7cf9742fd31ce421f29b78a9c045a46d15 Mon Sep 17 00:00:00 2001 From: rfeng Date: Mon, 10 Oct 2011 21:15:41 +0000 Subject: Use Jackson JsonNode as the unified representation of json data git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1181240 13f79535-47bb-0310-9956-ffa450edef68 --- .../binding/jsonrpc/protocol/JsonRpc10Request.java | 46 ++++------ .../jsonrpc/protocol/JsonRpc10Response.java | 79 ++--------------- .../jsonrpc/protocol/JsonRpc20BatchRequest.java | 30 +++---- .../jsonrpc/protocol/JsonRpc20BatchResponse.java | 16 ++-- .../binding/jsonrpc/protocol/JsonRpc20Error.java | 76 ++++------------- .../binding/jsonrpc/protocol/JsonRpc20Request.java | 76 ++++++++--------- .../jsonrpc/protocol/JsonRpc20Response.java | 28 ++----- .../binding/jsonrpc/protocol/JsonRpc20Result.java | 51 ----------- .../binding/jsonrpc/protocol/JsonRpcRequest.java | 54 ++++++------ .../binding/jsonrpc/protocol/JsonRpcResponse.java | 98 ++++++++++++++++++++++ .../jsonrpc/provider/JSONRPCDatabindingHelper.java | 27 +++--- .../binding/jsonrpc/provider/JsonRpcInvoker.java | 45 +++++----- .../binding/jsonrpc/provider/JsonRpcServlet.java | 67 +++++++-------- .../binding/jsonrpc/JSONRPCDataTypeTestCase.java | 2 +- 14 files changed, 302 insertions(+), 393 deletions(-) delete mode 100644 sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Result.java create mode 100644 sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpcResponse.java (limited to 'sca-java-2.x/trunk/modules/binding-jsonrpc-runtime') diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc10Request.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc10Request.java index ddd9722836..547d36abaf 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc10Request.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc10Request.java @@ -20,16 +20,12 @@ package org.apache.tuscany.sca.binding.jsonrpc.protocol; import java.io.OutputStream; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import org.apache.tuscany.sca.databinding.json.jackson.JacksonHelper; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ArrayNode; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.ObjectNode; /** * http://json-rpc.org/wiki/specification @@ -43,19 +39,19 @@ import org.json.JSONObject; */ public class JsonRpc10Request extends JsonRpcRequest { - public JsonRpc10Request(Object id, String method, Object[] params) { - super(id, method, params); + public JsonRpc10Request(String id, String method, Object[] params) { + super(JsonNodeFactory.instance.textNode(id), method, params); } - public JsonRpc10Request(JSONObject req) throws JSONException { + public JsonRpc10Request(ObjectNode req) { super(req); - method = req.getString("method"); - id = req.opt("id"); - Object args = req.opt("params"); - if (args instanceof JSONArray) { + method = req.get("method").getTextValue(); + id = req.get("id"); + JsonNode args = req.get("params"); + if (args instanceof ArrayNode) { // Positional parameters - JSONArray array = (JSONArray)args; - params = new Object[array.length()]; + ArrayNode array = (ArrayNode)args; + params = new Object[array.size()]; for (int i = 0; i < params.length; i++) { params[i] = array.get(i); } @@ -67,21 +63,7 @@ public class JsonRpc10Request extends JsonRpcRequest { } public void write(OutputStream os) throws Exception { - // Construct a map to hold JSON-RPC request - final Map map = new HashMap(); - map.put("id", id); - map.put("method", method); - - List parameters = null; - - if (params != null) { - parameters = Arrays.asList(params); - } else { - parameters = Collections.emptyList(); - } - - map.put("params", parameters); - JacksonHelper.MAPPER.writeValue(os, map); + JacksonHelper.MAPPER.writeValue(os, getJsonNode()); } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc10Response.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc10Response.java index 7facd2588a..4ca941580a 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc10Response.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc10Response.java @@ -19,11 +19,8 @@ package org.apache.tuscany.sca.binding.jsonrpc.protocol; -import java.io.IOException; -import java.io.Writer; - -import org.json.JSONException; -import org.json.JSONObject; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ObjectNode; /** * When the method invocation completes, the service must reply with a response. The response is a single object serialized using JSON. @@ -36,76 +33,18 @@ import org.json.JSONObject; *
  • id - This must be the same id as the request it is responding to. * */ -public class JsonRpc10Response { - public static final int REMOTE_EXCEPTION = 490; - private Object id; - private Object result; - private Object error; - - private volatile JSONObject response; - - public JsonRpc10Response(JSONObject response) { - super(); - this.response = response; - } +public class JsonRpc10Response extends JsonRpcResponse { - public JsonRpc10Response(Object id, Object result, Object error) { - super(); - this.id = id; - this.result = result; - this.error = error; - if (result != null && error != null) { - throw new IllegalArgumentException("Either result or error has to be null"); - } + public JsonRpc10Response(JsonNode id, JsonNode result) { + super(id, result); } - public JsonRpc10Response(Object id, Throwable t) { - super(); - this.id = id; - this.result = null; - try { - JSONObject obj = new JSONObject(); - // obj.put("msg", t.getMessage()); - obj.put("code", REMOTE_EXCEPTION); - obj.put("message", t.getMessage()); - JSONObject exception = new JSONObject(); - exception.put("class", t.getClass().getName()); - exception.put("message", t.getMessage()); - exception.put("stackTrace", JsonRpc20Error.stackTrace(t)); - obj.put("data", exception); - this.error = obj; - } catch (JSONException e) { - throw new IllegalArgumentException(e); - } - - } - - public JSONObject toJSONObject() throws JSONException { - if (response != null) { - return response; - } - response = new JSONObject(); - response.put("id", id); - if (result != null) { - response.put("result", result); - } else { - response.put("result", JSONObject.NULL); - } - - if (error != null) { - response.put("error", error); - } else { - response.put("error", JSONObject.NULL); - } - return response; + public JsonRpc10Response(JsonNode id, Throwable t) { + super(id, t); } - public void write(Writer writer) throws IOException { - try { - toJSONObject().write(writer); - } catch (JSONException e) { - throw new IOException(e); - } + public JsonRpc10Response(ObjectNode response) { + super(response); } } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20BatchRequest.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20BatchRequest.java index ab4db234cf..44627ddb08 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20BatchRequest.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20BatchRequest.java @@ -22,42 +22,34 @@ package org.apache.tuscany.sca.binding.jsonrpc.protocol; import java.util.ArrayList; import java.util.List; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ArrayNode; +import org.codehaus.jackson.node.ObjectNode; public class JsonRpc20BatchRequest { private List requests = new ArrayList(); // The corresponding batch response private JsonRpc20BatchResponse batchResponse; - public JsonRpc20BatchRequest(JSONArray array) { + public JsonRpc20BatchRequest(ArrayNode array) { super(); batchResponse = new JsonRpc20BatchResponse(); - for (int i = 0; i < array.length(); i++) { - Object req = null; - try { - req = array.get(i); - } catch (JSONException e1) { - // It shouldn't happen - throw new IllegalArgumentException(e1); - } - if (req instanceof JSONObject) { + for (int i = 0; i < array.size(); i++) { + JsonNode req = array.get(i); + if (req instanceof ObjectNode) { try { - requests.add(new JsonRpc20Request((JSONObject)req)); + requests.add(new JsonRpc20Request((ObjectNode)req)); batchResponse.getResponses().add(null); - } catch (JSONException e) { + } catch (Exception e) { // We should return invalid request errors JsonRpc20Error error = - new JsonRpc20Error(JSONObject.NULL, JsonRpc20Error.PARSE_ERROR, JsonRpc20Error.PARSE_ERROR_MSG, - req); + new JsonRpc20Error(null, JsonRpc20Error.PARSE_ERROR, JsonRpc20Error.PARSE_ERROR_MSG, req); batchResponse.getResponses().add(error); } } else { // We should return invalid request errors JsonRpc20Error error = - new JsonRpc20Error(JSONObject.NULL, JsonRpc20Error.INVALID_REQUEST, - JsonRpc20Error.INVALID_REQUEST_MSG, req); + new JsonRpc20Error(null, JsonRpc20Error.INVALID_REQUEST, JsonRpc20Error.INVALID_REQUEST_MSG, req); batchResponse.getResponses().add(error); } } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20BatchResponse.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20BatchResponse.java index 093b58d18b..d571458192 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20BatchResponse.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20BatchResponse.java @@ -22,24 +22,24 @@ package org.apache.tuscany.sca.binding.jsonrpc.protocol; import java.util.ArrayList; import java.util.List; -import org.json.JSONArray; -import org.json.JSONException; +import org.codehaus.jackson.node.ArrayNode; +import org.codehaus.jackson.node.JsonNodeFactory; public class JsonRpc20BatchResponse { - private List results = new ArrayList(); + private List results = new ArrayList(); public JsonRpc20BatchResponse() { super(); } - public List getResponses() { + public List getResponses() { return results; } - public JSONArray toJSONArray() throws JSONException { - JSONArray jsonArray = new JSONArray(); - for (JsonRpc20Result result : results) { - jsonArray.put(result.toJSONObject()); + public ArrayNode toJSONArray() { + ArrayNode jsonArray = JsonNodeFactory.instance.arrayNode(); + for (JsonRpcResponse result : results) { + jsonArray.add(result.getJsonNode()); } return jsonArray; } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Error.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Error.java index 0205be3d5f..30c61515ee 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Error.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Error.java @@ -19,16 +19,11 @@ package org.apache.tuscany.sca.binding.jsonrpc.protocol; -import java.io.PrintWriter; -import java.io.StringWriter; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.ObjectNode; -import org.json.JSONException; -import org.json.JSONObject; - -public class JsonRpc20Error extends JsonRpc20Result { - private final int code; // The error code - private final String messaege; // The error message - private final Object data; // The json data for the error +public class JsonRpc20Error extends JsonRpcResponse { public static final int PARSE_ERROR = 32700; public static final String PARSE_ERROR_MSG = @@ -48,59 +43,24 @@ public class JsonRpc20Error extends JsonRpc20Result { // -32099 to -32000 Server error Reserved for implementation-defined server-errors. - public JsonRpc20Error(Object id, int code, String messaege, Object data) { - super(id); - this.code = code; - this.messaege = messaege; - this.data = data; - } - - public JsonRpc20Error(Object id, Throwable t) { - super(id); - this.code = INTERNAL_ERROR; - this.messaege = t.getMessage(); - this.data = t; - } - - public static String stackTrace(Throwable t) { - StringWriter sw = new StringWriter(); - t.printStackTrace(new PrintWriter(sw)); - return sw.toString(); + public JsonRpc20Error(JsonNode id, Throwable t) { + super(id, t); + this.jsonNode.put("jsonrpc", "2.0"); + this.jsonNode.put("code", INTERNAL_ERROR); } - public JsonRpc20Error(JSONObject response) { - super(response); - this.id = response.opt("id"); - this.code = response.optInt("code"); - this.messaege = response.optString("message"); - this.data = response.opt("data"); - } - - public JSONObject toJSONObject() throws JSONException { - if (response != null) { - return response; - } - - response = new JSONObject(); - response.put("jsonrpc", "2.0"); - response.put("id", id); - JSONObject error = new JSONObject(); + public JsonRpc20Error(JsonNode id, int code, String message, JsonNode data) { + super(id, JsonNodeFactory.instance.nullNode()); + this.jsonNode.put("jsonrpc", "2.0"); + ObjectNode error = JsonNodeFactory.instance.objectNode(); error.put("code", code); - error.put("message", messaege); - - if (data instanceof Throwable) { - Throwable t = (Throwable)data; - JSONObject exception = new JSONObject(); - exception.put("class", t.getClass().getName()); - exception.put("message", t.getMessage()); - exception.put("stackTrace", JsonRpc20Error.stackTrace(t)); - response.put("data", exception); - } else { - error.put("data", data); - } - response.put("error", error); + error.put("message", message); + error.put("data", data); + this.jsonNode.put("error", error); + } - return response; + public JsonRpc20Error(ObjectNode jsonNode) { + super(jsonNode); } } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Request.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Request.java index de4862bb9a..22b3b7057f 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Request.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Request.java @@ -23,61 +23,61 @@ import java.io.OutputStream; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.tuscany.sca.databinding.json.jackson.JacksonHelper; -import org.json.JSONArray; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ArrayNode; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.ObjectNode; import org.json.JSONException; -import org.json.JSONObject; public class JsonRpc20Request extends JsonRpcRequest { - protected Map mappedParams; + protected ObjectNode mappedParams; - public JsonRpc20Request(Object id, String method, Object[] params) { - super(id, method, params); + public JsonRpc20Request(String id, String method, Object[] params) { + super(JsonNodeFactory.instance.textNode(id), method, params); + this.jsonNode.put("jsonrpc", "2.0"); this.mappedParams = null; } - public JsonRpc20Request(Object id, String method, Map mappedParams) { - super(id, method, null); + public JsonRpc20Request(String id, String method, ObjectNode mappedParams) { + super(JsonNodeFactory.instance.textNode(id), method, null); + this.jsonNode.put("jsonrpc", "2.0"); this.mappedParams = mappedParams; + this.jsonNode.put("params", mappedParams); } - public JsonRpc20Request(JSONObject req) throws JSONException { + public JsonRpc20Request(ObjectNode req) throws JSONException { super(req); - if (req.has("jsonrpc") && "2.0".equals(req.getString("jsonrpc"))) { - method = req.getString("method"); - id = req.opt("id"); - Object args = req.opt("params"); - if (args instanceof JSONArray) { - // Positional parameters - JSONArray array = (JSONArray)args; - params = new Object[array.length()]; - mappedParams = null; - for (int i = 0; i < params.length; i++) { - params[i] = array.get(i); - } - } else if (args instanceof JSONObject) { - JSONObject map = (JSONObject)args; - mappedParams = new HashMap(); - params = null; - Iterator keys = map.keys(); - while (keys.hasNext()) { - String key = keys.next(); - Object value = map.get(key); - mappedParams.put(key, value); - } - } else if (args == null) { - params = new Object[0]; - mappedParams = null; - } else { - throw new IllegalArgumentException("Invalid request: params is not a JSON array or object - " + args); + JsonNode node = req.get("jsonrpc"); + boolean v20 = node != null && "2.0".equals(node.getTextValue()); + if (!v20) { + throw new IllegalArgumentException("Invalid request: jsonrpc attribute must be \"2.0\""); + } + method = req.get("method").getTextValue(); + JsonNode idNode = req.get("id"); + if (idNode != null) { + id = idNode; + } + JsonNode args = req.get("params"); + if (args instanceof ArrayNode) { + // Positional parameters + ArrayNode array = (ArrayNode)args; + params = new Object[array.size()]; + for (int i = 0; i < params.length; i++) { + params[i] = array.get(i); } + } else if (args instanceof ObjectNode) { + ObjectNode map = (ObjectNode)args; + mappedParams = map; + params = null; + } else if (args == null) { + params = new Object[0]; } else { - throw new IllegalArgumentException("Invalid request: missing jsonrpc attribute"); + throw new IllegalArgumentException("Invalid request: params is not a JSON array - " + args); } } @@ -107,7 +107,7 @@ public class JsonRpc20Request extends JsonRpcRequest { } - public Map getMappedParams() { + public ObjectNode getMappedParams() { return mappedParams; } } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Response.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Response.java index e6f8282faf..aa433ede6c 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Response.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Response.java @@ -19,31 +19,19 @@ package org.apache.tuscany.sca.binding.jsonrpc.protocol; -import org.json.JSONException; -import org.json.JSONObject; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ObjectNode; -public class JsonRpc20Response extends JsonRpc20Result { - private Object result; +public class JsonRpc20Response extends JsonRpcResponse { - public JsonRpc20Response(Object id, Object result) { - super(id); - this.result = result; - } + public JsonRpc20Response(JsonNode id, JsonNode result) { + super(id, result); + this.jsonNode.put("jsonrpc", "2.0"); - public JsonRpc20Response(JSONObject response) { - super(response); - this.result = response.opt("result"); } - public JSONObject toJSONObject() throws JSONException { - if (response != null) { - return response; - } - response = new JSONObject(); - response.put("jsonrpc", "2.0"); - response.put("id", id); - response.put("result", result); - return response; + public JsonRpc20Response(ObjectNode jsonNode) { + super(jsonNode); } } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Result.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Result.java deleted file mode 100644 index 14f8f444de..0000000000 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpc20Result.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.tuscany.sca.binding.jsonrpc.protocol; - -import java.io.IOException; -import java.io.Writer; - -import org.json.JSONException; -import org.json.JSONObject; - -public abstract class JsonRpc20Result { - protected Object id; - protected volatile JSONObject response; - - protected JsonRpc20Result(JSONObject response) { - super(); - this.response = response; - } - - protected JsonRpc20Result(Object id) { - super(); - this.id = id; - } - - public abstract JSONObject toJSONObject() throws JSONException; - - public void write(Writer writer) throws IOException { - try { - toJSONObject().write(writer); - } catch (JSONException e) { - throw new IOException(e); - } - } -} diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpcRequest.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpcRequest.java index 8c0a71025a..cd98a30976 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpcRequest.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpcRequest.java @@ -19,12 +19,13 @@ package org.apache.tuscany.sca.binding.jsonrpc.protocol; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.OutputStream; -import org.apache.tuscany.sca.databinding.json.jackson.JacksonHelper; -import org.json.JSONObject; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ArrayNode; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.NullNode; +import org.codehaus.jackson.node.ObjectNode; /** * http://json-rpc.org/wiki/specification @@ -38,46 +39,45 @@ import org.json.JSONObject; */ public abstract class JsonRpcRequest { protected String method; - protected Object id; + protected JsonNode id; protected Object[] params; - protected JSONObject jsonObject; + protected ObjectNode jsonNode; - public JsonRpcRequest(Object id, String method, Object[] params) { + public JsonRpcRequest(ObjectNode jsonNode) { super(); - this.id = id; - this.method = method; - this.params = params; + this.jsonNode = jsonNode; } - protected JsonRpcRequest(JSONObject jsonObject) { + public JsonRpcRequest(JsonNode id, String method, Object[] params) { super(); - this.jsonObject = jsonObject; - } - - public JSONObject toJSONObject() throws Exception { - if (jsonObject != null) { - return jsonObject; - } else { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - write(bos); - ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); - jsonObject = JacksonHelper.MAPPER.readValue(bis, JSONObject.class); + this.id = id; + this.method = method; + this.params = params; + ObjectNode req = JsonNodeFactory.instance.objectNode(); + req.put("method", method); + req.put("id", id); + if (params != null) { + ArrayNode args = JsonNodeFactory.instance.arrayNode(); + for (Object p : params) { + args.add(JsonNodeFactory.instance.POJONode(p)); + } + req.put("params", args); } - return jsonObject; + this.jsonNode = req; } public abstract void write(OutputStream os) throws Exception; public boolean isNotification() { - return id == null || id == JSONObject.NULL; + return id == null || (id instanceof NullNode); } public String getMethod() { return method; } - public Object getId() { + public JsonNode getId() { return id; } @@ -85,4 +85,8 @@ public abstract class JsonRpcRequest { return params; } + public ObjectNode getJsonNode() { + return jsonNode; + } + } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpcResponse.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpcResponse.java new file mode 100644 index 0000000000..7d50cd772f --- /dev/null +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/protocol/JsonRpcResponse.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.binding.jsonrpc.protocol; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; + +import org.apache.tuscany.sca.databinding.json.jackson.JacksonHelper; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.ObjectNode; + +/** + * When the method invocation completes, the service must reply with a response. The response is a single object serialized using JSON. + *
    + * It has three properties: + * + *
      + *
    • result - The Object that was returned by the invoked method. This must be null in case there was an error invoking the method. + *
    • error - An Error object if there was an error invoking the method. It must be null if there was no error. + *
    • id - This must be the same id as the request it is responding to. + *
    + */ +public abstract class JsonRpcResponse { + public static final int REMOTE_EXCEPTION = 490; + + protected ObjectNode jsonNode; + + public JsonRpcResponse(ObjectNode response) { + super(); + this.jsonNode = response; + } + + public JsonRpcResponse(JsonNode id, Throwable t) { + super(); + ObjectNode response = JsonNodeFactory.instance.objectNode(); + response.put("id", id); + response.put("result", JsonNodeFactory.instance.nullNode()); + response.put("error", mapError(t)); + this.jsonNode = response; + } + + public JsonRpcResponse(JsonNode id, JsonNode result) { + super(); + ObjectNode response = JsonNodeFactory.instance.objectNode(); + response.put("id", id); + response.put("result", result); + response.put("error", JsonNodeFactory.instance.nullNode()); + this.jsonNode = response; + } + + private ObjectNode mapError(Throwable t) { + ObjectNode obj = JsonNodeFactory.instance.objectNode(); + // obj.put("msg", t.getMessage()); + obj.put("code", REMOTE_EXCEPTION); + obj.put("message", t.getMessage()); + ObjectNode exception = JsonNodeFactory.instance.objectNode(); + exception.put("class", t.getClass().getName()); + exception.put("message", t.getMessage()); + exception.put("stackTrace", JsonRpc20Error.stackTrace(t)); + obj.put("data", exception); + return obj; + } + + public void write(Writer writer) throws IOException { + JacksonHelper.MAPPER.writeValue(writer, jsonNode); + } + + public static String stackTrace(Throwable t) { + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + return sw.toString(); + } + + public ObjectNode getJsonNode() { + return jsonNode; + } + +} diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCDatabindingHelper.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCDatabindingHelper.java index fc43835b9b..059e44cc7e 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCDatabindingHelper.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCDatabindingHelper.java @@ -19,14 +19,13 @@ package org.apache.tuscany.sca.binding.jsonrpc.provider; -import java.math.BigDecimal; import java.util.List; -import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding; import org.apache.tuscany.sca.databinding.json.JSONDataBinding; import org.apache.tuscany.sca.interfacedef.DataType; import org.apache.tuscany.sca.interfacedef.Interface; import org.apache.tuscany.sca.interfacedef.Operation; +import org.codehaus.jackson.JsonNode; /** * JSONRPC Binding helper class to handle setting the proper @@ -46,20 +45,22 @@ public class JSONRPCDatabindingHelper { if (inputType != null) { List logical = inputType.getLogical(); for (DataType inArg : logical) { - if (!SimpleJavaDataBinding.NAME.equals(inArg.getDataBinding()) || - inArg.getPhysical() == BigDecimal.class) { - inArg.setDataBinding(JSONDataBinding.NAME); - } + inArg.setDataBinding(JSONDataBinding.NAME); + inArg.setPhysical(JsonNode.class); +// if (!SimpleJavaDataBinding.NAME.equals(inArg.getDataBinding()) || inArg.getPhysical() == BigDecimal.class) { +// inArg.setDataBinding(JSONDataBinding.NAME); +// } } } - for (DataType outputType : operation.getOutputType().getLogical() ) { - if (outputType != null) { - if (!SimpleJavaDataBinding.NAME.equals(outputType.getDataBinding()) || - outputType.getPhysical() == BigDecimal.class ) { - outputType.setDataBinding(JSONDataBinding.NAME); - } - } + for (DataType outputType : operation.getOutputType().getLogical()) { + if (outputType != null) { + outputType.setDataBinding(JSONDataBinding.NAME); + outputType.setPhysical(JsonNode.class); +// if (!SimpleJavaDataBinding.NAME.equals(outputType.getDataBinding()) || outputType.getPhysical() == BigDecimal.class) { +// outputType.setDataBinding(JSONDataBinding.NAME); +// } + } } } } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JsonRpcInvoker.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JsonRpcInvoker.java index efba2ac1ac..b2c7c428ec 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JsonRpcInvoker.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JsonRpcInvoker.java @@ -49,9 +49,11 @@ import org.apache.tuscany.sca.interfacedef.java.JavaOperation; import org.apache.tuscany.sca.invocation.DataExchangeSemantics; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.invocation.Message; +import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.type.TypeFactory; -import org.json.JSONObject; +import org.codehaus.jackson.node.NullNode; +import org.codehaus.jackson.node.ObjectNode; import org.oasisopen.sca.ServiceRuntimeException; /** @@ -63,14 +65,12 @@ public class JsonRpcInvoker implements Invoker, DataExchangeSemantics { private EndpointReference endpointReference; private Operation operation; private String uri; - private ObjectMapper mapper; private HttpClient httpClient; public JsonRpcInvoker(EndpointReference endpointReference, Operation operation, HttpClient httpClient) { this.endpointReference = endpointReference; this.operation = operation; this.uri = endpointReference.getBinding().getURI(); - this.mapper = createObjectMapper(null); this.httpClient = httpClient; } @@ -129,9 +129,9 @@ public class JsonRpcInvoker implements Invoker, DataExchangeSemantics { String entityResponse = EntityUtils.toString(entity); entity.consumeContent(); if (!db.equals(JSONDataBinding.NAME)) { - JSONObject jsonResponse = new JSONObject(entityResponse); + ObjectNode jsonResponse = (ObjectNode)JacksonHelper.MAPPER.readTree(entityResponse); - if (!jsonResponse.isNull("error")) { + if (jsonResponse.has("error") && jsonResponse.get("error") != NullNode.instance) { processException(jsonResponse); } DataType> outputType = operation.getOutputType(); @@ -145,22 +145,18 @@ public class JsonRpcInvoker implements Invoker, DataExchangeSemantics { } //check requestId - if (!requestId.equalsIgnoreCase(jsonResponse.optString("id"))) { + if (!requestId.equalsIgnoreCase(jsonResponse.get("id").getTextValue())) { throw new ServiceRuntimeException("Invalid response id:" + requestId); } - Object rawResult = jsonResponse.get("result"); + JsonNode rawResult = jsonResponse.get("result"); Class returnClass = returnType.getPhysical(); Type genericReturnType = returnType.getGenericType(); ObjectMapper mapper = createObjectMapper(returnClass); - String json = rawResult.toString(); + String json = mapper.writeValueAsString(rawResult); - // Jackson requires the quoted String so that readValue can work - if (returnClass == String.class) { - json = "\"" + json + "\""; - } Object body = mapper.readValue(json, TypeFactory.type(genericReturnType)); msg.setBody(body); @@ -191,19 +187,28 @@ public class JsonRpcInvoker implements Invoker, DataExchangeSemantics { return JacksonHelper.createObjectMapper(cls); } + private String opt(ObjectNode node, String name) { + JsonNode value = node.get(name); + if (value == null) { + return null; + } else { + return value.getValueAsText(); + } + } + /** * Generate and throw exception based on the data in the 'responseMessage' */ - protected void processException(JSONObject responseMessage) throws Throwable { + protected void processException(ObjectNode responseMessage) throws Throwable { // FIXME: We need to find a way to build Java exceptions out of the json-rpc error - JSONObject error = (JSONObject)responseMessage.opt("error"); + JsonNode error = responseMessage.get("error"); if (error != null) { - Object data = error.opt("data"); - if (data instanceof JSONObject) { - JSONObject fault = (JSONObject)data; - String javaClass = fault.optString("class"); - String message = fault.optString("message"); - String stackTrace = fault.optString("stackTrace"); + Object data = error.get("data"); + if (data instanceof ObjectNode) { + ObjectNode fault = (ObjectNode)data; + String javaClass = opt(fault, "class"); + String message = opt(fault, "message"); + String stackTrace = opt(fault, "stackTrace"); if (javaClass != null) { if (stackTrace != null) { message = message + "\n" + stackTrace; diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JsonRpcServlet.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JsonRpcServlet.java index a183d2211c..2febbf5dc3 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JsonRpcServlet.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JsonRpcServlet.java @@ -19,11 +19,8 @@ package org.apache.tuscany.sca.binding.jsonrpc.provider; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.List; @@ -43,15 +40,17 @@ import org.apache.tuscany.sca.binding.jsonrpc.protocol.JsonRpc20BatchRequest; import org.apache.tuscany.sca.binding.jsonrpc.protocol.JsonRpc20Error; import org.apache.tuscany.sca.binding.jsonrpc.protocol.JsonRpc20Request; import org.apache.tuscany.sca.binding.jsonrpc.protocol.JsonRpc20Response; -import org.apache.tuscany.sca.binding.jsonrpc.protocol.JsonRpc20Result; +import org.apache.tuscany.sca.binding.jsonrpc.protocol.JsonRpcResponse; import org.apache.tuscany.sca.databinding.json.JSONDataBinding; import org.apache.tuscany.sca.databinding.json.jackson.JacksonHelper; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.invocation.Message; import org.apache.tuscany.sca.invocation.MessageFactory; import org.apache.tuscany.sca.runtime.RuntimeEndpoint; -import org.json.JSONArray; -import org.json.JSONObject; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ArrayNode; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.ObjectNode; import org.oasisopen.sca.ServiceRuntimeException; public class JsonRpcServlet extends HttpServlet { @@ -101,7 +100,7 @@ public class JsonRpcServlet extends HttpServlet { private void handleJsonRpcInvocation(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, IOException, ServletException { - StringWriter data = new StringWriter(); + // Decode using the charset in the request if it exists otherwise // use UTF-8 as this is what all browser implementations use. // The JSON-RPC-Java JavaScript client is ASCII clean so it @@ -112,6 +111,7 @@ public class JsonRpcServlet extends HttpServlet { charset = "UTF-8"; } + JsonNode root = null; if (request.getMethod().equals("GET")) { // if using GET Support (see http://groups.google.com/group/json-rpc/web/json-rpc-over-http) @@ -127,49 +127,39 @@ public class JsonRpcServlet extends HttpServlet { sb.append("\"id\":" + request.getParameter("id")); sb.append("}"); - data.write(sb.toString()); + root = JacksonHelper.MAPPER.readTree(sb.toString()); } catch (Throwable e) { - JsonRpc10Response error = new JsonRpc10Response(request.getParameter("id"), e); + JsonRpc10Response error = + new JsonRpc10Response(JsonNodeFactory.instance.textNode(request.getParameter("id")), e); error.write(response.getWriter()); return; } } else { - - // default POST style - BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), charset)); - // Read the request into charArray - char[] buf = new char[4096]; - int ret; - while ((ret = in.read(buf, 0, 4096)) != -1) { - data.write(buf, 0, ret); - } + root = JacksonHelper.MAPPER.readTree(request.getReader()); } - String json = data.toString().trim(); - try { - if (json.startsWith("[")) { - JSONArray input = new JSONArray(json); + if (root.isArray()) { + ArrayNode input = (ArrayNode)root; JsonRpc20BatchRequest batchReq = new JsonRpc20BatchRequest(input); for (int i = 0; i < batchReq.getRequests().size(); i++) { - JsonRpc20Result result = batchReq.getBatchResponse().getResponses().get(i); + JsonRpcResponse result = batchReq.getBatchResponse().getResponses().get(i); if (result == null) { result = invoke(batchReq.getRequests().get(i)); batchReq.getBatchResponse().getResponses().set(i, result); } } - JSONArray responses = batchReq.getBatchResponse().toJSONArray(); - responses.write(response.getWriter()); + ArrayNode responses = batchReq.getBatchResponse().toJSONArray(); + JacksonHelper.MAPPER.writeValue(response.getWriter(), responses); } else { - JSONObject input = JacksonHelper.read(json); - if (input.has("jsonrpc")) { - JsonRpc20Request jsonReq = new JsonRpc20Request(input); - JsonRpc20Result jsonResult = invoke(jsonReq); + if (root.has("jsonrpc")) { + JsonRpc20Request jsonReq = new JsonRpc20Request((ObjectNode)root); + JsonRpcResponse jsonResult = invoke(jsonReq); if (jsonResult != null) { jsonResult.write(response.getWriter()); } } else { - JsonRpc10Request jsonReq = new JsonRpc10Request(input); + JsonRpc10Request jsonReq = new JsonRpc10Request((ObjectNode)root); JsonRpc10Response jsonResult = invoke(jsonReq); if (jsonResult != null) { jsonResult.write(response.getWriter()); @@ -181,7 +171,7 @@ public class JsonRpcServlet extends HttpServlet { } } - private JsonRpc20Result invoke(JsonRpc20Request request) throws Exception { + private JsonRpcResponse invoke(JsonRpc20Request request) throws Exception { if (request.isNotification()) { return null; } @@ -199,7 +189,7 @@ public class JsonRpcServlet extends HttpServlet { requestMessage.getHeaders().put("RequestMessage", request); if (jsonOperation.getWrapper().getDataBinding().equals(JSONDataBinding.NAME)) { - requestMessage.setBody(new Object[] {JacksonHelper.write(request.toJSONObject())}); + requestMessage.setBody(new Object[] {JacksonHelper.toString(request.getJsonNode())}); } else { requestMessage.setBody(params); } @@ -222,7 +212,7 @@ public class JsonRpcServlet extends HttpServlet { if (!responseMessage.isFault()) { if (jsonOperation.getWrapper().getDataBinding().equals(JSONDataBinding.NAME)) { result = responseMessage.getBody(); - return new JsonRpc20Response(JacksonHelper.read(result.toString())); + return new JsonRpc20Response((ObjectNode)JacksonHelper.MAPPER.readTree(result.toString())); } else { if (jsonOperation.getOutputType().getLogical().size() == 0) { // void operation (json-rpc notification) @@ -237,7 +227,7 @@ public class JsonRpcServlet extends HttpServlet { // regular operation returning some value try { result = responseMessage.getBody(); - JsonRpc20Response response = new JsonRpc20Response(request.getId(), result); + JsonRpc20Response response = new JsonRpc20Response(request.getId(), (JsonNode)result); //get response to send to client return response; } catch (Exception e) { @@ -273,7 +263,7 @@ public class JsonRpcServlet extends HttpServlet { requestMessage.getHeaders().put("RequestMessage", request); if (jsonOperation.getWrapper().getDataBinding().equals(JSONDataBinding.NAME)) { - requestMessage.setBody(new Object[] {JacksonHelper.write(request.toJSONObject())}); + requestMessage.setBody(new Object[] {JacksonHelper.toString(request.getJsonNode())}); } else { requestMessage.setBody(params); } @@ -295,17 +285,18 @@ public class JsonRpcServlet extends HttpServlet { if (!responseMessage.isFault()) { if (jsonOperation.getWrapper().getDataBinding().equals(JSONDataBinding.NAME)) { result = responseMessage.getBody(); - return new JsonRpc10Response(JacksonHelper.read(result.toString())); + return new JsonRpc10Response((ObjectNode)JacksonHelper.MAPPER.readTree(result.toString())); } else { if (jsonOperation.getOutputType().getLogical().size() == 0) { // void operation (json-rpc notification) - JsonRpc10Response response = new JsonRpc10Response(request.getId(), JSONObject.NULL, null); + JsonRpc10Response response = + new JsonRpc10Response(request.getId(), JsonNodeFactory.instance.nullNode()); return response; } else { // regular operation returning some value result = responseMessage.getBody(); - JsonRpc10Response response = new JsonRpc10Response(request.getId(), result, null); + JsonRpc10Response response = new JsonRpc10Response(request.getId(), (JsonNode)result); //get response to send to client return response; } diff --git a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCDataTypeTestCase.java b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCDataTypeTestCase.java index d09bce6365..107866137d 100644 --- a/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCDataTypeTestCase.java +++ b/sca-java-2.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCDataTypeTestCase.java @@ -214,6 +214,6 @@ public class JSONRPCDataTypeTestCase { JSONObject jsonResp = new JSONObject(response.getText()); - Assert.assertEquals("12345.67", jsonResp.get("result")); + Assert.assertEquals(12345.67, jsonResp.get("result")); } } \ No newline at end of file -- cgit v1.2.3