Allow RPC to support DTOs with non-public no-arg constructors.

Patch by: bobv
Review by: mmendez


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1703 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/rebind/rpc/CustomFieldSerializerValidator.java b/user/src/com/google/gwt/user/rebind/rpc/CustomFieldSerializerValidator.java
index 63c2c62..e01c7ed 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/CustomFieldSerializerValidator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/CustomFieldSerializerValidator.java
@@ -78,7 +78,7 @@
           serializee.getQualifiedSourceName()));
     }
 
-    if (!Shared.isDefaultInstantiable(serializee)) {
+    if (!serializee.isDefaultInstantiable() && !serializee.isAbstract()) {
       if (!hasInstantiationMethod(streamReaderClass, serializer, serializee)) {
         // Not default instantiable and no instantiate method was found.
         reasons.add(MessageFormat.format(NO_INSTANTIATE_METHOD,
diff --git a/user/src/com/google/gwt/user/rebind/rpc/FieldSerializerCreator.java b/user/src/com/google/gwt/user/rebind/rpc/FieldSerializerCreator.java
index fbe7c2f..222237b 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/FieldSerializerCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/FieldSerializerCreator.java
@@ -385,33 +385,35 @@
        */
       return;
     }
+    JArrayType isArray = serializableClass.isArray();
+    JEnumType isEnum = serializableClass.isEnum();
+    boolean isNative = (isArray == null) && (isEnum == null);
 
-    sourceWriter.print("public static ");
+    sourceWriter.print("public static" + (isNative ? " native " : " "));
     String qualifiedSourceName = serializableClass.getQualifiedSourceName();
     sourceWriter.print(qualifiedSourceName);
     sourceWriter.print(" instantiate(");
     sourceWriter.print(SerializationStreamReader.class.getName());
     sourceWriter.println(" streamReader) throws "
-        + SerializationException.class.getName() + "{");
+        + SerializationException.class.getName() + (isNative ? "/*-{" : "{"));
     sourceWriter.indent();
 
-    JArrayType isArray = serializableClass.isArray();
     if (isArray != null) {
       sourceWriter.println("int rank = streamReader.readInt();");
       sourceWriter.println("return "
           + createArrayInstantiationExpression(isArray) + ";");
-    } else if (serializableClass.isEnum() != null) {
+    } else if (isEnum != null) {
       sourceWriter.println("int ordinal = streamReader.readInt();");
       sourceWriter.println(qualifiedSourceName + "[] values = "
           + qualifiedSourceName + ".values();");
       sourceWriter.println("assert (ordinal >= 0 && ordinal < values.length);");
       sourceWriter.println("return values[ordinal];");
     } else {
-      sourceWriter.println("return new " + qualifiedSourceName + "();");
+      sourceWriter.println("return @" + qualifiedSourceName + "::new()();");
     }
 
     sourceWriter.outdent();
-    sourceWriter.println("}");
+    sourceWriter.println(isNative ? "}-*/;" : "}");
     sourceWriter.println();
   }
 
diff --git a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java
index f874f77..a87b145 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.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
@@ -828,11 +828,11 @@
         return false;
       }
 
-      if (!Shared.isDefaultInstantiable(type)) {
+      if (!type.isDefaultInstantiable()) {
         // Warn and return false.
         logger.log(
             TreeLogger.WARN,
-            "Was not default instantiable (it must have a zero-argument, non-private constructor or no constructors at all)",
+            "Was not default instantiable (it must have a zero-argument constructor or no constructors at all)",
             null);
         return false;
       }
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 c263436..0154fbb 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/Shared.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/Shared.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
@@ -20,7 +20,6 @@
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.typeinfo.JArrayType;
 import com.google.gwt.core.ext.typeinfo.JClassType;
-import com.google.gwt.core.ext.typeinfo.JConstructor;
 import com.google.gwt.core.ext.typeinfo.JParameterizedType;
 import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
 import com.google.gwt.core.ext.typeinfo.JType;
@@ -54,33 +53,6 @@
   }
 
   /**
-   * Returns <code>true</code> if the type is a non-abstract class that either
-   * has no constructors or it has a non-private, no argument constructor.
-   * 
-   * @param type
-   * @return <code>true</code> if the type is a non-abstract class that either
-   *         has no constructors or it has a non-private, no argument
-   *         constructor
-   */
-  static boolean isDefaultInstantiable(JClassType type) {
-    if (type.isInterface() != null || type.isAbstract()) {
-      return false;
-    }
-
-    boolean isDefaultInstantiable = false;
-    if (type.getConstructors().length == 0) {
-      isDefaultInstantiable = true;
-    } else {
-      JConstructor ctor = type.findConstructor(new JType[0]);
-      if (ctor != null && !ctor.isPrivate()) {
-        isDefaultInstantiable = true;
-      }
-    }
-
-    return isDefaultInstantiable;
-  }
-
-  /**
    * Returns <code>true</code> if the generated code should enforce type
    * versioning.
    */
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 0fa0d59..c1c0a1f 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.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
@@ -338,17 +338,17 @@
        * Only classes with custom field serializers that do no declare
        * instantiate methods get here
        */
-      srcWriter.print("private static ");
+      srcWriter.print("private static native ");
       srcWriter.print(type.getQualifiedSourceName());
       srcWriter.print(" ");
       srcWriter.print(getCreateMethodName(type));
-      srcWriter.println("(SerializationStreamReader streamReader) throws SerializationException {");
+      srcWriter.println("(SerializationStreamReader streamReader) throws SerializationException /*-{");
       srcWriter.indent();
-      srcWriter.print("return new ");
+      srcWriter.print("return @");
       srcWriter.print(type.getQualifiedSourceName());
-      srcWriter.println("();");
+      srcWriter.println("::new()();");
       srcWriter.outdent();
-      srcWriter.println("}");
+      srcWriter.println("}-*/;");
       srcWriter.println();
     }
   }
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 2f56dc7..b71323d 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
@@ -23,6 +23,7 @@
 import com.google.gwt.user.server.rpc.SerializationPolicyProvider;
 
 import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -499,7 +500,8 @@
 
   private Object instantiate(Class<?> customSerializer, Class<?> instanceClass)
       throws InstantiationException, IllegalAccessException,
