From 6035b204dcf958ef045a927fd6d14508960cedbd Mon Sep 17 00:00:00 2001 From: Brettflan Date: Wed, 22 Jun 2011 18:40:56 -0500 Subject: [PATCH] updating built-in GSON to 1.7.1 release --- ...onymousAndLocalClassExclusionStrategy.java | 1 - .../factions/gson/BaseMapTypeAdapter.java | 44 ++ src/org/mcteam/factions/gson/Cache.java | 16 +- .../gson/CamelCaseSeparatorNamingPolicy.java | 6 +- .../gson/DefaultConstructorAllocator.java | 91 +++ .../factions/gson/DefaultTypeAdapters.java | 513 ++++++++++----- .../gson/DelegatingJsonElementVisitor.java | 21 +- .../gson/DisjunctionExclusionStrategy.java | 7 +- src/org/mcteam/factions/gson/Escaper.java | 16 +- .../factions/gson/ExclusionStrategy.java | 14 + ...ationDeserializationExclusionStrategy.java | 5 +- ...otationSerializationExclusionStrategy.java | 4 +- .../mcteam/factions/gson/FieldAttributes.java | 44 +- .../factions/gson/FieldNamingStrategy2.java | 1 - .../gson/FieldNamingStrategy2Adapter.java | 16 +- .../factions/gson/GenericArrayTypeImpl.java | 70 --- src/org/mcteam/factions/gson/Gson.java | 84 +-- src/org/mcteam/factions/gson/GsonBuilder.java | 232 +++++-- .../gson/InnerClassExclusionStrategy.java | 2 +- src/org/mcteam/factions/gson/JsonArray.java | 10 + .../gson/JsonArrayDeserializationVisitor.java | 33 +- .../JsonDeserializationContextDefault.java | 27 +- .../gson/JsonDeserializationVisitor.java | 27 +- .../JsonDeserializerExceptionWrapper.java | 11 +- .../factions/gson/JsonFieldNameValidator.java | 56 -- src/org/mcteam/factions/gson/JsonNull.java | 2 +- src/org/mcteam/factions/gson/JsonObject.java | 16 +- .../JsonObjectDeserializationVisitor.java | 23 +- src/org/mcteam/factions/gson/JsonParser.java | 7 +- .../mcteam/factions/gson/JsonPrimitive.java | 27 +- .../gson/JsonSerializationContextDefault.java | 24 +- .../gson/JsonSerializationVisitor.java | 44 +- .../factions/gson/JsonStreamParser.java | 1 - src/org/mcteam/factions/gson/LruCache.java | 21 +- .../factions/gson/MapAsArrayTypeAdapter.java | 16 +- .../mcteam/factions/gson/MapTypeAdapter.java | 78 +++ .../gson/MappedObjectConstructor.java | 71 +-- .../mcteam/factions/gson/MemoryRefStack.java | 5 +- .../gson/ModifyFirstLetterNamingPolicy.java | 11 +- .../factions/gson/NullExclusionStrategy.java | 1 - .../mcteam/factions/gson/ObjectNavigator.java | 74 +-- .../factions/gson/ObjectNavigatorFactory.java | 61 -- .../mcteam/factions/gson/ObjectTypePair.java | 16 +- src/org/mcteam/factions/gson/Pair.java | 7 +- .../gson/ParameterizedTypeHandlerMap.java | 35 +- .../factions/gson/ParameterizedTypeImpl.java | 91 --- src/org/mcteam/factions/gson/Primitives.java | 37 +- .../gson/RecursiveFieldNamingPolicy.java | 1 - .../gson/ReflectingFieldNavigator.java | 106 ++++ ...ameAnnotationInterceptingNamingPolicy.java | 22 +- src/org/mcteam/factions/gson/Streams.java | 7 +- .../gson/SyntheticFieldExclusionStrategy.java | 2 +- src/org/mcteam/factions/gson/TypeAdapter.java | 35 -- src/org/mcteam/factions/gson/TypeInfo.java | 76 --- .../mcteam/factions/gson/TypeInfoArray.java | 69 -- .../factions/gson/TypeInfoCollection.java | 46 -- .../mcteam/factions/gson/TypeInfoFactory.java | 175 ------ src/org/mcteam/factions/gson/TypeInfoMap.java | 58 -- src/org/mcteam/factions/gson/TypeUtils.java | 95 --- .../mcteam/factions/gson/UnsafeAllocator.java | 104 ++++ .../gson/VersionExclusionStrategy.java | 5 +- .../$Gson$Preconditions.java} | 17 +- .../factions/gson/internal/$Gson$Types.java | 589 ++++++++++++++++++ .../factions/gson/internal/package-info.java | 7 + .../mcteam/factions/gson/package-info.java | 6 +- .../factions/gson/reflect/TypeToken.java | 227 +++---- .../factions/gson/stream/JsonReader.java | 3 +- 67 files changed, 2044 insertions(+), 1625 deletions(-) create mode 100644 src/org/mcteam/factions/gson/BaseMapTypeAdapter.java create mode 100644 src/org/mcteam/factions/gson/DefaultConstructorAllocator.java delete mode 100644 src/org/mcteam/factions/gson/GenericArrayTypeImpl.java delete mode 100644 src/org/mcteam/factions/gson/JsonFieldNameValidator.java create mode 100644 src/org/mcteam/factions/gson/MapTypeAdapter.java delete mode 100644 src/org/mcteam/factions/gson/ObjectNavigatorFactory.java delete mode 100644 src/org/mcteam/factions/gson/ParameterizedTypeImpl.java create mode 100644 src/org/mcteam/factions/gson/ReflectingFieldNavigator.java delete mode 100644 src/org/mcteam/factions/gson/TypeAdapter.java delete mode 100644 src/org/mcteam/factions/gson/TypeInfo.java delete mode 100644 src/org/mcteam/factions/gson/TypeInfoArray.java delete mode 100644 src/org/mcteam/factions/gson/TypeInfoCollection.java delete mode 100644 src/org/mcteam/factions/gson/TypeInfoFactory.java delete mode 100644 src/org/mcteam/factions/gson/TypeInfoMap.java delete mode 100644 src/org/mcteam/factions/gson/TypeUtils.java create mode 100644 src/org/mcteam/factions/gson/UnsafeAllocator.java rename src/org/mcteam/factions/gson/{Preconditions.java => internal/$Gson$Preconditions.java} (77%) create mode 100644 src/org/mcteam/factions/gson/internal/$Gson$Types.java create mode 100644 src/org/mcteam/factions/gson/internal/package-info.java diff --git a/src/org/mcteam/factions/gson/AnonymousAndLocalClassExclusionStrategy.java b/src/org/mcteam/factions/gson/AnonymousAndLocalClassExclusionStrategy.java index 2d4cd23a..77817e52 100644 --- a/src/org/mcteam/factions/gson/AnonymousAndLocalClassExclusionStrategy.java +++ b/src/org/mcteam/factions/gson/AnonymousAndLocalClassExclusionStrategy.java @@ -16,7 +16,6 @@ package org.mcteam.factions.gson; - /** * Strategy for excluding anonymous and local classes. * diff --git a/src/org/mcteam/factions/gson/BaseMapTypeAdapter.java b/src/org/mcteam/factions/gson/BaseMapTypeAdapter.java new file mode 100644 index 00000000..bf0480fc --- /dev/null +++ b/src/org/mcteam/factions/gson/BaseMapTypeAdapter.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011 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 the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mcteam.factions.gson; + +import java.lang.reflect.Type; +import java.util.Map; + +/** + * Captures all the common/shared logic between the old, ({@link MapTypeAdapter}, and + * the new, {@link MapAsArrayTypeAdapter}, map type adapters. + * + * @author Joel Leitch + */ +abstract class BaseMapTypeAdapter + implements JsonSerializer>, JsonDeserializer> { + + protected static final JsonElement serialize(JsonSerializationContext context, + Object src, Type srcType) { + JsonSerializationContextDefault contextImpl = (JsonSerializationContextDefault) context; + return contextImpl.serialize(src, srcType, false); + } + + @SuppressWarnings("unchecked") + protected static final Map constructMapType( + Type mapType, JsonDeserializationContext context) { + JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context; + ObjectConstructor objectConstructor = contextImpl.getObjectConstructor(); + return (Map) objectConstructor.construct(mapType); + } +} \ No newline at end of file diff --git a/src/org/mcteam/factions/gson/Cache.java b/src/org/mcteam/factions/gson/Cache.java index 278bdd01..9100abd3 100644 --- a/src/org/mcteam/factions/gson/Cache.java +++ b/src/org/mcteam/factions/gson/Cache.java @@ -18,7 +18,7 @@ package org.mcteam.factions.gson; /** * Defines generic cache interface. - * + * * @author Inderjeet Singh * @author Joel Leitch */ @@ -40,22 +40,12 @@ interface Cache { * @return the cached value for the given {@code key} */ V getElement(K key); - + /** * Removes the value from the cache for the given key. - * + * * @param key the key identifying the value to remove * @return the value for the given {@code key} */ V removeElement(K key); - - /** - * Removes everything from this cache. - */ - void clear(); - - /** - * @return the number of objects in this cache - */ - int size(); } diff --git a/src/org/mcteam/factions/gson/CamelCaseSeparatorNamingPolicy.java b/src/org/mcteam/factions/gson/CamelCaseSeparatorNamingPolicy.java index 91e3dd11..d4d3b388 100644 --- a/src/org/mcteam/factions/gson/CamelCaseSeparatorNamingPolicy.java +++ b/src/org/mcteam/factions/gson/CamelCaseSeparatorNamingPolicy.java @@ -16,6 +16,8 @@ package org.mcteam.factions.gson; +import org.mcteam.factions.gson.internal.$Gson$Preconditions; + import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collection; @@ -51,8 +53,8 @@ final class CamelCaseSeparatorNamingPolicy extends RecursiveFieldNamingPolicy { * is null or empty. */ public CamelCaseSeparatorNamingPolicy(String separatorString) { - Preconditions.checkNotNull(separatorString); - Preconditions.checkArgument(!"".equals(separatorString)); + $Gson$Preconditions.checkNotNull(separatorString); + $Gson$Preconditions.checkArgument(!"".equals(separatorString)); this.separatorString = separatorString; } diff --git a/src/org/mcteam/factions/gson/DefaultConstructorAllocator.java b/src/org/mcteam/factions/gson/DefaultConstructorAllocator.java new file mode 100644 index 00000000..2ebf636e --- /dev/null +++ b/src/org/mcteam/factions/gson/DefaultConstructorAllocator.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2011 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 the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mcteam.factions.gson; + + +import java.lang.reflect.Constructor; + +/** + * Use the default constructor on the class to instantiate an object. + * + * @author Joel Leitch + */ +final class DefaultConstructorAllocator { + private static final Constructor NULL_CONSTRUCTOR = createNullConstructor(); + + private final Cache, Constructor> constructorCache; + + public DefaultConstructorAllocator() { + this(200); + } + + public DefaultConstructorAllocator(int cacheSize) { + constructorCache = new LruCache, Constructor>(cacheSize); + } + + // for testing purpose + final boolean isInCache(Class cacheKey) { + return constructorCache.getElement(cacheKey) != null; + } + + private static final Constructor createNullConstructor() { + try { + return getNoArgsConstructor(Null.class); + } catch (Exception e) { + return null; + } + } + + public T newInstance(Class c) throws Exception { + Constructor constructor = findConstructor(c); + return (constructor != null) ? constructor.newInstance() : null; + } + + @SuppressWarnings("unchecked") + private Constructor findConstructor(Class c) { + Constructor cachedElement = (Constructor) constructorCache.getElement(c); + if (cachedElement != null) { + if (cachedElement == NULL_CONSTRUCTOR) { + return null; + } else { + return cachedElement; + } + } + + Constructor noArgsConstructor = getNoArgsConstructor(c); + if (noArgsConstructor != null) { + constructorCache.addElement(c, noArgsConstructor); + } else { + constructorCache.addElement(c, NULL_CONSTRUCTOR); + } + return noArgsConstructor; + } + + private static Constructor getNoArgsConstructor(Class c) { + try { + Constructor declaredConstructor = c.getDeclaredConstructor(); + declaredConstructor.setAccessible(true); + return declaredConstructor; + } catch (Exception e) { + return null; + } + } + + // placeholder class for Null constructor + private static final class Null { + } +} diff --git a/src/org/mcteam/factions/gson/DefaultTypeAdapters.java b/src/org/mcteam/factions/gson/DefaultTypeAdapters.java index 19aa7dce..d6020ef3 100644 --- a/src/org/mcteam/factions/gson/DefaultTypeAdapters.java +++ b/src/org/mcteam/factions/gson/DefaultTypeAdapters.java @@ -16,19 +16,23 @@ package org.mcteam.factions.gson; +import org.mcteam.factions.gson.internal.$Gson$Types; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; +import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.net.UnknownHostException; import java.sql.Time; import java.sql.Timestamp; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; @@ -36,12 +40,14 @@ import java.util.GregorianCalendar; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; +import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Properties; +import java.util.Queue; import java.util.Set; import java.util.SortedSet; import java.util.StringTokenizer; +import java.util.TimeZone; import java.util.TreeSet; import java.util.UUID; @@ -62,13 +68,15 @@ final class DefaultTypeAdapters { private static final DefaultTimestampDeserializer TIMESTAMP_DESERIALIZER = new DefaultTimestampDeserializer(); - @SuppressWarnings("rawtypes") + @SuppressWarnings("unchecked") private static final EnumTypeAdapter ENUM_TYPE_ADAPTER = new EnumTypeAdapter(); private static final UrlTypeAdapter URL_TYPE_ADAPTER = new UrlTypeAdapter(); private static final UriTypeAdapter URI_TYPE_ADAPTER = new UriTypeAdapter(); private static final UuidTypeAdapter UUUID_TYPE_ADAPTER = new UuidTypeAdapter(); private static final LocaleTypeAdapter LOCALE_TYPE_ADAPTER = new LocaleTypeAdapter(); - private static final CollectionTypeAdapter COLLECTION_TYPE_ADAPTER = new CollectionTypeAdapter(); + private static final DefaultInetAddressAdapter INET_ADDRESS_ADAPTER = + new DefaultInetAddressAdapter(); + private static final CollectionTypeAdapter COLLECTION_TYPE_ADAPTER = new CollectionTypeAdapter(); private static final MapTypeAdapter MAP_TYPE_ADAPTER = new MapTypeAdapter(); private static final BigDecimalTypeAdapter BIG_DECIMAL_TYPE_ADAPTER = new BigDecimalTypeAdapter(); private static final BigIntegerTypeAdapter BIG_INTEGER_TYPE_ADAPTER = new BigIntegerTypeAdapter(); @@ -83,20 +91,25 @@ final class DefaultTypeAdapters { private static final NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter(); private static final ShortTypeAdapter SHORT_TYPE_ADAPTER = new ShortTypeAdapter(); private static final StringTypeAdapter STRING_TYPE_ADAPTER = new StringTypeAdapter(); + private static final StringBuilderTypeAdapter STRING_BUILDER_TYPE_ADAPTER = + new StringBuilderTypeAdapter(); + private static final StringBufferTypeAdapter STRING_BUFFER_TYPE_ADAPTER = + new StringBufferTypeAdapter(); - private static final PropertiesCreator PROPERTIES_CREATOR = new PropertiesCreator(); - private static final TreeSetCreator TREE_SET_CREATOR = new TreeSetCreator(); - private static final HashSetCreator HASH_SET_CREATOR = new HashSetCreator(); private static final GregorianCalendarTypeAdapter GREGORIAN_CALENDAR_TYPE_ADAPTER = - new GregorianCalendarTypeAdapter(); + new GregorianCalendarTypeAdapter(); // The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS // must be defined after the constants for the type adapters. Otherwise, the type adapter // constants will appear as nulls. private static final ParameterizedTypeHandlerMap> DEFAULT_SERIALIZERS = createDefaultSerializers(); + static final ParameterizedTypeHandlerMap> DEFAULT_HIERARCHY_SERIALIZERS = + createDefaultHierarchySerializers(); private static final ParameterizedTypeHandlerMap> DEFAULT_DESERIALIZERS = createDefaultDeserializers(); + static final ParameterizedTypeHandlerMap> DEFAULT_HIERARCHY_DESERIALIZERS = + createDefaultHierarchyDeserializers(); private static final ParameterizedTypeHandlerMap> DEFAULT_INSTANCE_CREATORS = createDefaultInstanceCreators(); @@ -104,13 +117,10 @@ final class DefaultTypeAdapters { ParameterizedTypeHandlerMap> map = new ParameterizedTypeHandlerMap>(); - map.registerForTypeHierarchy(Enum.class, ENUM_TYPE_ADAPTER); map.register(URL.class, URL_TYPE_ADAPTER); map.register(URI.class, URI_TYPE_ADAPTER); map.register(UUID.class, UUUID_TYPE_ADAPTER); map.register(Locale.class, LOCALE_TYPE_ADAPTER); - map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER); - map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER); map.register(Date.class, DATE_TYPE_ADAPTER); map.register(java.sql.Date.class, JAVA_SQL_DATE_TYPE_ADAPTER); map.register(Timestamp.class, DATE_TYPE_ADAPTER); @@ -133,70 +143,106 @@ final class DefaultTypeAdapters { map.register(Short.class, SHORT_TYPE_ADAPTER); map.register(short.class, SHORT_TYPE_ADAPTER); map.register(String.class, STRING_TYPE_ADAPTER); + map.register(StringBuilder.class, STRING_BUILDER_TYPE_ADAPTER); + map.register(StringBuffer.class, STRING_BUFFER_TYPE_ADAPTER); map.makeUnmodifiable(); return map; } + private static ParameterizedTypeHandlerMap> createDefaultHierarchySerializers() { + ParameterizedTypeHandlerMap> map = + new ParameterizedTypeHandlerMap>(); + map.registerForTypeHierarchy(Enum.class, ENUM_TYPE_ADAPTER); + map.registerForTypeHierarchy(InetAddress.class, INET_ADDRESS_ADAPTER); + map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER); + map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER); + map.makeUnmodifiable(); + return map; + } + private static ParameterizedTypeHandlerMap> createDefaultDeserializers() { ParameterizedTypeHandlerMap> map = new ParameterizedTypeHandlerMap>(); - map.registerForTypeHierarchy(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER)); map.register(URL.class, wrapDeserializer(URL_TYPE_ADAPTER)); map.register(URI.class, wrapDeserializer(URI_TYPE_ADAPTER)); map.register(UUID.class, wrapDeserializer(UUUID_TYPE_ADAPTER)); map.register(Locale.class, wrapDeserializer(LOCALE_TYPE_ADAPTER)); - map.registerForTypeHierarchy(Collection.class, wrapDeserializer(COLLECTION_TYPE_ADAPTER)); - map.registerForTypeHierarchy(Map.class, wrapDeserializer(MAP_TYPE_ADAPTER)); map.register(Date.class, wrapDeserializer(DATE_TYPE_ADAPTER)); map.register(java.sql.Date.class, wrapDeserializer(JAVA_SQL_DATE_TYPE_ADAPTER)); map.register(Timestamp.class, wrapDeserializer(TIMESTAMP_DESERIALIZER)); map.register(Time.class, wrapDeserializer(TIME_TYPE_ADAPTER)); map.register(Calendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER); map.register(GregorianCalendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER); - map.register(BigDecimal.class, wrapDeserializer(BIG_DECIMAL_TYPE_ADAPTER)); - map.register(BigInteger.class, wrapDeserializer(BIG_INTEGER_TYPE_ADAPTER)); + map.register(BigDecimal.class, BIG_DECIMAL_TYPE_ADAPTER); + map.register(BigInteger.class, BIG_INTEGER_TYPE_ADAPTER); // Add primitive deserializers - map.register(Boolean.class, wrapDeserializer(BOOLEAN_TYPE_ADAPTER)); - map.register(boolean.class, wrapDeserializer(BOOLEAN_TYPE_ADAPTER)); - map.register(Byte.class, wrapDeserializer(BYTE_TYPE_ADAPTER)); - map.register(byte.class, wrapDeserializer(BYTE_TYPE_ADAPTER)); + map.register(Boolean.class, BOOLEAN_TYPE_ADAPTER); + map.register(boolean.class, BOOLEAN_TYPE_ADAPTER); + map.register(Byte.class, BYTE_TYPE_ADAPTER); + map.register(byte.class, BYTE_TYPE_ADAPTER); map.register(Character.class, wrapDeserializer(CHARACTER_TYPE_ADAPTER)); map.register(char.class, wrapDeserializer(CHARACTER_TYPE_ADAPTER)); - map.register(Double.class, wrapDeserializer(DOUBLE_TYPE_ADAPTER)); - map.register(double.class, wrapDeserializer(DOUBLE_TYPE_ADAPTER)); - map.register(Float.class, wrapDeserializer(FLOAT_TYPE_ADAPTER)); - map.register(float.class, wrapDeserializer(FLOAT_TYPE_ADAPTER)); - map.register(Integer.class, wrapDeserializer(INTEGER_TYPE_ADAPTER)); - map.register(int.class, wrapDeserializer(INTEGER_TYPE_ADAPTER)); - map.register(Long.class, wrapDeserializer(LONG_DESERIALIZER)); - map.register(long.class, wrapDeserializer(LONG_DESERIALIZER)); - map.register(Number.class, wrapDeserializer(NUMBER_TYPE_ADAPTER)); - map.register(Short.class, wrapDeserializer(SHORT_TYPE_ADAPTER)); - map.register(short.class, wrapDeserializer(SHORT_TYPE_ADAPTER)); + map.register(Double.class, DOUBLE_TYPE_ADAPTER); + map.register(double.class, DOUBLE_TYPE_ADAPTER); + map.register(Float.class, FLOAT_TYPE_ADAPTER); + map.register(float.class, FLOAT_TYPE_ADAPTER); + map.register(Integer.class, INTEGER_TYPE_ADAPTER); + map.register(int.class, INTEGER_TYPE_ADAPTER); + map.register(Long.class, LONG_DESERIALIZER); + map.register(long.class, LONG_DESERIALIZER); + map.register(Number.class, NUMBER_TYPE_ADAPTER); + map.register(Short.class, SHORT_TYPE_ADAPTER); + map.register(short.class, SHORT_TYPE_ADAPTER); map.register(String.class, wrapDeserializer(STRING_TYPE_ADAPTER)); + map.register(StringBuilder.class, wrapDeserializer(STRING_BUILDER_TYPE_ADAPTER)); + map.register(StringBuffer.class, wrapDeserializer(STRING_BUFFER_TYPE_ADAPTER)); map.makeUnmodifiable(); return map; } + private static ParameterizedTypeHandlerMap> createDefaultHierarchyDeserializers() { + ParameterizedTypeHandlerMap> map = + new ParameterizedTypeHandlerMap>(); + map.registerForTypeHierarchy(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER)); + map.registerForTypeHierarchy(InetAddress.class, wrapDeserializer(INET_ADDRESS_ADAPTER)); + map.registerForTypeHierarchy(Collection.class, wrapDeserializer(COLLECTION_TYPE_ADAPTER)); + map.registerForTypeHierarchy(Map.class, wrapDeserializer(MAP_TYPE_ADAPTER)); + map.makeUnmodifiable(); + return map; + } + + @SuppressWarnings("unchecked") private static ParameterizedTypeHandlerMap> createDefaultInstanceCreators() { ParameterizedTypeHandlerMap> map = new ParameterizedTypeHandlerMap>(); - map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER); + DefaultConstructorAllocator allocator = new DefaultConstructorAllocator(50); + + // Map Instance Creators + map.registerForTypeHierarchy(Map.class, + new DefaultConstructorCreator(LinkedHashMap.class, allocator)); // Add Collection type instance creators - map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER); + DefaultConstructorCreator listCreator = + new DefaultConstructorCreator(ArrayList.class, allocator); + DefaultConstructorCreator queueCreator = + new DefaultConstructorCreator(LinkedList.class, allocator); + DefaultConstructorCreator setCreator = + new DefaultConstructorCreator(HashSet.class, allocator); + DefaultConstructorCreator sortedSetCreator = + new DefaultConstructorCreator(TreeSet.class, allocator); + map.registerForTypeHierarchy(Collection.class, listCreator); + map.registerForTypeHierarchy(Queue.class, queueCreator); + map.registerForTypeHierarchy(Set.class, setCreator); + map.registerForTypeHierarchy(SortedSet.class, sortedSetCreator); - map.registerForTypeHierarchy(Set.class, HASH_SET_CREATOR); - map.registerForTypeHierarchy(SortedSet.class, TREE_SET_CREATOR); - map.register(Properties.class, PROPERTIES_CREATOR); map.makeUnmodifiable(); return map; } - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings("unchecked") private static JsonDeserializer wrapDeserializer(JsonDeserializer deserializer) { return new JsonDeserializerExceptionWrapper(deserializer); } @@ -205,6 +251,20 @@ final class DefaultTypeAdapters { return getDefaultSerializers(false, LongSerializationPolicy.DEFAULT); } + static ParameterizedTypeHandlerMap> getAllDefaultSerializers() { + ParameterizedTypeHandlerMap> defaultSerializers = + getDefaultSerializers(false, LongSerializationPolicy.DEFAULT); + defaultSerializers.register(DEFAULT_HIERARCHY_SERIALIZERS); + return defaultSerializers; + } + + static ParameterizedTypeHandlerMap> getAllDefaultDeserializers() { + ParameterizedTypeHandlerMap> defaultDeserializers = + getDefaultDeserializers().copyOf(); + defaultDeserializers.register(DEFAULT_HIERARCHY_DESERIALIZERS); + return defaultDeserializers; + } + static ParameterizedTypeHandlerMap> getDefaultSerializers( boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy) { ParameterizedTypeHandlerMap> serializers = @@ -240,30 +300,45 @@ final class DefaultTypeAdapters { return DEFAULT_INSTANCE_CREATORS; } - static class DefaultDateTypeAdapter implements JsonSerializer, JsonDeserializer { - private final DateFormat format; + /** + * This type adapter supports three subclasses of date: Date, Timestamp, and + * java.sql.Date. + */ + static final class DefaultDateTypeAdapter implements JsonSerializer, JsonDeserializer { + private final DateFormat enUsFormat; + private final DateFormat localFormat; + private final DateFormat iso8601Format; DefaultDateTypeAdapter() { - this.format = DateFormat.getDateTimeInstance(); + this(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US), + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); } - DefaultDateTypeAdapter(final String datePattern) { - this.format = new SimpleDateFormat(datePattern); + DefaultDateTypeAdapter(String datePattern) { + this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern)); } - DefaultDateTypeAdapter(final int style) { - this.format = DateFormat.getDateInstance(style); + DefaultDateTypeAdapter(int style) { + this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style)); } - public DefaultDateTypeAdapter(final int dateStyle, final int timeStyle) { - this.format = DateFormat.getDateTimeInstance(dateStyle, timeStyle); + public DefaultDateTypeAdapter(int dateStyle, int timeStyle) { + this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), + DateFormat.getDateTimeInstance(dateStyle, timeStyle)); + } + + DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) { + this.enUsFormat = enUsFormat; + this.localFormat = localFormat; + this.iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + this.iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); } // These methods need to be synchronized since JDK DateFormat classes are not thread-safe // See issue 162 public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { - synchronized (format) { - String dateFormatAsString = format.format(src); + synchronized (localFormat) { + String dateFormatAsString = enUsFormat.format(src); return new JsonPrimitive(dateFormatAsString); } } @@ -273,12 +348,33 @@ final class DefaultTypeAdapters { if (!(json instanceof JsonPrimitive)) { throw new JsonParseException("The date should be a string value"); } - try { - synchronized (format) { - return format.parse(json.getAsString()); + Date date = deserializeToDate(json); + if (typeOfT == Date.class) { + return date; + } else if (typeOfT == Timestamp.class) { + return new Timestamp(date.getTime()); + } else if (typeOfT == java.sql.Date.class) { + return new java.sql.Date(date.getTime()); + } else { + throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT); + } + } + + private Date deserializeToDate(JsonElement json) { + synchronized (localFormat) { + try { + return localFormat.parse(json.getAsString()); + } catch (ParseException ignored) { + } + try { + return enUsFormat.parse(json.getAsString()); + } catch (ParseException ignored) { + } + try { + return iso8601Format.parse(json.getAsString()); + } catch (ParseException e) { + throw new JsonSyntaxException(json.getAsString(), e); } - } catch (ParseException e) { - throw new JsonSyntaxException(e); } } @@ -286,12 +382,12 @@ final class DefaultTypeAdapters { public String toString() { StringBuilder sb = new StringBuilder(); sb.append(DefaultDateTypeAdapter.class.getSimpleName()); - sb.append('(').append(format.getClass().getSimpleName()).append(')'); + sb.append('(').append(localFormat.getClass().getSimpleName()).append(')'); return sb.toString(); } } - static class DefaultJavaSqlDateTypeAdapter implements JsonSerializer, + static final class DefaultJavaSqlDateTypeAdapter implements JsonSerializer, JsonDeserializer { private final DateFormat format; DefaultJavaSqlDateTypeAdapter() { @@ -322,7 +418,7 @@ final class DefaultTypeAdapters { } } - static class DefaultTimestampDeserializer implements JsonDeserializer { + static final class DefaultTimestampDeserializer implements JsonDeserializer { public Timestamp deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { Date date = context.deserialize(json, Date.class); @@ -330,7 +426,7 @@ final class DefaultTypeAdapters { } } - static class DefaultTimeTypeAdapter implements JsonSerializer