You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by lr...@apache.org on 2010/03/30 07:38:01 UTC

svn commit: r928999 - in /tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src: main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java

Author: lresende
Date: Tue Mar 30 05:38:01 2010
New Revision: 928999

URL: http://svn.apache.org/viewvc?rev=928999&view=rev
Log:
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

Modified:
    tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java
    tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java

Modified: tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java?rev=928999&r1=928998&r2=928999&view=diff
==============================================================================
--- tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java (original)
+++ tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceServlet.java Tue Mar 30 05:38:01 2010
@@ -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.JSONRPCB
 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 exten
     }
 
     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 exten
         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 exten
         } 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 exten
         }
 
         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;
     }    
 }

Modified: tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java?rev=928999&r1=928998&r2=928999&view=diff
==============================================================================
--- tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java (original)
+++ tuscany/sca-java-1.x/trunk/modules/binding-jsonrpc-runtime/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java Tue Mar 30 05:38:01 2010
@@ -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&params=" + 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