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.
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);
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);
} 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
.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<Object, Object> map,
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,
encode(value, restrictToInternalTypes, connectorMap,
connection));
}
- return combineTypeAndValue(VTYPE_ARRAY, jsonArray);
+ return jsonArray;
}
private static JSONValue encodeCollection(Collection collection,
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());
}
- 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.
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;
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;
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) {
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));
}
}
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 {
* @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
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);
}
Iterator<String> 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);
* @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();
}
}
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);