Merging releases/1.5 into trunk

svn merge -r3550:3556 https://google-web-toolkit.googlecode.com/svn/releases/1.5 .



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3591 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/hosted.html b/dev/core/src/com/google/gwt/core/ext/linker/impl/hosted.html
index 190408a..d02be07 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/hosted.html
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/hosted.html
@@ -17,7 +17,7 @@
 function gwtOnLoad(errFn, modName, modBase){
   $moduleName = modName;
   $moduleBase = modBase;
-  if (!external.gwtOnLoad(window, modName)) {
+  if (!external.gwtOnLoad(window, modName, "1.5")) {
     if (errFn) {
       errFn(modName);
     }
@@ -29,7 +29,7 @@
 };
 
 window.onunload = function() {
-  external.gwtOnLoad(window, null);
+  external.gwtOnLoad(window, null, "1.5");
 };
 
 window.__gwt_module_id = 0;
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java b/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java
index 9fafca9..bace787 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.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
@@ -153,6 +153,11 @@
     }
   }
 
+  /**
+   * The version number that should be passed into gwtOnLoad.
+   */
+  private static final String EXPECTED_GWT_ONLOAD_VERSION = "1.5";
+
   public static void launchExternalBrowser(TreeLogger logger, String location) {
     // check GWT_EXTERNAL_BROWSER first, it overrides everything else
     LowLevel.init();
@@ -361,6 +366,23 @@
   }
 
   /**
+   * Report that gwtOnLoad was called with the wrong number of
+   * arguments.
+   * 
+   * @param numArgs number of arguments supplied
+   */
+  protected void reportIncorrectGwtOnLoadInvocation(int numArgs) {
+    getHost().getLogger().log(
+        TreeLogger.ERROR,
+        "Not enough arguments ("
+        + numArgs
+        + ") passed to external.gwtOnLoad(), expected (3); "
+        + "your hosted mode bootstrap file may be out of date; "
+        + "if you are using -noserver try recompiling and redeploying "
+        + "your app");
+  }
+
+  /**
    * Unload the specified module.
    * 
    * @param moduleSpace a ModuleSpace instance to unload.
@@ -373,6 +395,31 @@
         + key.toString() + ")", null);
   }
 
+  /**
+   * Validate that the supplied hosted.html version matches.
+   * 
+   * This is to detect cases where users upgrade to a new version
+   * but forget to update the generated hosted.html file.
+   * 
+   * @param version version supplied by hosted.html file
+   * @return true if the version is valid, false otherwise
+   */
+  protected boolean validHostedHtmlVersion(String version) {
+    if (!EXPECTED_GWT_ONLOAD_VERSION.equals(version)) {
+      getHost().getLogger().log(
+          TreeLogger.ERROR,
+          "Invalid version number \""
+              + version
+              + "\" passed to external.gwtOnLoad(), expected \""
+              + EXPECTED_GWT_ONLOAD_VERSION
+              + "\"; your hosted mode bootstrap file may be out of date; "
+              + "if you are using -noserver try recompiling and redeploying "
+              + "your app");
+     return false;
+    }
+    return true;
+  }
+
   private Composite buildLocationBar(Composite parent) {
     Color white = new Color(null, 255, 255, 255);
 
diff --git a/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java b/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
index d7c8cc6..f0cbe8c 100644
--- a/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
+++ b/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
@@ -36,7 +36,7 @@
 
   private class ExternalObjectImpl implements ExternalObject {
 
-    public boolean gwtOnLoad(int scriptObject, String moduleName) {
+    public boolean gwtOnLoad(int scriptObject, String moduleName, String version) {
       try {
         if (moduleName == null) {
           // Indicates one or more modules are being unloaded.
@@ -45,6 +45,10 @@
           return true;
         }
 
+        if (!validHostedHtmlVersion(version)) {
+          return false;
+        }
+
         Object key = new Integer(scriptObject);
         // Attach a new ModuleSpace to make it programmable.
         //
diff --git a/dev/linux/src/com/google/gwt/dev/shell/moz/LowLevelMoz.java b/dev/linux/src/com/google/gwt/dev/shell/moz/LowLevelMoz.java
index d102fe8..1606f78 100644
--- a/dev/linux/src/com/google/gwt/dev/shell/moz/LowLevelMoz.java
+++ b/dev/linux/src/com/google/gwt/dev/shell/moz/LowLevelMoz.java
@@ -75,7 +75,7 @@
    * Safari.
    */
   interface ExternalObject {
-    boolean gwtOnLoad(int scriptGlobalObject, String moduleName);
+    boolean gwtOnLoad(int scriptGlobalObject, String moduleName, String version);
   }
 
   /**
diff --git a/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java b/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
index 4c83fa7..439cae7 100644
--- a/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
+++ b/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
@@ -48,7 +48,7 @@
       return this;
     }
 
-    public boolean gwtOnLoad(int scriptObject, String moduleName) {
+    public boolean gwtOnLoad(int scriptObject, String moduleName, String version) {
       try {
         if (moduleName == null) {
           // Indicates one or more modules are being unloaded.
@@ -56,6 +56,10 @@
           return true;
         }
 
+        if (!validHostedHtmlVersion(version)) {
+          return false;
+        }
+
         // Attach a new ModuleSpace to make it programmable.
         //
         Integer key = new Integer(scriptObject);
@@ -108,7 +112,7 @@
     }
   }
 
-  private static final class GwtOnLoad implements DispatchMethod {
+  private final class GwtOnLoad implements DispatchMethod {
 
     public int invoke(int jsContext, int jsthis, int[] jsargs, int[] exception) {
       int jsFalse = LowLevelSaf.toJsBoolean(jsContext, false);
@@ -124,6 +128,7 @@
         }
 
         if (jsargs.length < 2) {
+          reportIncorrectGwtOnLoadInvocation(jsargs.length);
           return jsFalse;
         }
 
@@ -136,8 +141,19 @@
         }
         String moduleName = LowLevelSaf.toString(jsContext, jsargs[1]);
 
+        /*
+         * gwtOnLoad may or may not be called with a third argument indicating
+         * which version of GWT the JavaScript bootstrap sequence assumes that
+         * its talking to.
+         */
+        String version = null;
+        if (jsargs.length == 3 && !LowLevelSaf.isJsNull(jsContext, jsargs[2])
+            && LowLevelSaf.isJsString(jsContext, jsargs[2])) {
+          version = LowLevelSaf.toString(jsContext, jsargs[2]);
+        }
+
         boolean result = ((ExternalObject) thisObj).gwtOnLoad(jsargs[0],
-            moduleName);
+            moduleName, version);
         // Native code eats the same ref it gave us.
         return LowLevelSaf.toJsBoolean(jsContext, result);
       } catch (Throwable e) {
diff --git a/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java b/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
index f91bd4e..2303df1 100644
--- a/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
+++ b/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
@@ -49,14 +49,19 @@
      * @param moduleName the name of the module to load, null if this is being
      *          unloaded
      */
-    public boolean gwtOnLoad(IDispatch frameWnd, String moduleName) {
+    public boolean gwtOnLoad(IDispatch frameWnd, String moduleName,
+        String version) {
       try {
         if (moduleName == null) {
           // Indicates one or more modules are being unloaded.
           handleUnload(frameWnd);
           return true;
         }
-        
+
+        if (!validHostedHtmlVersion(version)) {
+          throw new HResultException(COM.E_INVALIDARG);
+        }
+
         // set the module ID
         int moduleID = ++nextModuleID;
         Integer key = new Integer(moduleID);
@@ -121,11 +126,17 @@
       } else if (dispId == 1) {
         if ((flags & COM.DISPATCH_METHOD) != 0) {
           try {
+            if (params.length < 2) {
+              reportIncorrectGwtOnLoadInvocation(params.length);
+              throw new HResultException(COM.E_INVALIDARG);
+            }
             IDispatch frameWnd = (params[0].getType() == COM.VT_DISPATCH)
                 ? params[0].getDispatch() : null;
             String moduleName = (params[1].getType() == COM.VT_BSTR)
                 ? params[1].getString() : null;
-            boolean success = gwtOnLoad(frameWnd, moduleName);
+            String version = (params.length > 2 && params[2].getType() == COM.VT_BSTR)
+                ? params[2].getString() : null;
+            boolean success = gwtOnLoad(frameWnd, moduleName, version);
 
             // boolean return type
             return new Variant(success);
@@ -136,7 +147,7 @@
           // property get on the method itself
           try {
             Method gwtOnLoadMethod = getClass().getMethod("gwtOnLoad",
-                new Class[] {IDispatch.class, String.class});
+                new Class[] {IDispatch.class, String.class, String.class});
             MethodAdaptor methodAdaptor = new MethodAdaptor(gwtOnLoadMethod);
             IDispatchImpl funcObj = new MethodDispatch(null, methodAdaptor);
             IDispatch disp = new IDispatch(funcObj.getAddress());
@@ -170,7 +181,7 @@
     OleAutomation window = null;
     try {
       window = new OleAutomation(frameWnd);
-      int[] dispID = window.getIDsOfNames(new String[] { propName });
+      int[] dispID = window.getIDsOfNames(new String[] {propName});
       if (dispID == null) {
         throw new RuntimeException("No such property " + propName);
       }
@@ -203,7 +214,7 @@
     OleAutomation window = null;
     try {
       window = new OleAutomation(frameWnd);
-      int[] dispID = window.getIDsOfNames(new String[] { propName });
+      int[] dispID = window.getIDsOfNames(new String[] {propName});
       if (dispID == null) {
         throw new RuntimeException("No such property " + propName);
       }
diff --git a/jni/linux/ExternalWrapper.cpp b/jni/linux/ExternalWrapper.cpp
index 12e7324..990fc99 100644
--- a/jni/linux/ExternalWrapper.cpp
+++ b/jni/linux/ExternalWrapper.cpp
@@ -68,6 +68,11 @@
     moduleName = JS_ValueToString(cx, argv[1]);
   }
 
+  JSString* version = 0;
+  if (argc > 2 && argv[2] != JSVAL_NULL && argv[2] != JSVAL_VOID) {
+    version = JS_ValueToString(cx, argv[2]);
+  }
+
   nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(0);
   if (scriptWindow) {
     nsCOMPtr<nsIXPConnect> xpConnect = do_GetService(nsIXPConnect::GetCID());
@@ -93,6 +98,19 @@
     tracer.log("null module name");
   }
 
+  jstring jVersion(0);
+  if (version) {
+    jVersion = savedJNIEnv->NewString(JS_GetStringChars(version),
+        JS_GetStringLength(version));
+    if (!jVersion || savedJNIEnv->ExceptionCheck()) {
+      tracer.setFail("can't get module name in Java string");
+      return JS_FALSE;
+    }
+    tracer.log("version=%s", JS_GetStringBytes(version));
+  } else {
+    tracer.log("null version");
+  }
+
   jobject externalObject = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
   jclass objClass = savedJNIEnv->GetObjectClass(externalObject);
   if (!objClass || savedJNIEnv->ExceptionCheck()) {
@@ -101,7 +119,7 @@
   }
 
   jmethodID methodID = savedJNIEnv->GetMethodID(objClass, "gwtOnLoad",
-      "(ILjava/lang/String;)Z");
+      "(ILjava/lang/String;Ljava/lang/String;)Z");
   if (!methodID || savedJNIEnv->ExceptionCheck()) {
     tracer.setFail("can't get gwtOnLoad method");
     return JS_FALSE;
@@ -110,7 +128,7 @@
   tracer.log("scriptGlobal=%08x", unsigned(scriptGlobal.get()));
 
   jboolean result = savedJNIEnv->CallBooleanMethod(externalObject, methodID,
-      NS_REINTERPRET_CAST(jint, scriptGlobal.get()), jModuleName);
+      NS_REINTERPRET_CAST(jint, scriptGlobal.get()), jModuleName, jVersion);
   if (savedJNIEnv->ExceptionCheck()) {
     tracer.setFail("LowLevelMoz.ExternalObject.gwtOnLoad() threw an exception");
     return JS_FALSE;
diff --git a/jni/linux/prebuilt/libgwt-ll.so b/jni/linux/prebuilt/libgwt-ll.so
index 88d2b41..ac1f72f 100755
--- a/jni/linux/prebuilt/libgwt-ll.so
+++ b/jni/linux/prebuilt/libgwt-ll.so
Binary files differ
diff --git a/user/src/com/google/gwt/user/RemoteService.gwt.xml b/user/src/com/google/gwt/user/RemoteService.gwt.xml
index 2c9a680..32649e5 100644
--- a/user/src/com/google/gwt/user/RemoteService.gwt.xml
+++ b/user/src/com/google/gwt/user/RemoteService.gwt.xml
@@ -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   -->
 <!-- may obtain a copy of the License at                                    -->
@@ -20,15 +20,6 @@
 	<inherits name="com.google.gwt.http.HTTP"/>  
 	
 	<!-- 
-		Declare a property to determine whether or not RPC type versioning 
-		should be enforced. 
-	-->
-	<define-property name="gwt.enforceRPCTypeVersioning" values="true,false" />
-	
-	<!-- Default RPC versioning to be on. -->
-	<set-property name="gwt.enforceRPCTypeVersioning" value="true"/>
-	
-	<!-- 
 		Declare a property to determine whether warnings for final instance 
 		fields should be suppressed.
 	-->
diff --git a/user/src/com/google/gwt/user/client/rpc/IncompatibleRemoteServiceException.java b/user/src/com/google/gwt/user/client/rpc/IncompatibleRemoteServiceException.java
index be3b628..be91c7b 100644
--- a/user/src/com/google/gwt/user/client/rpc/IncompatibleRemoteServiceException.java
+++ b/user/src/com/google/gwt/user/client/rpc/IncompatibleRemoteServiceException.java
@@ -51,20 +51,23 @@
  */
 public final class IncompatibleRemoteServiceException extends RuntimeException
     implements IsSerializable {
+
+  private static final String DEFAULT_MESSAGE = "This application is out of "
+      + "date, please click the refresh button on your browser.";
+
   /**
    * Constructor used by RPC serialization. Note that the client side code will
    * always get a generic error message.
    */
   public IncompatibleRemoteServiceException() {
-    super(
-        "This application is out of date, please click the refresh button on your browser");
+    super(DEFAULT_MESSAGE);
   }
 
   /**
    * Constructs an instance with the specified message.
    */
   public IncompatibleRemoteServiceException(String msg) {
-    super(msg);
+    super(DEFAULT_MESSAGE + " ( " + msg + " )");
   }
 
   /**
diff --git a/user/src/com/google/gwt/user/client/rpc/impl/AbstractSerializationStream.java b/user/src/com/google/gwt/user/client/rpc/impl/AbstractSerializationStream.java
index 7e8d168..51c4483 100644
--- a/user/src/com/google/gwt/user/client/rpc/impl/AbstractSerializationStream.java
+++ b/user/src/com/google/gwt/user/client/rpc/impl/AbstractSerializationStream.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
@@ -22,17 +22,12 @@
  */
 public abstract class AbstractSerializationStream {
 
-  public static final int SERIALIZATION_STREAM_FLAGS_NO_TYPE_VERSIONING = 1;
-  public static final int SERIALIZATION_STREAM_VERSION = 3;
-
   /**
-   * The last legacy stream version which does not use a
-   * {@link com.google.gwt.user.server.rpc.SerializationPolicy SerializationPolicy}.
+   * This is the only supported RPC protocol version.
    */
-  public static final int SERIALIZATION_STREAM_VERSION_WITHOUT_SERIALIZATION_POLICY = 2;
+  public static final int SERIALIZATION_STREAM_VERSION = 4;
 
   private int flags = 0;
-
   private int version = SERIALIZATION_STREAM_VERSION;
 
   public final void addFlags(int flags) {
@@ -51,21 +46,6 @@
     this.flags = flags;
   }
 
-  public final boolean shouldEnforceTypeVersioning() {
-    return (flags & SERIALIZATION_STREAM_FLAGS_NO_TYPE_VERSIONING) == 0;
-  }
-
-  /**
-   * Returns <code>true</code> if this stream encodes information which can be
-   * used to lookup a {@link com.google.gwt.user.server.rpc.SerializationPolicy}.
-   * 
-   * @return <code>true</code> if this stream encodes information which can be
-   *         used to lookup a <code>SerializationPolicy</code>
-   */
-  protected boolean hasSerializationPolicyInfo() {
-    return getVersion() > SERIALIZATION_STREAM_VERSION_WITHOUT_SERIALIZATION_POLICY;
-  }
-
   protected final void setVersion(int version) {
     this.version = version;
   }
diff --git a/user/src/com/google/gwt/user/client/rpc/impl/ClientSerializationStreamReader.java b/user/src/com/google/gwt/user/client/rpc/impl/ClientSerializationStreamReader.java
index f9a7a82..748f4b3 100644
--- a/user/src/com/google/gwt/user/client/rpc/impl/ClientSerializationStreamReader.java
+++ b/user/src/com/google/gwt/user/client/rpc/impl/ClientSerializationStreamReader.java
@@ -18,6 +18,7 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.core.client.UnsafeNativeLong;
+import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
 import com.google.gwt.user.client.rpc.SerializationException;
 
 /**
@@ -56,6 +57,13 @@
     results = eval(encoded);
     index = getLength(results);
     super.prepareToRead(encoded);
+
+    if (getVersion() != SERIALIZATION_STREAM_VERSION) {
+      throw new IncompatibleRemoteServiceException("Expecting version "
+          + SERIALIZATION_STREAM_VERSION + " from server, got " + getVersion()
+          + ".");
+    }
+
     stringTable = readJavaScriptObject();
   }
 
diff --git a/user/src/com/google/gwt/user/client/rpc/impl/ClientSerializationStreamWriter.java b/user/src/com/google/gwt/user/client/rpc/impl/ClientSerializationStreamWriter.java
index df00dc1..f44d1ec 100644
--- a/user/src/com/google/gwt/user/client/rpc/impl/ClientSerializationStreamWriter.java
+++ b/user/src/com/google/gwt/user/client/rpc/impl/ClientSerializationStreamWriter.java
@@ -48,20 +48,6 @@
   private final Serializer serializer;
 
   /**
-   * Constructs a <code>ClientSerializationStreamWriter</code> that does not
-   * use a serialization policy file.
-   * 
-   * @param serializer the {@link Serializer} to use
-   */
-  public ClientSerializationStreamWriter(Serializer serializer) {
-    this.serializer = serializer;
-    this.moduleBaseURL = null;
-    this.serializationPolicyStrongName = null;
-    // Override the default version if no policy info is given.
-    setVersion(SERIALIZATION_STREAM_VERSION_WITHOUT_SERIALIZATION_POLICY);
-  }
-
-  /**
    * Constructs a <code>ClientSerializationStreamWriter</code> using the
    * specified module base URL and the serialization policy.
    * 
@@ -85,10 +71,9 @@
     super.prepareToWrite();
     encodeBuffer = new StringBuffer();
 
-    if (hasSerializationPolicyInfo()) {
-      writeString(moduleBaseURL);
-      writeString(serializationPolicyStrongName);
-    }
+    // Write serialization policy info
+    writeString(moduleBaseURL);
+    writeString(serializationPolicyStrongName);
   }
 
   @Override
diff --git a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
index 26b12a7..75615ff 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
@@ -36,7 +36,6 @@
 import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
 import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
 import com.google.gwt.user.client.rpc.SerializationException;
-import com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader;
 import com.google.gwt.user.client.rpc.impl.ClientSerializationStreamWriter;
 import com.google.gwt.user.client.rpc.impl.RemoteServiceProxy;
 import com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.ResponseReader;
@@ -139,8 +138,6 @@
     stob.addRootType(logger, icseType);
   }
 
-  private boolean enforceTypeVersioning;
-
   private JClassType serviceIntf;
 
   {
@@ -236,9 +233,6 @@
         sto.getTypeSerializerQualifiedName(serviceIntf));
     tsc.realize(logger);
 
-    enforceTypeVersioning = Shared.shouldEnforceTypeVersioning(logger,
-        context.getPropertyOracle());
-
     String serializationPolicyStrongName = writeSerializationPolicyFile(logger,
         context, sto);
 
@@ -362,12 +356,6 @@
       w.indent();
     }
 
-    if (!shouldEnforceTypeVersioning()) {
-      w.println(streamWriterName + ".addFlags("
-          + ClientSerializationStreamReader.class.getName()
-          + ".SERIALIZATION_STREAM_FLAGS_NO_TYPE_VERSIONING);");
-    }
-
     // Write the method name
     w.println(streamWriterName + ".writeString(\"" + syncMethod.getName()
         + "\");");
@@ -541,10 +529,6 @@
     return composerFactory.createSourceWriter(ctx, printWriter);
   }
 
-  private boolean shouldEnforceTypeVersioning() {
-    return enforceTypeVersioning;
-  }
-
   private String writeSerializationPolicyFile(TreeLogger logger,
       GeneratorContext ctx, SerializableTypeOracle sto)
       throws UnableToCompleteException {
diff --git a/user/src/com/google/gwt/user/rebind/rpc/Shared.java b/user/src/com/google/gwt/user/rebind/rpc/Shared.java
index e5d7992..ed1ddd1 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/Shared.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/Shared.java
@@ -27,11 +27,6 @@
 import java.util.Locale;
 
 class Shared {
-  /**
-   * Property used to control whether or not the RPC system will enforce the
-   * versioning scheme or not.
-   */
-  static final String RPC_PROP_ENFORCE_TYPE_VERSIONING = "gwt.enforceRPCTypeVersioning";
 
   /**
    * Property used to control whether or not the RPC system will emit warnings
@@ -58,16 +53,6 @@
   }
 
   /**
-   * Returns <code>true</code> if the generated code should enforce type
-   * versioning.
-   */
-  static boolean shouldEnforceTypeVersioning(TreeLogger logger,
-      PropertyOracle propertyOracle) {
-    return getBooleanProperty(logger, propertyOracle,
-        RPC_PROP_ENFORCE_TYPE_VERSIONING, true);
-  }
-
-  /**
    * Returns <code>true</code> if warnings should not be emitted for final
    * fields in serializable types.
    */
diff --git a/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java b/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
index d5d04db..206ed81 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
@@ -54,8 +54,6 @@
 
   private final GeneratorContext context;
 
-  private final boolean enforceTypeVersioning;
-
   private final JType[] serializableTypes;
 
   private final SerializableTypeOracle serializationOracle;
@@ -74,9 +72,6 @@
     this.serializationOracle = serializationOracle;
     this.typeOracle = context.getTypeOracle();
 
-    enforceTypeVersioning = Shared.shouldEnforceTypeVersioning(logger,
-        context.getPropertyOracle());
-
     serializableTypes = serializationOracle.getSerializableTypes();
 
     srcWriter = getSourceWriter(logger, context);
@@ -99,9 +94,7 @@
 
     writeCreateMethodMapMethod();
 
-    if (shouldEnforceTypeVersioning()) {
-      writeCreateSignatureMapMethod();
-    }
+    writeCreateSignatureMapMethod();
 
     writeRaiseSerializationException();
 
@@ -246,10 +239,6 @@
     return true;
   }
 
-  private boolean shouldEnforceTypeVersioning() {
-    return enforceTypeVersioning;
-  }
-
   private void writeCreateMethodMapMethod() {
     srcWriter.println("@SuppressWarnings(\"restriction\")");
     srcWriter.println("private static native JavaScriptObject createMethodMap() /*-" + '{');
@@ -270,11 +259,8 @@
           needComma = true;
         }
 
-        String typeString = serializationOracle.getSerializedTypeName(type);
-        if (shouldEnforceTypeVersioning()) {
-          typeString += "/"
-              + serializationOracle.getSerializationSignature(type);
-        }
+        String typeString = serializationOracle.getSerializedTypeName(type)
+            + "/" + serializationOracle.getSerializationSignature(type);
 
         srcWriter.print("\"" + typeString + "\":");
 
@@ -427,19 +413,13 @@
   }
 
   private void writeGetSerializationSignatureMethod() {
-    if (!shouldEnforceTypeVersioning()) {
-      srcWriter.println("public String getSerializationSignature(String typeName) {");
-      srcWriter.indentln("return null;");
-      srcWriter.println("};");
-    } else {
-      String serializerTypeName = getTypeSerializerClassName();
-      srcWriter.println("public native String getSerializationSignature(String typeName) /*-" + '{');
-      srcWriter.indent();
-      srcWriter.println("return @" + serializerTypeName
-          + "::signatureMap[typeName];");
-      srcWriter.outdent();
-      srcWriter.println("}-*/;");
-    }
+    String serializerTypeName = getTypeSerializerClassName();
+    srcWriter.println("public native String getSerializationSignature(String typeName) /*-" + '{');
+    srcWriter.indent();
+    srcWriter.println("return @" + serializerTypeName
+        + "::signatureMap[typeName];");
+    srcWriter.outdent();
+    srcWriter.println("}-*/;");
     srcWriter.println();
   }
 
@@ -490,9 +470,7 @@
 
   private void writeStaticFields() {
     srcWriter.println("private static final JavaScriptObject methodMap = createMethodMap();");
-    if (shouldEnforceTypeVersioning()) {
-      srcWriter.println("private static final JavaScriptObject signatureMap = createSignatureMap();");
-    }
+    srcWriter.println("private static final JavaScriptObject signatureMap = createSignatureMap();");
     srcWriter.println();
   }
 }
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamReader.java b/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamReader.java
index 00a16b0..3e1d87e 100644
--- a/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamReader.java
+++ b/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamReader.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.user.server.rpc.impl;
 
+import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
 import com.google.gwt.user.client.rpc.SerializationException;
 import com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader;
 import com.google.gwt.user.server.rpc.RPC;
@@ -381,23 +382,27 @@
 
     super.prepareToRead(encodedTokens);
 
+    // Check the RPC version number sent by the client
+    if (getVersion() != SERIALIZATION_STREAM_VERSION) {
+      throw new IncompatibleRemoteServiceException("Expecting version "
+          + SERIALIZATION_STREAM_VERSION + " from client, got " + getVersion()
+          + ".");
+    }
+
     // Read the type name table
     //
     deserializeStringTable();
 
-    // If this stream encodes resource file information, read it and get a
-    // SerializationPolicy
-    if (hasSerializationPolicyInfo()) {
-      String moduleBaseURL = readString();
-      String strongName = readString();
-      if (serializationPolicyProvider != null) {
-        serializationPolicy = serializationPolicyProvider.getSerializationPolicy(
-            moduleBaseURL, strongName);
+    // Write the serialization policy info
+    String moduleBaseURL = readString();
+    String strongName = readString();
+    if (serializationPolicyProvider != null) {
+      serializationPolicy = serializationPolicyProvider.getSerializationPolicy(
+          moduleBaseURL, strongName);
 
-        if (serializationPolicy == null) {
-          throw new NullPointerException(
-              "serializationPolicyProvider.getSerializationPolicy()");
-        }
+      if (serializationPolicy == null) {
+        throw new NullPointerException(
+            "serializationPolicyProvider.getSerializationPolicy()");
       }
     }
   }
@@ -646,12 +651,8 @@
       throws SerializationException {
     String clientTypeSignature = serializedInstRef.getSignature();
     if (clientTypeSignature.length() == 0) {
-      if (shouldEnforceTypeVersioning()) {
-        throw new SerializationException("Missing type signature for "
-            + instanceClass.getName());
-      }
-
-      return;
+      throw new SerializationException("Missing type signature for "
+          + instanceClass.getName());
     }
 
     String serverTypeSignature = SerializabilityUtil.getSerializationSignature(instanceClass);
diff --git a/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamWriter.java b/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamWriter.java
index 474dd3b..f355f3c 100644
--- a/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamWriter.java
+++ b/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamWriter.java
@@ -568,11 +568,7 @@
     assert (instance != null);
 
     Class<?> clazz = getClassForSerialization(instance);
-    if (shouldEnforceTypeVersioning()) {
-      return SerializabilityUtil.encodeSerializedInstanceReference(clazz);
-    } else {
-      return SerializabilityUtil.getSerializedTypeName(clazz);
-    }
+    return SerializabilityUtil.encodeSerializedInstanceReference(clazz);
   }
 
   @Override
diff --git a/user/test/com/google/gwt/user/server/rpc/RPCTest.java b/user/test/com/google/gwt/user/server/rpc/RPCTest.java
index ab9b7ec..8eb1bb3 100644
--- a/user/test/com/google/gwt/user/server/rpc/RPCTest.java
+++ b/user/test/com/google/gwt/user/server/rpc/RPCTest.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
@@ -41,7 +41,7 @@
     void method1();
   }
 
-  private final String VALID_ENCODED_REQUEST = "3\uffff" + // version
+  private static final String VALID_ENCODED_REQUEST = "4\uffff" + // version
       "0\uffff" + // flags
       "4\uffff" + // string table entry count
       A.class.getName() + "\uffff" + // string table entry #0
@@ -54,7 +54,7 @@
       "2\uffff" + // method name
       "0\uffff"; // param count
 
-  private final String INVALID_METHOD_REQUEST = "3\uffff" + // version
+  private static final String INVALID_METHOD_REQUEST = "4\uffff" + // version
       "0\uffff" + // flags
       "4\uffff" + // string table entry count
       A.class.getName() + "\uffff" + // string table entry #0
@@ -67,7 +67,7 @@
       "2\uffff" + // method name
       "0\uffff"; // param count
 
-  private final String INVALID_INTERFACE_REQUEST = "3\uffff" + // version
+  private static final String INVALID_INTERFACE_REQUEST = "4\uffff" + // version
       "0\uffff" + // flags
       "4\uffff" + // string table entry count
       B.class.getName() + "\uffff" + // string table entry #0
@@ -80,7 +80,7 @@
       "2\uffff" + // method name
       "0\uffff"; // param count
 
-  private final String VALID_PRE_RPC_RESOURCE_ENCODED_REQUEST = "2\uffff" + // version
+  private static final String VALID_V2_ENCODED_REQUEST = "2\uffff" + // version
       "0\uffff" + // flags
       "2\uffff" + // string table entry count
       A.class.getName() + "\uffff" + // string table entry #0
@@ -89,6 +89,39 @@
       "2\uffff" + // method name
       "0\uffff"; // param count
 
+  private static final String VALID_V3_ENCODED_REQUEST = "3\uffff" + // version
+      "0\uffff" + // flags
+      "4\uffff" + // string table entry count
+      A.class.getName() + "\uffff" + // string table entry #0
+      "method2" + "\uffff" + // string table entry #1
+      "moduleBaseURL" + "\uffff" + // string table entry #2
+      "whitelistHashcode" + "\uffff" + // string table entry #4
+      "3\uffff" + // module base URL
+      "4\uffff" + // whitelist hashcode
+      "1\uffff" + // interface name
+      "2\uffff" + // method name
+      "0\uffff"; // param count
+
+  /**
+   * Tests that seeing obsolete RPC formats throws an
+   * {@link IncompatibleRemoteServiceException}.
+   */
+  public void testDecodeObsoleteFormats() {
+    try {
+      RPC.decodeRequest(VALID_V2_ENCODED_REQUEST, A.class, null);
+      fail("Should have thrown an IncompatibleRemoteServiceException");
+    } catch (IncompatibleRemoteServiceException e) {
+      // Expected
+    }
+
+    try {
+      RPC.decodeRequest(VALID_V3_ENCODED_REQUEST, A.class, null);
+      fail("Should have thrown an IncompatibleRemoteServiceException");
+    } catch (IncompatibleRemoteServiceException e) {
+      // Expected
+    }
+  }
+
   /**
    * Tests for method {@link RPC#decodeRequest(String)}
    * 
@@ -184,20 +217,6 @@
   }
 
   /**
-   * Tests that method
-   * {@link RPC#decodeRequest(String, Class, SerializationPolicyProvider)} can
-   * handle the decoding of requests from pre-RPC resource (whitelist) clients.
-   * 
-   * @throws SerializationException
-   */
-  public void testDecodeRequestPreRPCResourceFile() {
-    RPCRequest rpcRequest = RPC.decodeRequest(
-        VALID_PRE_RPC_RESOURCE_ENCODED_REQUEST, A.class, null);
-    SerializationPolicy serializationPolicy = rpcRequest.getSerializationPolicy();
-    assertEquals(RPC.getDefaultSerializationPolicy(), serializationPolicy);
-  }
-
-  /**
    * Tests for method {@link RPC#encodeResponseForFailure(Method, Throwable)}.
    * 
    * Cases: