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) {