From e2990637d5b7602f8ee9a6f503c5c17b20e896f8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Wed, 30 May 2012 17:35:22 +0300 Subject: [PATCH] Drop explicit type info from client -> server communication (#8879) --- .../gwt/client/communication/JsonEncoder.java | 54 ++++++--------- .../server/AbstractCommunicationManager.java | 11 ++- .../vaadin/terminal/gwt/server/JsonCodec.java | 68 +++++++------------ 3 files changed, 47 insertions(+), 86 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index 20ed319253..541dc631c6 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -46,12 +46,6 @@ public class JsonEncoder { public static final String VTYPE_SET = "q"; public static final String VTYPE_NULL = "n"; - /** - * Temporary hack to get variable changes decoded as internal types in - * JsonCodec. - */ - public static final String VTYPE_UIDL_VALUE = "v"; - /** * Encode a value to a JSON representation for transport from the client to * the server. @@ -67,20 +61,18 @@ public class JsonEncoder { boolean restrictToInternalTypes, ConnectorMap connectorMap, ApplicationConnection connection) { if (null == value) { - return combineTypeAndValue(VTYPE_NULL, JSONNull.getInstance()); + return JSONNull.getInstance(); } else if (value instanceof String[]) { String[] array = (String[]) value; JSONArray jsonArray = new JSONArray(); for (int i = 0; i < array.length; ++i) { jsonArray.set(i, new JSONString(array[i])); } - return combineTypeAndValue(VTYPE_STRINGARRAY, jsonArray); + return jsonArray; } else if (value instanceof String) { - return combineTypeAndValue(VTYPE_STRING, new JSONString( - (String) value)); + return new JSONString((String) value); } else if (value instanceof Boolean) { - return combineTypeAndValue(VTYPE_BOOLEAN, - JSONBoolean.getInstance((Boolean) value)); + return JSONBoolean.getInstance((Boolean) value); } else if (value instanceof Object[]) { return encodeObjectArray((Object[]) value, restrictToInternalTypes, connectorMap, connection); @@ -99,8 +91,7 @@ public class JsonEncoder { connectorMap, connection); } else if (value instanceof Connector) { Connector connector = (Connector) value; - return combineTypeAndValue(VTYPE_CONNECTOR, new JSONString( - connector.getConnectorId())); + return new JSONString(connector.getConnectorId()); } else if (value instanceof Collection) { return encodeCollection((Collection) value, restrictToInternalTypes, connectorMap, connection); @@ -110,8 +101,7 @@ public class JsonEncoder { } else { String transportType = getTransportType(value); if (transportType != null) { - return combineTypeAndValue(transportType, - new JSONString(String.valueOf(value))); + return new JSONString(String.valueOf(value)); } else { // Try to find a generated serializer object, class name is the // type @@ -120,18 +110,20 @@ public class JsonEncoder { .getSerializer(transportType); // TODO handle case with no serializer found - return combineTypeAndValue(transportType, - serializer.serialize(value, connectorMap, connection)); + return serializer.serialize(value, connectorMap, connection); } } } - private static JSONValue encodeVariableChange(UidlValue value, + private static JSONValue encodeVariableChange(UidlValue uidlValue, ConnectorMap connectorMap, ApplicationConnection connection) { - JSONArray encodedValue = encode(value.getValue(), true, connectorMap, - connection).isArray(); + Object value = uidlValue.getValue(); - return combineTypeAndValue(VTYPE_UIDL_VALUE, encodedValue); + JSONArray jsonArray = new JSONArray(); + jsonArray.set(0, new JSONString(getTransportType(value))); + jsonArray.set(1, encode(value, true, connectorMap, connection)); + + return jsonArray; } private static JSONValue encodeMap(Map map, @@ -155,13 +147,12 @@ public class JsonEncoder { connectorMap, connection); jsonMap.put(encodedKey.toString(), encodedValue); } - return combineTypeAndValue(VTYPE_MAP, jsonMap); + return jsonMap; } private static JSONValue encodeEnum(Enum e, ConnectorMap connectorMap, ApplicationConnection connection) { - return combineTypeAndValue(e.getClass().getName(), - new JSONString(e.toString())); + return new JSONString(e.toString()); } private static JSONValue encodeObjectArray(Object[] array, @@ -179,7 +170,7 @@ public class JsonEncoder { encode(value, restrictToInternalTypes, connectorMap, connection)); } - return combineTypeAndValue(VTYPE_ARRAY, jsonArray); + return jsonArray; } private static JSONValue encodeCollection(Collection collection, @@ -193,9 +184,9 @@ public class JsonEncoder { jsonArray.set(idx++, encodedObject); } if (collection instanceof Set) { - return combineTypeAndValue(VTYPE_SET, jsonArray); + return jsonArray; } else if (collection instanceof List) { - return combineTypeAndValue(VTYPE_LIST, jsonArray); + return jsonArray; } else { throw new RuntimeException("Unsupport collection type: " + collection.getClass().getName()); @@ -203,13 +194,6 @@ public class JsonEncoder { } - private static JSONValue combineTypeAndValue(String type, JSONValue value) { - JSONArray outerArray = new JSONArray(); - outerArray.set(0, new JSONString(type)); - outerArray.set(1, value); - return outerArray; - } - /** * Returns the transport type for the given value. Only returns a transport * type for internally handled values. diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index 11e86b99fc..b32525a703 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -1628,12 +1628,9 @@ public abstract class AbstractCommunicationManager implements Serializable { "Invalid parameters in legacy change variables call. Expected 2, was " + parametersJson.length()); } - String variableName = (String) JsonCodec - .decodeInternalType(String.class, true, - parametersJson.getJSONArray(0), application); + String variableName = parametersJson.getString(0); UidlValue uidlValue = (UidlValue) JsonCodec.decodeInternalType( - UidlValue.class, true, parametersJson.getJSONArray(1), - application); + UidlValue.class, true, parametersJson.get(1), application); Object value = uidlValue.getValue(); @@ -1658,10 +1655,10 @@ public abstract class AbstractCommunicationManager implements Serializable { .getGenericParameterTypes(); for (int j = 0; j < parametersJson.length(); ++j) { - JSONArray parameterJson = parametersJson.getJSONArray(j); + Object parameterValue = parametersJson.get(j); Type parameterType = declaredRpcMethodParameterTypes[j]; parameters[j] = JsonCodec.decodeInternalOrCustomType(parameterType, - parameterJson, application); + parameterValue, application); } invocation.setParameters(parameters); return invocation; diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index a7515c7135..b853c90a3b 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -13,7 +13,6 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -26,6 +25,7 @@ import com.vaadin.Application; import com.vaadin.external.json.JSONArray; import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; +import com.vaadin.external.json.JSONTokener; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.communication.JsonEncoder; import com.vaadin.terminal.gwt.client.communication.UidlValue; @@ -66,7 +66,6 @@ public class JsonCodec implements Serializable { registerType(HashMap.class, JsonEncoder.VTYPE_MAP); registerType(List.class, JsonEncoder.VTYPE_LIST); registerType(Set.class, JsonEncoder.VTYPE_SET); - registerType(UidlValue.class, JsonEncoder.VTYPE_UIDL_VALUE); } private static void registerType(Class type, String transportType) { @@ -84,6 +83,10 @@ public class JsonCodec implements Serializable { if (type instanceof Class && ((Class) type).isPrimitive()) { // All primitive types are handled internally return true; + } else if (type == UidlValue.class) { + // UidlValue is a special internal type wrapping type info and a + // value + return true; } return typeToTransportType.containsKey(getClassForType(type)); } @@ -101,32 +104,22 @@ public class JsonCodec implements Serializable { } public static Object decodeInternalOrCustomType(Type targetType, - JSONArray valueAndType, Application application) - throws JSONException { + Object value, Application application) throws JSONException { if (isInternalType(targetType)) { - return decodeInternalType(targetType, false, valueAndType, - application); + return decodeInternalType(targetType, false, value, application); } else { - return decodeCustomType(targetType, valueAndType, application); + return decodeCustomType(targetType, value, application); } } - public static Object decodeCustomType(Type targetType, - JSONArray valueAndType, Application application) - throws JSONException { + public static Object decodeCustomType(Type targetType, Object value, + Application application) throws JSONException { if (isInternalType(targetType)) { throw new JSONException("decodeCustomType cannot be used for " + targetType + ", which is an internal type"); } - String transportType = getCustomTransportType(getClassForType(targetType)); - String encodedTransportType = valueAndType.getString(0); - if (!transportTypesCompatible(encodedTransportType, transportType)) { - throw new JSONException("Expected a value of type " + transportType - + ", received " + encodedTransportType); - } // Try to decode object using fields - Object value = valueAndType.get(1); if (value == JSONObject.NULL) { return null; } else { @@ -159,29 +152,21 @@ public class JsonCodec implements Serializable { * @throws JSONException */ public static Object decodeInternalType(Type targetType, - boolean restrictToInternalTypes, JSONArray valueAndType, + boolean restrictToInternalTypes, Object encodedJsonValue, Application application) throws JSONException { - String encodedTransportType = valueAndType.getString(0); if (!isInternalType(targetType)) { throw new JSONException("Type " + targetType + " is not a supported internal type."); } String transportType = getInternalTransportType(targetType); - if (!transportTypesCompatible(encodedTransportType, transportType)) { - throw new JSONException("Expected a value of type " + targetType - + ", received " + getType(encodedTransportType)); - } - - Object encodedJsonValue = valueAndType.get(1); - if (JsonEncoder.VTYPE_NULL.equals(encodedTransportType)) { + if (encodedJsonValue == JSONObject.NULL) { return null; } - // VariableChange - if (JsonEncoder.VTYPE_UIDL_VALUE.contentEquals(transportType)) { - return decodeVariableChange((JSONArray) encodedJsonValue, - application); + // UidlValue + if (targetType == UidlValue.class) { + return decodeUidlValue((JSONArray) encodedJsonValue, application); } // Collections @@ -233,14 +218,12 @@ public class JsonCodec implements Serializable { throw new JSONException("Unknown type " + transportType); } - private static UidlValue decodeVariableChange(JSONArray encodedJsonValue, + private static UidlValue decodeUidlValue(JSONArray encodedJsonValue, Application application) throws JSONException { String type = encodedJsonValue.getString(0); - JSONArray valueAndType = new JSONArray(Arrays.asList(type, - encodedJsonValue.get(1))); Object decodedValue = decodeInternalType(getType(type), true, - valueAndType, application); + encodedJsonValue.get(1), application); return new UidlValue(decodedValue); } @@ -267,8 +250,8 @@ public class JsonCodec implements Serializable { Iterator it = jsonMap.keys(); while (it.hasNext()) { String key = it.next(); - JSONArray encodedKey = new JSONArray(key); - JSONArray encodedValue = jsonMap.getJSONArray(key); + Object encodedKey = new JSONTokener(key).nextValue(); + Object encodedValue = jsonMap.get(key); Object decodedKey = decodeParametrizedType(targetType, restrictToInternalTypes, 0, encodedKey, application); @@ -291,20 +274,18 @@ public class JsonCodec implements Serializable { * @throws JSONException */ private static Object decodeParametrizedType(Type targetType, - boolean restrictToInternalTypes, int typeIndex, - JSONArray encodedValueAndType, Application application) - throws JSONException { + boolean restrictToInternalTypes, int typeIndex, Object value, + Application application) throws JSONException { if (!restrictToInternalTypes && targetType instanceof ParameterizedType) { Type childType = ((ParameterizedType) targetType) .getActualTypeArguments()[typeIndex]; // Only decode the given type - return decodeInternalOrCustomType(childType, encodedValueAndType, - application); + return decodeInternalOrCustomType(childType, value, application); } else { // Only UidlValue when not enforcing a given type to avoid security // issues UidlValue decodeInternalType = (UidlValue) decodeInternalType( - UidlValue.class, true, encodedValueAndType, application); + UidlValue.class, true, value, application); return decodeInternalType.getValue(); } } @@ -391,8 +372,7 @@ public class JsonCodec implements Serializable { if (fieldName == null) { continue; } - JSONArray encodedFieldValue = serializedObject - .getJSONArray(fieldName); + Object encodedFieldValue = serializedObject.get(fieldName); Type fieldType = pd.getReadMethod().getGenericReturnType(); Object decodedFieldValue = decodeInternalOrCustomType( fieldType, encodedFieldValue, application); -- 2.39.5