-      IllegalArgumentException, InvocationTargetException {
+      IllegalArgumentException, InvocationTargetException,
+      NoSuchMethodException {
     if (customSerializer != null) {
       try {
         Method instantiate = customSerializer.getMethod("instantiate",
@@ -520,7 +522,9 @@
       assert (ordinal >= 0 && ordinal < enumConstants.length);
       return enumConstants[ordinal];
     } else {
-      return instanceClass.newInstance();
+      Constructor<?> constructor = instanceClass.getDeclaredConstructor();
+      constructor.setAccessible(true);
+      return constructor.newInstance();
     }
   }
 
diff --git a/user/test/com/google/gwt/user/client/rpc/ObjectGraphTest.java b/user/test/com/google/gwt/user/client/rpc/ObjectGraphTest.java
index e351c71..3bf3757 100644
--- a/user/test/com/google/gwt/user/client/rpc/ObjectGraphTest.java
+++ b/user/test/com/google/gwt/user/client/rpc/ObjectGraphTest.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
@@ -18,6 +18,7 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializableDoublyLinkedNode;
+import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg;
 
 /**
  * TODO: document me.
@@ -82,6 +83,24 @@
       }
     });
   }
+  
+  public void testPrivateNoArg() {
+    delayTestFinish(TEST_DELAY);
+
+    ObjectGraphTestServiceAsync service = getServiceAsync();
+    final SerializablePrivateNoArg node = TestSetFactory.createPrivateNoArg();
+    service.echo_PrivateNoArg(node, new AsyncCallback() {
+      public void onFailure(Throwable caught) {
+        TestSetValidator.rethrowException(caught);
+      }
+
+      public void onSuccess(Object result) {
+        assertNotNull(result);
+        assertTrue(TestSetValidator.isValid((SerializablePrivateNoArg) result));
+        finishTest();
+      }
+    });
+  }
 
   public void testTrivialCyclicGraph() {
     delayTestFinish(TEST_DELAY);
diff --git a/user/test/com/google/gwt/user/client/rpc/ObjectGraphTestService.java b/user/test/com/google/gwt/user/client/rpc/ObjectGraphTestService.java
index a956168..abaa9f2 100644
--- a/user/test/com/google/gwt/user/client/rpc/ObjectGraphTestService.java
+++ b/user/test/com/google/gwt/user/client/rpc/ObjectGraphTestService.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
@@ -16,6 +16,7 @@
 package com.google.gwt.user.client.rpc;
 
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializableDoublyLinkedNode;
+import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg;
 
 /**
  * TODO: document me.
@@ -31,6 +32,8 @@
   SerializableDoublyLinkedNode echo_ComplexCyclicGraph(
       SerializableDoublyLinkedNode node1, SerializableDoublyLinkedNode node2);
 
+  SerializablePrivateNoArg echo_PrivateNoArg(SerializablePrivateNoArg node);
+
   SerializableDoublyLinkedNode echo_TrivialCyclicGraph(
       SerializableDoublyLinkedNode node);
 }
diff --git a/user/test/com/google/gwt/user/client/rpc/ObjectGraphTestServiceAsync.java b/user/test/com/google/gwt/user/client/rpc/ObjectGraphTestServiceAsync.java
index db964fe..68ff8be 100644
--- a/user/test/com/google/gwt/user/client/rpc/ObjectGraphTestServiceAsync.java
+++ b/user/test/com/google/gwt/user/client/rpc/ObjectGraphTestServiceAsync.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
@@ -16,6 +16,7 @@
 package com.google.gwt.user.client.rpc;
 
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializableDoublyLinkedNode;
+import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg;
 
 /**
  * TODO: document me.
@@ -30,6 +31,8 @@
   void echo_ComplexCyclicGraph(SerializableDoublyLinkedNode node1,
       SerializableDoublyLinkedNode node2, AsyncCallback callback);
 
+  void echo_PrivateNoArg(SerializablePrivateNoArg node, AsyncCallback callback);
+
   void echo_TrivialCyclicGraph(SerializableDoublyLinkedNode node,
       AsyncCallback callback);
 }
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java b/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
index 2ab7811..693bfdc 100644
--- a/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
+++ b/user/test/com/google/gwt/user/client/rpc/TestSetFactory.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
@@ -167,6 +167,24 @@
   }
 
   /**
+   * Tests that classes with a private no-arg constructor can be serialized.
+   */
+  public static class SerializablePrivateNoArg implements IsSerializable {
+    private int value;
+
+    private SerializablePrivateNoArg() {
+    }
+
+    public SerializablePrivateNoArg(int value) {
+      this.value = value;
+    }
+
+    public int getValue() {
+      return value;
+    }
+  }
+
+  /**
    * TODO: document me.
    */
   public static class SerializableSet extends HashSet implements IsSerializable {
@@ -293,6 +311,10 @@
     return new short[] {
         Short.MAX_VALUE, Short.MIN_VALUE, Short.MAX_VALUE, Short.MIN_VALUE};
   }
+  
+  public static SerializablePrivateNoArg createPrivateNoArg() {
+    return new SerializablePrivateNoArg(1);
+  }
 
   public static Short[] createShortArray() {
     return new Short[] {
@@ -305,8 +327,9 @@
    * to make sure they are handled properly.
    */
   public static String[] createStringArray() {
-    return new String[] {null, "", "one", "two", "toString", "watch",
-        "prototype", "eval", "valueOf", "constructor", "__proto__" };
+    return new String[] {
+        null, "", "one", "two", "toString", "watch", "prototype", "eval",
+        "valueOf", "constructor", "__proto__"};
   }
 
   public static Vector createVector() {
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
index 0bb64d1..010ef97 100644
--- a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
+++ b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.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
@@ -17,6 +17,7 @@
 
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializableClass;
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializableDoublyLinkedNode;
+import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -296,6 +297,14 @@
     return true;
   }
 
+  public static boolean isValid(SerializablePrivateNoArg actual) {
+    if (actual == null) {
+      return false;
+    }
+
+    return actual.getValue() == 1;
+  }
+
   public static boolean isValid(Vector expected, Vector actual) {
     if (actual == null) {
       return false;
diff --git a/user/test/com/google/gwt/user/server/rpc/ObjectGraphTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/ObjectGraphTestServiceImpl.java
index b293bf1..5bcab6d 100644
--- a/user/test/com/google/gwt/user/server/rpc/ObjectGraphTestServiceImpl.java
+++ b/user/test/com/google/gwt/user/server/rpc/ObjectGraphTestServiceImpl.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
@@ -18,6 +18,7 @@
 import com.google.gwt.user.client.rpc.ObjectGraphTestService;
 import com.google.gwt.user.client.rpc.TestSetValidator;
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializableDoublyLinkedNode;
+import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg;
 
 /**
  * TODO: document me.
@@ -52,6 +53,15 @@
     return root;
   }
 
+  public SerializablePrivateNoArg echo_PrivateNoArg(
+      SerializablePrivateNoArg node) {
+    if (!TestSetValidator.isValid(node)) {
+      throw new RuntimeException();
+    }
+
+    return node;
+  }
+
   public SerializableDoublyLinkedNode echo_ComplexCyclicGraph(
       SerializableDoublyLinkedNode node1, SerializableDoublyLinkedNode node2) {
     if (node1 != node2) {