Author: b...@google.com
Date: Wed Feb  4 08:23:36 2009
New Revision: 4622

Modified:
     
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
     
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/RPC.java
     
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java
     
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/impl/TypeNameObfuscator.java
     
changes/bobv/elide_rpc_type_names_r4602/user/test/com/google/gwt/user/server/rpc/SerializationPolicyLoaderTest.java

Log:
Obfuscate the name of the RPC service interface.
Add type signature data to gwt.rpc file to ensure  
IncompatibleRemoteServiceExceptions are thrown when type signatures change.


Modified:  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
==============================================================================
---  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
        
(original)
+++  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
        
Wed Feb  4 08:23:36 2009
@@ -44,6 +44,7 @@
  import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
  import com.google.gwt.user.rebind.SourceWriter;
  import com.google.gwt.user.server.rpc.SerializationPolicyLoader;
+import com.google.gwt.user.server.rpc.impl.TypeNameObfuscator;

  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
@@ -52,7 +53,6 @@
  import java.io.PrintWriter;
  import java.io.UnsupportedEncodingException;
  import java.util.Arrays;
-import java.util.Collections;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Map;
@@ -150,10 +150,11 @@
     * Take the union of two type arrays, and then sort the results
     * alphabetically.
     */
-  private static JType[] unionOfTypeArrays(JType[] types1, JType[] types2)  
{
+  private static JType[] unionOfTypeArrays(JType[]... types) {
      Set<JType> typesList = new HashSet<JType>();
-    typesList.addAll(Arrays.asList(types1));
-    typesList.addAll(Arrays.asList(types2));
+    for (JType[] a : types) {
+      typesList.addAll(Arrays.asList(a));
+    }
      JType[] serializableTypes = typesList.toArray(new JType[0]);
      Arrays.sort(serializableTypes,
          SerializableTypeOracleBuilder.JTYPE_COMPARATOR);
@@ -161,6 +162,12 @@
    }

    private boolean elideTypeNames;
+
+  /**
+   * The possibly obfuscated type signatures used to represent a type.
+   */
+  private Map<JType, String> typeSignatures;
+
    private JClassType serviceIntf;

    {
@@ -271,19 +278,23 @@
          typesSentFromBrowser, typesSentToBrowser, context,
          SerializationUtils.getTypeSerializerQualifiedName(serviceIntf));
      tsc.realize(logger);
-    Map<JType, String> obfuscatedTypeNames = elideTypeNames
-        ? tsc.getTypeSignatures() : Collections.<JType, String> emptyMap();
+
+    typeSignatures = new HashMap<JType, String>(tsc.getTypeSignatures());
+    typeSignatures.put(serviceIntf,  
TypeNameObfuscator.SERVICE_INTERFACE_ID);

      String serializationPolicyStrongName =  
writeSerializationPolicyFile(logger,
          context, typesSentFromBrowser, typesSentToBrowser);

+    String remoteServiceInterfaceName = elideTypeNames
+        ? TypeNameObfuscator.SERVICE_INTERFACE_ID
+        : TypeOracleMediator.computeBinaryClassName(serviceIntf);
      generateProxyFields(srcWriter, typesSentFromBrowser,
-        serializationPolicyStrongName);
+        serializationPolicyStrongName, remoteServiceInterfaceName);

      generateProxyContructor(javadocAnnotationDeprecationBranch, srcWriter);

      generateProxyMethods(srcWriter, typesSentFromBrowser,
-        syncMethToAsyncMethMap, obfuscatedTypeNames);
+        syncMethToAsyncMethMap);

      if (elideTypeNames) {
        generateStreamWriterOverride(srcWriter);
@@ -319,12 +330,10 @@
     */
    private void generateProxyFields(SourceWriter srcWriter,
        SerializableTypeOracle serializableTypeOracle,
-      String serializationPolicyStrongName) {
+      String serializationPolicyStrongName, String  
remoteServiceInterfaceName) {
      // Initialize a field with binary name of the remote service interface
      srcWriter.println("private static final String  
REMOTE_SERVICE_INTERFACE_NAME = "
-        + (elideTypeNames ? "null" : ("\""
-            + TypeOracleMediator.computeBinaryClassName(serviceIntf)  
+ "\""))
-        + ";");
+        + "\"" + remoteServiceInterfaceName + "\";");
      srcWriter.println("private static final String SERIALIZATION_POLICY  
=\""
          + serializationPolicyStrongName + "\";");
      String typeSerializerName =  
SerializationUtils.getTypeSerializerQualifiedName(serviceIntf);
@@ -338,7 +347,7 @@
     */
    private void generateProxyMethod(SourceWriter w,
        SerializableTypeOracle serializableTypeOracle, JMethod syncMethod,
-      JMethod asyncMethod, Map<JType, String> obfuscatedTypeNames) {
+      JMethod asyncMethod) {

      w.println();

@@ -415,11 +424,13 @@
      for (JParameter param : syncParams) {
        JType paramType = param.getType().getErasedType();
        String typeName;
-      if (obfuscatedTypeNames.containsKey(paramType)) {
-        typeName = obfuscatedTypeNames.get(paramType);
+      if (typeSignatures.containsKey(paramType)) {
+        typeName = typeSignatures.get(paramType);
        } else {
          typeName = TypeOracleMediator.computeBinaryClassName(paramType);
        }
+      assert typeName != null : "Could not compute a type name for "
+          + paramType.getQualifiedSourceName();
        w.println(streamWriterName + ".writeString(\"" + typeName + "\");");
      }

@@ -483,8 +494,7 @@

    private void generateProxyMethods(SourceWriter w,
        SerializableTypeOracle serializableTypeOracle,
-      Map<JMethod, JMethod> syncMethToAsyncMethMap,
-      Map<JType, String> obfuscatedTypeNames) {
+      Map<JMethod, JMethod> syncMethToAsyncMethMap) {
      JMethod[] syncMethods = serviceIntf.getOverridableMethods();
      for (JMethod syncMethod : syncMethods) {

@@ -506,8 +516,7 @@
          }
        }

-      generateProxyMethod(w, serializableTypeOracle, syncMethod,  
asyncMethod,
-          obfuscatedTypeNames);
+      generateProxyMethod(w, serializableTypeOracle, syncMethod,  
asyncMethod);
      }
    }

@@ -603,11 +612,12 @@
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(baos,
            SerializationPolicyLoader.SERIALIZATION_POLICY_FILE_ENCODING);
+      TypeOracle oracle = ctx.getTypeOracle();
        PrintWriter pw = new PrintWriter(osw);

        JType[] serializableTypes = unionOfTypeArrays(
            serializationSto.getSerializableTypes(),
-          deserializationSto.getSerializableTypes());
+          deserializationSto.getSerializableTypes(), new JType[]  
{serviceIntf});

        for (int i = 0; i < serializableTypes.length; ++i) {
          JType type = serializableTypes[i];
@@ -620,7 +630,14 @@
          pw.print(", " +  
Boolean.toString(serializationSto.isSerializable(type)));
          pw.print(", "
              + Boolean.toString(serializationSto.maybeInstantiated(type)));
-        pw.print(", " + Integer.toString(i, Character.MAX_RADIX));
+        pw.print(", " + typeSignatures.get(type));
+
+        /*
+         * Include the serialization signature to bump the RPC file name if
+         * obfuscated identifiers are used.
+         */
+        pw.print(", "
+            + SerializationUtils.getSerializationSignature(oracle, type));
          pw.print('\n');
        }


Modified:  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/RPC.java
==============================================================================
---  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/RPC.java
         
(original)
+++  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/RPC.java
         
Wed Feb  4 08:23:36 2009
@@ -238,7 +238,8 @@
        streamReader.prepareToRead(encodedRequest);

        // Read the name of the RemoteService interface
-      String serviceIntfName = streamReader.readString();
+      String serviceIntfName = maybeDeobfuscate(streamReader,
+          streamReader.readString());

        if (type != null) {
          if (!implementsInterface(type, serviceIntfName)) {
@@ -273,20 +274,9 @@
        Class<?>[] parameterTypes = new Class[paramCount];

        for (int i = 0; i < parameterTypes.length; i++) {
-        String paramClassName = streamReader.readString();
-        if  
(streamReader.hasFlags(AbstractSerializationStream.FLAG_ELIDE_TYPE_NAMES)) {
-          if (!(serializationPolicy instanceof TypeNameObfuscator)) {
-            throw new IncompatibleRemoteServiceException(
-                "RPC request was encoded with obfuscated type names, "
-                    + "but the SerializationPolicy in use does not  
implement "
-                    + TypeNameObfuscator.class.getName());
-          }
+        String paramClassName = maybeDeobfuscate(streamReader,
+            streamReader.readString());

-          String maybeNewTypeName = ((TypeNameObfuscator)  
serializationPolicy).getClassNameForTypeId(paramClassName);
-          if (maybeNewTypeName != null) {
-            paramClassName = maybeNewTypeName;
-          }
-        }
          try {
            parameterTypes[i] = getClassFromSerializedName(paramClassName,
                classLoader);
@@ -821,6 +811,31 @@
      }

      return false;
+  }
+
+  /**
+   * Given a type identifier in the stream, attempt to deobfuscate it.  
Retuns
+   * the original identifier if deobfuscation is unnecessary or no mapping  
is
+   * known.
+   */
+  private static String maybeDeobfuscate(
+      ServerSerializationStreamReader streamReader, String name)
+      throws SerializationException {
+    if  
(streamReader.hasFlags(AbstractSerializationStream.FLAG_ELIDE_TYPE_NAMES)) {
+      SerializationPolicy serializationPolicy =  
streamReader.getSerializationPolicy();
+      if (!(serializationPolicy instanceof TypeNameObfuscator)) {
+        throw new IncompatibleRemoteServiceException(
+            "RPC request was encoded with obfuscated type names, "
+                + "but the SerializationPolicy in use does not implement "
+                + TypeNameObfuscator.class.getName());
+      }
+
+      String maybe = ((TypeNameObfuscator)  
serializationPolicy).getClassNameForTypeId(name);
+      if (maybe != null) {
+        return maybe;
+      }
+    }
+    return name;
    }

    /**

Modified:  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java
==============================================================================
---  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java
   
(original)
+++  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java
   
Wed Feb  4 08:23:36 2009
@@ -16,6 +16,7 @@
  package com.google.gwt.user.server.rpc;

  import com.google.gwt.user.server.rpc.impl.StandardSerializationPolicy;
+import com.google.gwt.user.server.rpc.impl.TypeNameObfuscator;

  import java.io.BufferedReader;
  import java.io.IOException;
@@ -37,7 +38,7 @@
    public static final String SERIALIZATION_POLICY_FILE_ENCODING = "UTF-8";

    private static final String FORMAT_ERROR_MESSAGE = "Expected:  
className, "
-      + "[true | false], [true | false], [true | false], [true | false],  
typeId";
+      + "[true | false], [true | false], [true | false], [true | false],  
typeId, signature";

    /**
     * Returns the serialization policy file name from the from the  
serialization
@@ -115,7 +116,7 @@
        if (line.length() > 0) {
          String[] components = line.split(",");

-        if (components.length != 2 && components.length != 6) {
+        if (components.length != 2 && components.length != 7) {
            throw new ParseException(FORMAT_ERROR_MESSAGE, lineNum);
          }

@@ -146,10 +147,11 @@
            instantDeser = Boolean.valueOf(components[idx++]);
            typeId = components[idx++];

-          if (!fieldSer && !fieldDeser) {
+          if (!fieldSer && !fieldDeser
+              && !TypeNameObfuscator.SERVICE_INTERFACE_ID.equals(typeId)) {
              throw new ParseException("Type " + binaryTypeName
-                + " is neither field serializable nor field  
deserializable",
-                lineNum);
+                + " is neither field serializable, field deserializable "
+                + "nor the service interface", lineNum);
            }
          }


Modified:  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/impl/TypeNameObfuscator.java
==============================================================================
---  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/impl/TypeNameObfuscator.java
     
(original)
+++  
changes/bobv/elide_rpc_type_names_r4602/user/src/com/google/gwt/user/server/rpc/impl/TypeNameObfuscator.java
     
Wed Feb  4 08:23:36 2009
@@ -21,10 +21,19 @@
   * This is a private interface that allows ProxyCreator to provide  
obfuscated
   * type names to the server components via {...@link  
StandardSerializationPolicy}.
   * <p>
- * The particulars of the implementation are deeply tied to the specifiecs  
of
- * the RPC wire format and the code generated by TypeSerializerCreator.
+ * The particulars of the implementation are deeply tied to the specifics  
of the
+ * RPC wire format and the code generated by TypeSerializerCreator.
+ * <p>
+ * This interface is not public in order to allow the API to be switched  
from
+ * Strings to ints in a future revision.
   */
  public interface TypeNameObfuscator {
+  /**
+   * A reserved ID for specifying the identifier for the service interface
+   * itself.
+   */
+  String SERVICE_INTERFACE_ID = "_";
+
    /*
     * TODO: Replace strings with integral constants once the RPC whitelist  
can be
     * given as a hard requirement for deploying GWT-RPC.

Modified:  
changes/bobv/elide_rpc_type_names_r4602/user/test/com/google/gwt/user/server/rpc/SerializationPolicyLoaderTest.java
==============================================================================
---  
changes/bobv/elide_rpc_type_names_r4602/user/test/com/google/gwt/user/server/rpc/SerializationPolicyLoaderTest.java
      
(original)
+++  
changes/bobv/elide_rpc_type_names_r4602/user/test/com/google/gwt/user/server/rpc/SerializationPolicyLoaderTest.java
      
Wed Feb  4 08:23:36 2009
@@ -40,6 +40,9 @@
    static class B {
    }

+  static class I {
+  }
+
    private static final String OLD_VALID_POLICY_FILE_CONTENTS =  
A.class.getName()
        + ", true";

@@ -49,8 +52,10 @@
    private static final String POLICY_FILE_TRIGGERS_CLASSNOTFOUND  
= "C,false";

    private static final String VALID_POLICY_FILE_CONTENTS =  
A.class.getName()
-      + ", true, true, false, false, a\n" + B.class.getName()
-      + ", false, false, true, false, b\n";
+      + ", true, true, false, false, a, 1234\n" + B.class.getName()
+      + ", false, false, true, false, b, 5678\n" + I.class.getName()
+      + ", false, false, false, false, "
+      + TypeNameObfuscator.SERVICE_INTERFACE_ID + ", 999\n";

    public static InputStream getInputStreamFromString(String content)
        throws UnsupportedEncodingException {
@@ -90,6 +95,10 @@
      assertEquals(A.class.getName(), ob.getClassNameForTypeId("a"));
      assertEquals("b", ob.getTypeIdForClass(B.class));
      assertEquals(B.class.getName(), ob.getClassNameForTypeId("b"));
+    assertEquals(TypeNameObfuscator.SERVICE_INTERFACE_ID,
+        ob.getTypeIdForClass(I.class));
+    assertEquals(I.class.getName(),
+        ob.getClassNameForTypeId(TypeNameObfuscator.SERVICE_INTERFACE_ID));
    }

    /**

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to