diff options
author | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2010-03-30 05:38:01 +0000 |
---|---|---|
committer | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2010-03-30 05:38:01 +0000 |
commit | ea66dbe56f131834dc6d71a00e7c0bea93e9404b (patch) | |
tree | 9c37aea19f1132c8229eb9483cf4ebdf238c316c | |
parent | 3fed38d9212456b95c410b0e1b9d7275dadb0b5d (diff) |
TUSCANY-3516 - Merging changes from 2.x to enable calling services exposed with JSON-RPC binding using GET method and properly handling HTTP Headers such eTags when usig GET method
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@928999 13f79535-47bb-0310-9956-ffa450edef68
2 files changed, 112 insertions, 16 deletions
diff --git a/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java b/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java index 4f6f5c6077..bdfdeb8392 100644 --- a/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java +++ b/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java @@ -24,6 +24,10 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.net.URLDecoder; +import java.security.MessageDigest; +import java.util.Date; import java.util.List; import javax.servlet.ServletConfig; @@ -46,6 +50,8 @@ import com.metaparadigm.jsonrpc.JSONRPCBridge; import com.metaparadigm.jsonrpc.JSONRPCResult; import com.metaparadigm.jsonrpc.JSONRPCServlet; +import com.sun.xml.internal.messaging.saaj.util.Base64; + /** * Servlet that handles JSON-RPC requests invoking SCA services. * @@ -115,14 +121,6 @@ public class JSONRPCServiceServlet extends JSONRPCServlet { } private void handleServiceRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { - // Encode using UTF-8, although We are actually ASCII clean as - // all unicode data is JSON escaped using backslash u. This is - // less data efficient for foreign character sets but it is - // needed to support naughty browsers such as Konqueror and Safari - // which do not honour the charset set in the response - response.setContentType("text/plain;charset=utf-8"); - OutputStream out = response.getOutputStream(); - // 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 @@ -132,15 +130,42 @@ public class JSONRPCServiceServlet extends JSONRPCServlet { if (charset == null) { charset = "UTF-8"; } - BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), charset)); - - // Read the request + CharArrayWriter data = new CharArrayWriter(); - char[] buf = new char[4096]; - int ret; - while ((ret = in.read(buf, 0, 4096)) != -1) { - data.write(buf, 0, ret); + if (request.getMethod().equals("GET")) { + // if using GET Support (see http://groups.google.com/group/json-rpc/web/json-rpc-over-http) + + //parse the GET QueryString + try { + String params = Base64.base64Decode(URLDecoder.decode(request.getParameter("params"),charset)); + + StringBuffer sb = new StringBuffer(); + sb.append("{"); + sb.append("\"method\": \"" + request.getParameter("method") + "\","); + sb.append("\"params\": " + params + ","); + sb.append("\"id\":" + request.getParameter("id")); + sb.append("}"); + + data.write(sb.toString().toCharArray(), 0, sb.length()); + } catch (Exception e) { + //FIXME Exceptions are not handled correctly here + // They should be reported to the client JavaScript as proper + // JavaScript exceptions. + throw new RuntimeException("Unable to parse request", e); + } + + } else { + // default POST style + BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), charset)); + + // Read the request + char[] buf = new char[4096]; + int ret; + while ((ret = in.read(buf, 0, 4096)) != -1) { + data.write(buf, 0, ret); + } } + JSONObject jsonReq = null; String method = null; @@ -163,6 +188,42 @@ public class JSONRPCServiceServlet extends JSONRPCServlet { } else { bout = handleJSONRPCMethodInvocation(request, response, jsonReq); } + + // Encode using UTF-8, although We are actually ASCII clean as + // all unicode data is JSON escaped using backslash u. This is + // less data efficient for foreign character sets but it is + // needed to support naughty browsers such as Konqueror and Safari + // which do not honour the charset set in the response + response.setContentType("text/plain;charset=utf-8"); + + //set Cache-Control to no-cache to avoid intermediary + //proxy/reverse-proxy caches and always hit the server + //that would identify if the value was current or not + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Expires", new Date(0).toGMTString()); + + //handle etag if using GET + if( request.getMethod().equals("GET")) { + String eTag = calculateETag(bout); + + // Test request for predicates. + String predicate = request.getHeader( "If-Match" ); + if (( predicate != null ) && ( !predicate.equals(eTag) )) { + // No match, should short circuit + response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); + return; + } + predicate = request.getHeader( "If-None-Match" ); + if (( predicate != null ) && ( predicate.equals(eTag) )) { + // Match, should short circuit + response.sendError(HttpServletResponse.SC_NOT_MODIFIED); + return; + } + + response.addHeader("ETag", eTag); + } + + OutputStream out = response.getOutputStream(); // Send response to client out.write(bout); @@ -314,5 +375,22 @@ public class JSONRPCServiceServlet extends JSONRPCServlet { } return result; + } + + + private String calculateETag(byte[] content) { + String eTag = "invalid"; + try { + MessageDigest messageDigest = MessageDigest.getInstance("MD5"); + byte[] digest = messageDigest.digest(content); + BigInteger number = new BigInteger(1, digest); + StringBuffer sb = new StringBuffer('0'); + sb.append(number.toString(16)); + eTag = sb.toString(); + } catch(Exception e) { + //ignore, we will return random etag + eTag = Integer.toString((new java.util.Random()).nextInt(Integer.MAX_VALUE)); + } + return eTag; } } diff --git a/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java b/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java index 67d3eda6b2..5f902fd40c 100644 --- a/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java +++ b/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java @@ -19,15 +19,18 @@ package org.apache.tuscany.sca.binding.jsonrpc; import java.io.ByteArrayInputStream; +import java.net.URLEncoder; import junit.framework.Assert; +import org.apache.axiom.om.util.Base64; import org.apache.tuscany.sca.host.embedded.SCADomain; import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Test; +import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.PostMethodWebRequest; import com.meterware.httpunit.WebConversation; import com.meterware.httpunit.WebRequest; @@ -66,5 +69,20 @@ public class JSONRPCServiceTestCase{ JSONObject jsonResp = new JSONObject(response.getText()); Assert.assertEquals("echo: Hello JSON-RPC", jsonResp.getString("result")); - } + } + + @Test + public void testJSONRPCBindingGET() throws Exception { + String params = Base64.encode("[\"Hello JSON-RPC\"]".getBytes()); + String queryString = "?method=echo¶ms=" + URLEncoder.encode(params,"UTF-8") + "&id=1"; + + WebConversation wc = new WebConversation(); + WebRequest request = new GetMethodWebRequest(SERVICE_URL + queryString); + WebResponse response = wc.getResource(request); + + Assert.assertEquals(200, response.getResponseCode()); + + JSONObject jsonResp = new JSONObject(response.getText()); + Assert.assertEquals("echo: Hello JSON-RPC", jsonResp.getString("result")); + } }
\ No newline at end of file |