Provide access to the decoded RPCRequest object in RemoteServiceServlet subclasses.
Updates RPCRequest to have a useful toString() when debugging.

Patch by: rdamazio
Review by: bobv


git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4096 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/server/rpc/RPCRequest.java b/user/src/com/google/gwt/user/server/rpc/RPCRequest.java
index df4d846..8663454 100644
--- a/user/src/com/google/gwt/user/server/rpc/RPCRequest.java
+++ b/user/src/com/google/gwt/user/server/rpc/RPCRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
  * 
  * Licensed 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
@@ -65,12 +65,50 @@
 
   /**
    * Returns the {@link SerializationPolicy} used to decode this request. This
-   * is also the <code>SerializationPolicy</code> that should be used to
-   * encode responses.
+   * is also the <code>SerializationPolicy</code> that should be used to encode
+   * responses.
    * 
    * @return {@link SerializationPolicy} used to decode this request
    */
   public SerializationPolicy getSerializationPolicy() {
     return serializationPolicy;
   }
+
+  /**
+   * For debugging use only.
+   */
+  @Override
+  public String toString() {
+    StringBuilder callSignature = new StringBuilder();
+
+    // Add the class and method names
+    callSignature.append(method.getDeclaringClass().getName());
+    callSignature.append('.');
+    callSignature.append(method.getName());
+
+    // Add the list of parameters
+    callSignature.append('(');
+    for (Object param : parameters) {
+      if (param instanceof String) {
+        // Put it within quotes and escape quotes, for readability
+        callSignature.append('"');
+        String strParam = (String) param;
+        String escapedStrParam = strParam.replaceAll("\\\"", "\\\\\"");
+        callSignature.append(escapedStrParam);
+        callSignature.append('"');
+      } else {
+        // We assume that anyone who wants to use this method will implement
+        // toString on his serializable objects.
+        callSignature.append(param.toString());
+      }
+      callSignature.append(", ");
+    }
+
+    // Remove the last ", "
+    int length = callSignature.length();
+    callSignature.delete(length - 2, length);
+    callSignature.append(')');
+
+    return callSignature.toString();
+  }
 }
diff --git a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
index 7e11b43..c43128c 100644
--- a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
+++ b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
@@ -162,6 +162,7 @@
   public String processCall(String payload) throws SerializationException {
     try {
       RPCRequest rpcRequest = RPC.decodeRequest(payload, this.getClass(), this);
+      onAfterRequestDeserialized(rpcRequest);
       return RPC.invokeAndEncodeResponse(this, rpcRequest.getMethod(),
           rpcRequest.getParameters(), rpcRequest.getSerializationPolicy());
     } catch (IncompatibleRemoteServiceException ex) {
@@ -262,15 +263,15 @@
   /**
    * Override this method to control what should happen when an exception
    * escapes the {@link #processCall(String)} method. The default implementation
-   * will log the failure and send a generic failure response to the client.<p/>
-   * 
+   * will log the failure and send a generic failure response to the client.
+   * <p>
    * An "expected failure" is an exception thrown by a service method that is
    * declared in the signature of the service method. These exceptions are
    * serialized back to the client, and are not passed to this method. This
    * method is called only for exceptions or errors that are not part of the
    * service method's signature, or that result from SecurityExceptions,
-   * SerializationExceptions, or other failures within the RPC framework.<p/>
-   * 
+   * SerializationExceptions, or other failures within the RPC framework.
+   * <p>
    * Note that if the desired behavior is to both send the GENERIC_FAILURE_MSG
    * response AND to rethrow the exception, then this method should first send
    * the GENERIC_FAILURE_MSG response itself (using getThreadLocalResponse), and
@@ -286,9 +287,9 @@
   }
 
   /**
-   * Gets the <code>HttpServletRequest</code> object for the current call. It
-   * is stored thread-locally so that simultaneous invocations can have
-   * different request objects.
+   * Gets the <code>HttpServletRequest</code> object for the current call. It is
+   * stored thread-locally so that simultaneous invocations can have different
+   * request objects.
    */
   protected final HttpServletRequest getThreadLocalRequest() {
     return perThreadRequest.get();
@@ -304,6 +305,14 @@
   }
 
   /**
+   * Override this method to examine the deserialized version of the request
+   * before the call to the servlet method is made. The default implementation
+   * does nothing and need not be called by subclasses.
+   */
+  protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
+  }
+
+  /**
    * Override this method to examine the serialized response that will be
    * returned to the client. The default implementation does nothing and need
    * not be called by subclasses.
diff --git a/user/test/com/google/gwt/user/RPCSuite.java b/user/test/com/google/gwt/user/RPCSuite.java
index 24d44ec..499446a 100644
--- a/user/test/com/google/gwt/user/RPCSuite.java
+++ b/user/test/com/google/gwt/user/RPCSuite.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
  * 
  * Licensed 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
@@ -26,6 +26,7 @@
 import com.google.gwt.user.client.rpc.ValueTypesTest;
 import com.google.gwt.user.rebind.rpc.SerializableTypeOracleBuilderTest;
 import com.google.gwt.user.rebind.rpc.TypeHierarchyUtilsTest;
+import com.google.gwt.user.server.rpc.RPCRequestTest;
 import com.google.gwt.user.server.rpc.RPCServletUtilsTest;
 import com.google.gwt.user.server.rpc.RPCTest;
 import com.google.gwt.user.server.rpc.SerializationPolicyLoaderTest;
@@ -68,6 +69,7 @@
     suite.addTestSuite(StandardSerializationPolicyTest.class);
     suite.addTestSuite(SerializationPolicyLoaderTest.class);
     suite.addTestSuite(RPCServletUtilsTest.class);
+    suite.addTestSuite(RPCRequestTest.class);
     return suite;
   }
 }